-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlogplot
executable file
·451 lines (380 loc) · 17.9 KB
/
logplot
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
#!/bin/bash
# ================================================================== #
# Script using gnuplot and ps2pdf/imagemagick to create a graph #
# on an A4 landscape PDF of the CSV data from the logging #
# volt/amp meter. It can also extract the summary-info on the last #
# line and put it in the title. See also https://logger.brechtve.be #
# #
# USAGE: see "logplot -h" #
# #
# Brecht Van Eeckhoudt - 14/02/2022 (development started 03/12/2021) #
# Initially written on Ubuntu 20.04 #
# ================================================================== #
# Version of this script (date)
VERSION="14/02/2022"
# TODO add argument to plot voltage and power ( -voltpow )
# TODO add argument to set xrange with minutes
# TODO add argument to change some axes to logaritmic ones ( set logscale (x|y|y2) )
# TODO add argument to remove seconds from x-axis
# TODO add arguments to add labels/arrows
# TODO add argument to plot in a window/to a PNG instead of to a PDF
# TODO add argument to enable boxes with values on the lines
# Print help menu if no arguments are given when calling the script
if [[ $# -eq 0 ]]; then
NOARGUMENTS='1'
ARGUMENTS=1
else
ARGUMENTS=$#
fi
# Loop through all of the arguments and change variables accordingly
for ((i=1; i<=$ARGUMENTS; i++))
do
# "${!i}" = Indirect expansion (parameter is expanded twice)
if [[ ${!i} == '-h' || $NOARGUMENTS == '1' ]]; then
# echo "-e" for enabling escape sequences
# echo "-n" for not advancing to the next line
# - "\e[1m" = bold
# - "\e[93m" = light yellow
# - "\e[0m" = reset all attributes
echo -e "\e[93m\e[1mLOGPLOT HELP MENU (version $VERSION)"
echo -e "Brecht Van Eeckhoudt - https://logger.brechtve.be\e[0m\n"
echo -e "\e[93mAvailable arguments: "
echo " -h : Print this menu"
echo " -f <inputfile> : Set input-file"
echo " -t <title> : Set graph title (subscript: \"A_{BC}\", superscript: \"A^{BC}\")"
echo " -st <subtitle> : Set graph subtitle"
echo " -ndt : Don't print date and time of first measurement above graph (no datetime)"
echo " -nrt : Don't print total runtime above graph (no runtime)"
echo " -av : Print capacity and max/min voltage/current values above graph (all values)"
echo " -c : Print capacity values above graph"
echo " -mv : Print max/min voltage values above graph"
echo " -mc : Print max/min current values above graph"
echo " -(x|y|y2)r <range> : Set x|y|y2range (ex.: \"[1:]\" or \"[0:10]\")"
echo " -(x|y|y2)t <tics> : Set x|y|y2tics (ex.: \"0.25\" or \"(1, 5, 10)\")"
echo " -l <position>|off : Set key/legend position (ex.: \"outside right top\", \"left bmargin\" or \"at 10,10\") or disable it"
echo " -(x|y|y2)l <label> : Set x|y|y2 axis label (ex.: \"\" to disable axis label)"
echo " -l(1|2) <label> : Set line 1|2 label name in key/legend"
echo " -time : Plot time instead of runtime on the horizontal (x) axis"
echo " -volt : Only plot voltage over (run)time"
echo " -curr : Only plot current over (run)time"
echo " -pow : Only plot power over (run)time"
echo " -ne : Disable extension of the axis-ranges to the next tic-mark position"
echo " -e <text> : Define extra text to add to the output-filename before the .pdf extension"
echo " -noFooter : Footer is missing, use the last runtime-value-entry for the title and don't print capacity/min/max values"
echo -en "\e[0m"
CONTINUE='0' # Make sure no other code is executed
elif [[ ${!i} == '-f' ]]; then # Set filename
j=$((i+1))
FILE="${!j}"
elif [[ ${!i} == '-t' ]]; then # Set title
j=$((i+1))
TITLE="${!j}"
elif [[ ${!i} == '-st' ]]; then # Set subtitle
j=$((i+1))
SUBTITLE="${!j}"
elif [[ ${!i} == '-ndt' ]]; then # Disable date and time above graph
NODATETIME='1'
elif [[ ${!i} == '-nrt' ]]; then # Disable runtime above graph
NORUNTIME='1'
elif [[ ${!i} == '-av' ]]; then # Print capacity and max/min voltage/current values above graph
CAPACITY='1'
MAXMINVOLT='1'
MAXMINCURR='1'
elif [[ ${!i} == '-c' ]]; then # Print capacity values above plot
CAPACITY='1'
elif [[ ${!i} == '-mv' ]]; then # Print max/min voltage values above plot
MAXMINVOLT='1'
elif [[ ${!i} == '-mc' ]]; then # Print max/min curent values above plot
MAXMINCURR='1'
elif [[ ${!i} == '-xr' ]]; then # Set xrange
j=$((i+1))
XRANGE="set xr ${!j}"
elif [[ ${!i} == '-yr' ]]; then # Set yrange
j=$((i+1))
YRANGE="set yr ${!j}"
elif [[ ${!i} == '-y2r' ]]; then # Set y2range
j=$((i+1))
Y2RANGE="set y2r ${!j}"
elif [[ ${!i} == '-xt' ]]; then # Set xtics
j=$((i+1))
XTICS="set xtics ${!j}; "
elif [[ ${!i} == '-yt' ]]; then # Set ytics
j=$((i+1))
YTICS="set ytics ${!j}; "
elif [[ ${!i} == '-y2t' ]]; then # Set y2tics
j=$((i+1))
Y2TICS="set y2tics ${!j}; "
elif [[ ${!i} == '-l' ]]; then # Set key/legend position or disable it
j=$((i+1))
if [[ ${!j} == 'off' ]]; then
LEGEND1="set key ${!j}"
LEGEND='0' # Don't call other key/legend settings
else
LEGEND1="set key ${!j}"
fi
elif [[ ${!i} == '-xl' ]]; then # Set xlabel
j=$((i+1))
XLBL="${!j}"
elif [[ ${!i} == '-yl' ]]; then # Set ylabel
j=$((i+1))
YLBL="${!j}"
elif [[ ${!i} == '-y2l' ]]; then # Set y2label
j=$((i+1))
Y2LBL="${!j}"
elif [[ ${!i} == '-l1' ]]; then # Set line 1 title
j=$((i+1))
LINE1="title \"${!j}\""
elif [[ ${!i} == '-l2' ]]; then # Set line 2 title
j=$((i+1))
LINE2="title \"${!j}\""
elif [[ ${!i} == '-time' ]]; then # Plot using time instead of runtime
TIME='1'
elif [[ ${!i} == '-volt' ]]; then # Only plot voltage
VOLT='1'
elif [[ ${!i} == '-curr' ]]; then # Only plot current
CURR='1'
elif [[ ${!i} == '-pow' ]]; then # Only plot power
POW='1'
elif [[ ${!i} == '-ne' ]]; then # Disable extension of the axis ranges to next tic-mark position
EXTENSIONSCALE="set autoscale fix"
elif [[ ${!i} == '-e' ]]; then # Set extra text before .pdf extension
j=$((i+1))
EXTRA="${!j}"
elif [[ ${!i} == '-noFooter' ]]; then # Footer is missing, use the last runtime-value-entry for the title and don't print capacity/min/max values
NOFOOTER='1'
fi
done
# Don't execute other code if "help" is called
if [[ $CONTINUE != '0' ]]; then
# gnuplot enhanced text mode: "{/=12 TEXT}\n": Changes the font size of each line (but not of new line character) to increase space between lines
# "{/:Bold TEXT}": Puts text in bold
# Add a title if one was given
if [[ -n "$TITLE" ]]; then PLOTTITLE+="{/:Bold {/=12 $TITLE}}"; fi
# Add a subtitle if one was given
if [[ -n "$SUBTITLE" ]]; then
if [[ -n "$TITLE" ]]; then PLOTTITLE+="\n"; fi # Add a newline if necessary
PLOTTITLE+="{/=12 $SUBTITLE}"
fi
OLDIFS=$IFS
IFS=','
# Gather the date and time from the second line of the input-file to add to the title if necessary
if [[ $NODATETIME != '1' ]]; then
[ ! -f "$FILE" ] && { echo "$FILE file not found"; exit 99; } # Quote marks so spaces can exist in the filepath
while read datetime runtime volt curr pow
do
if [[ -n "$TITLE" || -n "$SUBTITLE" ]]; then PLOTTITLE+="\n"; fi # Add a newline if necessary
PLOTTITLE+="{/=12 $datetime}"
# Read the second line of the file and pass the output as a file to the while loop using process substitution ("<(...)") (quote marks so spaces can exist in the filepath)
done < <(sed '2q;d' "$FILE")
# "2q" will quit immediately when the line number is 2, "d" will delete the line instead of printing it; this is inhibited on the last line because the "q" causes the rest of the script to be skipped when quitting.
fi
# Footer is missing, use the last runtime-value-entry for the title and don't print capacity/min/max values
if [[ $NOFOOTER == '1' ]]; then
[ ! -f "$FILE" ] && { echo "$FILE file not found"; exit 99; } # Quote marks so spaces can exist in the filepath
while read datetime runtime volt curr pow
do
# Add runtime to title if required
if [[ $NORUNTIME != '1' ]]; then
if [[ -n "$TITLE" || -n "$SUBTITLE" || $NODATETIME != '1' ]]; then PLOTTITLE+="\n\n"; fi # Add two newlines if necessary
PLOTTITLE+="{/=12 Runtime [hh:mm:ss]: $runtime}"
fi
# Read the last line of the file (-n = quiet mode) and pass the output as a file to the while loop using process substitution ("<(...)") (quote marks so spaces can exist in the filepath)
done < <(tail -n -1 "$FILE")
# Gather info from the last line of the input-file to add to the title if necessary
elif [[ $NORUNTIME != '1' || $CAPACITY == '1' || $MAXMINVOLT == '1' || $MAXMINCURR == '1' ]]; then
[ ! -f "$FILE" ] && { echo "$FILE file not found"; exit 99; } # Quote marks so spaces can exist in the filepath
while read runtime capAh capWh vMax vMin aMax aMin
do
# Add runtime to title if required
if [[ $NORUNTIME != '1' ]]; then
if [[ -n "$TITLE" || -n "$SUBTITLE" || $NODATETIME != '1' ]]; then PLOTTITLE+="\n\n"; fi # Add two newlines if necessary
PLOTTITLE+="{/=12 Runtime [hh:mm:ss]: $runtime}"
fi
# Add capacity to title if required
if [[ $CAPACITY == '1' ]]; then
if [[ -n "$TITLE" || -n "$SUBTITLE" || $NODATETIME != '1' ]] && [[ $NORUNTIME == '1' ]]; then PLOTTITLE+="\n\n"; fi # Add two newlines if necessary
if [[ $NORUNTIME != '1' ]]; then PLOTTITLE+="\n"; fi # Add a newline if necessary
PLOTTITLE+="{/=12 Capacity [Ah]: $capAh - Capacity [Wh]: $capWh}"
fi
# Add min/max voltage values to title if required
if [[ $MAXMINVOLT == '1' ]]; then
if [[ -n "$TITLE" || -n "$SUBTITLE" || $NODATETIME != '1' ]] && [[ $NORUNTIME == '1' && $CAPACITY != '1' ]]; then PLOTTITLE+="\n\n"; fi # Add two newlines if necessary
if [[ $NORUNTIME != '1' || $CAPACITY == '1' ]]; then PLOTTITLE+="\n"; fi # Add a newline if necessary
PLOTTITLE+="{/=12 Max Volt [V]: $vMax - Min Volt [V]: $vMin}"
fi
# Add min/max current values to title if required
if [[ $MAXMINCURR == '1' ]]; then
if [[ -n "$TITLE" || -n "$SUBTITLE" || $NODATETIME != '1' ]] && [[ $NORUNTIME == '1' && $CAPACITY != '1' && $MAXMINVOLT != '1' ]]; then PLOTTITLE+="\n\n"; fi # Add two newlines if necessary
if [[ $NORUNTIME != '1' || $CAPACITY == '1' || $MAXMINVOLT == '1' ]]; then PLOTTITLE+="\n"; fi # Add a newline if necessary
PLOTTITLE+="{/=12 Max Curr [A]: $aMax - Min Curr [A]: $aMin}"
fi
# Read the last line of the file (-n = quiet mode) and pass the output as a file to the while loop using process substitution ("<(...)") (quote marks so spaces can exist in the filepath)
done < <(tail -n -1 "$FILE")
fi
IFS=$OLDIFS
# Move all but the last two lines to a temporary file ("-n" = quiet mode, quote marks so spaces can exist in the filepath)
head -n -2 "$FILE" > "$FILE".temp
# Add default legend/key settings if necessary
if [[ $LEGEND != '0' ]]; then
LEGEND2="set key autotitle columnhead" # Use the first line as the "title" for the line in the key/legend
LEGEND3="set key spacing 1.2 font \",12\"" # Increase inter-line spacing in the key/legend
LEGEND4="set key box width -2 height 0.5" # Draw a box around the key/legend and update the dimensions
fi
# Add default legend/key position if necessary
if [[ -z "$LEGEND1" ]]; then LEGEND1="set key right top"; fi
# Add default XLBL if necessary
# ${var+x} is a parameter expansion which evaluates to nothing if var is unset, and substitutes the string x otherwise
# Quotes can be omitted because this syntax and usage guarantees this will only expand to something that does not require quotes
# (since it either expands to x (which contains no word breaks so it needs no quotes), or to nothing (which results in [ -z ],
# which conveniently evaluates to the same value (true) that [ -z "" ] does as well)).
if [[ $TIME == '1' ]]; then
if [[ -z ${XLBL+x} ]]; then XLBL="Time [hh:mm:ss]"; fi
else
if [[ -z ${XLBL+x} ]]; then XLBL="Runtime [hh:mm:ss]"; fi
fi
# Configure labels according to variables
if [[ $VOLT == '1' ]]; then
# Add default YLBL if necessary
if [[ -z ${YLBL+x} ]]; then YLBL="Voltage [V]"; fi
# Construct final plot-command
if [[ $TIME == '1' ]]; then
PLOTCMD="plot \"${FILE}.temp\" using 1:3 with lines ls 101 ${LINE1}"
else
PLOTCMD="plot \"${FILE}.temp\" using 2:3 with lines ls 101 ${LINE1}"
fi
elif [[ $CURR == '1' ]]; then
# Add default YLBL if necessary
if [[ -z ${YLBL+x} ]]; then YLBL="Current [A]"; fi
# Construct final plot-command
if [[ $TIME == '1' ]]; then
PLOTCMD="plot \"${FILE}.temp\" using 1:4 with lines ls 101 ${LINE1}"
else
PLOTCMD="plot \"${FILE}.temp\" using 2:4 with lines ls 101 ${LINE1}"
fi
elif [[ $POW == '1' ]]; then
# Add default YLBL if necessary
if [[ -z ${YLBL+x} ]]; then YLBL="Power [W]"; fi
# Construct final plot-command
if [[ $TIME == '1' ]]; then
if [[ -n "$LINE1" ]]; then
PLOTCMD="plot \"${FILE}.temp\" using 1:5 with lines ls 101 ${LINE1}"
else
PLOTCMD="plot \"${FILE}.temp\" using 1:5 with lines ls 101 title \" Power [W]\"" # Manual title name here to fix spacing...
fi
else
if [[ -n "$LINE1" ]]; then
PLOTCMD="plot \"${FILE}.temp\" using 2:5 with lines ls 101 ${LINE1}"
else
PLOTCMD="plot \"${FILE}.temp\" using 2:5 with lines ls 101 title \" Power [W]\"" # Manual title name here to fix spacing...
fi
fi
else
# Add default YLBL if necessary
if [[ -z ${YLBL+x} ]]; then YLBL="Voltage [V]"; fi
# Add default Y2LBL if necessary
if [[ -z ${Y2LBL+x} ]]; then Y2LBL="Current [A]"; fi
# Gather whole "set" line for label name
Y2LABEL="set y2label \"${Y2LBL}\" offset -1,0 font \",12\""
# Enable y2tics
Y2TICSEN="set y2tics font \",12\""
# Construct final plot-command
if [[ $TIME == '1' ]]; then
PLOTCMD="plot \"${FILE}.temp\" using 1:3 with lines ls 101 ${LINE1}, '' using 1:4 with lines axis x1y2 ls 102 ${LINE2}"
else
PLOTCMD="plot \"${FILE}.temp\" using 2:3 with lines ls 101 ${LINE1}, '' using 2:4 with lines axis x1y2 ls 102 ${LINE2}"
fi
fi
# Construct time commands
if [[ $TIME == '1' ]]; then
TIMEFORMAT="%d/%m/%Y %H:%M:%S"
FORMATX="%H:%M:%S"
else
TIMEFORMAT="%H:%M:%S"
FORMATX="%tH:%tM:%tS"
# %tH +/- hours relative to time=0 (does not wrap at 24)
# %tM +/- minutes relative to time=0
# %tS +/- seconds associated with previous tH or tM field
fi
# Gather whole "set" lines for label names
XLABEL="set xlabel \"${XLBL}\" offset 0,-2 font \",12\""
YLABEL="set ylabel \"${YLBL}\" offset 1,0 font \",12\""
# Use "heredoc" to do final gnuplot call
gnuplot <<- EOF
# <font ",12"> is used everywhere because the global font size is bigger and newlines (\n)
# of this size can be used to increase the inter-line spacing in the title
set datafile separator ','
set xdata time # Indicate that the X-axis is time-data
set timefmt "${TIMEFORMAT}" # Specify the time-string format
set format x "${FORMATX}" # Format the X-axis (otherwise MM:SS is used)
set xtics rotate by 45 offset -3.5,-2.4 # Rotate and move the labels of the X-axis
set title "${PLOTTITLE}"
# Incude label settings
${XLABEL}
${YLABEL}
${Y2LABEL}
# Enable second axis if necessary
${Y2TICSEN}
# Disable extension of the axis ranges to next tic-mark position if necessary
${EXTENSIONSCALE}
set ytics nomirror font ",12" # Don't show tics of the left axis on the right axis
set xtics nomirror font ",12" # Don't show tics on top of the graph
set format y "%.2f" # Format Y-axis as a 2 decimal float
set format y2 "%.2f" # Format Y2-axis as a 2 decimal float
set style line 100 lt 1 lc rgb "grey" lw 0.5 # Define a new line style for the grid
set grid ls 100 # Use the defined line style for the grid lines
set style line 101 lw 3 lt rgb "#008080" # Define a new line style for plotting (color = teal)
set style line 102 lw 3 lt rgb "#ff7f00" # Define a new line style for plotting (color = orange)
# Include range settings
${XRANGE}
${YRANGE}
${Y2RANGE}
# Include tick settings
${XTICS}
${YTICS}
${Y2TICS}
# Include key/legend settings
${LEGEND1}
${LEGEND2}
${LEGEND3}
${LEGEND4}
# EXTRA THINGS (TODO)
#set label "Test" at 40, 10
#set arrow from 1,1 to 5,10
#set xtic auto
#set mytics 4
#set xzeroaxis lt -1
# MULTIPLOT (TODO)
#set multiplot # multiplot mode (prompt changes to 'multiplot')
#set size 1, 0.5
#set origin 0.0,0.5
#plot sin(x), log(x)
#set origin 0.0,0.0
#plot sin(x), log(x), cos(x)
#unset multiplot # exit multiplot mode (prompt changes back to 'gnuplot')
# Configure the terminal so a postscript file is produced
# NOTE: A bigger font than elsewhere is used to increase the inter-line-spacing in the title (keep "\n" size 14)
set terminal postscript enhanced color landscape 'Arial' 14
set output "${FILE}.ps" # Set the output filename using the filename passed by a variable
#set size ratio 0.71 # Change size ratio so graph looks more square
# Configure the terminal so a PNG file is produced (TODO)
#set terminal pngcairo size 1200,900 enhanced font 'Arial, 14'
#set output 'filename.png'
# Configure the terminal so a different gnuplot window with another font(size) is used (TODO)
# set terminal wxt size 1200,900 enhanced font 'Segoe UI,10' persist
# Plot the whole thing
${PLOTCMD}
EOF
# Remove the extension from the filename (quote marks so spaces can exist in the filepath)
NAME="${FILE##*/}"
NAME="${NAME%.*}"
# Convert the postscript data to a PDF-file (quote marks so spaces can exist in the filepath)
if [[ -n "$EXTRA" ]]; then
ps2pdf -sPAGESIZE=a4 "$FILE".ps "$NAME-$EXTRA".pdf # Add extra text before the PDF extension if given
else
ps2pdf -sPAGESIZE=a4 "$FILE".ps "$NAME".pdf
fi
# Clean up temporary files (quote marks so spaces can exist in the filepath)
rm "$FILE".temp
rm "$FILE".ps
echo -e "\e[93mDone!\e[0m"
fi