The gnuplot doc for set offsets is extremely terse and I cannot find how offsets interact with multiple x-axes or y-axes.
I have 2 plots and they use x1y1 and x1y2, so there are 2 y-axes one on the left one on the right. Right now, when I add some top offset it applies to the plot which uses y1. How can I make it affect the plot which uses y2?
That's what gnuplot help offsets says:
Offsets provide a mechanism to put an empty boundary around the data
inside an autoscaled graph. The offsets only affect the x1 and y1
axes, and only in 2D plot commands.
So it looks like, it's not (directly) possible.
By the way, do you want offsets affecting...
only y2 axis or
y1 and y2 axes in the same way or
y1 and y2 axes differently?
Maybe you can edit your question and add an example for illustration.
Addition:
Maybe the following is helpful. As you already did, you can use the GPVAL_ variables.
Important to know, that these values are only set after plotting.
So, you have to plot, then modify your y1 and y2 ranges as desired and then replot. You could also use the variables GPVAL_Y_MIN, GPVAL_Y_MAX, GPVAL_Y2_MIN, and GPVAL_Y2_MAX which gnuplot's autoscaling algorithm suggests as ranges.
Code:
### different "offsets" for y1 and y2 axes
reset session
set xlabel "x1-axis"
set ylabel "y1-axis"
set ytics nomirror
set y2label "y2-axis"
set y2tics nomirror
plot 100*(sin(x)+1) axes x1y1 w l, \
10*cos(x) axes x1y2 w l
Y1FromBottom = 0.40 # y1 data will use 40% space from bottom
Y2FromBottom = 0.80 # y2 data will use 80% space from bottom
set yrange[:(GPVAL_DATA_Y_MAX-GPVAL_DATA_Y_MIN)/Y1FromBottom+GPVAL_DATA_Y_MIN]
set y2range[:(GPVAL_DATA_Y2_MAX-GPVAL_DATA_Y2_MIN)/Y2FromBottom+GPVAL_DATA_Y2_MIN]
replot
### end of code
Result:
Related
I have the following 'data.dat' file:
# x y z radius
-1.64905083 -1.14142799 -2657.88232 177.358566
-449.735321 416.586914 -2865.25366 10.0000000
178.955292 -256.291138 -2856.96069 89.9588394
-336.942322 184.932343 -2839.22876 90.6131058
-443.635315 -80.0183029 -2863.29077 70.7404404
236.385406 349.893188 -2901.33984 10.0000000
485.313416 -366.513947 -2868.35083 10.0000000
with the positions of the spheres and their radii.
My file.p reads:
set terminal png size 500,500
set output 'file.png'
set multiplot
set xrange [-1000:1000]
set yrange [-1000:1000]
set zrange [-3000:-2500]
splot "data.dat" using 1:2:3:4 ps variable pt 7
splot -(3000**2-x**2-y**2)**(0.5)
but the dots that gnuplot provides me are much bigger.
I understand that it is because ps yields points that are radius times bigger than the normal size.
Meaning that ps does not allow to set the radius of the dots, but rather how many times bigger it is than the normal points.
How can I set the radius of the points please ?
Use "with circles" rather than "with points pt 7".
From the manual:
gnuplot> help with circles
The `circles` style plots a circle with an explicit radius at each data point.
The radius is always interpreted in the units of the plot's horizontal axis
(x or x2). The scale on y and the aspect ratio of the plot are both ignored.
If the radius is not given in a separate column for each point it is taken from
`set style circle`. In this case the radius may use graph or screen coordinates.
Many combinations of per-point and previously set properties are possible.
For 2D plots these include
using x:y
using x:y:radius
using x:y:color
using x:y:radius:color
using x:y:radius:arc_begin:arc_end
using x:y:radius:arc_begin:arc_end:color
By default a full circle will be drawn. It is possible to instead plot arc
segments by specifying a start and end angle (in degrees) in columns 4 and 5.
A per-circle color may be provided in the last column of the using specifier.
In this case the plot command must include a corresponding variable color
term such as `lc variable` or `fillcolor rgb variable`.
Is it possible to plot a graph using different scale for negative and positive values in y-axes in Gnuplot?
I want to set the y range of the values in the y-axes from -2 to 70.
For values from 0 to 70 I want a scale e.g. 0,10,20,30,..70.
For values from 0 to -2 I want a different scale: 0, -0.1, -0.2, -0.3,..-2.
Thanks in advance.
Understanding your intention in general, I'm not sure whether the data you are providing are good enough to illustrate your desired outcome, so I have added two more data points where the negative y axis section is actually being used (see at the bottom of the post).
I used
multiplot to produce two separate plots, one for y values larger and one for those smaller than zero
the ternary operator (a ? b : c) to separate the date for each plot
I have done no work on the resulting graph, so it is extremely basic, and the large point size and different shape is only to "make the point". This is not a solution but should get you started:
# set up multiplot so that the two subgraphs are joined
set multiplot layout 2,1 margins 0.1,0.95,0.1,0.95 spacing 0
# no titles please
unset key
# we don't want tics for the upper half
unset xtics
plot[-2:2][0:70] "so.dat" using 2:($3>0?$3:NaN)\
w points pt 7 ps 2
# we do want xtics at the bottom
set xtics
plot[-2:2][-2:0] "so.dat" using 2:($3<0?$3:NaN)\
w points pt 5 ps 2
# cleanup
unset multiplot
reset
yields
My version of the data so.dat:
# TCP TFO
"Preparation" 1.126717 68.852979
"Establishment" -0.0436158 1.5529298
"Transfer" -0.1172298 0.5735358
"Interruption" 0.125 -1.25
"Execution" -1.5 -0.05
This has an answer already that has been accepted, but I have done some more work that I want to share; in particular,I wanted to have more control over the two subgraphs than the line
set multiplot layout 2,1 margins 0.1,0.95,0.1,0.95 spacing 0
allows. The lower subgraph should be visibly "thinner" than the upper one. Taking the opportunity, I also wanted to address Vladimir's question in his comment. So here we go:
### set up multiplot so that the two subgraphs are joined
set multiplot
# we need to set a left margin to keep the subgraphs aligned,
# and we need enough space for the ylabel
set lmargin 10
# no bottom margin, so that the second subgraph touches the upper one
set bmargin 0
# no titles please
unset key
# but we want a ylabel
set ylabel "Scales"
# no xtics
unset xtics
For Vladimir: see help set border
# we want left, top and right 2 + 4 + 8
# but no bottom border
set border 14
Now manually fix the area where we want to draw the first subgraph:
set size 1,0.5 # full with, half hight
set origin 0,0.5 # start at the left border, half way up
# optional: colour background
# set object 1 rect from -2,0 to 2,80 fc rgb "yellow" fillstyle solid .15 noborder
Ready to draw the graph:
plot[-2:2][0:80] "so.dat" using 2:($3>0?$3:NaN)\
w points pt 7 ps 2
The rest in one go:
# we do want xtics a label at the bottom
set xtics -2,.5,2 nomirror
set xlabel "Multiplot In Action"
set ylabel "Different"
set size 1,0.3 # full width, 30% of height, keep space for xlabel
set origin 0,0.2 # left, keep bottom 20% free
set tmargin 0 # no top margin, touch the upper subgraph
set bmargin 2 # for the xlabel
set border 11 # we want left, bottom and right border, no top 1 + 2 + 8
# set object 2 rect from -2,-2 to 2,0 fc rgb "blue" fillstyle solid .15 noborder
plot[-2:2][-2:0] "so.dat" using 2:($3<0?$3:NaN)\
w points pt 5 ps 2
# cleanup
unset multiplot
reset
This gives us
I would have liked the colour backgrounds, but the lower one is drawing over the dots in the upper one and I have not been able to fix that (back doesn't help).
Since gnuplot 5.2 you can define nonlinear coordinate systems with set nonlinear. This works similar to set link: You must provide a mapping function and its inverse for the axis you want to change.
In your case, the mapping function would scale all positive y-values and leave the negative ones unscaled:
RATIO=0.1
map(y) = y > 0 ? y*RATIO : y
inv_map(y) = y > 0 ? y/RATIO : y
set nonlinear y via map(y) inverse inv_map(y)
set xrange[-5:50]
plot x
I'd like to know how to set the same number of ytics for both independent y and y2 axis using gnuplot, still using automatic scaling, so that the grid is well aligned.
Right now, as you can see below, there are 6 ticks for the y axis and 7 for y2, and the chart looks poorly readable.
As far as I know, Gnuplot lets you only to specify the increment defining the tics not their count. A slightly dirty workaround would be to first generate the plot into a "fake" terminal, remember the detected autoscaled ranges on each axis, calculate the required tics spacing, and finally generate the image with these settings.
N = 6
set term unknown
set ytics
set y2tics #setting y2tics affects autoscale
set ylabel 'MSE'
set y2label 'CE'
set grid
set format y "%.2f"
set format y2 "%.1f"
plot \
'mse.dat' u 1:2 axis x1y1 w l t 'MSE', \
'ce.dat' u 1:2 axis x1y2 w l t 'CE'
min_y1 = GPVAL_Y_MIN
max_y1 = GPVAL_Y_MAX
min_y2 = GPVAL_Y2_MIN
max_y2 = GPVAL_Y2_MAX
dy1 = (max_y1 - min_y1) / N
dy2 = (max_y2 - min_y2) / N
set ytics min_y1, dy1
set y2tics min_y2, dy2
set yr [min_y1:max_y1]
set y2r [min_y2:max_y2]
set term png enhanced
set output "test.png"
replot
This then produces (using a digitized approximation of your data):
I seem to be having some difficulty finding the answer to this question online. The title is the basic question, but to be more specific I would like to have two x axes, one at the top of the figure that is dependent on the one at the bottom. However, this is not a simple relationship, i.e. x2!=5*x1 or something like that. The relationship is given by the data file itself. So to be more specific I have a file that looks something like this:
V T P
2.0 15.0 0.586
3.0 17.4 0.798
4.0 25.3 1.023
5.0 28.9 1.124
6.0 30.2 1.456
I would like to make a plot of T with respect to (wrt) P on the x1y1 axes and have T wrt V on the x2y1 axes. So the x1 axis would display the P range and x2 would display the V range in the corresponding places of x1, i.e. 0.586 on x1 axis would have 2.0 on x2 axis at the same place. Is this actually possible in Gnuplot or do I have to have a relationship with the two x axes to do this? Any help would be greatly appreciated. Thank you in advance.
Here is how you can achieve this. I first show you the script and the result, and later explain the steps:
reset
set xtics nomirror
set x2tics
set autoscale xfix
set autoscale x2fix
set xlabel 'P'
set ylabel 'T'
set x2label 'V'
plot 'data.txt' using 3:2 with linespoints ps 2 lw 2 title 'T wrt P', \
'' using 3:2:x2tic(1) axes x2y1 with points ps 2 lw 2 title 'T wrt V'
I first plot T wrt P on x1y1. Afterwards I plot T wrt V on x2y1 and use for this the range and tic positions of P, but use the V values as tic labels for the x2 axis. This gives a linear scale for P and adapts V accordingly.
In order for this to work you must use set autoscale xfix and set autoscale x2fix. This uses the exact ranges and does not expand an axis to the next major tics, which would be done only for the x axis, but not for the x2 axis, which has custom tics.
You could of course also reverse the process and use a linear scale for V and adapt the P tics. In any case, for the custom tics, which are placed with xtic() or x2tic, the numbers are used like they are formatted in the data file.
reset
set xtics nomirror
set x2tics 1
set autoscale xfix
set autoscale x2fix
set xlabel 'P'
set ylabel 'T'
set x2label 'V'
plot 'data.txt' using 1:2:xtic(3) with linespoints ps 2 lw 2 title 'T wrt P', \
'' using 1:2 axes x2y1 with points ps 2 lw 2 title 'T wrt V'
Here, the points are shown for both plot lines, to demonstrate, that they really coincide.
In order to have the one command only generating the xtics, one can use NaN for the y-value. And if only some of the custom tics should be labels, one needs an appropriate check in the x2tic call. Here, I set labels only for all even rows $0 is the current row number, starting from 0):
reset
set xtics nomirror
set x2tics
set autoscale xfix
set autoscale x2fix
set xlabel 'P'
set ylabel 'T'
set x2label 'V'
plot 'data.txt' using 3:2 with linespoints ps 2 lw 2 title 'T wrt P', \
'' using 3:(NaN):x2tic((int($0) % 2) ? '' : stringcolumn(1)) axes x2y1 t ''
With the result:
The best way: Plot your data as usual on the x1 and y1 axes, but place additional labels on the x2-axis with x2tic(column_number):
set x2tics
set xtics nomirror
plot 'data.txt' using 3:2:x2tic(1) w lp
see: Plot y1 in x1 with respect to x2 axis
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.