Anyone have a way to plot a bean plot in gnuplot? - plot

Title is pretty self explanatory but here is a picture of what I'd like to do. I'm having a tough time figuring out if its even possible.
Plot borrowed from:
Evaluation of geochemical background levels around sulfide mines – A new statistical procedure with beanplots. Gusstavason et al. 2012.

Doing the plot in exactly this orientation could be very cumbersome, if possible at all.
My suggestion is to plot everything with the usual orientation (i.e. having the 'sediments' axis as x-axis, or rather as x2-axis), rotate all labels a bit and finally rotate the complete output by 90 degree (pdf file with e.g. pdftk etc).
With this you can use any plot style as usual. In the script below I just show you how to plot the violet and yellow filled curves (using pseudo data) for two different data sets. Adding the other peaks should be straight forward (plot the bars with e.g. boxes or vector plotting style).
In order to have distinct ytics for the different plots, I associated a certain y-value with a certain plot, 1=Water, ..., 4=Gyttja).
Putting all toghether gives the following script:
reset
set terminal pdfcairo linewidth 2
outfile='bean'
set output outfile.'.pdf'
set encoding utf8
set x2range [0.5:9000]
set logscale x2
set x2tics (1, 5, 10, 50, '' 100, 500, '' 1000, 5000) out
set x2label 'mg/kg (sediments), µg/L (water)'
unset xtics
set yrange[0.5:4.5]
set ytics ('Water' 1, 'Minerogenic' 2, 'Peat' 3, 'Gyttja' 4) center rotate by -90 out
set label at graph 0.95, graph 0.05 right rotate by -90 'Nickel' font ',20' front
# cover possible data overlapping with the label
set object rectangle from graph 0.9, graph 0 to graph 1,graph 0.2 fillcolor rgb 'white' fillstyle solid noborder front
unset key
set macros
fs1="fillcolor rgb '#fc9e00' linewidth 2 fillstyle solid border lt -1"
fs2="fillcolor rgb '#9119f7' linewidth 2 fillstyle solid border lt -1"
# use pseudo data
set samples 500
plot '+' using 1:(4-0.3*exp(-(($1-10)/5.0)**4)) axes x2y1 with filledcurves y1=4 #fs1,\
'' using 1:(4+0.2*exp(-(($1-70)/50.0)**4)) axes x2y1 with filledcurves y1=4 #fs2,\
'' using 1:(1-0.4*exp(-(($1-5)/2.0)**2)) axes x2y1 with filledcurves y1=1 #fs1,\
'' using 1:(1+0.1*exp(-(($1-30)/20.0)**2)) axes x2y1 with filledcurves y1=1 #fs2
set output
system(sprintf('pdftk %s.pdf cat 1W output %s-rot.pdf', outfile, outfile))
system(sprintf('pdftocairo -r 150 -png %s-rot.pdf', outfile))
This gives (conventional and rotated output side-by-side) with 4.6.3:
Some stuff is required for the pseudo data. For a real data file, the plotting line looks a bit differently. The different plots have a separation of 1 in y-direction, so you must scale your data accordingly (done here manually with a scaling factor sc):
sc = 5.1
plot 'datafile.txt' using 1:(4 + $2/sc) axes x2y1 with filledcurves y1=4 #fs1
You can of course also do the scaling automatically, by extracting some minimum/maximum values using the stats command.

Related

How to label zrange in multiplot graph in gnuplot?

I am plotting multiplot surfaces.
I found this code 1 very helpful to plot my graph.
However, I want to label the z-axis throughout all surfaces in one plot.
I tried this set zrange[0.5:b+0.5], but nothing showed up. then I tried min_z and max_z, still, nothing showed up.
though I calculated and checked the range by the following the command.
print min_z,max_z.
can anyone please tell me how can I choose zrange with my own choice? like 1 ,2 3 4 5.
I will expand my comment as a possible answer. Multiplot is not needed for this style of plot. Here is an approximate recreation of the figure you linked to.
If you want to customize the axis labels along z, you can add a command to change the format like this: set ztic format "%.2f", and/or add additional commands of the form: set ztic add ( pi/2 "z = π/2" )
f(x,y,z) = besj0(x*x/z + y*y/z) / z
set palette cubehelix
set xyplane 0
set view 64,58
set ztics 0.2
unset key
splot for [i=1:6] z=(1.+i/6.), '++' using 1:2:(z):(f(x,y,z)) with pm3d
Answer expanded to show plotting from a series of files
Plotting from a series of files is essentially the same. The splot command again inserts a constant z value to create a plane, taking the data coordinates [x,y] from columns 1 and 3 and the f(x,y) value from column 4.
Here is an example:
set palette defined( 0 "dark-red", 1 "yellow" )
set xyplane 0
set view 74, 62, 0.85, 1.8
set border 16 # z axis only
unset xtics; unset ytics
unset key
file(i) = sprintf("map%d.dat",i)
set ztics ("File 1" 1, "File 2" 2, "File 3" 3, "File 4" 4)
splot for [i=1:4] file(i) using 1:2:(i):3 with image

Gnuplot 3D plotting from file, not enough detailed values on x-,y-, and z-ticks

I have a simple data I want to plot as 3D plot (3 columns divided by a comma):
33.26,0.0000001,1
67.02,0.0000010,2
101.64,0.0000100,3
137.53,0.0001000,4
175.06,0.0010000,5
214.59,0.0100000,6
256.47,0.1000000,7
301.09,1.0000000,8
348.78,10.0000000,9
399.92,100.0000000,10
454.87,1000.0000000,11
513.99,10000.0000000,12
577.65,10000.0000000,13
646.22,10000.0000000,14
720.05,10000.0000000,15
799.51,10000.0000000,16
884.96,10000.0000000,17
976.77,10000.0000000,18
1075.29,10000.0000000,19
1180.89,10000.0000000,20
1293.92,10000.0000000,21
1414.77,10000.0000000,22
1431.83,10000.0000000,23
1449.15,10000.0000000,24
1466.97,10000.0000000,25
1485.79,10000.0000000,26
1505.97,10000.0000000,27
1527.88,10000.0000000,28
1551.87,10000.0000000,29
1578.3,10000.0000000,30
1607.56,10000.0000000,31
1639.98,10000.0000000,32
1675.95,10000.0000000,33
1715.82,10000.0000000,34
1759.96,10000.0000000,35
1808.72,10000.0000000,36
1862.49,10000.0000000,37
1921.6,10000.0000000,38
1986.44,10000.0000000,39
2057.35,10000.0000000,40
2134.71,10000.0000000,41
2218.87,10000.0000000,42
2310.2,10000.0000000,43
2409.06,10000.0000000,44
2515.83,10000.0000000,45
I wrote a simple script to plot the above data:
#!/usr/bin/gnuplot
set palette rgbformulae 33,13,10
set datafile separator ","
set terminal postscript eps size 10.5, 5.62 enhanced color font 'Helvetica,20' linewidth 2
set output 'test.eps'
set xlabel "time [s] (no operation)" offset -4, 0, 0
set xtics left offset 0,-0.3 rotate by 45 right
set xrange [0:400]
set ylabel "ranges" offset 2, 0, 0
set ytics left offset 0,-0.5
set zlabel "devices" offset -4, 0, 0
set zrange [0:50]
set autoscale
set title " "
set key inside left top;
set dgrid3d 30,30
set hidden3d
set style line 1 linecolor rgb '00FF00' linetype 4 linewidth 1
splot "data.csv" u 1:2:3 title "" with lines palette
And my output:
As you all can see, the output image (or, I should say), the x,y and z ticks on axis x,y, and z are not enough detailed. It is hard to say that the output image was plotted with this data.
Is there a way that would let me manipulate the x,y, and z ticks, to be taken from file, in some elegant way?
I also would like the image to be more readable with new x,y, and z ticks, so I think that the 10000.0000000 value should appear only once, when it appeared for the first time in data file.
Thank you.
Not exactly an answer to your question, and it is my personal opinion, but you might be interested in the ideas:
The data seems not to be grid data, so I would not use a surface plot of any kind.
Plotting only the datapoints in 3d does not give a useful picture, it is only a single line somewhere in space. I would try to use a 2D plot which contains the height information as color.
I would use a logscale for the y-axis.
This leads to the following script:
set terminal pngcairo
set output 'test.png'
set datafile separator ","
set palette rgbformulae 33,13,10
# Set margins to keep colorbox label inside the picture
set lmargin screen 0.12
set rmargin screen 0.85
set xlabel "time [s] (no operation)"
set ylabel "ranges"
set cblabel "devices"
unset key
set yrange [1e-8:1e5]
set ytics format "1e%+T"
set logscale y
set view map
set cbrange [0:50]
set zrange [0:50]
splot "data.csv" u 1:2:3 w p pt 7 palette ,\
"data.csv" every 5::4 u ($1+0):($2/3):(0):($3 != 30 ? 3 : "") with labels
It also prints the z-labels of some datapoints, skipping 30 for spacing reasons.
This is the result:

gnuplot: superimposing contour plot and data on x-y plane

I am new to gnuplot. I am trying to superimpose both a contour plot and some data points on the x-y plane.
Data for my contour is given (surface1.txt) here
Data for the single points is given (points1.txt) here
I am trying to run this script:
set multiplot
# plot the contour from the surface1.txt
unset key
set dgrid3d
unset surface
set contour base
# these values need to be set (requirement)
set cntrparam level incremental 0.16, 0.259, 4.47
set view 0,0
unset ztics
splot "surface1.txt" with lines
# plot the points on the x-y plane
unset xtics
unset ytics
splot "points1.txt"
unset multiplot
and I am getting this output:
As you can see, the single points that I am trying to put on the x-y plane also comes as contour, what I need to do is:
display the points from "points1.txt" as single points (not contour)
the plot is zoomed out, I need a full screen image.
move the y-axis ticks from right to left vertical.
remove all the colors. I need a grayscale image.
Please help.
EDIT:
I have also tried this way --
set contour base
set cntrparam bspline
set cntrparam level incremental 0.16, 0.259, 4.47
set view map
set dgrid3d
unset key
splot 'surface1.txt' nosurface with lines, \
'points1.txt' nocontour
and I am getting this plot --
There are several things you must regard:
set dgrid3d interpolates your data and is thought to be used for non-gridded data. There is no option nodgrid3d which allows you to use it only for one plot part. This is what you see in your second attempt: the data for the points is interpolated and a 10x10 grid is generated.
However, you don't need to use this, because you have gridded data, but are missing a few empty lines in your data file. Just insert a single empty line when the x-value changes, like:
...
0.0 0.7999999999999999 2.0477812692428836
0.0 0.8999999999999999 2.3096674656635523
0.0 0.9999999999999999 2.5772908911794614
0.1 0.0 0.8254201558219569
0.1 0.1 1.0350909705482707
0.1 0.2 1.2504990143698247
...
Use the nosurface option for the contours, and nocontours when plotting the points.
A possible script could be:
set contour base
set cntrparam level incremental 0.16, 0.259, 4.47
unset key
set view map
set for [i=1:20] linetype i lc rgb 'black'
set terminal pngcairo dashed size 600,400
set output 'contour-with-points.png'
splot 'surface1.txt' with lines nosurface, 'points1.txt' with points nocontour pt 7
with the result
I used the pngcairo terminal only for this example, for your document you should probably use a vector format, like produced by pdfcairo, postscript, epslatex or similar.

Plotting an IR Spectrum with Gnuplot

I have an infrared spectrum for a compound of interest that I would like to plot, and I have a spectrum.dat file with all of the data points. It is of the form:
# X Y
300 100
301 100
302 99
303 70
...
3999 98
4000 100
I would like to plot this using an x axis typical of IR spectra, but I am having trouble doing so. If you are unfamiliar, this is what a typical IR spectrum might look like (aside from the labels on the graph itself). Notice that the x-axis is reversed, and that it abruptly doubles its scaling above 2000 units (reciprocal centimeters). Is there a way to coerce Gnuplot into plotting my data this way? I so far have managed to come up with the following script:
# Make an SVG of size 800x500
set terminal svg size 800,500 fname 'CMU Sans Serif' fsize '10'
set output 'ir.svg'
# Color definitions
set border linewidth 1.5
set style line 1 lc rgb '#a0a0a0' lt 1 lw 2 pt 7 # gray
# Format graph
unset key
set xlabel 'Wavenumbers'
set ylabel 'Transmittance'
set xrange [4000:300]
# Plot data
plot 'spectrum.dat' with lines ls 1
This reverses the x-axis nicely, but I can't figure out how to change the scaling in such an unusual way.
As a chemist I am motivated to answer...
As far as I know gnuplot doesn't easily allow for arbitrary axis scaling (unless anyone has bright ideas about how to use set link). My strategy in this kind of situation is to plot the two halves separately and have them join seamlessly:
#!/usr/bin/env gnuplot
set terminal png size 800,500
set output 'ir.png'
set xlabel 'Wavenumbers' offset 20
set ylabel 'Transmittance'
set tics out nomirror
set key bottom right
set bmargin 4
set yrange [0:1]
set multiplot layout 1,2 title 'IR Spectrum of Cholesterol'
# left half of plot
set xrange [4000:2000]
set rmargin 0
set border 7
plot 'cholesterol.txt' notitle
# right half of plot
set xrange [1999:300]
set lmargin 0
set rmargin 2
set border 13
unset xlabel
unset ylabel
unset ytics
plot 'cholesterol.txt' title 'Cholesterol'
unset multiplot
My one quibble is that the 2000 is written twice and looks bolder on my screen, but I will leave fidgeting with the tics to you.
andyras' answer is a nice one, this is an arguably simpler (more elegant :-P) solution in terms of layout options. This should also be a more universal solution. If there are not too many tics (read below the figure if there are too many), then this could be done scaling the curve itself beyond 2000, and then adding all the tics by hand. Since I don't have IR spectrum data available I will use the dummy file "+" and plot log(x) from 4000 to 500:
xmax=4000 ; xmin = 500
pivot = 2000 ; rescfactor = 2.
rescale(x) = (x >= pivot ? x : pivot + rescfactor*(x-pivot))
set xrange [rescale(xmax):rescale(xmin)]
set xtics ("4000" 4000, "3000" 3000, "2000" 2000, \
"1500" rescale(1500), "1000" rescale(1000), "500" rescale(500))
plot "+" u (rescale($1)):(log($1)) w l
In your case you just substitute log($1) by 2 or whatever you're plotting.
In newer versions of gnuplot (starting from 4.4) adding the tics can be done automatically using a loop:
xmax = 4000 ; xmin = 500 ; step = 500
set xtics (sprintf("%i",xmax) rescale(xmax)) # Add the first tic by hand
set for [i=xmin:xmax-step:step] xtics add (sprintf("%i",i) rescale(i))
Starting from gnuplot 4.6 also a different for construction can be made using do for:
do for [i=xmin:xmax-step:step] {set xtics add (sprintf("%i",i) rescale(i))}

gnuplot: Points overlap in pm3d with a wide xrange

I'm using gnuplot to plot three dimentions of data using pm3d. I'm trying to plot the number of times an event occurs (z value) with respect to the day of the year (x value) and hour of the day (y value).
Using pm3d works great for up to a range of 600 (rought 2 years of data). However, the points begin to overlap each other when a wider range is required.
I believe this is related to the fact that gnuplot isn't stretching the plot to the full size specified in set terminal. I haven't however been able to find a setting that controls this directly.
the script I'm using:
set terminal png size 10000, 1000
set output "%s_plot.png"
set title "%s's"
set ytics 1,1
set xtics 1
set xrange[0:%s]
set yrange[0:23]
set cbrange[0:%s]
set pm3d map
set palette defined (0 "white", 1 "blue", 31 "red")
splot '%s.data'
aspect of the plot for a range of [0:1000] in x:
aspect of the plot for a range of [0,100] in x:
(the images above are just snippets of the whole thing)
What can I do to remedy this? Perhaps the solution is manually setting the points (squares) to have a fixed width.
Thanks.
For the kind of plot that you want, I would replace your last line with:
plot '%s.data' matrix with image

Resources