/
gplot
executable file
·291 lines (272 loc) · 10.3 KB
/
gplot
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
#!/bin/bash
#
# gplot: Use gnuplot to plot one or more files directly from the command line.
#
# Copyright (C) 2010-2014 Rhys Ulerich
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# Fail on first error
set -e
# Create temporary files to hold gnuplot script
tmp1=$(mktemp "${TMPDIR-/tmp}/tmp.XXXXXXXXXX")
tmp2=$(mktemp "${TMPDIR-/tmp}/tmp.XXXXXXXXXX")
builtin trap "rm -f \"$tmp1\" \"$tmp2\"" EXIT
## TODO Permit controlling these options
# set termoption font "<fontname>{,<fontsize>}"
# set termoption fontscale <scale>
# set termoption {solid|dashed}
# set termoption {linewidth <lw>}{lw <lw>}
# Process (and then remove) command line options
# Build up any post-terminal processing in tmp2 for later use
echo "invocation = '$(date +%r): gplot $*'" >> "$tmp1"
if test -n "$GNUTERM"; then
terminal="set term ${GNUTERM} title invocation"
else
terminal="if (exists(\"GPVAL_TERMINALS\") && (strstrt(GPVAL_TERMINALS, 'wxt') > 0)) set term wxt title invocation; else set term x11 title invocation"
fi
autotitle=
forexpr=
grepcmd=
pause=
plotcmd=plot
showhelp=
stdin=
while getopts "3cef:g:hilo:ps:t:x:y:z:CF:GH:LMS:T:X:Y:Z:" opt
do
case $opt in
3) plotcmd=splot
;;
c) autotitle=true
;;
e) echo "set termoption enhanced" >> "$tmp2"
;;
f) forexpr=" for [$OPTARG] "
;;
g) grepcmd="grep \"$OPTARG\""
;;
h) showhelp=0
;;
i) pause='pause -1 "Plot interactive until Enter pressed.\nHit h in plot window for help.\n"'
;;
l) echo "set logscale y" >> "$tmp2"
;;
o)
outputfile="${OPTARG##*/}"
outputext="${outputfile##*.}"
case "$outputext" in
eps|EPS)
terminal="if (strstrt(GPVAL_TERMINALS, 'epscairo') > 0) set term epscairo color; else set term postscript eps color"
;;
jpeg|JPEG|jpg|JPG)
terminal="set term jpeg"
;;
pdf|PDF)
terminal="set term pdfcairo color"
;;
png|PNG)
terminal="if (strstrt(GPVAL_TERMINALS, 'pngcairo') > 0) set term pngcairo; else set term png"
;;
svg|SVG)
terminal="set term svg dynamic"
;;
*)
echo "Output \"$OPTARG\" has unknown extension \"$outputext\"" 1>&2
exit 1
;;
esac
pause='' # Disable interactive on file output
echo "set output \"$OPTARG\"" >> "$tmp2"
;;
p) stdin=true
;;
s) savescript="$OPTARG"
;;
t) echo "set title \"$OPTARG\"" >> "$tmp2"
;;
x) echo "set xlabel \"$OPTARG\"" >> "$tmp2"
;;
y) echo "set ylabel \"$OPTARG\"" >> "$tmp2"
;;
z) echo "set zlabel \"$OPTARG\"" >> "$tmp2"
;;
C) echo "set datafile separator \",\"" >> "$tmp2"
;;
F) pause="pause $OPTARG; reread"
;;
G) echo "set grid" >> "$tmp2"
;;
H) echo "bw = $OPTARG" >> "$tmp2"
echo "set boxwidth bw" >> "$tmp2"
echo "bin(x, width) = width*floor(x/width) + bw/2.0" >> "$tmp2"
echo "set style fill solid 0.5" >> "$tmp2"
;;
L) echo "set logscale x" >> "$tmp2"
;;
M) echo "set pm3d map" >> "$tmp2"
;;
S) appendscript="$OPTARG"
;;
T) echo "set xdata time" >> "$tmp2"
echo "set timefmt \"$OPTARG\"" >> "$tmp2"
;;
X) echo "set xrange [$OPTARG]" >> "$tmp2"
;;
Y) echo "set yrange [$OPTARG]" >> "$tmp2"
;;
Z) echo "set zrange [$OPTARG]" >> "$tmp2"
;;
esac
done
shift $((OPTIND-1))
if [ x$showhelp != x ]; then
cat <<-HERE
Usage: gplot [OPTION]... [GNUPLOTSPEC...] [::: [FILE]...]
Use gnuplot to plot one or more files directly from the command line.
-3 Perform 3D plotting using gnuplot's splot command.
-c Populate the key using autotitling.
-e Turn on enhanced terminal features.
-f FOREXPR Prepend a 'for [FOREXPR]' to the plotting command.
-g PATTERN Grep for PATTERN in the input processing only matches.
-h Show this help message.
-i Interactive plotting mode. Hit 'h' on plot for help.
-l Use logarithmic scale for y axis.
-o FILE Save the plot to FILE with type chosen via the extension.
Formats EPS, JPEG, PDF, PNG, and SVG supported.
-p Read data from pipe (stdin) rather than file.
-s FILE Save the generated gnuplot commands as a script called FILE.
-t TITLE Set TITLE as the plot title.
-x XLABEL Specify XLABEL as the x axis label.
-y YLABEL Specify YLABEL as the y axis label.
-z ZLABEL Specify ZLABEL as the z axis label.
-C Process comma-separated value (CSV) data.
-F FREQUENCY Replot the inputs every FREQUENCY seconds.
-G Show grid lines.
-H BW Ease making histograms using binwidth BW; see examples.
-L Use logarithmic scale for x axis.
-M In conjunction with option -3, employ 'set pm3d map'.
-S FILE Append the generated gnuplot commands to some FILE.
-T TIMEFMT Expect temporal x data formatted per 'set timefmt "TIMEFMT"'.
-X XLOW:XHIGH Specify an explicit x axis range instead of autoscaling.
-Y YLOW:YHIGH Specify an explicit y axis range instead of autoscaling.
-Z ZLOW:ZHIGH Specify an explicit z axis range instead of autoscaling.
Examples (see gnuplot documentation for complete GNUPLOTSPEC details):
gplot -eci using 1:2 with linespoints ::: foo.dat
gplot -s foo.gp -X 0:1 -Y 0:2 using 1:2 with linespoints ::: foo.dat
gplot -c -o foo.eps using 1:2 with linespoints ::: <(head foo.dat | tail)
gplot -f i=2:5 -o foo.png using 1:i with points ::: foo.dat
gplot -C -T %Y%m%d using 1:2 ::: timedata.csv
gplot -3 using '"x":"y":"z"' ::: restart*.dat # Escaping of column names...
gplot -3 using x:y:z ::: restart*.dat # ...is done automatically
gplot -H 0.01 using '(bin(\$1,bw)):(1.0)' smooth frequency w boxes ::: foo.dat
ls -rt | head | gplot using '9:(0.0001)' smooth kdensity
mycalc.x | gplot -p using 1:2:3 w yerrorbars # mycalc.x prints to stdout
Input FILE(s) compressed by bzip2, gzip, or xz are transparently decompressed.
If [::: [FILE]...] and [-p] are absent, filenames are read from standard input.
The [-p] option is incompatible with [-f FOREXPR] and [-F FREQUENCY].
Variable \$GNUTERM, defaulting to "wxt" then "x11", sets the default terminal.
On error, the failing gnuplot script is shown.
HERE
exit $showhelp
fi
# Set terminal
echo "$terminal" >> "$tmp1"
# Slurp any settings built up during getopt processing
cat "$tmp2" >> "$tmp1"
# Build the regular expressions used just below
# Grab plot specification and data files per GNU parallel syntax. That is,
# [SPECIFICATION...] ::: [DATAFILE...]
# where a missing ::: separator mandates reading lines from standard input.
# Additionally, quote to using specifications consisting of 2-or-3 column names
declare -r token='[[:alpha:]][_[:alnum:]]*'
declare -r usingspec2="^($token):($token)\$"
declare -r usingspec3="^($token):($token):($token)\$"
declare -a spec
while [ $# -gt 0 ]; do
if [[ "$1" = ":::" ]]; then
break
elif [[ "$1" =~ $usingspec2 ]]; then
spec+=("\"${BASH_REMATCH[1]}\":\"${BASH_REMATCH[2]}\"")
elif [[ "$1" =~ $usingspec3 ]]; then
spec+=("\"${BASH_REMATCH[1]}\":\"${BASH_REMATCH[2]}\":\"${BASH_REMATCH[3]}\"")
else
spec+=("$1")
fi
shift
done
declare -a files
if [ "$1" = ":::" ]; then
while shift && [ $# -gt 0 ]; do
files+=("$1")
done
elif [ "$stdin" ]; then
files+=("<cat")
else
if [ -t 0 ]; then
echo "$0 warning: reading newline-separated filenames from terminal"
fi
while IFS= read -r; do files+=("$REPLY"); done # Bash 3.x-friendly...
[[ $REPLY ]] && files+=("$REPLY") # ...readarray clone
fi
# Tweak autotitle based on options and incoming argument details
if [ "$autotitle" ]; then
# Use columnheader option iff only one file provided
if [ ${#files[@]} -eq 1 -a $plotcmd != splot ]; then
echo 'set key autotitle columnheader' >> "$tmp1"
else
echo 'set key autotitle' >> "$tmp1"
fi
else
echo 'set key noautotitle' >> "$tmp1"
fi
# Build gnuplot script to plot possibly multiple files
declare -i count=0
for file in "${files[@]}"
do
# Automatically add any required decompresser in a pipeline
case $(file -ib "$file") in #(
application/bzip2\;*) datafile="< bzcat \"$file\"" ;;#(
application/gzip\;*) datafile="< zcat \"$file\"" ;;#(
application/xz\;*) datafile="< xzcat \"$file\"" ;;#(
application/x-bzip2\;*) datafile="< bzcat \"$file\"" ;;#(
application/x-gzip\;*) datafile="< zcat \"$file\"" ;;#(
application/x-xz\;*) datafile="< xzcat \"$file\"" ;;
*) datafile=$file
esac
# Incorporate any nontrivial grepcmd for this file
if test -n "$grepcmd"; then
if [ "$stdin" ] && [ $datafile = "<cat" ]; then
datafile="< $grepcmd" # Begin pipeline without file
elif test \< = "${datafile:0:1}"; then
datafile+="| $grepcmd" # Append to pipeline
else
datafile="< $grepcmd $datafile" # Begin pipeline
fi
fi
count+=1
if [ $count -eq 1 ]; then
echo "$plotcmd" "$forexpr" "'$datafile'" "${spec[@]}" \\ >> "$tmp1"
else
echo " " , "$forexpr" "'$datafile'" "${spec[@]}" \\ >> "$tmp1"
fi
done
echo '' >> "$tmp1"
# If requested, add a pause command to the end of the script
if [ "$pause" ]; then
echo "$pause" >> "$tmp1"
fi
# If requested, save the plotting commands as an executable script
if [ "$savescript" ]; then
echo '#!/usr/bin/env gnuplot' > "$savescript"
cat "$tmp1" >> "$savescript"
chmod a+x "$savescript"
fi
# If requested, append to plotting commands to a possibly existing file
if [ "$appendscript" ]; then
echo '#!/usr/bin/env gnuplot' >> "$appendscript"
cat "$tmp1" >> "$appendscript"
fi
# Generate the plot
# Display the script when an error occurs to aid debugging
gnuplot -persist "$tmp1" || cat "$tmp1"