I'm attempting to use gnuplot v5.4 to generate multiple graphs from one data set, though using select data from the set per graph.
I generate stats for a small program I'm developing, and write them to a CSV file:
(This CSV format is just what I've made the best progress with - I'm open to changing)
TotalPlayerCount,22
BluePlayerCount,10
RedPlayerCount,12
BluePlayerScoreTotal,50
RedPlayerScoreTotal,60
The following gives me the below graph:
cat <<"EOF" | gnuplot -p
$db <<DB
TotalPlayerCount,22
BluePlayerCount,10
RedPlayerCount,12
BluePlayerScoreTotal,50
RedPlayerScoreTotal,60
DB
set terminal windows size 2000,1000 enhanced font 'Arial,8'
set datafile separator ','
set yrange [0:100]
set boxwidth 0.1 relative
set style fill solid 1.0
plot $db using 2:xticlabel(1) notitle with boxes linestyle 1
EOF
I'm aiming for this:
which I have achieved using this:
cat <<"EOF" | gnuplot -p
$db <<DB
TotalPlayerCount,22
BluePlayerCount,10
RedPlayerCount,12
BluePlayerScoreTotal,50
RedPlayerScoreTotal,60
DB
set terminal windows size 2000,1000 enhanced font 'Arial,8'
set datafile separator ','
set yrange [0:100]
set boxwidth 0.1 relative
set style fill solid 1.0
set multiplot layout 1,2
plot $db using 2:xticlabel(1) every ::1::2 notitle with boxes linestyle 1
plot $db using 2:xticlabel(1) every ::3::4 notitle with boxes linestyle 1
unset multiplot
EOF
Is there a better or more idiomatic way to select from the data file what 'rows' to plot? These indices (in the every clause) work OK, but seem fragile.
I have previously used the trick where a ternary returning undefined in the using will cause gnuplot to ignore that row (e.g. maybe I could use it to select based on string compare) but that doesn't seem much more elegant either and I don't really enjoy how complex it makes the plot command.
One possibility that gives you a more "readable" syntax would be to use columnheaders, for which you would need to transpose your dataset. You don't necessarily need to use comma; spaces or tabs will do the trick as well:
$db <<DB
TotalPlayerCount BluePlayerCount RedPlayerCount BluePlayerScoreTotal RedPlayerScoreTotal
22 10 12 50 60
DB
Set up the layout:
set xrange [0:3]
set yrange [0:100]
set boxwidth 0.5
set style fill solid 1.0
Now you can select the column that you want to plot with column("string"), which will give you the correct y value. As for the x value, I simply took the constant number 1 for the first plot and 2 for the second one. In order to produce xticlabels one has to repeat the string:
plot $db u (1):(column("BluePlayerCount")):xticlabels("BluePlayerCount") w boxes not, \
$db u (2):(column("RedPlayerCount")):xticlabels("RedPlayerCount") w boxes not
Alternatively, you could delete the xticlabels part from the plot command and instead use: set xtics ("BluePlayerCount" 1, "RedPlayerCount" 2)
You could also automate the plot even further:
whattoplot_1 = "BluePlayerCount"
whattoplot_2 = "RedPlayerCount"
x_pos_1 = 1
x_pos_2 = 2
set xtics (whattoplot_1 x_pos_1, whattoplot_2 x_pos_2)
plot $db u (x_pos_1):(column(whattoplot_1)) w boxes not, \
$db u (x_pos_2):(column(whattoplot_2)) w boxes not
Depending on what you want to achieve in the end, you might consider using arrays and iterate over the elements:
array whattoplot[2] = ["BluePlayerCount", "RedPlayerCount"]
plot for [i=1:|whattoplot|] $db u (i):(column(whattoplot[i])) w boxes not
I hope this gives you some inspiration for how to proceed!
If you are flexible with the input data, I would organize it in the following way:
Instead of dumping everything into one file and separating it again, I would create two files, e.g. 'Counts.dat' and 'Scores.dat'.
In the (copy&paste) example below it is included in the code with datablocks $Counts and $Scores, however, if you have your data in files, simply skip the datablocks and in the plot command change it to 'Counts.dat' and 'Scores.dat', respectively.
You don't necessarily need the total count in your data, gnuplot can do this for you.
Furthermore, in the example below I introduced a third column for the color of the boxes. Check the following example as starting point for further optimization.
Code:
### multiplot with boxes and total sum
reset session
$Counts <<EOD
Red 12 0xff0000
Green 5 0x00cc00
Blue 10 0x0000ff
Yellow 7 0xffff00
EOD
$Scores <<EOD
Red 60 0xff0000
Green 30 0x00cc00
Blue 50 0x0000ff
Yellow 80 0xffff00
EOD
set yrange[0:100]
set boxwidth 0.5 relative
set style fill solid 1.0
set key left noautotitle
set grid x,y
set multiplot layout 1,2
set title "Counts"
plot sum=0 $Counts u 0:(sum=sum+column(2),column(2)):3:xtic(1) w boxes lc rgb var, \
keyentry w p ps 0 ti sprintf("Total count: %d",sum)
set title "Scores"
plot $Scores u 0:2:3:xtic(1) w boxes lc rgb var
unset multiplot
### end of code
Result:
Addition: (all data in one datablock or file)
Code:
### multiplot with boxes and total sum in a single file
reset session
$AllInOne <<EOD
# counts
Red 12 0xff0000
Green 5 0x00cc00
Blue 10 0x0000ff
Yellow 7 0xffff00
# scores
Red 60 0xff0000
Green 30 0x00cc00
Blue 50 0x0000ff
Yellow 80 0xffff00
EOD
set yrange[0:100]
set boxwidth 0.5 relative
set style fill solid 1.0
set key left noautotitle
set grid x,y
set multiplot layout 1,2
set title "Counts"
plot sum=0 $AllInOne u 0:(sum=sum+column(2),column(2)):3:xtic(1) index 0 w boxes lc rgb var, \
keyentry w p ps 0 ti sprintf("Total count: %d",sum)
set title "Scores"
plot $AllInOne u 0:2:3:xtic(1) index 1 w boxes lc rgb var
unset multiplot
### end of code
Related
I have a script that generates a gnuplot file, I have edited so I have 2 sets of data in the same plot. One is multiplied by -1 to change color. However, only one set appears in the plot, the last one stated. The script is the following.
set arrow from graph 0,first 0.61237, graph 0 to graph1,first0.61237,0 nohead front lt -1
set arrow from graph 0,first 1.67303, graph 0 to graph 1,first 1.67303,0 nohead front lt -1
set arrow from graph 0,first 2.53906, graph 0 to graph 1,first 2.53906,0 nohead front lt -1
set arrow from graph 0,first 3.24616, graph 0 to graph 1,first 3.24616,0 nohead front lt -1
set arrow from graph 0,first 3.74616, graph 0 to graph 1,first 3.74616,0 nohead front lt -1
set arrow from graph 0,first 4.74616, graph 0 to graph 1,first 4.74616,0 nohead front lt -1
set pm3d at b
unset surf
set view 180,90
set palette defined (-1 "red",0 "white", 1 "blue");
set grid xtics mxtics ytics
unset border
set xrange [-10:40]
set xtics -10,((40+10)/5),40
set mxtics 3
set yzeroax lt 2
set ytics ("L" 0.0,"K" 0.61237,"G" 1.67303,"L" 2.53906,"W" 3.24616,"X" 3.74616,"G" 4.74616)
set cbrange resto
set cbrange[-1:1]
set colorbox
set terminal png enhanced nocrop size 1920,1080
set out "SPF_NO_SO.png"
splot "specfun.pm3d" u ($1*13.60569806):2:(1*$4/476.70750366666666666666),\
"specfun.pm3d" u ($1*13.60569806):2:(1*$3/573.04673900000000000000)
unset out
Sample image:
The script produces the desired plot only for the negative set. If I flip the order I get the blue one.
Here is a sample data:
data_sample
FYI-these arrays are quite big
as #user8153 pointed out, I also don't see a reason why using splot.
And as #Christoph pointed out it's difficult without knowing how the data looks like,
for example, what's in columns $3 and $4?
By the way, with your plot command ...u ($1*13.60569806):2 aren't you plotting the same function twice on top of each other, i.e. that's why you see either the red or the blue?
Nevertheless, I tried to anticipate what you probably want to do. I scaled the second function and assumed something linear for columns $3 and $4. Please clarify.
With the code:
### start code
reset session
# generate some dummy data
undefine $Data
set print $Data append
do for [n=1:5] {
a = rand(0)*10
b = rand(0)*0.1+0.1
c = rand(0)*20
do for [i=1:100] {
print sprintf("%g\t%g\t%g\t%g",i,(a*sin(b*i-c)),cos(b*i),cos(b*3*i))
}
print "" # insert empty line for data curve separation
}
set print
# print $Data
# end generating dummy data
set palette defined (-1 "red",0 "white", 1 "blue")
set cbrange [-1:1]
plot $Data u 1:2:($3-$4) w l lc palette z
### end of code
You'll get the following:
I am plotting a 3D 'fence plot' with multiple colors for each fence. My sample data can be found here:
https://gist.github.com/anonymous/a926221ea96e92e86332
I plot this data using this:
colors = "red red red red red"
splot for [i=1:words(colors)] 'input.sep.txt' index i u 2:1:3 w lines lc rgb word(colors,i)
The lines are drawn without issue, and I believe they are drawn correctly. My question is this: how do I fill below the line so that it looks like a solid wall (i.e. all the way down to the 0 z value)? I tried using w pm3d, however this did not actually plot anything visible on the axis.
The best option you have is to use pm3d. For this to work you must change your data file a bit: You must duplicate very line, change the z-value of the duplicate to 0 and add a new line, i.e. your first two data lines
1 1 2
2 1 4
must become
1 1 2
1 1 0
2 1 4
2 1 0
and so on. You still need the two consecutive empty lines later to separate different "walls".
If you have control over your data output, you could change your output routine, or you can use a command line tool like sed
sed 's/^\([0-9]* [0-9]* \)\(.*\)$/&\n\1 0\n/' gistfile1.txt
or awk:
awk '1; {print $1,$2,0,"\n"}' gistfile1.txt
to do the conversion. Of course this can be done on-the-fly from within gnuplot. A complete, working script is then:
filename = 'gistfile1.txt'
sed = '< sed ''s/^\([0-9]* [0-9]* \)\(.*\)$/&\n\1 0\n/'' '
set autoscale cbfix
set palette defined (0 'red', 1 'blue')
set pm3d depthorder
unset colorbox
unset key
set ticslevel 0
splot sed.filename using 1:2:3:(column(-2)) with pm3d
and the result using gnuplot 4.6.5 with your example data is:
Some additional notes:
The fourth column is used to select a different value than the z-value for the coloring.
column(-2) uses the block number (adjacent blocks are delimited by two empty lines) as color index.
Points belonging to different data blocks aren't connected.
With set autoscale cbfix you can better control the colors used for the planes.
If you know, that you have e.g. three planes which should have specific colors you could also use set palette defined (0 'red', 1 'green', 2 'blue').
This is a workaround rather than a proper solution, but it might work for you. Play with the filledcurves option which is not really designed for 3D plotting. What you have, as it is, would look like:
colors = "red red red red red"
splot for [i=1:words(colors)] 'input.sep.txt' index i u 2:1:3 w filledcurve lc rgb \
word(colors,i), for [i=1:words(colors)] 'input.sep.txt' index i u 2:1:3 w l lc "black" lw 2
Using a tricksy trick with the set dgrid3d command, you can increase the number of vertical lines that get drawn (set dgrid3d 100,2 in this case):
Until you're happy with the result (set dgrid3d 200,2):
i am 3d plotting a matrix with some values, and i need to add contour lines to the plot, is there a simple gnuplot command to do this?
I tried the command: "set contour base" but only 1 line came up, i think it should be many lines. See matlab picture
When i plot it in gnuplot i only get 1 contour line in the top left corner.But everything else is correct.
My goal is to get it to look like in matlab like this Matlabplot
I also found this example: see link in comments (dont have enough rep), but i dont understand where i should put in the data values from test.txt
test.txt
test.txt
gnuplot commands
set view map
set yrange [0:30]
set xrange [0:30]
set dgrid3d 100,100,4
set contour base
splot 'test.txt' u 1:2:3 w pm3d
What you are missing is to tell gnuplot where to put the contours. This is done via the set cntrparam levels incr -0.3,0.1,0.5 command which means: start at -0.3 and trace a contour every o.1 up to 0.5.
AFAIK if you want to make contours all black, you have to save the contour lines in a temporary file (here contour.txt).
So your script would be
reset
set contour
unset surface
set cntrparam levels incr -0.3,0.1,0.5
set view map
set xrange [0:30]
set yrange [0:30]
set dgrid3d 100,100,4
set table "contour.txt"
splot 'test.txt'
unset table
unset contour
set surface
set table "dgrid.txt"
splot 'test.txt'
unset table
reset
set pm3d map
unset key
set palette defined (0 '#352a87', 1 '#0363e1',2 '#1485d4', 3 '#06a7c6', 4 '#38b99e', 5 '#92bf73', 6 '#d9ba56', 7 '#fcce2e', 8 '#f9fb0e')
set autoscale fix
set grid
splot 'dgrid.txt' w pm3d, 'contour.txt' w l lc rgb "black"
which gives you this:
Note:
you can get rid of interpolation file (dgrid.txt) if you format a bit your datafile by leaving a blank line after each row (i.e. every 30 datapoints) because they are already mesh-ordered.
This could be done also with a awk script. But I'm too lazy to look into it...
The rest will remain the same and will work as expected.
here is how it should look like :
In which case the script would simply become:
set pm3d map impl
set contour
set style increment user
do for [i=1:18] { set style line i lc rgb "black"}
set cntrparam levels incr -0.3,0.1,0.5
set palette defined (0 '#352a87', 1 '#0363e1',2 '#1485d4', 3 '#06a7c6', 4 '#38b99e', 5 '#92bf73', 6 '#d9ba56', 7 '#fcce2e', 8 '#f9fb0e')
set autoscale fix
splot 'test.txt' w pm3d notitle
with no need of ntermediate file and with better contour since data in not interpolate by gridded:
I want to create a streamline like arrow lines in Gnuplot,I already have the data points that I needed, so I think my problem is not the same as this post says and different from this post because I have already obtain the data needed for stramlines.
What I have done is like this:
So the red lines are vectors show flow field and green line is streamlines to guide the readers the direction of the flux. And all the large blue arrows are my aim to be plotted in GNUPLOT. I have kown how to plot middle arrows as this post has shown but what code I need to do if I want to plot more arrows along the lines?
To be more detailed, How can I plot like this:
I supply my data file here :
velocity.txt is for vector flow field data as "index,X,Y,vx,vy,particle-numbers"
line.txt is for streamline data as "X,Y"
and My gnu file is bleow:
set terminal postscript eps size 108,16 enhanced font "Arial-Bold,100"
set output 'vector.eps'
unset key
set tics
set colorbox
set border 0
set xtics 2
#set xlabel 'x'
#set ylabel 'y'
set xrange [0:108]
set yrange [0:16]
#set cbrange [0:40]
set nolabel
set style line 4 lt 2 lc rgb "green" lw 2
plot 'velcoity.txt' u 2:3:(250*$4):(250*$5) with vectors lc 1,'line.txt' u 1:2 ls 4
Thank you!
To plot arrows along a line you can again use the vectors plotting style like you do already for the stream field.
But to get a proper plot you must consider several points:
Usually gnuplot limits the size of the arrow heads to a fraction of the arrow length. So, if you want to plot a continuous line with arrows heads, the arrows themselves should have a very short length. To avoid downscaling of the arrow heads, use the size ... fixed option, which is available only since version 5.0
You have only the trajectory, x and y values, of the line. To extract the arrow direction, the simplest approach would be to use the difference between two neighbouring points (or at a distance of two or three points).
You can extract these differences in the using statement. As pseudo code, one could do the following:
if rownumber modulo 10 == 0:
save x and y values
else if rownumber modulo 10 == 1:
draw arrow from previous point to current point, only with a head
else
ignore the point.
Putting this pseudo-code in the using statement gives the following:
ev = 10
avg = 1
sc = 0.1
plot 'line.txt' u (prev_x = (int($0)%ev == 0 ? $1 : prev_x), prev_y = (int($0)%ev == 0 ? $2 : prev_y), int($0)%ev == avg ? $1 : 1/0):2:(sc*(prev_x-$1)):(sc*(prev_y-$2)) w vectors backhead size 2,20,90 fixed ls 4
To make things more flexible, I introduced some variables: ev tells you the difference count between two arrows heads, avg the distance between two points used to calculate the arrow direction, and sc the length of the arrow shaft.
As further improvement you can use the length of the stream field arrows to colour the stream field vectors. This gives the following script
reset
unset key
set tics
set colorbox
set border 0
set xtics 2
set autoscale xfix
set autoscale yfix
set autoscale cbfix
set style line 4 lt 2 lc rgb "green" lw 2
ev=30
avg=3
sc=0.1
field_scale=500
plot 'velcoity.txt' u 2:3:(field_scale*$4):(field_scale*$5):(sqrt($4**2+$5**2)) with vectors size 1,15,45 noborder lc palette,\
'line.txt' u 1:2 ls 4 w l,\
'' u (prev_x = (int($0)%ev == 0 ? $1 : prev_x), prev_y = (int($0)%ev == 0 ? $2 : prev_y), int($0)%ev == avg ? $1 : 1/0):2:(sc*(prev_x-$1)):(sc*(prev_y-$2)) w vectors backhead size 2,20,90 fixed ls 4
With the result (qt terminal):
I have used gnuplot succesfully to plot boxplots. But now I would like to stick to gnuplot for all my plotting needs and looking to do something that eg. Prism can do:
http://www.graphpad.com/support/faqid/132/
I only have two columns of data (before and after) and want all pairs to be joined up with a line. If anyone has any idea, it would be great.
That is not possible out of the box, so it requires some fiddling.
The xtics are set manually, 0 is the x-value of 'Before', 1 for 'After'. These numerical values must be used explicitely later in the plots.
The lines are plotted as arrows without heads. Using lc variable (i.e. linecolor variable), we can use the last column of the using statement to select the color from the respective line type.
The 'Before' points are plotted first. Unfortunately, there is no option pointtype variable, so I use the plot for iteration to assign each point a different pointtype (pt).
I use the stats command to determine the number of points to plot. To get the total count, I must sum up the records, which are the inside points, and the outofrange points, because the classification is done based on the first column's value, which conflict with the 'manual' xtics settings for the 'Before' and 'After' labels.
These are the main points. Of course, there are many other possibilities (using line styles etc.), but should be a good starting point.
The script is:
reset
file='beforeafter.txt'
set xtics ('Before' 0, 'After' 1)
set xrange [-0.2:1.2]
set offset 0,0,0.2,0.2
stats file nooutput
cnt = int(STATS_records+STATS_outofrange)
plot for [i=0:cnt-1] file using (0):1 every ::i::i with points lc i+1 pt (6+i) ps 2 t '',\
for [i=0:cnt-1] file using (1):2 every ::i::i with points lc i+1 pt (6+i) ps 2 t '',\
file using (0):1:(1):($2-$1):($0+1) with vectors nohead lc variable t ''
With the test data beforeafter.txt:
1 5.5
2 0.3
3 3
And you get the result:
Using line styles
Another variant uses line styles to set the color, line type, and point type. For the iterations you must use explicitely ls (i+1), whereas for the vectors the as variable (arrowstyle variable) is used. With the lc variable it is not possible to set different dash patterns for the arrows.
So here is a, in my opinion, much more readable and flexible variant:
reset
set termoption dashed
file='beforeafter.txt'
set xtics ('Before' 0, 'After' 1)
set xrange [-0.2:1.2]
set offset 0,0,0.2,0.2
stats file nooutput
cnt = int(STATS_records+STATS_outofrange)
set style line 1 lt 1 pt 5 ps 2 lw 2 lc rgb '#AE1100'
set style line 2 lt 2 pt 7 ps 2 lw 2 lc rgb '#6EB043'
set style line 3 lt 3 pt 9 ps 2 lw 2 lc rgb '#7777ff'
set for [i=1:3] style arrow i ls i nohead
unset key
plot file using (0):1:(1):($2-$1):($0+1) with vectors as variable,\
for [i=0:cnt-1] file using (0):1 every ::i::i with points ls (i+1),\
for [i=0:cnt-1] file using (1):2 every ::i::i with points ls (i+1)
With the result: