Gnuplot: point size units - plot

How can I set the point size in gnuplot in the units of the plot coordinates?
In other words, the points should get smaller if I increase xrange.
It looks like this is all terminal dependent. Is there a workaround?

Here's a small example using inline data ...
plot '-' u 1:2:1 ps variable
1 2
2 3
3 4
4 5
5 6
e
Note that while it is possible to change the pointsize using a column from your datafile, I am not aware of any way to specify how large each point should be since the pointsize (and even the pointtype) is a terminal dependent quantity. The only workaround that I can come up with is to scale the points by a terminal dependent value.
default_value=1.0
func(x)=1.0*x #Change this to change the functional dependence of the pointsize on x.
scale_point(x)=(GPVAL_TERM=="postscript") ? 1.0*func(x) :\
(GPVAL_TERM=="png") ? 2.0*(x) :\
default_value
plot "mydata.dat" u 1:2:(scale_point($1)) w pt ps variable
It's ugly, but it should get the job done -- You could also write a similar function which returns the pointtype to achieve some sort of terminal independence with that as well...
EDIT
Note, my points increase in size linearly as x gets bigger, but you can substitute any function you want to make the points get smaller as you see fit.
What I am saying is that I don't believe that option exists since as you state "all this is terminal dependent". I tried to provide a ugly hack to allow you to modify this on a per-plot basis with minimal intervention -- allowing for different terminals, etc.
EDIT 2
While responding to your comment, I remembered an odd little corner of the gnuplot documentation that may be helpful.
set style fill transparent solid noborder #whatever fillstyle you want...
plot 'mydata' u 1:2:3 w circles
see help circles ... I'm not sure when this feature was introduced, probably with gnuplot 4.3, but if you're using 4.2 then give it a try and let me know how it goes...

If I understand the question correctly, you just want the pointsize to be a decreasing function of the xrange. Exactly how big the points are printed and what they look like does depend on the terminal. But it's not hard to get the basic behavior that you want.
First, define a function to return the pointsize. Let's try
sps(a,b) = 1./(b-a)
Set your xrange:
set xrange [0:3]
Make a plot that you won't use:
plot sin(X)
We did that in order to get some of gnuplot's special variables defined. Now we can do
plot sin(x) with points pt 7 ps sps(GPVAL_X_MIN, GPVAL_X_MAX)
If you now reset the xrange and re-enter both plot commands, you will see that the pointsize changes, inversely proportional to the xrange. You probably want a different function for pointsize than the "sps" example that I used. I hope this is something like what you were after.

Related

iteration and parametric mode with t ranging according to a function - gnuplot

I'm trying to iterate in parametric mode to plot several concentric arcs of circles with the parameter t ranging according to a function. I've tried, among others,
a=sqrt(2)
plot [-pi/2:pi/2] a*cos(t), a*sin(t)
do for [i=2:10] {
a=sqrt(2)/i
set trange [-1./2*acos(-(a**2)/2.):1./2*acos(-(a**2)/2.)]
replot a*cos(t), a*sin(t)
}
what I see is a plot of 10 identical overlapped arcs. I also replaced replot with plot and only the last arc is retained.
I know "that iteration does not work for plots in parametric mode" (ref. "plot for" in the manual), but this is using a do for construct. There must be a way to do this! How?
System: gnuplot Version 5.2 patchlevel 2, windows 10.
Today I developed my own solution, which is
a(i)=sqrt(2)/30*(31-i)
s(t, i)=t*(1./2*acos(-(a(i)**2)/2.))/(pi/2)
set trange [-pi/2:pi/2]
plot [-pi/2:pi/2] for [j=1:30] a(j)*cos(s(t,j)), a(j)*sin(s(t,j)) lw 2
Notice that in the meanwhile I made a little math adjustment from a=sqrt(2)/i to a(i)=sqrt(2)/30*(31-i).
Output:
The settings used to output that picture are
set term wxt size 800,800
set grid
set size ratio -1
set parametric
set xrange [-1.6:1.6]
set yrange [-1.6:1.6]
The rationale behind this is that in this way I set trange only once, and then with a variable substitution I map [0:pi/2] to [0:s(pi/2,i)].
You can use the for loop inside your plot statement. Try this:
set term png
set out "tmp.png"
unset key
set parametric
plot for [i=2:10] (sqrt(2)/i)*cos(t), (sqrt(2)/i)*sin(t)
exit
Output:
Update: the solution above won't take care of the trange requirement of the question. For that, one possible solution is to create a series of tables with proper ranges, and then loop through the files created for the plot. Something like the following:
set term png
set out "tmp.png"
unset key
set parametric
do for [i=2:10] {
a=sqrt(2)/i
set trange [-1./2*acos(-(a**2)/2.):1./2*acos(-(a**2)/2.)]
set table 'data'.i.'.txt'
plot a*cos(t), a*sin(t)
unset table
}
plot for [i=2:10] 'data'.i.'.txt' w l
exit
Output:
Hope this solution works! With a little help from this post.
You can often avoid parametric mode by using the + special filename in conjunction with a using statement:
plot for [i=2:10] [t=-1./2*acos(-((sqrt(2)/i)**2)/2.):1./2*acos(-((sqrt(2)/i)**2)/2.)] '+' using (sqrt(2)/i)*cos(t):(sqrt(2)/i)*sin(t) notitle with lines

plot every tick on axis[SAS]

I have dataset include about 100 observations, say all of them are in (x,y) format, all of y is in integer format. I need proc sgplot to make a graphic about them. The range about my y is from 1 to 150. I hope I can force the graphic to show every corresponding y value on the y-axis instead of automatically reducing the ticks to a small number in order to show them clearly. For example, if the first five value of my y is (1,3,4,6,7,....), I hope the y tick shows exactly (1,3,4,6,7,....) instead (1,5,...).
I tried
yaxis value=(1 to 150 by 1) valueshint display=all;
It does not work as maybe I have too many observations. I know the result maybe overwhelming, but I just want to see the result. Thanks.
You don't say if you're using SAS/GRAPH or ODS GRAPHICS (SGPLOT etc.), so I'll answer the latter which is what I know; the answer should be useful for both in concept.
You likely cannot get SAS to plot so much on the axis unless the axis is very large itself. This means you have two options.
Raise the size of the graphic produced a lot in terms of pixels(and then shrink that to a usable size via image physical size, or using an external tool). Not necessarily usable in all cases, but produces a very high resolution plot (which is very big size-wise). This page explains how to do that for ODS graphics (use image_dpi as a high number, and width and height in inches as a normal number), and this page explains for SAS/GRAPH. You may need to make your font small to make it work (if you're adding numbers, which I assume you are), or you may need to make an initially large plot first and then go into paint/photoshop/gimp/etc. and make it smaller.
Use annotate to create the axis marks. This is fairly easy if you know how to use annotate, as you're just writing to the location of the axis (y) and the item (x), and then a bit below that for the text. This will make it very easy to make a total garbage plot, but it will likely work ultimately.
These likely work in both SAS/GRAPH and ODS GRAPHICS, and I can't test either as you don't post any code or simulated data to test with, but I think both approaches have some merit (as does the approach of "don't do this", but you've thought that through).

Transparency for specific values in matrix using Gnuplot while preserving the palette?

Here's an interesting problem:
I have a 2D "matrix" of double-precision, binary data I'd like to plot using Gnuplot. This is easily done as follows:
plot "foo.dat" binary array=384x384 format='%double' with image
The trick is that certain "regions" of the data have a special value, say 1234567890.0. I want those elements to be fully transparent, and all other matrix entires to be fully opaque. Is there a way to set the transparency channel based on the data itself?
I have looked through the relevant parts of the Gnuplot documentation (link), and I think I need to use the with rgbalpha style, but I'm not sure how that applies or how to map the transparency correctly.
I have also looked at these examples (link), but I'm not sure how I could apply it.
I wonder if this could be done in a one-liner (as above), or if it would need a couple lines (as when plotting contours on top of a binary matrix).
Thanks in advance!
UPDATE
I thought I'd give some examples for posterity. In all examples, I use the following preamble:
set title "Basic Plot" # Or as appropriate
set size square
set palette #MATLAB # see <http://www.gnuplotting.org/matlab-colorbar-with-gnuplot/>
set cbrange [-100000:100000] # This cbrange fits my data well enough
# I would LOVE an automated way to do this!
val = 1234567890.0 # For missing data
My basic command produces the following:
plot "foo.dat" binary array=384x384 format='%double' with image
I also tried what #Christoph suggested: replace values equal to val with NaN:
plot "foo.dat" binary array=384x384 format='%double' \
using ($1 == val ? NaN : $1) with image
I tried using rgbalpha in order to truly control transparency, and it produces the following:
plot "foo.dat" binary array=384x384 format='%double' \
using 1:1:1:($1 == val ? 0 : 255) with rgbalpha
CONCLUSION
The first two methods produce similar results. The first is bad because it messes up the colormap with false maxima. The first and second fall short in that they don't actually achieve transparency ("undefined" values in Gnuplot aren't automatically given transparency). The last is great in that it actually controls transparency, but it is in grayscale and doesn't use the #MATLAB palette as I want it to.
If somebody can cause all entries equal to val to be transparent and get the colormap to work correctly, I'll accept their answer.
***Where to go next****
The Gnuplot Documentation mentions the set datafile missing command (link). This looks promising, but it only seems to work for column-based data -- not binary files.
I imagine the best way to answer my original question is by setting up a set of functions to imitate a given palette for each "column" of the rgbalpha method -- something like this:
red(z) = <stuff>
green(z) = <stuff>
blue(z) = <stuff>
plot "foo.dat" binary array=384x384 format='%double' \
using red($1):green($1):blue($1):($1 == val ? 0 : 255) with rgbalpha
Bonus points if those functions somehow reference the current palette, so the specifics of a palette aren't hard-coded into these three functions. :-)
You can achieve that by giving the respective pixel a value of 'NaN':
value = 123456789.0
plot "foo.dat" binary array=384x384 format='%double' \
using ($1 == val ? NaN : $1) with image
Note, that this depends on the selected terminal. It works at least with wxt, pdfcairo, pngcairo and png, and does not work with x11 and postscript. I didn't test other terminals.
Here is a self-contained example. The background color is set to show that the pixel indeed is transparent and not white:
set xrange [0:1]
set yrange [0:1]
set isosamples 11
set samples 11
plot '++' using 1:2:($1 == 0.5 && $2 == 0.5 ? NaN : $1) with image
The result with 4.6.5 is:
Using your example data file, the following script works fine and gives a nice result:
set terminal pngcairo size 800,800
set output 'foo.png'
set size square
f(x)=1.5-4*abs(x)
set palette model RGB
set palette functions f(gray-0.75),f(gray-0.5),f(gray-0.25)
val = 1234567890.0
set autoscale xfix
set autoscale yfix
set cbrange [-10000:10000]
plot 'foo.dat' binary array=(512,512) format='%double' using ($1 == val ? NaN : $1) with image notitle

White space between data and axis when using pcolor in octave

I am trying to create a colorplot using pcolor. I want to use "shading interp" so am not using imagesc(). However when I set the axis manually the plot has white space between the data and the axis.
I want to zoom into one section of the data rather than the whole image. (This problem does not occur when the matrix and using "axis("tight") )
Thank you in advance for your help
The code I am using is :
clf
load x.dat;
load y.dat;
load 15-1-14_E2_lam_7410nm.txt
x=x;
y=y;
A=X15_1_14_E2_lam_7410nm;
A=rot90(A);
h=pcolor(x,y,A);
shading interp
set(h,"EdgeColor",'none');
axis([60 90 -20 20])
#axis("tight")
colorbar
I believe the white space at one or more axis edges is because your data does not go fully to the edge of the frame (or the axis) you are setting. This can happen frequently when using something like meshgrid() to set the frame from -L to L in steps dl but then your data may start at -L and only go to, say, L-dl.

Gnuplot: How to remove vectors below a certain magnitude from vector field?

I have a 2D CFD code that gives me the x and y flow velocity at every point on a grid. I am currently visualizing the data using a vector field in gnuplot. My goal is to see how far the plume from an eruption extends, so it would be much cleaner if I could prevent vectors from showing up at all in the field if they fall below a certain magnitude. Does anyone have an idea how to go about this? My current gnuplot script is below. I can also modify the input file as necessary.
reset
set nokey
set term png
set xrange [0:5.1]
set yrange [0:10.1]
do for [i=0:10] {
set title 'Eruption simulation: Timestep '.i
set output 'path/FlowVel'.sprintf('%04.0f',i).'.png'
plot 'path/Flow'.sprintf('%04.0f',i).'.dat' using 1:2:3:4 with vec
}
I guess you want a kind of filtering, which gnuplot doesn't really have, but can be achieved with the following trick (taken from "help using examples" in gnuplot):
One trick is to use the ternary `?:` operator to filter data:
plot 'file' using 1:($3>10 ? $2 : 1/0)
which plots the datum in column two against that in column one provided
the datum in column three exceeds ten. `1/0` is undefined; `gnuplot`
quietly ignores undefined points, so unsuitable points are suppressed.
Or you can use the pre-defined variable NaN to achieve the same result.
So I guess you would want something like this in your case
plot "data.dat" u 1:2:($3**2+$4**2>mag_sq?$3:NaN):($3**2+$4**2>mag_sq?$4:NaN) w vector
where mag_sq is the square of your desired magnitude.

Resources