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
Related
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):
My data file looks like:
0 12.6 303.1 3.4577387486
120 10.5 278.9 2.8814489572
...
640 9.45 301.3 2.5933040615
My code looks like:
set xlabel "Tiempo (min)"
set ylabel "Corriente en el anillo (mA)"
set y2label "Flujo (fotones/s)"
set ytics nomirror
set y2tics
set tics out
set autoscale y
set autoscale y2
plot 'tan_time_curr_flux.dat' using 1:3 lc rgb 'black' pt 6 lw 2 w lp axes x1y1 title "Corriente", 'tan_time_curr_flux.dat' using 1:4 lc rgb 'blue' pt 5 lw 2 w lp axes x2y2 title "Flujo"
My plot looks like:
As you can see, there is a little offset, in x, between respective data points. It is more clear as x grows. For example the actual last point for flux (flujo) is 640,2.59. But the plot shows that point at 700, 2.59. How can I tell gnuplot not to add any offset to the second (blue) line?
Thanks a lot! :)
Ps If I plot time (col. 1) vs either flux (col. 4) or current (col. 3)...
The values for x stay normal. (i.e. There is no offset)
I guess that's a bug.
However, simply use axes x1y2 for your second plot, since you only have one x-value.
I have a data files including multiple float-value columns such as following and I want to plot some columns in gnuplot.
1.08 1.6 4.83
1.53 2.5 5.95
2.11 3.2 6.1
2.60 4.1 7.0
I want to have x2-axis by following:
set xtics nomirror
set x2tics
set autoscale xfix
set autoscale x2fix
set ylabel 'Y_H
set xlabel 'Y_O'
set x2label 'Y_C'
p 'datafile' u 1:2 w l ls 1 t '',\
'' u 1:(NaN):x2ticlabels(3) axes x2y1 w l ls 1 t ''
This way displays every single tic and It's label on the x2 axis. I would like to set custom labels for x2-axis such as 4,5,6,7 and their tics to write. How can I have custom labels and tics on x2-axis?
x2tics behave the same way as xtics so all functions available for xtics are also applicable to x2tics.
Set a range by:
set x2range [1:5]
This command will give you a range of 1 to 5 on the x2 axis.
If you want to set custom labels then:
set x2tics ("one" 1, "two" 2, "three" 3, "four" 4, "five" 5)
This command will give you the words inside double quotes at x2=1, x2=2 and so on.
In your case you can get numerical values on x2 axis by using set x2range [4.83:7] and changing second plot to 1:(NaN):3
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))}
I want to plot a 18x18 matrix with gnuplot. Here is my codes:
set size ratio 1
set palette gray negative
set xrange[-0.5:17.5]
set yrange[-0.5:17.5]
set cbrange[-0.2:0.8]
set xtics 0,1,17
set ytics 0,1,17
set xtics offset -0.5,0
set title "Resolusition Matrix for E"
plot "Mat" matrix w image noti
Then I got a fig like this:
Now I would like to add borders to each cell, which will look like this:
Thank you.
For your case you can set one minor tic, which then lies on the border between two pixels, and draw a grid on them:
set size ratio 1
set palette gray negative
set autoscale xfix
set autoscale yfix
set xtics 1
set ytics 1
set title "Resolution Matrix for E"
set tics scale 0,0.001
set mxtics 2
set mytics 2
set grid front mxtics mytics lw 1.5 lt -1 lc rgb 'white'
plot "Mat" matrix w image noti
Note, that set grid front also brings the tics to the front. To avoid that you can scale the tics to 0. For the minor tics you must use a very small number, 0 would omit the grid lines on the minor tics.
The result with 4.6.3 is:
EDIT: In order to control the grid lines and tic labels independently, you can use the unused x2 and y2 to draw the grid (inspired by an answer to How do I draw a vertical line in gnuplot?):
set size ratio 1
set palette gray negative
# grid lines
set x2tics 1 format '' scale 0,0.001
set y2tics 1 format '' scale 0,0.001
set mx2tics 2
set my2tics 2
# labeling
set xtics 5 out nomirror
set ytics 5 out nomirror
set grid front mx2tics my2tics lw 1.5 lt -1 lc rgb 'white'
set xrange[-0.5:39.5]
set yrange[-0.5:39.5]
set x2range[-0.5:39.5]
set y2range[-0.5:39.5]
plot "Mat" matrix w image notitle
With gnuplot version 4.6, this requires setting explicit ranges, so that the x and x2 (unused!) are equal. The information might be extracted with stats from the data file.
Using version 5 allows you to use set link. Instead of all the set *range stuff. You could use:
set autoscale fix
set link x
set link y
Result: