Gnuplot erases circles when zoomed in - plot

I am trying to plot a file of data along with 2 circles with gnuplot. The data file is here and the circle file is here. The circles are quite big compared to the dataset, and when I plot it on a large scale everything works fine. But when I try to zoom in, the circles disappear. Here are the gnuplot commands I use (v5.4.2):
plot 'data.txt' us (log($2)):(log($3)) w lp, 'circ.txt' us 1:2:3 w circles
Here is the result (looks ok):
Now if I try to zoom in a little (still ok):
set xrange [*:55]
replot
Trying to zoom in more (circles disappear!)
set xrange [*:8]
replot
Is this a bug in gnuplot, or is there a way to fix this and visualize the circles on a zoomed in view?

As #Ethan already explained, with the plotting style with circles if the center of a circle is not in the graph range anymore, the circle will not be plotted.
You can workaround this if you plot the circles yourself. Then you can zoom in as long as a datapoint of the circumference is still in the graph. For large zoom-in you could increase the number of samples, e.g. set samples 500.
However, in order to have the circle visually appear as a circle (not as an ellipse) you have to set size ratio -1 which will change the graph size.
Code:
### plot circles which "allow" zoom-in
reset session
set size ratio -1
$Circles <<EOD
50 0 50
100 0 100
220 0 220
EOD
CircX(x0,y0,r,t) = x0+r*cos(2*pi*t)
CircY(x0,y0,r,t) = y0+r*sin(2*pi*t)
x0(n) = word($Circles[n],1)
y0(n) = word($Circles[n],2)
r(n) = word($Circles[n],3)
set key noautotitle
set samples 100
set yrange[-100:100]
plot for [i=1:|$Circles|] [0:1] '+' u \
(CircX(x0(i),y0(i),r(i),$1)):(CircY(x0(i),y0(i),r(i),$1)) w l
### end of code
Result: (original plot)
(zoomed-in):

Gnuplot does not draw points that are out of range. You can think of a circle as a point defined by its center and radius. As soon as the center goes out of range, in this case xmin < xmax < center, the circle is no longer drawn.

Another solution using 'set object circle'
There is a way to display all circles defined in 'circ.txt' as objects using set object circle.
set table $DATA
plot "circ.txt" using 1:2:3 with table
unset table
do for [k=1:|$DATA|] {
line = $DATA[k]
xpos = word(line, 1)
ypos = word(line, 2)
r = word(line, 3)
set object circle at xpos, ypos radius r fill empty border lc black
}
set xrange [*:30]
set yrange [*:16]
plot "data.txt" using (log($2)):(log($3)) with lp

Related

gnuplot: how to set the size of the points according to the grid

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`.

Gnuplot polar plot with top theta clockwise keeps the inner radial grid origin at 0 angle

I have a simple time/value dataset like this:
1 20
2 21
# ...
15 36
Where the first column is a time value, and other columns store some measurements. I wanted to plot these values in a "clock plot", that is a polar plot (or a radar chart) where angles correspond to time instants, and the radius keeps the value of the measurement.
Since I would like to reproduce a clock, I want my first measurement to start in a vertical position, and I can do set theta top clockwise. Having 15 seconds in my dataset, I can split the 360 degrees in angles of 24 degrees (one for each second) set grid polar 24.
However, the grid values start from the 0 degree angle (and not, as expected, from the top angle of 90 degrees). This bothers me because my measurements have an offset with respect to the grid. (Check the picture attached).
How can I solve this problem? Can I rotate the grid to start counting at 90 degrees? Thank you a lot in advance.
As a workaround you could draw your grid lines manually. Not very nice but you visually get the desired result.
Code:
### polar grids aligned to north
reset session
set size square
set angle degrees
set polar
set theta clockwise top
unset border
set border polar
unset xtics
unset ytics
set ttics 24 format ""
set rtics 10
set grid rtics
unset key
set rrange[0:40]
# manually draw grid lines
do for [i=0:360:24] {
set arrow i+1 from 0,0 to polar i,40 lw 0.5 dt 3 lc rgb "black" nohead
}
set samples 16
plot t/9 w lp pt 7 lc rgb "red"
### end of code
Result:

Gnuplot - Weighted point size

I have an unsorted data set of two columns with most of the points aligning diagonally along y=x, however some points misalign.
I would like to show that most of the points actually do align along the function, however just pointplotting would just overlap the over-represented points to one. The viewer would then get the impression that the data points are actually scattered randomly because there is no weight to the occurrence count.
Is there a way to implement a weight to the points that occur more than once - maybe through point size? Couldnt find anything on this topic.
Thanks a lot!
You don't show data so I assumed something from your description. As #Christoph already mentioned you could use jitter or transparency to indicate that there are many more datapoints more or less at the same location. However, transparency is limited to 256 values (actually, 255 because fully transparent you won't see). So, in extreme case, if you have more than 255 points on top of each other you won't see a difference to 255 points on top of each other.
Basically, you're asking for displaying the density of points. This reminds me to this question: How to plot (x,y,z) points showing their density
In the example below a "pseudo" 2D-histogram is created. I'm not aware of 2D-histograms in gnuplot, so you have to do it as 1D-histogram mapping it onto 2D. You divide the plot into fields and count the occurrence of point in each field. This number you use either for setting the point variable color via palette or for variable pointsize.
The code example will generate 5 ways to plot the data:
solid points
empty points
transparent points
colored points
sized points (your question)
I leave it up to you to judge which way is suitable. Certainly it will depend pretty much on the data and your special case.
Code:
### different ways to show density of datapoints
reset session
# create some random test data
set print $Data
do for [i=1:1000] {
x=invnorm(rand(0))
y=x+invnorm(rand(0))*0.05
print sprintf("%g %g",x,y)
}
do for [i=1:1000] {
x=rand(0)*8-4
y=rand(0)*8-4
print sprintf("%g %g",x,y)
}
set print
Xmin=-4.0; Xmax=4.0
Ymin=-4.0; Ymax=4.0
BinXSize = 0.1
BinYSize = 0.1
BinXCount = int((Xmax-Xmin)/BinXSize)+1
BinYCount = int((Ymax-Ymin)/BinYSize)+1
BinXNo(x) = floor((x-Xmin)/BinXSize)
BinYNo(y) = floor((y-Ymin)/BinYSize)
myBinNo(x,y) = (_tmp =BinYNo(y)*BinXCount + BinXNo(x), \
_tmp < 0 || _tmp > BinXCount*BinYCount-1 ? NaN : int(_tmp+1))
# get data into 1D histogram
set table $Bins
plot [*:*][*:*] $Data u (myBinNo($1,$2)):(1) smooth freq
unset table
# initialize array all values to 0
array BinArr[BinXCount*BinYCount]
do for [i=1:BinXCount*BinYCount] { BinArr[i] = 0 }
# get histogram values into array
set table $Dummy
plot myMax=NaN $Bins u ($2<myMax?0:myMax=$2, BinArr[int($1)] = int($2)) w table
unset table
myBinValue(x,y) = (_tmp2 = myBinNo(x,y), _tmp2>0 && _tmp2<=BinXCount*BinYCount ? BinArr[_tmp2] : NaN)
# point size settings
myPtSizeMin = 0.0
myPtSizeMax = 2.0
myPtSize(x,y) = myBinValue(x,y)*(myPtSizeMax-myPtSizeMin)/myMax*myPtSizeMax + myPtSizeMin
set size ratio -1
set xrange [Xmin:Xmax]
set yrange [Ymin:Ymax]
set key top center out opaque box
set multiplot layout 2,3
plot $Data u 1:2 w p pt 7 lc "red" ti "solid points"
plot $Data u 1:2 w p pt 6 lc "red" ti "empty points"
plot $Data u 1:2 w p pt 7 lc "0xeeff0000" ti "transparent points"
set multiplot next
plot $Data u 1:2:(myBinValue($1,$2)) w p pt 7 ps 0.5 palette z ti "colored points"
plot $Data u 1:2:(myPtSize($1,$2)) w p pt 7 ps var lc "web-blue" ti "sized points"
unset multiplot
### end of code
Result:

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

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.

drawing a circle around many points with different radius

I can draw a circle around a given point (x,y) with a command like flowing (here for example point is at (X=5,Y=7) and the circle have a radius R=2.73):
set object 1 circle at 5,7 size first 2.73 fc rgb "navy"
Now, if I have many points (in a txt file where each line is "x y") and I want to draw a circle around each point with different specified radius. Should I repeat the command "set object i circle at Xi,Yi size first Ri fc rgb "navy"" for each point i ?!
It looks like you may want to use the with circles option. If you have a data file with three columns (x y radius), the following command will plot circles with radii from the file at each point:
plot 'datafile' u 1:2:3 with circles
http://gnuplot.sourceforge.net/demo/circles.html
You can create a loop in gnuplot for multiple circles.
do for[k=1:20]{
set object k circle front at k*3,0 size 1 fillcolor rgb "black" lw 1
}
This will create 20 circles at x points (3,6,9...) of radius 1. Please keep in mind to set the object count with the loop variable too ("object k").

Resources