Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
a61c4d726This file is pinned to the selected release. Download the original to open it in your design tool.
#!/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