Gnuplot: plotting from string skips the first line - string

Here's my minimal Gnuplot script:
data="3.000000\t49.200000\n3.500000\t42.800000\n4.000000\t37.800000\n4.500000\t33.800000\n5.000000\t30.400000\n5.500000\t28.000000\n"
plot '< echo -e '.sprintf('"%s"', data) using 1:2 title 'there is no data point for x=3.0?' w linespoints
In my actual script, of course, I populate the data string in a different way (using the stats command), so saving the data to a file first, then running plot should work, but I don't like it! Seems overly cumbersome, leaves stray files around, etc.
My current solution is to prepend the string with a dummy line (data="0\t0\n..."), but my concern is: am I doing something wrong, or is this a bug?
(I'm on ubuntu 14.04, gnuplot 4.6 patchlevel 4, which I guess is not the super-most-up-to-date...)
Thanks!

Remove the -e option and it works fine:
data="3.000000\t49.200000\n3.500000\t42.800000\n4.000000\t37.800000\n4.500000\t33.800000\n5.000000\t30.400000\n5.500000\t28.000000\n"
plot '< echo '.sprintf('"%s"', data) using 1:2 title 'there is a data point for x=3.0!' w linespoints
But I can't tell you exactly why it works ;)
As an outlook for you: Gnuplot 5 has a new way of saving inline data as some kind of heredoc. In my eyes it isn't a good way to include actual data files into the plotting script, but it is supported:
$data <<EOD
3.000000 49.200000
3.500000 42.800000
4.000000 37.800000
4.500000 33.800000
5.000000 30.400000
5.500000 28.000000
EOD
plot $data using 1:2 notitle w linespoints

Related

Gnuplot: Change Density of dotted line in splot

I am trying to plot a dotted line within an splot with the following code in Gnuplot 4.6 patchlevel 4:
set terminal "pdfcairo" enhanced dashed size 15,10
set pm3d map
set output "test.pdf"
splot 'map.dat' using 1:($2/1000):3 notitle, \
'line1.dat' using 1:($2/1000):1 notitle with lines ls 2, \
'line2.dat' using 1:($2/1000):1 notitle with lines ls 2
unset output
The heat map works and so does line1.dat. However, the second line appears mostly solid. The difference is that line1.dat has 70 entries and line2.dat has 900. The second line has a jump between two points and there it is dotted.
Does somebody know how I can change the dot density so that the whole line appears dotted. Changing the original data file is not an option.
Thank you for your help,
noes
EDIT:
One workaround I found is
splot 'line2.dat' every ...
but that can get unconvenient at the jump in the data.
The command (s)plot 'line.dat' with lines first plots the datapoints and then connects the datapoints using lines with the respective linestyle. If the datapoints are too close to each other, there is no place for some gaps when a dashed linestyle is used.
To display a dotted/dashed line, you can try to replace the points by a function or to reduce the number of points.
Try dotted lines instead of dashed lines. Linestyle and linecolor can be set independently: splot 'line.dat' with lines ls 0 lc 2. 900 points might be too many for this approach.
Fitting a function would work, but probably it is too difficult to find a suitable function.
The every option reduces the number of points.
Another possibility to reduce the number of points would be to interpolate the points using the smooth option. This requires a temporary file and works as follows:
# [prepare plot]
set samples 100
set table "line2.dat.tmp"
plot 'line2.dat' using 1:($2/1000) smooth mcsplines with lines ls 2
unset table
set terminal "pdfcairo" enhanced dashed size 15,10
set pm3d map
set output "test.pdf"
# [plot]
splot 'map.dat' using 1:($2/1000):3 notitle, \
'line1.dat' using 1:($2/1000):1 notitle with lines ls 2, \
'line2.dat.tmp' using 1:2:1 notitle with lines ls 2
unset output
In the [prepare plot] section a temporary file "line2.dat.tmp" is created which contains datapoints interpolating line2.dat. You have to play with set samples to get the right number of points. In the example we have 100 equidistant points instead of 900 points with different distances.
The option smooth mcsplines preserves the monotonicity and convexity of the original data points, see help smooth mcsplines in a gnuplot shell.
In the [plot] section the original "lines2.dat" is replaced by the interpolated data.
This approach works if the original data is smooth enough so that replacing 900 points by 100 points does not skip important information. Maybe you want to plot both "lines2.dat" and "lines2.dat.tmp" in a single diagram to compare them.
User the every key-word, like this:
'line2.dat' every 20 using 1:($2/1000):1 notitle with lines ls 2

set multiple delimiter with gnuplot

I'm doing some simulations in OpenFOAM, using probes to get a time series of the velocity in a point. The output file has the following delimiter setup.
if it is possible, what would be the command to set the delimiter ?? when using gnuplot
set datafile separator '???'
Bonus info if I remove all ( and ) and use the default command the plot "plots"
plot "U" using 1:2
You can use
plot "U" using 1:2 "%lf (%lf %lf %lf)"
This format specifies your data format in the plot command. See help using for more details on this and the using examples for more complex examples.
If you don't want to type this each time, and you have a copy of gnuplot compiled with support for string macros, you also can do
dformat = "\"%lf (%lf %lf %lf)\""
plot "U" using 1:2 #dformat
which will expand the format specifier into the command. See help macros for more on this.
I would suggest to use sed :
plot "< sed 's|[()]||g' U" u 1:2

Iterating over powers of two in gnuplot

I want to plot the data stored in bunch of files using gnuplot. If the files were named using sequential numbers, (eg. "1.dat" "2.dat", ...) I'd use something like
plot for [i=1:10] i.'.dat' u 1:2 w lp t 'I='.i;
However, the files are now named using powers of 2, i.e. "2.dat", "4.dat", "8.dat", .... I tried
plot for [i=1:10] (2**i).'.dat' u 1:2 w lp t 'I='.(2**i);
but I get the error
STRING operator applied to non-STRING type
I suppose this happens because gnuplot considers (2**i) as a floating point number rather than integer.
I'm sure there is a way to do what I want to do but as I'm very new to using the control statements of gnuplot I cannot find out how. Could someone please help me?
You can use sprintf to convert a number to a string:
plot for [i=1:10] sprintf('%d',2**i).'.dat' u 1:2 w lp t 'I='.(2**i)
Interestingly, concatenating (2**i) with 'I=' in the title causes no problems.
Try using an empty string ("") to commence the string concatenation operation. That is "".(2**i).".dat" instead of (2**i).".dat".

How to manage `;` expected error in gnuplot

I am getting the following error while plotting graph in gnuplot 4.4
gnuplot> set style fill transparent pattern 2 noborder
^
"./clusterload_all.pg", line 16: ';' expected
Also some errors like this :
gdImageStringFT: Could not find/open font while printing string 45 with font Arial
gnuplot> plot "cpu.dat" using 1:2 with lines title "CPU% total" lw 5 lc 1,
'' using 1:3 with lines title "MEM% total" lw 5 lc 2,
'' using 1:4 with lines title "CPU% for clmServer" lw 5 lc 6,
'' using 1:5 with lines title "MEM% for clmServer" lw 5 lc 10,
'' using 1:8 with boxes fill transparent pattern 2 title "1: Uninstall Licenses" lw 2 lc 5,
'' using 1:9 with boxes fill transparent pattern 2 title "2: Install Licenses" lw 2 lc 6,
'' using 1:10 with boxes fill transparent pattern 2 title "3: Query Installed Licenses" lw 2 lc 7,
'' using 1:11 with boxes fill transparent pattern 2 title "4: Creating Feature Codes" lw 2 lc 11,
'' using 1:12 with boxes fill transparent pattern 2 title "5: Register Feature Codes" lw 2 lc 3,
'' using 1:13 with boxes fill transparent pattern 2 title "6: Query Feature Codes" lw 2 lc 1,
'' using 1:14 with boxes fill transparent pattern 2 title "7: Unregister Feature Codes" lw 2 lc 21
^
"./clusterload_all.pg", line 29: ';' expected
Could anyone please help me regarding this.
To manage the error you need to understand what happens in the line that generated it.
Gnuplot interpreter gives an help signing with the cursor "^" the first letter of the offending word and writing the line number where it is possible to find it (the line number if a script is loaded with load "myscript.gp" or gnuplot is invoked by command line asgnuplot myscript.gp).
The origin can be various since, until that offending word, the syntax seems to be acceptable.
Let me cite just a few examples:
A not correct order in the option sequence
plot "<seq 1 20" with lines using 0:($1) # before "using" after "with"
A line currently accepted by a version of gnuplot but not from a different one (that differs not only for version or subversion number, but even only for compilation option)
Note: with the use of the backslash(\) it's possible to split on different lines a long long command as if it was written in a single line. It's cosy and clean especially in a script.
When the error is generated the output of this long long line is recomposed so the column of the cursor(^) can appear wrong if compared with the position of the offending word in the script.
To reproduce your specific error we can check only the kernel of your command with some different version of gnuplot.
set style fill transparent pattern 2 noborder
With the results reported below:
in gnuplot 4.1.0 and it gives me the same error message
gnuplot> set style fill transparent pattern 2 noborder
^
';' expected
in gnuplot 4.6.3 I have no error at all.
in a gnuplot linux Version 4.4 patchlevel 0 (last modified March 2010) with no error.
If you avoid the feature transparent you will avoid the error in the older version too (4.1.0).
Please verify once again the version you have on your system...
...and feel you free to update it as you can :-) it's rather old.
More seriously if you cannot upload the version you use, you can take hints about the past syntax from the old demo (i.e. http://gnuplot.sourceforge.net/demo_4.4/ )... or from the older ones. Usually there is backward compatibility, meanwhile the forward compatibility is more difficult to find.
ps> You can write that long command line from the internal interpreter or in a more cosy way you can write it in an external file (a script). You can load the script in gnuplot or with the command load "./clusterload_all.pg" inside the gnuplot interpreter or you can call with the command line gnuplot -persist ./clusterload_all.pg from the shell prompt.

plot audio data in gnuplot

how could I convert an audio file such as a aiff into a svg using gnuplot? I used sox (sound exchange) to convert an .aiff into a .dat, which I can load now in gnuplot.
I did something similar to:
set terminal svg
set output "test.svg"
plot "test.dat"
I get a svg file, but only with dots / or a lot of x.
How could I connect the dots?
To draw lines between the points, use
plot "test.dat" with lines
Or to keep the point markers as well as the lines, use
plot "test.dat" with linespoints
So your example becomes
set terminal svg
set output "test.svg"
plot "test.dat" with lines
Further tips:
Don't consider every sample:
With large files you may also find it useful to plot only every nth sample with "every n". This will make the plot much faster to generate and will also yield a smaller (but less detailed) svg file.
e.g.
plot "test.dat" every 100 with lines
Ignore .dat file header:
If your sox-produced .dat file has some lines of introductory metadata, such as
; Sample Rate 44100
; Channels 2
you can add the following to have gnuplot consider those lines comments and ignore them.
set datafile commentschars ";"
This will save you having to pre-process your .dat file in order to remove those lines before gnuplot chokes on them.
Plot both left and right channels of stereo audio:
If you're working with a stereo file, you probably want to see both channels.
We can use "multiplot" to lay out the following two plots (of left then right channel) one above the other on a shared x-axis, as many sound-editing programs do.
set multiplot layout 2,1
plot "test.dat" using 1:2 with lines
plot "" using 1:3 with lines
The 1:2 and 1:3 instruct gnuplot which columns of the dat file to use as x and y sources. I'm assuming your stereo .dat file produced by sox looks as mine does, with columns for
- 1: time since beginning of first sample
- 2: normalized sample value of left channel
- 3: normalized sample value of right channel
example snippet:
10.840113 0.20101929 0.17840576
10.840136 0.26062012 0.14831543
10.840159 0.23779297 0.13146973
Putting it together:
Here's a script which puts all of the above together. If you don't have a stereo data file to try this with, you'll want to remove the plot of 1:3 and the multiplot setting.
#!/usr/bin/env gnuplot
set datafile commentschars ";"
set terminal svg
set output "test.svg"
set multiplot layout 2,1
plot "test.dat" using 1:2 every 100 with lines
plot "" using 1:3 every 100 with lines
unset multiplot
Prettification
Finally, I've tweaked the script for presentation (borrowing heavily from the excellent "gnuplot in action" book by Philipp K. Janert):
#!/usr/bin/env gnuplot
set datafile commentschars ";"
set terminal svg
set output "test.svg"
set multiplot layout 2,1
set ylabel "sample value"
set bmargin 0
set format x ""
set ytics -0.8,0.2
set key bottom
plot "test.dat" using 1:2 every 100 with lines lc rgbcolor "#a0a0b0" title "left channel"
set xlabel "time (s)"
set bmargin
set tmargin 0
set format x "%g"
set ytics -1.0,0.2,0.8
set key top
plot "" using 1:3 every 100 with lines lc rgbcolor "#a0a0b0" title "right channel"
unset multiplot
Here's an example output (albeit png):
How to make a .dat file
For anyone following along at home, you can use sox to generate a .dat file from an audio file with the following command:
sox input.wav output.dat
Big file warning: Converting even just 10 seconds of stereo audio at 40kHz will produce a 25Mb output file.
Note that you can also plot the binary data directly:
set terminal svg
set output "test.svg"
plot '< sox test.aiff -t s32 -' binary format='%int32' using 0:1 with lines
Just wanted to document this - well, I was looking for a long time for a Linux command line audio waveform viewer, which could be called from the command line, with a raw binary file as input, and where the format of the data could be specified on the command line.
Audacity can import raw data, but only from the GUI (there is no way to specify raw datafile format through its command line options); while wave viewers like gwave, gtkwave or Gaw - Gtk Analog Wave viewer can either read proper .wav, or SPICE based formats.
And thanks to the answer by #Thor, now I know I can use gnuplot for the purpose. Here is an example command line, which interprets the raw binary data as 16-bit stereo:
gnuplot -p -e "set terminal x11 ; set multiplot layout 2,1 ; plot 0 ls 2, 'data.raw' binary format='%int16%int16' using 0:1 with lines ls 1; plot 0 ls 2, 'data.raw' binary format='%int16%int16' using 0:2 with lines ls 1 ; unset multiplot"
... or broken in several lines:
gnuplot -p -e "set terminal x11 ; set multiplot layout 2,1 ; \
plot 0 ls 2, 'data.raw' binary format='%int16%int16' using 0:1 with lines ls 1; \
plot 0 ls 2, 'data.raw' binary format='%int16%int16' using 0:2 with lines ls 1; \
unset multiplot"
Note that:
you should only use pipe "< ..." if you want to output from a shell command - if you have a file (like above), don't use the pipe (else getting permission denied)
Note the format '%int16%int16' will cause the byte stream to be "grouped" as 2 bytes representing column (channel) 1, the next 2 bytes as column (channel) 2, the next 2 bytes again as column 1, and so on... see gnuplot docs_4.2: Binary General - Format (also related: Gnuplot: How to plot multiple time series from a binary format)
Finally with two independent plots, one using 0:1 and the other using 0:2, we can get a typical waveform rendering (as in accepted answer) - with one channel above the other
Since the --persist option is used above, gnuplot will exit, while the (x11 or wxt) window will remain - and so, the typical gnuplot interaction with the window will not work
Anyways, glad I found this, will save me quite a bit of time, I think :)

Resources