Hierarchial Axis in GNUPLOT - plot

I am trying to plot a figure using GNUPLOT, but I want to have a hierarchical x-axis, it should be six tick points in x-axis with first level of label in x-axis being 32,64,128,32,64 and 128. Here the first 32, 64 and 128 should be grouped as stencil and the second 32, 64 and 128 should be grouped as diamond in second level of label . Current i am doing this as stencil-32, stencil-64, stencil-128, diamond-32, diamond-64 and diamond-128. Is there a way to change it into hierarchical axis lableling?

If I correctly understand what you mean with hierachical axis the following code could be one possible way of many others.
You could simply increase the bottom margin and add some labels. But if you want to have some axis, using multiplot might be an option. You need to make sure that the margins are identical (especially the left margin).
Code:
### hierarchical axis
reset session
$Data <<EOD
1 stencil 32 0.3
2 stencil 64 0.4
3 stencil 128 0.5
4 diamond 32 0.6
5 diamond 64 0.7
6 diamond 128 0.8
EOD
myBottomMargin = 0.12
myColor(col) = strcol(col) eq "stencil" ? 0xff0000 : 0x0000ff
set multiplot
set origin 0, myBottomMargin
set size 1, 1-myBottomMargin
set lmargin screen 0.1
set style fill solid 1.0
set boxwidth 0.8
set yrange [0:1]
plot $Data u 0:4:(myColor(2)):xtic(3) w boxes lc rgb var notitle
set origin 0, 0
set size 1, myBottomMargin
set border 1 # only bottom border
set xtics nomirror
set xrange [0.5:2.5]
set mxtics 2
set xtics 1 add ("stencil" 1, "diamond" 2) scale 0,1
set yrange [0:1]
unset ytics
unset key
plot NaN # dummy plot just for the extra axis
unset multiplot
### end of code
Result:

Related

Different scale for negative and positive values in y-axes - Gnuplot

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

How can i limit polar grid in gnuplot?

My data is in polar coordinates and when i plot them and try to add the polar grid it will be complete circles but my data is only from 0-60 degrees.
How can i limit the grid only from 0-60 degrees only, and not a complete circle?
I am not aware of a built-in feature for this. However, as a workaround, one might use the multiplot in order to draw the grid lines manually.
For example:
set term pngcairo enhanced size 800,800
set output 'fig.png'
set angles degrees
set multiplot
set lmargin at screen 0.1
set tmargin at screen 0.9
set rmargin at screen 0.9
set bmargin at screen 0.1
set samples 1000
unset border
R_max = 1
dR = 0.2
phi_max = 60.
dphi = 15
set xr [0:R_max]
set yr [0:R_max]
set xtics out nomirror
unset ytics
set style line 42 lc rgb '#666666' dt 3
unset key
plot \
for [i=0:phi_max/dphi] (x>=0&&x<=R_max*cos(i*dphi))?tan(i*dphi)*x:1/0 w l ls 42
set polar
set trange [0:phi_max]
unset raxis
unset rtics
plot \
for [i=1:ceil(R_max/dR)] i*dR<=R_max?i*dR:1/0 w l ls 42
unset raxis
unset rtics
plot cos(t) w l lw 2 lc rgb 'dark-red'
produces:

gnuplot error:"Tic label does not evaluate as string!" in bar chart

I'm working on Gnuplot 4.6 patch 4.
I want to create the bar chart with palette. I've followed this but I got error:
Tic label does not evaluate as string!
Yes, the different with the reference that I mentioned above are the xtics. My graph uses string in xtics.
Here is my sample data:
off 100.0
gpl 60.0
docs 99
vim 9.4
box 95
goo 60
ama 99.9
eba 99.98
and my plot file is:
set term pos eps font 20
set style data histogram
set style histogram rowstacked
set boxwidth 0.75
set format y "%.0f%%"
set style fill solid border -1
set xtics font "Times-Roman, 15" rotate by 45 right
#set xtics center offset 0,-1
set ytics font "Times-Roman, 15"
set palette defined ( 0 "#FFFFFF",\
1 "#FFCCCC",\
2 "#FF9999 ",\
3 "#FF6666",\
4 "#FF3333",\
5 "#FF0000",\
6 "#CC0000",\
7 "#C00000",\
8 "#B00000",\
9 "#990000",\
10 "#A00000")
set ylabel "Percentages"
#set xlabel "Services"
set yrange [70:100]
set output 'a2.eps'
plot 'a2.dat' \
using ($2):xtic(1):($2<=10 ? 0 : $2<=20 ? 1 : 2) t '' with boxes palette
Thanks for help!
The xtic label part should always be the last in a using statement. Also, when using the boxes plotting style you must specify x, y and color values:
plot 'a2.dat' \
using 0:2:($2<=10 ? 0 : $2<=20 ? 1 : 2):xtic(1) t '' with boxes palette
Note, that with boxes overwrites the histogram style you set earlier. Also, the values given in the palette aren't absolute values, but those color values are scaled to accomodate your effictive color range of [0:2].

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 plot 2D matrix with image, want to draw borders for each cell

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:

Resources