Gnuplot offsets with custom range (v5.4) - gnuplot

I have a problem with how offsets work in gnuplot v5.4 compared to v5.2.
I tried to make the following graph (v5.2):
To create this graph, I used the following code...
set style line 1 lc rgb '#808080' lt 1 lw 2
set border 0 ls 1
set arrow from 0, graph 0 to 5, graph 0 nohead front ls 1
set arrow from graph 0,first 0 to graph 0, first 5 nohead front ls 1
set xtics nomirror
set ytics nomirror
set lmargin 10
set bmargin 3.5
set xrange [0:5]
set yrange [0:5]
set offsets graph 0.1, graph 0.1, graph 0.1, graph 0.1
plot 'example.txt'
... and data.
#x y
0 3.88222
1 4.20754
2 4.424
3 2.41443
4 1.95107
5 2.79098
In v5.4, this code results in a graph without offsets:
The documentation unfortunately does not address custom ranges.
I am not sure if this is a bug, a problem with my code or if the feature of using offsets and custom ranges got removed in gnuplot v5.4 altogether.
Thank you in advance!

The documentation section for "offset" is not good in gnuplot version 5.
My understanding is that the current (version 5.4) behavior is
offsets only affect auto-scaling
explicit axis ranges take precedence over auto-scaling, so offsets have no effect if there is an explicit range for that axis
The style of plot shown in the query is best achieved in gnuplot 5.4 by using the keyword rangelimited, e.g. set tics rangelimited if you want this on all axes
The commands below work the same way in gnuplot versions 5.0 and 5.2 as they do in version 5.4, so I am thinking that this example shows not a sudden change between the two versions but rather a gradual accumulation of small differences between versions 4 and 5. I will file a bug report pointing out the inadequacy of the current documentation section on "offset".
Revised code
# Modified for gnuplot version 5.4
set xtics rangelimited nomirror
set ytics rangelimited nomirror
set border 3
set offsets graph 0.1, graph 0.1, graph 0.1, graph 0.1
plot 'example.txt' with points

A strange observation which I can reproduce. The following further minimized code behaves differently in gnuplot 5.2 and gnuplot 5.4
reset session
set xrange[0:5]
set yrange[0:5]
set offset graph 0.1, graph 0.1, graph 0.1, graph 0.1
plot x
I'm not sure why it is different. The following a bit cumbersome workaround will lead to the same result in gnuplot 5.2. and gnuplot 5.4 with the cost of replotting. But I hope there will be an easier solution which is currently not obvious to me. Maybe there is another setting in gnuplot 5.4 which "recovers" this 5.2 behaviour.
Code:
### "manual" offset for gnuplot 5.4
reset session
$Data <<EOD
#x y
0 3.88222
1 4.20754
2 4.424
3 2.41443
4 1.95107
5 2.79098
EOD
set style line 1 lc rgb '#808080' lt 1 lw 2
set border 0 ls 1
set arrow from 0, graph 0 to 5, graph 0 nohead front ls 1
set arrow from graph 0,first 0 to graph 0, first 5 nohead front ls 1
set xtics nomirror
set ytics nomirror
set lmargin 10
set bmargin 3.5
set xrange [0:5]
set yrange [0:5]
xRange(a) = GPVAL_X_MAX -GPVAL_X_MIN
yRange(a) = GPVAL_Y_MAX - GPVAL_Y_MIN
xOffMin(a) = GPVAL_X_MIN - a*xRange(a)
xOffMax(a) = GPVAL_X_MAX + a*xRange(a)
yOffMin(a) = GPVAL_Y_MIN - a*yRange(a)
yOffMax(a) = GPVAL_Y_MAX + a*yRange(a)
plot $Data
set xrange [xOffMin(0.1):xOffMax(0.1)] # graph 0.1
set yrange [yOffMin(0.1):xOffMax(0.1)] # graph 0.1
replot
### end of code
Result: (gnuplot 5.2 and gnuplot 5.4)
Addition:
Well, you are setting a fixed x- and y-range and then you add 10% extra offset. So, you either could set directly set xrange[-0.5:5.5] and set yrange[-0.5:5.5] or do a calculation as in the code below. But, I agree if it worked as in gnuplot 5.2 where you set the ranges and then add 10% extra offset would be much more convenient.
reset session
xMin=0
xMax=5
yMin=0
yMax=5
OffLeft = 0.1
OffRight = 0.1
OffTop = 0.1
OffBottom = 0.1
xRange = xMax-xMin
yRange = yMax-yMin
set xrange[xMin-OffLeft *xRange : xMin+OffRight*xRange]
set yrange[xMin-OffBottom*yRange : yMin+OffTop *yRange]
plot x

Related

Gnuplot: set angular grid limits in polar plot

I am trying to make a wedge-shaped plot in polar coordinates spanning from 0 to 60 degrees. Something like the following figure: Wedge-plot I want
However, the command "trange" is used for the range of the plot, not of the grid itself, and I always end up with the full-circle grid, like this: Same plot but with full grid.
Is there a simple command to set the limits in the angle variable? Here is the code I used to plot the former figure in gnuplot 5.2
set terminal pngcairo enhanced font "arial,10" fontscale 1.0 size 600, 400
set output 'polar1.png'
unset key
set border 4096 lt black linewidth 1.000 dashtype solid
unset xtics
unset ytics
set size ratio 1 1,1
set raxis
set ttics 0.00000,30 font ":Italic"
set polar
set grid polar 30.0000 lw 1.5
plot cos(4*t) lt 3 lw 2
Thank you in advance!
I guess there is no "intended" way to limit the maximum angle in a polar plot.
So, there is a simpler (but ugly) workaround, which simply covers the unwanted part by a filled polygon.
Note: There will be an issue if your rmax is not an integer multiple of rtic 0.2, i.e. a plot with rmax=1.05 will not look as desired. Therefore, as a workaround an extra rtic at rmax is added.
Script:
### plot only part of polar plot
reset session
rmax = 1.05
amax = 60
set polar
set rrange [0:rmax]
set rtics 0.2 scale 0.5
set rtics add ('' rmax)
set grid r polar 10 lt black lw .3
set trange [0:2*pi]
set ttics 0,10 format "%g°" font ":Italic" scale 0.5,0.25 offset -1,0
set mttics 2
set xlabel "r-label"
set xrange [0:rmax]
unset xtics
set yrange [0:rmax]
unset ytics
set size square
set border 4096
set lmargin 0
set tmargin 0
unset title
unset key
set samples 300
set obj 1 polygon from graph 0,0 to first rmax*cos(pi/180*amax),rmax*sin(pi/180*amax) \
to first rmax*cos(pi/180*amax), screen 1.0 \
to first 0, screen 1 to screen 0,1 to screen 0,0 to graph 0,0 \
fc rgb 0xffffff fs solid 1.0 front
set arrow 1 from graph 0,0 to first rmax*cos(pi/180*amax),rmax*sin(pi/180*amax) lc "black" nohead front
plot cos(4*t) lt 3 lw 2
### end of script
Result:

How to move and manage overlapping of x ticks with axis in Gnuplot

I am trying to plot an inlet graph which is shown in Figure. Being an inlet graph it is needed to show x tics and y ticks of relatively big sizes for clear visibility. But when I increase the fonts as,
set xtics font ", 40"
tics overlaps with axis. I increased the plot size set term png size 1000, 1000 but still the issue persists. Kindly suggest if there is a way to move the tics below or to a desired position in graph.
Edit:
The gnuplot script looks like this,
set term png size 1000, 1000
set output "b_vs_N.png"
set style fill solid
set style circle radius 0.001
FIT_LIMIT=1.e-14
set yrange [0.15:0.25]
set style fill solid
set style circle radius 0.001
set xtics 10
set ytics 0.03
set border 15 back lw 6
set xtics font ", 40"
set ytics font ", 22"
set ylabel "b" enhanced font "1 {,40}"
set xlabel "N_i" font "1 {,40}"
set lmargin 12
set bmargin 4
set palette model HSV
set palette rgb 3,2,2
set palette maxcolors 12
set view map
AA(x)=a+b*x+c*x**2
fit AA(x) "data.txt" using 1:2 via c, b, a
plot "data.txt" using 1:2 lt 1 pt 11 ps 2.0 lc rgb "black" notitle, AA(x) w lines lw 2 lc rgb "sienna1" notitle
Your example is uncomplete without code and therefore difficult to reproduce. Please check help xtics. There is the option offset.
Maybe the following example helps to solve your issue.
In the example below no special offset seems to be necessary, i.e. offset 0,0, but you can shift and adjust the labels in x and y direction.
Code:
### tic label offset
reset session
set multiplot
plot sin(x)/x
set origin 0.07, 0.6
set size 0.3,0.3
set xrange [0:10]
set xtics 5 out font ",20" offset 0,0
plot x**2
unset multiplot
### end of code
Result:

Show error bars in a multiaxis plot in Gnuplot

I have a dataset (show-errorbar.dat) containing:
Model# DE IE Error
Apple -4.6 -128.9538 4.0
Huawei -5.2 -176.6343 5.3
One-Pro -5.2 -118.1106 3.2
#!/usr/bin/gnuplot
#set terminal pdfcairo enhanced color font 'Helvetica,12' linewidth 0.8
set terminal png
set output 'BrandError.png'
set boxwidth 1.0 relative
set bmargin 5
set style fill solid border -1
set xtic rotate by -45 scale 0
#set auto x
set style line 81 lt 0 lc rgb "#808080" lw 0.5
set grid xtics
set grid ytics
set grid mxtics
set grid mytics
set grid back ls 81
set arrow from graph 0,first -4.6 to graph 1, first -4.6 nohead lw 2 lc rgb "#000000" front
set border 11
set border lw 2.0
set xtics font ",11"
set ytics font ",14"
set tics out
set ytics nomirror
set y2tics
set y2tics font ",14"
set mxtics 10
set mytics 2
set my2tics 2
set yrange [-10:0]
set y2range [-260:0]
set key left bottom
set y2label offset -2
set ylabel offset 2
set ylabel 'DE' tc rgb "red"
set y2label 'IE' tc rgb "green"
set style data histograms
set style histogram cluster gap 2
set linetype 2 lc rgb 'red'
set linetype 3 lc rgb 'yellow'
set linetype 4 lc rgb 'green'
plot 'show-errorbars.dat' using 2 ti 'DE' lc 2 axis x1y1, '' u 3:xticlabels(1) ti 'IE' lc 4 axis x1y2
set output
enter image description here
I would like to plot a histogram comparing DE vs IE and also show error bars (data in column 4) for the IE values.
Please any help on how to go about it.
There is a variant histogram style for exactly that purpose
set style histogram errorbars gap 2 {lw W}.
Here is the help section from the docs:
The `errorbars` style is very similar to the `clustered` style, except that it
requires additional columns of input for each entry. The first column holds
the height (y value) of that box, exactly as for the `clustered` style.
2 columns: y yerr bar extends from y-yerr to y+err
3 columns: y ymin ymax bar extends from ymin to ymax
The appearance of the error bars is controlled by the current value of
`set errorbars` and by the optional <linewidth> specification.
Updated answer
Notes:
You can't mix axis choice within a single histogram. So I have removed the axes x1y1 and axes x1y2 from the plot command. Since you have explicitly given the range for both y1 and y2, the plot border and labels are not affected.
However since the green bars are now being plotted against y1, we have to scale them so that the y2 axis labels apply. So the column 3 and column 4 values will be divided by 26, which is (y2 range) / (y1 range)
In "histogram errorbars" mode each plot component looks for an extra column of data to determine the size of the errorbar. Since your column 2 data has no corresponding column of errors, we dummy it up to use all a constant not-a-number (no data) value: (NaN)
Your data contains a line of columnheaders, which could confuse the program if it thinks this is a line of data. There are a number of ways you can tell the program to skip this line; I have used set key autotitle columnhead for convenience and because it is supported by old versions of gnuplot. If you have a current version it would be better to use instead set datafile columnheaders.
I have kept all of your commands except that the plot command is replaced by the following 3 lines:
set style histogram errorbars gap 2 lw 1.5
set key autotitle columnhead
plot 'show-errorbars.dat' using 2:(NaN) ti 'DE' lc 2, '' u ($3/26.):($4/26.):xticlabels(1) ti 'IE' lc 4

Aligning values with timestamps to a timeline

I want to visualize data given at certain timestamps from multiple sources along a timeline. For example, with the follwing to input files with column 1 being the timestamp and column 2 the data:
O1.dat:
100 5
300 10
O2.dat:
200 7
400 3
Along with that the average of all values is sampled at certain intervals:
Avg.dat:
250 6.5
500 6.25
I would like to plot all values in a table-like manner so it looks something like this, with the values aligned to the time on the top:
My real data reaches timestamps of up to 10000, so something dynamic would be nice.
So far I only plotted simple box or line plots, so I'm not sure how to go about this one.
Thanks for your time.
EDIT:
This is what it looks like so far with adjustments made to the accepted answer:
There is still some overlapping, but that is simply because of the data being too close to each other. The script used for this:
#set term pdf
#set term pdf size 8, 5
#set output 'out.pdf'
set term png
set term png size 1200, 700
set output 'out.png'
set termoption font ",20"
set label 'Time (ms)' at graph 0, graph 1 offset -0.75, char 1 right
unset border
unset key
unset xtics
set ytics scale 0
set x2tics () scale 0
set yrange [0:5.5]
set x2range[0:10000]
set lmargin 9
set arrow from graph -0.15, graph 1 to graph 1.1, graph 1 nohead
set arrow from graph -0.01, graph 1.2 to graph -0.01, graph -0.2 nohead
set arrow from graph -0.15, first 0.3 to graph 1.1, first 0.3 nohead
set style data labels
plot for [i=0:9] 'desc'.i.'.txt' using 1:(5-0.5*i):(sprintf('%d', $2)):ytic('Object '.i) axes x2y1, \
'Avg.dat' using 1:(0):(sprintf('%d', $2)):ytic('Avg') axes x2y1
The conventional, simple part is plotting of the actual data. For this you can use the labels plotting style. A very simple example would be:
set xtics (0)
set xrange [0:*]
set offsets graph 0, graph 0.2, graph 0.2, graph 0.2
set style data labels
unset key
plot 'O1.dat' using 1:(5):(gprintf('%g', $2)):ytic('O1'),\
'O2.dat' using 1:(4):(gprintf('%g', $2)):ytic('O2'),\
'Avg.dat' using 1:(3):(gprintf('%g', $2)):ytic('Avg'):xtic(1)
That simply plots the values from your data files as labels at the x-positions given in the first columns. The y-positions are set as fixed numbers:
In order to move the xtick labels to the top and have some table-like lines you need a bit more tweaking:
reset
set termoption font ",20"
set label 'Object' at graph 0, graph 1 offset -1, char 1 right
unset border
unset key
unset xtics
set ytics scale 0
set x2tics () scale 0 format "%g"
set yrange [2:5.5]
set x2range[0:*]
set lmargin 8
set arrow from graph -0.15, graph 1 to graph 1.1, graph 1 nohead
set arrow from graph 0, graph 1.2 to graph 0, graph 0 nohead
set arrow from graph -0.15, first 3.25 to graph 1.1, first 3.25 nohead
set style data labels
plot 'O1.dat' using 1:(5):(sprintf('%d', $2)):ytic('O1') axes x2y1,\
'O2.dat' using 1:(4):(sprintf('%d', $2)):ytic('O2') axes x2y1,\
'Avg.dat' using 1:(2.5):(gprintf('%g', $2)):ytic('Avg'):x2tic(1) axes x2y1
Such a table layout isn't a typical task, so you must adapt several settings to your final result. Main impact comes from canvas size, font and, font size.
If you have more than those two files you could of course also iterate over a file list.

gnuplot - autoscale y axis with filledcurves + xrange + xdata time

in gnuplot 5.0 patchlevel 1 on my old server I used:
set term pngcairo transparent truecolor size 190,40
set output "some.png"
unset bmargin
set bmargin 0
set lmargin 0
set rmargin 0
set tmargin 0
unset border
unset xtics
unset ytics
unset y2tics
unset key
unset title
unset colorbox
set timefmt '%Y-%m'
set xdata time
set style fill transparent solid 0.25 noborder
tt = "`date +%Y-%m-%d\ %H:%M`"
TIMEFMT = "%Y-%m-%d %H:%M"
now_secs = strptime(TIMEFMT,tt)
two_years_past = now_secs - 3600.0*24*365*2
eval(sprintf('set xrange ["%s":]',strftime(TIMEFMT,two_years_past)))
set autoscale yfix
plot "datafile" using 1:2 with filledcurves below x1 lw 1 lc rgb "#a7eeeeee" title ''
...it produced a graph with y range correctly auto-scaled.
But on my new server with gnuplot 5.0 patchlevel 3 installed it does not work anymore. It seems they screwed something in the code. The yrange is computed from all x timedata, not over the selected xrange only.
I have no idea how to correct the yrange in this case. It could be computed using the stats command, but the "xdata time" must be switched off before, but in that case I do not know, how to set the right xrange for the stats command.
Regards
Pavel
EDIT:
minimal datafile:
2014-01 2
2014-06 6
2015-01 4
2015-06 8
2016-01 6
2016-06 10
I can reproduce your y-range autoscale issue with gnuplot<=5.0.1 and all versions >5.0.1 to 5.4.0.
Although, gnuplot is not scaling to the full y-data-range as you assumed, but apparently filledcurves x1 seems to always (auto)scale to 0 unless there is y-data <0.
To me, this looks more like a bug than a feature. I don't see a reason why filledcurves should always autoscale to 0.
In contrary to this behaviour, the plotting style with boxes will still autoscale in y to the minimum as you want it.
So, as a workaround to keep your desired behaviour you need to add two lines:
stats $Data u 2 nooutput
set yrange[STATS_min:]
The x-range is already limited when executing the stats command, hence you will get the y-minimum in STATS_min which you can use to set the y-range.
By the way: I cleaned up your script a bit. Why making a platform-dependent system call for getting the current time, if you have the gnuplot function time()? Check help time.
Script: (works identical for all gnuplot versions >=5.0.0)
### adjust time range via current time with proper y autoscale
reset session
$Data <<EOD
2020-01 12
2020-06 6
2021-01 4
2021-06 8
2022-01 6
2022-06 10
EOD
t0 = time(0) # now, i.e. seconds from Jan, 1st 1970 00:00:00
TwoYearsInSec = 3600*24*365*2 # two years in seconds
myTimeFmt = "%Y-%m"
set format x "%Y\n%m" timedate
set style fill transparent solid 0.25 noborder
set xrange [t0-TwoYearsInSec:t0]
set multiplot layout 2,1
set title "undesired y-autoscaling to 0 with filledcurves"
plot $Data u (timecolumn(1,myTimeFmt)):2 w filledcurves above x1 lc rgb 0xff0000 not
set title "workaround to scale to y-minimum"
stats $Data u 2 nooutput
set yrange[STATS_min:]
replot
unset multiplot
### end of script
Result: (created with gnuplot 5.4.0)

Resources