Empty space in GNUPLOT graph - gnuplot

I am encountering strange behavior on my gnuplot script. The objective of this script is to read in a file and plot a specific set of lines (3 consecutive lines based on a given start point in the file) using the very first line of the file as the series headers.
While the plot works conceptually, I am encountering a large insert into the image on the left side, as if an empty line is read and plotted as 0 (with no header)
Input File:
Level,Filter,Type,Set1,Set2,Set3
Level1,Filter1,Type1,112,186,90
Level1,Filter1,Type2,233,335,159
Level1,Filter1,Type3,224,332,157
Code:
set terminal postscript color
set output '| epstopdf --filter --outfile=output.pdf'
set boxwidth 0.5
set style fill solid
set style data histograms
set datafile separator ","
LINE1 = 1 + 3 * COUNT
LINE2 = LINE1 + 1
LINE3 = LINE1 + 2
plot '../test.csv' \
u ( ( int($0) == LINE1 || int($0) == LINE2 || int($0) == LINE3)? $4 : 1/0) ti col,'' \
u ( ( int($0) == LINE1 || int($0) == LINE2 || int($0) == LINE3)? $5 : 1/0) ti col,'' \
u ( ( int($0) == LINE1 || int($0) == LINE2 || int($0) == LINE3)? $6 : 1/0) ti col
Command Line Call
>gnuplot -e "COUNT=0" test.plot
How can I get rid of the empty fields that lead to the right shift?
My gnuplot version is 4.6.

Since you're already using pipes and unix-ish tools, I would use sed here as well:
set term post color
set output 'foo.ps'
set style data histograms
set style histogram clustered
set datafile separator ","
set boxwidth 0.5
set style fill solid
SED_CMD = sprintf('< sed -n -e 1p -e %d,%dp test.csv',COUNT*3+2,COUNT*3+4)
plot for [COL=4:6] SED_CMD u COL ti col
I've simplified a lot of things while I was trying to figure out what your script was doing -- I used plot iteration (introduced in gnuplot 4.3). Originally I had thought that plot '...' every ... would work, but histograms seem to choke on every and I don't (yet!) understand why.
Here's an explanation of the sed command:
-e 1p #print first line in file
-e %d,%dp #print n'th line through m'th line (inclusive) where n=COUNT*3+2 and m=COUNT*3+4
If you're worried about shell injection, this seems to be safe as well:
gnuplot -e 'COUNT=";echo hi"' -persist test.gp
"test.gp", line 10: Non-numeric string found where a numeric expression was expected
Gnuplot will only write numbers to your command string.

Related

How to run a shell command in Gnuplot and place the output in new file

I have the following Gnuplot:
set encoding iso_8859_1
set key right bottom #font "Helvetica,17"
set ylabel "Lookup error probability" font "Helvetica,17"
set xlabel "Hight of the reader (m)" font "Helvetica,17"
set xtics font "Helvetica,15"
set ytics font "Helvetica,15"
set size 0.75, 1.05
set terminal postscript eps enhanced color #"Helvetica" 16 #size 3.5in,3in
set grid
set key spacing 1.5
set output "ProbError6x6.eps"
list(start,end,increment)=system(sprintf("seq %g %g %g", start, increment, end))
system("(awk '(NR>8 ){print; }' Hight_6x6.csv | sed -e 's/[",]/ /g' | sort -nk36) > pe_H_6x6.txt")
set print "pe_H_6x6.dat"
do for [i in list(2,3.5,0.25) ] {
stats "pe_H_6x6.txt" u ($36==i?($37/$38):1/0) name "A" nooutput
print i*1, A_mean, (A_mean - 1.833*A_ssd/sqrt(A_records)),\
(A_mean + 1.833*A_ssd/sqrt(A_records))
}
plot [][] "pe_H_6x6.dat" using 1:2:3:4 with yerrorlines ls 2 title "6x6 blocks"
The line with the system and with the awk code does not work in my Gnuplot script. However, it works in the unix shell. This code removes commas and , in Hight_6x6.csv, skips the first 8 lines and sort the result by the values of the 36th column.
I cannot make it work in the Gnuplot script.
The CSV file is in this link.
Your issue is probably that you include a double quote inside the command:
system("(awk '(NR>8 ){print; }' Hight_6x6.csv | sed -e 's/[",]/ /g' | sort -nk36) > pe_H_6x6.txt"
^
One work-around is to use backquotes, e.g.:
`(awk '(NR>8 ){print; }' Hight_6x6.csv | sed -e 's/[",]/ /g' | sort -nk36 > pe_H_6x6.txt`
Or as I would have written it:
`tail -n+8 Hight_6x6.csv | tr '",' ' ' | sort -nk36 > pe_H_6x6.txt`

