I'm using software that uses Gnuplot language to plot some data, but I've never used Gnuplot before.
So I was trying to place labels and rectangles in a way that created a nice and readable text, which wasn't bad (as you can see with the number 182 in the image below), but I wanted to learn how to rotate the rectangle and label so that they line up with the white line.
(I can't post images, but it's like that in this link Right now, it looks like:
)
I've already learned to rotate the label (as you can see the number 171), but apparently, it doesn't work the same way with the object.
# setting the label and rotating it works
set label 1 "TEXT" at 10, 20 center rotate by 30 front
# setting the object works
set object 1 rect center 10,20 size 1,2 front
# But this doesn't work
set object 1 rect center 10,20 size 1,2 rotate by 30 front
# this line return the error message "Unrecognized or duplicate option"
The important part of my code that sets a rectangle and a label is here below:
x1 = 2979
x2 = 3140
y1 = -225
y2 = -168
ang = 19.9275
h = 30
w = 60
# set object 1 rect center (x1+x2)/2,(y1+y2)/2 size w,h rotate by ang front fillcolor "black" fillstyle transparent solid 0.5 noborder
set object 1 rect center (x1+x2)/2,(y1+y2)/2 size w,h front fillcolor "black" fillstyle transparent solid 0.5 noborder
set label 1 sprintf("{/:Bold %1.0f}",sqrt((x2-x1)**2 + (y2-y1)**2)) at (x1+x2)/2,(y1+y2)/2 center rotate by ang front tc rgb "white"
set arrow from x1,y1 to x2,y2 heads size 10,90 front linecolor rgb "white" linewidth 2.5 dashtype 6
So how do I rotate the rect object? And if it's not possible, is there another way to do this (other than having to manually set a polygon)?
Check the following example and help labels.
You can create a datablock and add your labels and plot them rotated and boxed together with your map.
Edit: ...forgot the semitransparent boxes. You need to play with the alpha channel, i.e. 0xAARRGGBB.
Code:
### boxed semitransparent text labels
reset session
# create some background test data
f(x,y)=(sin(1.3*x)*cos(.9*y)+cos(.8*x)*sin(1.9*y)+cos(y*.2*x))*3+15
set samples 51
set isosamples 51
set table $Data
splot [0:600][0:600] f(x/60.,y/60.)
unset table
$myLabels <<EOD
# text x y a
171 300 300 45
182 100 500 90
197 500 400 60
333 400 100 -30
EOD
set style fill transparent solid 1.0 noborder
set style textbox opaque fc rgb 0xaaffffff noborder
set angle degrees
set key noautotitle
plot $Data u 1:2:3 with image palette,\
$myLabels u 2:3:1:4 w labels rotate var boxed font ",24"
### end of code
Result:
Related
I need help with my polar plot shown below.
The plot was generated using the same code as in GNUPlot - Plotting a data set in polar form (r, θ, T(r,θ)) to a contour/heat map.
The code plot the whole of quadrant 1, but I only want the plot from 0 to 60 degrees, for radius up to 3000.
Can anyone help to suggest which part of the code that I should change?
Or what software that I can use to clean the unnecessary areas?
Thank you in advance.
Apparently, you can limit the polar graph to a quadrant.
However, I haven't found out how to get an other section than a quadrant.
So, maybe you have to draw it "manually"?
Check the following example as starting point.
Script:
### show only a section of a polar graph
reset session
set angle degrees
set size ratio 1
set margins 0,0,0,0
set origin 0.05,0.1
set size 0.9,0.9
set border 1
unset ytics
set xtics nomirror
# create some test data
set print $Data
do for [i=1:100] { print sprintf("%g %g",0.6+0.3*cos(7.2*i),i*0.6) }
set print
# draw polar graph "manually"
rmax = 1
rstep = 0.2
rcount = int(real(rmax)/rstep)+1
set xrange [0:rmax]
set yrange [0:rmax]
set for [r=1:rcount] obj 1+r circ at 0,0 size r*rstep arc [0:60] fc rgb r<rcount?0x777777:0x000000 dt r==rcount?1:3
amax = 60
astep = 10
acount = amax/astep
astepMin = 1
set for [a=0:acount] arrow 1+a \
from 0,0 angle a*astep length rmax lc rgb a<acount?0x777777:0x000000 dt a==acount?1:3 nohead
set for [a=0:amax:astepMin] arrow 1000+a \
from rmax*cos(a), rmax*sin(a) angle 180+a length rmax/100. lc "black" nohead
roff = 1.03 # factor for label offset
set for [a=0:amax:astep] label 1+a at cos(a)*rmax*roff, sin(a)*rmax*roff sprintf("%g°",a) center
# conversion polar to cartesian
xPtC(colR,colA) = column(colR)*cos(column(colA))
yPtC(colR,colA) = column(colR)*sin(column(colA))
plot $Data u (xPtC(1,2)):(yPtC(1,2)) w l lw 2 lc "red" ti "Data"
### end of script
Result:
I use the splot commadn to produce a heat map of the earth. The x- and y-values represent lattitude and longitude of a specific point on the Earth's surface, while the related z-value is the outcome of an analysis. The zrange is between 0 and 60. However, for some locations on Earth, there is no result available (which is correct) and z is set to 9999 for these cases.
I'm using the following script to produce the heat map:
set terminal png large size 1600,\
1200 font arial 24 crop
set output "map.png"
set palette model RGB defined (0 "dark-green",1 "forest-green",2 "green",3 "light-green",4 "dark-yellow",5 "yellow",6 "red",7 "dark-red")
set xrange[-180.00: 180.00]
set yrange[ -90.00: 90.00]
set zrange[ *: 60]
set grid
set pm3d map
set xlabel "Longitude [deg]"
set ylabel "Latitude [deg]"
unset key
set cblabel "Time [h]"
splot "output\\map.dat" u 5:6:8,\
"input\\world.dat" u 1:2:( .00) w l lw 1 lt -1
It works fine but because of the limitation in zrange, regions with z > 60 are shown in white.
I want to have something like a condition which enables that all 9999 z-values are shown in a specific colour like purple with a declaration like "no result" in the legend.
Any idea how to achieve this?
Thanks in advance,
Florian
Not exactly sure how to modify the style for the selected points, but you can use the ternary operator not to draw them at all. Something like:
splot "output\\map.dat" u 5:6:(($8<=60)?($8):(1/0))
You basically want to have 3 "ranges" of colors:
0 to 60 your defined palette colors
>60 "out of range" color
=9999 "no data" color
Not sure if splot ... w pm3d will allow an easy "independent" setting for z and color.
Furthermore, if you have NxN datapoints you will get (N-1)x(N-1) quadrangles and the color is determined by the z-values of the involved vertices (check help corners2color) and http://gnuplot.sourceforge.net/demo_5.5/pm3d.html (the very last graph). Maybe there is an easy way which I am not aware of.
That's why I would perfer the plotting style with boxxyerror (check help boxxyerror), maybe this is not the intended way, but it is rather flexible. If you are running gnuplt 5.4 you have the function palette() (check help palette).
I would take for missing data (backgroundcolor here:white) and for data out of range "grey", but you can easily change it. You can skip the random data generation part and in the plot command replace $Data with your filename and the corresponding columns. As well, replace 180./N and 90./N with the width (delta longitude) and height (delta latitude) of one data element.
Script: (requires gnuplot>=5.4)
### define separate color for missing values
reset session
set xrange[-180:180]
set yrange[-90:90]
# create some "random" test data
N = 90
set samples N
set isosamples N
set table $Data
c = 0.05
x0 = 70 # (rand(0)*360-180) # or random
y0 = -50 # (rand(0)*180-90) #
size0 = 2
x1 = -150 # (rand(0)*360-180) # or random
y1 = -20 # (rand(0)*180-90) #
size1 = 1
holeP0(x,y) = (1-erf((x-x0)*c/size0)**2) * (1-erf((y-y0)*c/size0)**2)
holeP1(x,y) = (1-erf((x-x1)*c/size1)**2) * (1-erf((y-y1)*c/size1)**2)
f(x,y) = rand(0)<holeP0(x,y) || rand(0)<holeP1(x,y) ? 9999 : (sin(1.3*x*c)*cos(.9*y*c)+cos(.8*x*c)*sin(1.9*y*c)+cos(y*.2*x*c**2))*11.5+33
splot f(x,y)
unset table
set palette model RGB defined (0 "dark-green",1 "forest-green",2 "green",3 "light-green",4 "dark-yellow",5 "yellow",6 "red",7 "dark-red")
myZmin = 0
myZmax = 60
myColorNoData = 0xffffff
myColorOutOfRange = 0x999999
set rmargin screen 0.8
set colorbox user origin screen 0.85,graph 0.2 size graph 0.05,graph 0.8
set cblabel "Amplitude"
set cbrange [myZmin:myZmax]
set tics out
set style fill solid 1.0 border
set key noautotitle at graph 1.27, graph 0.15 reverse Left samplen 2
myColor(col) = (z=column(col), z==9999 ? myColorNoData : z>myZmax ? myColorOutOfRange : palette(z))
plot $Data u 1:2:(180./N):(90./N):(myColor(3)) w boxxy lc rgb var, \
"world.dat" u 1:2:(0) w l lc "black", \
NaN w l lc palette, \
keyentry w boxes lc rgb 0x000000 fill empty ti "no data", \
keyentry w boxes lc rgb myColorOutOfRange ti "\ndata out\nof range"
### end of script
Result:
I am plotting a curve in gnuplot. I would like to call out a couple of specific points on the curve.
This is what the curve looks like:
Shown below is what I'm hoping to get (but I had to draw in the points and lines to the axes with GIMP). I'd like to call out two specific points on the curve. The first, where Vgs (x-axis) equals -0.5. The second, where Id (y-axis) equals 2.5. If possible, I'd like to also have a dashed line over to the axis to aid in reading the values.
I found a reference that said to try plotting a circle using set object circle and the coordinates, but I must not have it right, because it complains about extra parameters. Browsing the manual is so far unsuccessful. I'm not even sure what term to search for.
Is there an easy way to call out a couple of points on the curve that I've drawn and have it look similar to the screenshot below?
Here are the commands I used to plot the curve:
set xlabel "Vgs (Volts)"
set ylabel "Id (mA)"
set grid
Idss=5
Vgs_off=-1
Id(Vgs) = Idss * (1 - (Vgs / Vgs_off) ) ** 2
plot [Vgs=Vgs_off:0][0:Idss + 1] Id(Vgs)
It's the characteristic curve for a Fairchild J112 JFET if anyone is curious.
Edited to replace the -1 in the denominator with Vgs_off to avoid confusion. This is a value from the JFET's datasheet and just happened to be -1 in this particular case.
ADDENDUM:
After incorporating the pieces from the answer given by #Eldrad, I came up with this much improved representation of the JFET characteristic curve:
Here are the commands used to create it:
# JFET parameters from data sheet
Vgs_off=-1
Idss=5
# JFET characteristic curve
Id(Vgs) = Idss * (1 - (Vgs / Vgs_off) ) ** 2
# Graph properties
set title "I_D vs V_{GS}"
set xlabel "V_{GS} (Volts)"
set ylabel "I_D (mA)"
set grid
set key off
set monochrome
# Plot the characteristic curve
plot [Vgs=Vgs_off:0][0:Idss] Id(Vgs)
# Plot interesting points
set object circle center 0.5 * Vgs_off, Id(0.5 * Vgs_off) radius char 0.33 fillstyle solid fillcolor rgb 'black'
set object circle center 0.293 * Vgs_off, Id(0.293 * Vgs_off) radius char 0.33 fillstyle solid fillcolor rgb 'black'
# Mark interesting points with dashed lines to where they intersect the x and y axes.
set arrow from first 0.5 * Vgs_off, graph 0 to first 0.5 * Vgs_off, graph 1 dashtype "-" nohead
set arrow from graph 0, first Id(0.5 * Vgs_off) to graph 1, first Id(0.5 * Vgs_off) dashtype "-" nohead
set arrow from 0.293 * Vgs_off, graph 0 to 0.293 * Vgs_off, graph 1 dashtype "_" nohead
set arrow from graph 0, first Id(0.293 * Vgs_off) to graph 1, first Id(0.293 * Vgs_off) dashtype "_" nohead
# Label the lines
set label "I_{DSS}" at graph 1.01, graph 1
set label "I_{DSS} / 2" at graph 1.01, graph 0.50
set label "I_{DSS} / 4" at graph 1.01, graph 0.25
set rmargin at screen 0.9
# Update the graph
replot
Getting specific values of a function is straightforward if the function y=f(x) and its inverse x=f(y) have an analytical expression, like it is in your case.
A couple of remarks about your function definition: You should use x as the variable, because this is the default gnuplot is looking for, it also makes the plot command shorter. Also, division by -1 is the same as putting a minus in front, so an easier function definition, including the inverse would be:
Idss = 5.0
Id (x) = Idss * (1 + x)**2
Id_inv (x) = sqrt(x/Idss) -1
Now the dashed lines can be drawn as arrows (check set arrow):
set arrow 11 from first -0.5, graph 0 to first -0.5, first Id(-0.5) lc "red" lw 2 dt 2 nohead
set arrow 12 from first -0.5, Id(-0.5) to graph 0, first Id(-0.5) lc "red" lw 2 dt 2 nohead
set arrow 21 from first Id_inv(2.5), graph 0 to Id_inv(2.5), 2.5 lc "green" lw 2 dt 2 nohead
set arrow 22 from first Id_inv(2.5), 2.5 to graph 0, first 2.5 lc "green" lw 2 dt 2 nohead
I would recommend drawing the horizontal lines to the axis where the tics are actually printed (i.e. to the left side). The reference points are the x- or y-values of the function and the border of the graphs, see the manual about coordinates for a detailed explanation.
You could add specific tic marks at those points:
set xtics add (-0.5, Id_inv(2.5))
set ytics add (Id(-0.5), 2.5)
You also asked about points in your comment and got the correct approach. The size of the circle can be chosen in any coordinate system (I think character is the width of a letter – x? – in the current font, but I'm not 100% sure)
set object 1 circle center -0.5,Id(-0.5) radius first 0.01 fs solid noborder fc "red"
set object 2 circle center Id_inv(2.5),2.5 radius first 0.01 fs solid noborder fc "green"
Now the remaining decoration can be added:
set title "{/:Italic I}_d vs {/:Italic V}_{gs}"
set xlabel "{/:Italic V}_{gs} /V"
set ylabel "{/:Italic I}_d /mA"
set xrange [-1:0]
plot Id(x)
I would like to plot the positive and negative values of a non-equidistant matrix with different palettes (each a logscale), such that the overall effective color code is (-max "blue", <1e-6 "white", max "red"). In order to do that it is required to use multiplot for each plot and overlay them perfectly. The problem is now, that the complement values, which should be "NaNs", are plotted as white and not transparent (please see figure). As a result, the latter plot completely overlays the former, which cannot be seen. I tried to define my own color palette with transparent colors, but cannot make it work with the "plot for" command. (Remark: This is a follow-up question from here.)
Current plotscript:
CoordsX = "0.04 0.11 0.24 0.4 0.51"
CoordsY = "0.04 0.11 0.24 0.4 0.51"
dim_x = words(CoordsX)
dim_y = words(CoordsY)
dx(i) = (word(CoordsX,i)-word(CoordsX,i-1))*0.5
dy(i) = (word(CoordsY,i)-word(CoordsY,i-1))*0.5
ndx(i,j) = word(CoordsX,i) - (i-1<1 ? dx(i+1) : dx(i))
pdx(i,j) = word(CoordsX,i) + (i+1>dim_x ? dx(i) : dx(i+1))
ndy(i,j) = word(CoordsY,j) - (j-1<1 ? dy(j+1) : dy(j))
pdy(i,j) = word(CoordsY,j) + (j+1>dim_y ? dy(j) : dy(j+1))
set size square
set xrange[ndx(1,1):pdx(dim_x,1)]
set yrange[ndy(1,1):pdy(1,dim_y)] reverse
set tic out
set term png truecolor
set output "test.png"
set multiplot
max = 25
set cbrange [0:max]
set object rectangle from screen 0,0 to screen 1,1 behind fillcolor rgb "grey" fillstyle solid noborder # Only added to see transparency
set palette defined (0 "white", max "blue")
plot for [i=1:dim_x] file u\
(real(word(CoordsX,i))):1:(ndx(i,int($0))):(pdx(i,int($0))):(ndy(i,int($0+1))):(pdy(i,int($0+1))):(column(i)<0?abs(column(i)):NaN)\
with boxxyerror fs transparent solid 1.0 palette notitle
set palette defined (0 "white", max "red")
plot for [i=1:dim_x] file u\
(real(word(CoordsX,i))):1:(ndx(i,int($0))):(pdx(i,int($0))):(ndy(i,int($0+1))):(pdy(i,int($0+1))):(column(i)>0?abs(column(i)):NaN)\
with boxxyerror fs transparent solid 1.0 palette notitle
unset multiplot
set output
A few comments:
1) multiplot is not the right mechanism to create a single plot. You will get better results by reorganizing your command sequence into a single plot command. If necessary you can split your palette into two halves, a red half and a blue half. E.g.
set palette defined (0 "white", 1 "dark-red", 1 "white", 2 "dark blue")
set cbrange [0 : 2*max]
plot 'redstuff' using 1:...:(color) fc palette, \
'bluestuff' using 1:...:(color+max) fc palette
2) The fill style you selected is fully opaque. If you want 50% transparency it needs to be
set style fill transparent solid 0.5
3) It is not clear where exactly your NaN values appear. If one of the component rectangles has NaN as a coordinate, it will not be drawn at all - so effectively it is fully transparent. However providing NaN as a color value will not in general produce transparency. As a special case the with image plot style does know to omit pixels with value NaN, but other plot styles don't have a notion of 'pixels'.
I would like get something like this:
Rectangle outside graph:
Could I get that with set object <number> rect ? Or is this only to draw rectangles inside graph?
you can use the screen coordinates (which refer to the entire window) like so:
set object 1 rect from screen 0.0, screen 0.9 to screen 0.1, screen 1.0
this would create a rectangle in the top left 10% of the plotting window
As suggested in #ewcz's answer, you can use screen coordinates for drawing objects (partly) outside the graph area .
However, if you check help object and you will find the option noclip at least since gnuplot 4.6.5. (default is clip).
With this you can draw objects outside the graph using, e.g. graph, first, second, etc. coordinates as well (check help coordinates), especially in case you want to adjust the size of your rectangle to graph or x/y-coordinates.
Script:
### draw rectangle outside graph area
reset session
set xrange [0:20]
set yrange [0:10]
set xlabel "x-axis"
set ylabel "y-axis"
set origin 0.1, 0.1
set size 0.8, 0.8
set obj 1 rect noclip from graph -0.1, 0.9 to graph 0.1, 1.1
set obj 1 fs empty border rgb "red" lw 2 dt 4
set obj 2 rect noclip from first -2,-2 to first 7,3
set obj 2 fs empty border rgb "green" lw 2 dt 1
set obj 3 rect noclip from screen 0.6,0.6 to screen 1,1
set obj 3 fs empty border rgb "blue" lw 2 dt 3
plot x
### end of script
Result: