I would like to shade a specific region in a polar plot using GNUPlot. This region is bounded by limits in R (r1, r2) and Theta (t1, t2), so the final shape is an annulus segment defined by only 4 points in polar space.
In a Cartesian plot, it is quite easy to draw a rectangle, either by (set object rect) or filledcurve of a closed shape with 4 vertices. However, a filledcurve shape specified by 4 points in a polar plot still results in a quadrilateral (lines with constant R should be circular arcs, not straight lines).
Is there a simple or straightforward way to plot this shape in polar coordinates? I've tried using two arcs and then filling the space between them, but this has not been working correctly so far and I'm not sure if there's a better way to go about this.
Unfortunately, that is not too easy. You can set a circle object for which you specify the begin and end angles. To cut out the center part you must draw a second white circle above:
set xrange [-1:1]
set yrange [-1:1]
set size ratio -1
r1 = 0.5
r2 = 1
theta1 = -30
theta2 = 60
set angles degrees
set style fill solid noborder
set object circle at first 0,0 front size r2 arc [theta1:theta2] fillcolor lt 1
set object circle at first 0,0 front size r1 fillcolor rgb 'white'
plot -10 notitle
Here it is essential, that x and y axis have the same unit (set size ratio -1), because a circle object is defined in units of the first x-axis and does not respect the y-axis at all. If you don't have anything else to plot, you must use a plot command which plots something outside of the defined ranges. Without a plot the objects aren't drawn.
The result with 4.6.5 is:
With the upcoming 5.0 version you can use pseudo-data (with the special file name +) together with the filledcurves plotting style:
r1 = 0.5
r2 = 1.0
theta1 = 20
theta2 = 135
set polar
set angles degrees
set size ratio -1
unset raxis
unset rtics
set trange [theta1:theta2]
set style fill solid noborder
plot '+' using 1:(r1):(r2) with filledcurves notitle
Related
I want to draw an ellipse with gnuplot. It should be slightly tilted, hence I use the angle option.
But the angle messes with the size of the ellipse. Am I getting something wrong in the docu?
See the following example:
set output "test.pdf"
set obj ellipse center 5,0.5 size 4,0.2 angle 20
set xrange [0:10]
plot sin(x)
The added two png's show my results. I use version 5.2.8.
If you want the proportions of the ellipse to remain constant after rotation you must give the major and minor diameters in the same units, e.g. "units xx" or "units yy". Here I define the ellipse in terms of a 4:1 ratio of major:minor axis using x coordinates.
set obj 1 ellipse center 5,0.5 size 4,1 fs empty bo lc "blue" angle 0 units xx
set obj 2 ellipse center 5,0.5 size 4,1 fs empty bo lc "red" angle 20 units xx
set obj 3 ellipse center 5,0.5 size 4,1 fs empty bo lc "green" angle 40 units xx
set xrange [0:10]
plot sin(x)
Edit: Ethan's solution is certainly the way to go.
Just keep in mind, if you don't have set size ratio -1, a line, e.g. like plot x will not appear in a 45° degree angle to the x-axis.
Probably, the simplest solution would be to set size ratio -1 to have the same scale for x and y-axis. If you need different scale there should be a different solution.
Code:
### draw tilted ellipse with same proportions
reset session
set size ratio -1
set obj 1 ellipse center 5,0.5 size 4,0.2 angle 0 fc "red"
set obj 2 ellipse center 5,0.5 size 4,0.2 angle 20 fc "green"
set obj 3 ellipse center 5,0.5 size 4,0.2 angle 45 fc "blue"
set obj 5 ellipse center 5,0.5 size 4,0.2 angle 90 fc "magenta"
set xrange [0:10]
set yrange [-3:3]
plot sin(x)
### end of code
Result:
If the output to a dummy file is allowed, how about the following solution.
set terminal pdf size 10cm,10cm
set xrange [0:10]
# dummy plotting
set output "dummy.pdf"
plot sin(x)
factor = real(GPVAL_X_MAX - GPVAL_X_MIN)/real(GPVAL_Y_MAX-GPVAL_Y_MIN) \
* real(GPVAL_TERM_YMAX - GPVAL_TERM_YMIN)/real(GPVAL_TERM_XMAX - GPVAL_TERM_XMIN)
# real plotting
set output "test.pdf"
set obj ellipse center 5,0.5 size 4,factor*0.2 angle 20 unit xx
replot
In this script, the ratio of visible unit length between x and y axis is calculated using from variable GPVAL_* determined by the dummy plotting. Multipling it to vertical axis of the ellipse and using 'unit xx' as same as Ethan's answer, you may get the figure that you want.
If you are on UNIX(-like) system, replace 'set output "dummy.pdf"' as,
set output "/dev/null"
I haven't been able to find any example of what I'm trying to do in GNUplot from raking docs and demos.
Essentially I want to plot the Blue, Green, and Red lines I manually drew on this output (for demonstration) at the 10/50/90% marks.
EDIT: For clarity, I'm looking to determine where the distribution lines hit the cumulative distribution at 0.1/0.5/0.9 to know which co-ordinates to draw the lines at. Thanks!
set terminal png size 1600,800 font "Consolas" 16
set output "test.png"
set title "PDF and CDF - 1000 Simulations"
set grid y2
set ylabel "Date Probability"
set y2range [0:1.00]
set y2tics 0.1
set y2label "Cumulative Distribution"
set xtics rotate by 90 offset 0,-5
set bmargin 6
plot "data.txt" using 1:3:xtic(2) notitle with boxes axes x1y1,'' using 1:4 notitle with linespoints axes x1y2
Depending on the number of points in your cumulative data curve you might need interpolation. The following example is chosen such that no original data point will be at your levels 10%, 50%, 90%. If your data is not steadily increasing, it will take the last value which matches your level(s).
The procedure is as follows:
plot your data to a dummy table.
check when Level is between to successive y-values (y0,y1).
remember the interpolated x-value in xp.
draw arrows from the borders of the graph to the point (xp,Level) (or instead use the partly outside rectangle "trick" from #Ethan).
Code:
### linear interpolation of data
reset session
set colorsequence classic
set key left
# create some dummy data
set sample 10
set table $Data
plot [-2:2] '+' u 1:(norm(x)) with table
unset table
Interpolate(yi) = x0 + (x1-x0)*(yi-y0)/(y1-y0)
Levels = "0.1 0.5 0.9"
do for [i=1:words(Levels)] {
Level = word(Levels,i)
x0 = x1 = y0 = y1 = NaN
set table $Dummy
plot $Data u (x0=x1,x1=$1,y0=y1,y1=$2, (y0<=Level && Level<=y1)? (xp=Interpolate(Level)):NaN ): (Level) w table
unset table
set arrow i*2 from xp, graph 0 to xp,Level nohead lc i
set arrow i*2+1 from xp,Level to graph 1,Level nohead lc i
}
plot $Data u 1:2 w lp pt 7 lc 0 t "Original data"
### end code
Result:
It is not clear if you are asking how to find the x-coordinates at which your cumulative distribution line hits 0.1, 0.5, 0.9 (hard to do so I will leave that for now) or asking how to draw the lines once you know those x values. The latter part is easy. Think of the lines you want to draw as the unclipped portion of a rectangle that extends off the plot to the lower right:
set object 1 rectangle from x1, 0.1 to graph 2, -2 fillstyle empty border lc "blue"
set object 2 rectangle from x2, 0.1 to graph 2, -2 fillstyle empty border lc "green"
set object 3 rectangle from x3, 0.1 to graph 2, -2 fillstyle empty border lc "red"
plot ...
How do I plot a white spherical surface? In three dimensions, radius should be 1, center at the origin.
I have scattered point data on the sphere. It is hard to look at it, since the points from the opposite end of the sphere are just as visible. Therefore I would like to create a white spherical "background" on top of which the data is clearly visible.
Restricting the range of one coordinate axis to [0:1] is cumbersome since it cuts off half the points at which I also want to look.
Tanks!
Here is an example, borrowed from the gnuplot demo page. For a white sphere, replace yellow with white:
set parametric
set isosamples 50,50
set hidden
R = 1. # radius of sphere
set urange [-pi/2:pi/2]
set vrange [0:2*pi]
splot R*cos(u)*cos(v),R*cos(u)*sin(v),R*sin(u) w l lc rgb "yellow", \
"-" w p
1 0 0
-1 0 0
e
You can see that only one of the two data points is visible, while the other is hidden behind the sphere.
I have 4D data X,Y,Z plus a field. I would like to do a 4d plot of the field restricted to a sphere. I already use splot w pm3d to have the color bar on the sphere indexed by my field, but I think it would be more readable if I could add 3d contour lines.
I would like something like last example of "function plot" (protein orientation) at http://www.originlab.com/index.aspx?go=Products/Origin/Graphing
Is it even possible in gnuplot ? If so, how to do it ?
Gnuplot cannot generate 4d contour plots.
But if I understand correctly, you have a special case, you do not really have 4d data. The z coordinate depends on x and y such that the point is on a sphere. Maybe this can be used to get the contours.
I assume the datafile contains datapoints for the complete sphere, arranged circle by circle from bottom to top of the sphere, each circle in a separate block.
I have tried this:
Separate the points on the upper half from points of the lower half of the sphere, we need this separation for the sign of z.
Plot the contours of the two halfs in two datafiles contour_l.dat and contour_u.dat. This will only plot the x and y coordinates.
Merge the original datafile and the two contour datafiles into one plot. Pythagoras could help reconstructing the z coordinates for the contour datafiles.
This is the script:
set pm3d depthorder interpolate 5,5
set hidden3d front
unset surface
set contour surface
set zrange [0:1.1]
set table "contour_u.dat"
splot "sh.dat" using 1:2:4 w l
unset table
set zrange [-1.1:0]
set table "contour_l.dat"
splot "sh.dat" using 1:2:4 w l
unset table
set surface
unset contour
set xrange [-1.1:1.1]
set yrange [-1.1:1.1]
set zrange [-1.1:1.1]
set xyplane relative 0.0
set terminal pngcairo size 640,640
set output "c.png"
unset key
splot "sh.dat" using 1:2:3:4 w pm3d, \
"contour_u.dat" using 1:2:( sqrt(1.0-($1*$1+$2*$2))):3 w l lc rgb "black",\
"contour_l.dat" using 1:2:(-sqrt(1.0-($1*$1+$2*$2))):3 w l lc rgb "black"
You did not post data, so I have taken one of the spherical harmonics. With Gnuplot 4.6, I get the following result:
As you can see, it is still not perfect. The contour at x=0 should be investigated, and if I remove the "sh.dat" w pm3d line, the image gets very strange.
But at least this approach might be a starting point, one could try to manually play with the contour line datafiles.
I'd like to take a plot that I have done as a surface in 3D using cartesian coordinates and view it as a heatmap in 2D in POLAR coordinates. The reason for this is I am obtaining data on a system in that coordinate system. I've only found some related examples, but am getting stuck trying to get it to work with my data. I am currently using the matrix format, and I can reformat the data set if this would help get the chart working.
The data is SPL measurements taken on a loudspeaker. The microphone is positioned at a fixed distance away (e.g. fixed radius) and measurements are made at every 10 degrees around the entire loudspeaker horizontally. The SPL measurement is obtained as a function of frequency, 20Hz to 20kHz.
I would like to use gnuplot to create a 2D polar plot. Frequency would be plotted as the radius, the angle around the loudspeaker would be the angle, and the "height" would be the SPL level. This should generate a surface, however, I would like to create a heat map pm3d and then view that from above (e.g. view 0,0) or as a 2D plot. I also need to add contour lines that show intervals of SPL and superimpose that on the heat map.
I found something similar for cartesian coordinates here:
http://gnuplot-tricks.blogspot.com/2009/07/maps-contour-plots-with-labels.html
When I tried this approach using polar coordinates for the final 2D plot, I got an error message that the "with image" option is not supported for polar plots. Can someone try this or confirm this?
I have been able to plot my polar data as a heatmap+contour lines in 3D using splot and view from directly above (set view 0.0). If I first convert my existing polar coordinate data into cartesian coordinates I will probably get something like what is shown in this web page:
how to create a 3d polar graph with gnuplot
I could view this from above, too, but I would like to add in the polar grid and have labels for the angle and radius. Would I have to do this manually or could I use multiplot to overlay a 2D grid and the 3D plot viewed from 0.0?
I am not sure how to approach this. Any advice about what direction to take would be appreciated.
-Charlie
The image plotting works only for equally distributed rectangular grids, just like any bitmap image is arranged. Otherwise you must use splot with pm3d.
The set grid polar works only for 2D, so you must use multiplot to overlay your heatmap with the polar grid. Here a, quite lengthy, example to show you how it might work:
reset
set terminal pngcairo size 800,800
set output '3d-polar.png'
set lmargin at screen 0.05
set rmargin at screen 0.85
set bmargin at screen 0.1
set tmargin at screen 0.9
set pm3d map
unset key
set multiplot
# plot the heatmap
set parametric
set isosamples 500
unset border
unset xtics
unset ytics
set angles degree
r = 6
set urange[0:r] # radius
set vrange[0:360] # angle
set xrange[-r:r]
set yrange[-r:r]
set colorbox user origin 0.9,0.1 size 0.03,0.8
splot u*cos(v), u*sin(v), (cos(v)*besj0(2*u))**2
# now plot the polar grid only
set style line 11 lc rgb 'white' lw 2
set grid polar ls 11
set polar
set rrange[0:r]
unset raxis
set rtics format '' scale 0
unset parametric
set for [i=0:330:30] label at first (r+0.35)*cos(i), first (r+0.35)*sin(i)\
center sprintf('%d', i)
plot NaN w l
unset multiplot
The result is:
And now some details about some tricks:
In order to get a square size, you can't use set size ratio 1, because the margins differ for the 2D and 3D plots, even if you would specify some absolute margins. Therefore, I set a square canvas size (terminal option size 800,800), and set appropriate absolute margins.
You cannot unset rtics because then the grid would disappear.
The grid labels must be set manually.
The colorbox was also set manually because otherwise it would have overlapped with the 0 label.
Plotting NaN does only plot the grid
I took the command file that Christoph posted and played around a bit and managed to get it working for my needs EXCEPT for the labels, which I am still having problems with. The plot is looking like this:
In order to get this result, I had to recalculate the coordinates of my measurement data, changing them from a polar coordinate system (frequency=r, theta=off-axis angle, z=SPL) to a Cartesian one (x,y,z). At the same time I modified the way that the polar grid was presented. Although I wanted a logarithmic polar r-axis, Cartesian coordinates must be used for the pm3d data, so I took the log of the r data before using it to calculate x,y,z coordinates. Also, I knew that the minimum value of the polar log r-axis scale would be 10, and this seems to be set equal to the center of the plot when a logscale polar grid is used. In order for the grid and the surface data to line up properly, I subtracted log10(10) from the r values before using them to calculate the Cartesian coordinates used for the pm3d map. So in total, the equations I used were
r = log10( frequency ) - 1
x = r cos( theta )
y = r sin( theta )
z = SPL
I then used the following command file to plot the data:
reset
set terminal pngcairo size 800,800
set output '3d-polar.png'
set lmargin at screen 0.05
set rmargin at screen 0.85
set bmargin at screen 0.1
set tmargin at screen 0.9
set pm3d map interpolate 20,20
unset key
set multiplot
# plot the heatmap
set cntrparam levels increment 3,-3, -24
set contour surface
set palette rgb 33,13,10 #rainbow (blue-green-yellow-red)
set cbrange [-18:0]
unset border
unset xtics
unset ytics
set angles degree
r = 3.31
set xrange[-r:r]
set yrange[-r:r]
set colorbox user origin 0.9,0.1 size 0.03,0.8
splot 'new_test.dat' using 1:2:3
# now plot the polar grid only
set style line 11 lc rgb 'black' lw 1 lt 0
set grid polar ls 11
set polar
set logscale r 10
set rrange[10:20000]
unset raxis
set rtics format '' scale 0
set rtics (10,20,100,200,1000,2000,10000,20000)
#unset parametric
#set for [i=0:330:30] label at first (r+0.35)*cos(i), first (r+0.35)*sin(i) \
#center sprintf('%d', i)
plot NaN w l
unset multiplot
unset output
The data used to generate the plot only span +/- 30 degrees, so only that sector fills the polar plot. Additional angular data can be used to fill out the plot.
If I can get some help with labels, I can call this "done". I still need to get the labels of angle working. Input on how to label the polar r-axis tics that would be very welcome, too.