How to fix gnuplot -e "plot 'file' u 1:($2)-1 w l" syntax?

I need to plot files using gnuplot without going to gnuplot terminal. So, I am taking a quick look at the plots using the following line.
i=2; while [ $i -le 14 ] ; do gnuplot -e "plot 'pop05' u 1:$i w l, 'pop01' u 1:$i w l; pause 2"; ((i++)); done
However, gnuplot -e does not seem to work for the cases of
gnuplot -e "plot 'pop01' u 1:($2)-1 w l"
ie, when I try to use an altered value in a particular column like I subtract 1 from the second column. However, plot 'file' u 1:($2)-1 w l works perfectly in gnuplot terminal. What should be the syntax for me to plot an altered column in the loop as well as without the loop?
I use gnuplot 4.4 patchlevel 3.
$2 has a special meaning in shell in double quotes (it returns the second positional argument). Just backslash the dollar sign:
gnuplot -e "plot 'pop01' u 1:(\$2)-1 w l"

How to plot single/multiple lines depending on values in a column with GNUPlot

I have a little problem using gnuplot. Here is my datafile:
From Time Packets Jitter
127.0.0.1:53091 1 0 274
127.0.0.1:53091 2 0 417
127.0.0.1:53091 3 36 53
127.0.0.1:53091 4 215 55
127.0.0.1:53090 4 215 55
127.0.0.1:53091 5 215 33
127.0.0.1:53090 6 256 78
(I put that "time" for the test, but it will be replaced by a datetime after it works)
I want to draw two different graphics, with Time column in x axis on both, and Packets column (on a first graphic) & Jitter column (on a second graphic) in y axis. But, as you may have seen, I don't know how many different values from the From column I will have (minimum 1, but I don't know the maximum, the data file will be refresh and some values will be added each x seconds).
So my problem is that I want to make another 'line' each different From values on both graphics.
In fact, having the From value in title of lines (example : "127.0.0.1:53091").
I want to add that if it's possible to change column order.
I tried:
plot 'data.log' using 3:xtic(2) title 'Packets' with lines, \
'data.log' using 4:xtic(2) title 'Jitter' with lines
But it's on the same graphic (I don't use multiplot yet, I tried to make the multiple lines works before).
Is it possible ? If it is, How can I plot this two graphics in gnuplot ?
If not, we can remove the Jitter graphic, and plot only the Packets column on a single graphic but with the different From values.
Here is a solution, which doesn't need external files. First I extract all the different sources in the first column and store them in a gnuplot variable:
filename = 'data.log'
from=system('tail -n +2 '.filename. '| cut -f 1 -d " " | sort | uniq')
For the filtering during plotting I use awk and define a gnuplot function
select_source(w) = sprintf('< awk ''{if ($1 == "%s") print }'' %s', w, filename)
Now you can iterate over all source stored in from. The complete gnuplot script is as follows:
filename = 'data.log'
from=system('tail -n +2 '.filename. '| cut -f 1 -d " " | sort | uniq')
select_source(w) = sprintf('< awk ''{if ($1 == "%s") print }'' %s', w, filename)
set style data linespoints
set multiplot layout 1,2
set title 'Packets'
plot for [f in from] select_source(f) using 2:3 title f
set title 'Jitter'
plot for [f in from] select_source(f) using 2:4 title f
unset multiplot
Here is a solution relying on several standard tools that should be available on any standard Linux box, and mostly based on bash. Lets starts with the datafile you provide, without the first line.
Step 1: split data into one file per field 1 : awk -f split.awk < data.log, with the following in split.awk:
#!/usr/bin/awk -f
# erase previous files
BEGIN { system("rm file_*.dat"); }
# print each line in a specific file
{ print $0 >>( "file_" $1 ".dat") }
Step 2: duplicate first line of each produced datafile (because using one of the fields as title in gnuplot makes this line ignored when plotting):
for f in `ls file_*.dat`; do
head -n 1 $f > tmp.dat
cat $f >> tmp.dat
mv tmp.dat $f
done;
Step 3: generate a gnuplot script that holds a plot command that plots the different files (see full script below).
echo "plot \\" >> plot.plt
for f in `ls file_*.dat`; do
echo " '$f' using 2:3 title columnheader(1) with linespoints lw 2, \\" >> plot.plt
done;
echo " 0 notitle" >> plot.plt
FIY, the last "0" plot is there only because to plot several files onto a single plot, gnuplot needs a trailing backslash at the end of the line. And if there is one, and nothing to plot at the following line, an error is generated. So I could only find this dumb trick to make it work...
Step 4: call the generated gnuplot script.
With the data you provided, the script below ends up as:
Probably could have been shorter, but I like to keep things readable.
Full script:
#!/bin/bash
# 1 - split data into one file per field 1
awk -f split.awk < data.log
# 2 - duplicate first line (useful for gnuplot)
for f in `ls file_*.dat`; do
head -n 1 $f > tmp.dat
cat $f >> tmp.dat
mv tmp.dat $f
done;
# 3 - generate gnuplot script
echo "set terminal pngcairo size 800,500" > plot.plt
echo "set output 'b.png'" >> plot.plt
echo "set multiplot layout 1,2" >> plot.plt
echo "set title 'Packets'" >> plot.plt
echo "plot \\" >> plot.plt
for f in `ls file_*.dat`; do
echo " '$f' using 2:3 title columnheader(1) with linespoints lw 2, \\" >> plot.plt
done;
echo " 0 notitle" >> plot.plt
echo "set title 'Jitter'" >> plot.plt
echo "plot \\" >> plot.plt
for f in `ls file_*.dat`; do
echo " '$f' using 2:4 title columnheader(1) with linespoints lw 2, \\" >> plot.plt
done;
echo " 0 notitle" >> plot.plt
echo "unset multiplot" >> plot.plt
# 4 - call gnuplot script
gnuplot plot.plt
I am not sure I understand your problem, but at least I can answer How can I plot this two graphics in gnuplot ?:
set multiplot layout 1,2
plot 'data.log' using 3:xtic(2) title 'Packets' with lines
plot 'data.log' using 4:xtic(2) title 'Jitter' with lines
unset multiplot
Will produce this:

Howto improve a coloured line plot by key in third column?

I'm trying to plot temperatures of my laptop, here are my working files at github
I have epoch, temperature & kernel identifier data like so:
1357786501 72 3.6.11-1-ARCH
1357786801 72 3.6.11-1-ARCH
1357787101 60 3.0.57-1-lts
1357787401 54 3.0.57-1-lts
1357800301 52 3.0.57-1-lts
1357800601 48 3.6.11-1-ARCH
1357800902 45 3.6.11-1-ARCH
The closest I've got to what I want is (using this):
set term svg size 1024,708
set xdata time
set key outside
set timefmt "%s"
set ytics 5
set format x "%d/%m"
plot "< awk '{if($3 == \"3.0.57-1-lts\") print}' temp.csv" u 1:2 t column(3) w p pt 2, \
"< awk '{if($3 == \"3.6.10-1-ARCH\") print}' temp.csv" u 1:2 t column(3) w p pt 2, \
"< awk '{if($3 == \"3.6.11-1-ARCH\") print}' temp.csv" u 1:2 t column(3) w p pt 2, \
"< awk '{if($3 == \"3.8.1-1-mainline-dirty\") print}' temp.csv" u 1:2 t column(3) w p pt 2
gihub kaihendry
Is there a way to avoid using awk? When I don't use this awk, it fails to plot differing kernel identifiers.
Can I make it a continuous line with different colours instead somehow?
Any ideas how to make SVG output without width/height? Any tricks to make it look better?
If your version of Gnuplot is recent enough, you can use a for-loop and iterator to loop over the different strings you want to match, see for example manual page 88-89 or this blog entry. To ignore non-matching lines you can use the ternary operator (cond ? iftrue : iffalse) to set these values to "Not-A-Number" (1/0 or NaN):
set xdata time
set key outside
set timefmt '%s'
set ytics 5
set format x '%d/%m'
set style data linespoints
archs = "`cut -d' ' -f3 temp.csv | sort -u | tr '\n' ' '`"
plot for [arch in archs] 'temp.csv' using 1:((strcol(3) eq arch) ? $2:1/0) title arch

Can the string for "set title" be obtained from a file?

I'm using Gnuplot with scripts and data files.
In my script there is a command;
set title "blah title here"
Is it possible to have that string taken from a data file? e.g. such that I can use a single script with many data files, because the data file will contain the title for the plot.
I'm not sure if this would be easy to do in pure gnuplot, but here is a solution using a wrapper bash script. You would use the script by calling plotscript.sh data.dat at the command line.
#!/bin/bash
my_title=$(head -n 1 $1 | sed 's/^# \(.*\)/\1/')
echo "set terminal postscript enhanced color
set output 'plot.eps'
set title '$my_title'
plot '$1' u 1:2" | gnuplot
To make the script usable put the code in a textfile and run chmod +x on it. If you tell me what format the title is in I can try to tailor the script to match that. This script assumes that the title is the first line of the data file in this type of format:
# mytitle
1 4
2 5
3 2
you can use backtic substitution...e.g.
set title "`head -1 datafile.dat`"
However, that doesn't quite get what you want since the backtic substitution is done prior to string operations (You can't specify the datafile name as a string). However, Macros are expanded prior to backtic substitutions.
My test datafile looked like:
"this is the title"
10 20
20 30
30 40
And my test script looked like:
DATAFILE="datafile.dat"
set macro
TI='`head -1 '.DATAFILE.'`' #macro: Single quotes are important here to prevent expansion of backtics.
set title #TI
plot DATAFILE u 1:2 title columnhead(1)
Note that if your title isn't enclosed in double quotes in the datafile, you'll need to add
them so that the resulting set title command is valid. (You can either add them to the macro, or to the datafile)
Even if this is rather late and the OP's account doesn't exist anymore, I need to add an answer, because it is simply not true that you cannot extract a title from a datafile with gnuplot only.
You can run stats (check help stats) without actually being interested in statistics but just for extracting the title.
You limit the data to the line of interest via every (check help every).
This works for gnuplot 4.6.0 (March 2012).
For gnuplot>=4.6.0 you can set a character as datafile separator (check help datafile separator). Take a character which doesn't appear in the line with the title. For gnuplot>=4.6.0 you can set datafile separator "\t" or for gnuplot>=5.0.0 you can also set datafile separator "\n".
Data: SO10968529.dat
# This is a commented line
"Line2: This is a uncommented line in double quotes"
"Line3: my Title"
Line5: This is a title without quotation marks
"Line6: Another title"
# x y
1 5.0
2 3.0
3 4.0
4 2.0
# end of data
Script:
### read title from datafile
reset
FILE = "SO10968529.dat"
set multiplot layout 1,2
set datafile separator "\t"
stats FILE u (myTitle=strcol(1),0) every ::0:0:0:0 nooutput
set datafile separator whitespace
set title myTitle
plot FILE u 1:2 w lp pt 7 lc rgb "red"
set datafile separator "\t"
stats FILE u (myTitle=strcol(1),0) every ::0:1:0:1 nooutput
set datafile separator whitespace
set title myTitle
plot FILE u 1:2 w lp pt 7 lc rgb "blue"
unset multiplot
### end of script
Result:

Resources