unexpected line in a plot of function defined by parts - gnuplot - plot

I'm trying to plot a piece wise defined function give by,
equation
Implemented in gnuplot, like this,
h(x)=0
g(x)=(4/3)*(1-x**3)
plot h(x)*(x<0) + g(x)*(x>0)*(x<1) + h(x)*(x>1)
The problem is that the line that goes from h(x) to g(x) is not a vertical line, is a inclined one. I really need a vertical one.
How to fix it?
plot

You have to increase the sampling rate, for example by
set samples 1000
Also note that you might have to change the definition of the function g(x) to
g(x)=(4./3.)*(1-x**3)
because you otherwise evaluate (4/3), which is equal to 1 rather than 1.333...

You mustn't have (mathematically speaking) a connecting line between the noncontinous parts, because that implies that there are actual function values there.
You should do this instead:
plot sample [:0] h(x) lc 1 title "f(x)", \
[0:1] g(x) lc 1 notitle, \
[1:] h(x) lc 1 notitle

Related

Force 1st point of pointinterval to be plotted

I tried to plot graph using the pointinterval command and I would like the 1st point of my data to be plotted which is not the case for the hot side of my first plot. Indeed we see the purple dashed line but no point at the bottom left corner (around y+=0.35).
My code involves for loop and is displayed below:
plot for [i=1:words(FILES)] myDataFile(i) u (column(1)):(column(6)/word(UTAUS_ch,i)) w lp pointinterval 2 pt myPointtype(i) ps myPointsize(i) dt myDashtype(i) lt myLinetype(i) lw myLinewidth(i) lc rgb myLinecolor(i) title myTitle(i)
If I plot with pointinterval 1 we see that those points exist (see picture below).
How can I force the first point to be plotted with pointinterval?
Is that possible to plot half of my points every 2 points and the other part every 2 points but with an offset of 1 point?
I do not think you will be able to do what you want using the pointinterval property. It is designed so that the offset of the initial point increases by one for each plot drawn, with the intention of reducing the chance that point symbols from successive plots will overlap. This is exactly opposite to what you are trying to do.
Therefore I suggest not plotting each dataset with linespoints pi N. Instead plot each dataset twice, once with lines and once with points using a filter in the using specifier like this:
plot FOO using 1:2 with lines, '' using ((int($0)%N) ? NaN : $1) : 2 with points
The filter (int($0)%N ? NaN : $1) suppresses all points whose line number is not evenly divisible by N. This is essentially what the pointinterval property does, except that pointinterval skips out-of-range points and otherwise unplottable points rather than strictly using the line number as an index.
Edit If individual offset values are required because x-coordinates are not consistent:
array offset[N] = [1,1,2,-1, and so on]
plot for [i=1:N] \
MyDataFile(i) using 1:2 with lines, \
'' using (((int($0)+offset[i] % N) ? NaN : $1) : 2 with points

GNU plot - count the number of peaks

I have a very huge text file with 11 columns. As I can't post the whole data, I have uploded the text file to a public repo and is found in this link: http://s000.tinyupload.com/?file_id=59483318155908771897
Is there any way to COUNT the number of peaks using GNU plot in Linux? From the above text file, I am plotting the 1st and 7th column as x and y columns where the peaks are variations of the 7th column and that's what I am interested in. For example, to count the number of peaks of frequency as in the following image as 10.
Here a simple plotting script i am using.
set key right top
set xrange [:10]
#show timestamp
set xlabel "time in sec"
set ylabel "Freq"
set title "Testing"
plot "data/freq.csv" using 1:7 title "Freq", \
Thanks for any help.
Gnuplot is for plotting and minor arithmetic, finding peaks in a signal is a signal processing task and you need something like GNU Octave to do a reasonable job. If you load freq.csv file and run findpeaks() on it with a plausible value for MinPeakDistance you get:
The code I used to generate the above plot:
y = dlmread('freq.csv', ' ');
[peak_y, peak_x] = findpeaks(y(:,7), "MinPeakDistance", 40);
plot(y(:,1), y(:,7), y(peak_x,1), peak_y, '.r');
Depending on what you want findpeaks() might be enough, see help findpeaks and demo findpeaks for other options you can tweak.
It's a bit of tweaking but this example should help:
y2=y1=y0=NaN
stat "data/freq.csv" using (y2=y1,y1=y0,y0=$7,(y1>y2&&y1>y0?y1:NaN)) prefix "data"
Now in the variable data_records you should get the COUNT of local maximums you have in column 7.
You can print via
print data_records
To understand more, I post here an example of the sinus function
set table 'test.dat'
plot sin(x)
unset table
x2=x1=x0=NaN
y2=y1=y0=NaN
plot 'test.dat' using (x2=x1,x1=x0,x0=$1,x1):(y2=y1,y1=y0,y0=$2,(y1>y2&&y1>y0?y1:NaN)) w p, 'test.dat' u 1:2 w l
Should plot a sinus and also the maximum points.
In case several points have the same value:
x2=x1=x0=NaN
y2=y1=y0=NaN
plot 'freq.csv' u 0:7 w l, '' using (x2=x1,x1=x0,x0=$0,x1):(y2=y1,y1=y0,y0=$7,(y1>=y2&&y1>y0?y1:NaN)) w p
or
plot 'freq.csv' u 0:7 w l, '' using (x2=x1,x1=x0,x0=$0,x1):(y2=y1,y1=y0,y0=$7,(y1>y2&&y1>=y0?y1:NaN)) w p
depending on which side of the plateau you want to count the peak
The stat command becomes:
stat 'freq.csv' using (y2=y1,y1=y0,y0=$7,(y1>=y2&&y1>y0?y1:NaN)) prefix "data"

Iterative parametric plot with gnuplot

I want to use the iterative plot function plot for in gnuplot for a parametric plot.
set parametric
f(x) = x
plot for [i=1:2] t,f(i*t)
However, as I learned in this Question, the for iteration ends after a comma. So the iteration only applies to t and not to f(i*t). But since a parametric plot needs a pair of functions separated by a comma, how can I tell gnuplot to iteratively plot my parametric plot?
Did you actually try it? gnuplot distinguishes a comma between parametric coordinates and the end of a plot-element as it is called (which can contain a for-loop): this is simply done by counting the number of coordinates given.
E.g.,
set parametric
set size ratio -1
plot for [i=1:3] cos(t),i*sin(t) title "Ellipse ".i, \
for [i=1:3] i*cos(t),i*sin(t) title "Circle ".i
If you do
plot for [i=1:3] cos(t),i*sin(t),i*cos(t),i*sin(t)
then you keep the 3 ellipses (well, including the circle when i=1), and have one circle plotted for i=3 (the value i kept after the for loop) from the last pair of coordinates.

gnuplot - plot random points inside an ellipsoid

I want to create and plot a set of random points within the boundaries of an ellipsoid using gnuplot. Is it possible to do this directly in gnuplot, or would I need to generate my random data points in an external program?
Ultimately I would like to produce an ellipsoid figure similar to this ellipse figure.
There are some examples on the use of rand and cylindrical/spherical coordinates, but I'm not sure how to generate the random points inside the boundaries of an ellipsoid.
Based on #Bernhard's answer, here is how you can do that with gnuplot only. To reuse a random number, you can put the two rand calls and the assignments to variables in the first argument of the using statement, separated by commas. The using statements are evaluated from left to right, so you can access those variables in all following using parameters.
To demonstrate this, see the following examples:
set samples 1000
plot '+' using (x=rand(0), y=rand(0), x):(y)
Applying this to the ellipsoid, this gives the script:
a=3
b=2
phi=30*pi/180
max(x,y) = (x > y ? x : y)
set xrange[-max(a,b):max(a,b)]
set yrange[-max(a,b):max(a,b)]
set offset 0.1,0.1,0.1,0.1
set samples 2000
ex(x, y) = a*(2*x-1)
ey(x, y) = b*(sqrt(1-((2*x-1))**2))*(2*y-1)
unset key
plot '+' using (x=rand(0), y=rand(0), ex(x,y)*cos(phi)-ey(x,y)*sin(phi)):\
(ey(x,y)*cos(phi)+ex(x,y)*sin(phi)) pt 7 ps 0.5
with the result:
This, however, leads to an apparently unequal distribution of the points (see the agglomarations at the ellipse's ends, see #andyras's comment). To avoid this, here is how you can filter equally distributed random points to be inside the ellipsoid:
a=3
b=2
set angles degree
phi=30
max(x,y) = (x > y ? x : y)
set xrange[-max(a,b):max(a,b)]
set yrange[-max(a,b):max(a,b)]
set offset 0.1,0.1,0.1,0.1
set samples 2000
set size ratio 1
check(x, y) = (((x/a)**2 + (y/b)**2) <= 1)
unset key
plot '+' using (x=2*a*(rand(0)-0.5), y=2*b*(rand(0)-0.5), \
check(x,y) ? x*cos(phi)-y*sin(phi) : 1/0):\
(x*sin(phi)+y*cos(phi)) pt 7 ps 0.5
This gives the much better result:
Extending this to three dimensions:
a=3
b=1
c=1
set angles degree
phi=30
mx(x,y) = (x > y ? x : y)
max(x,y,z) = mx(mx(x,y), mx(x,z))
set xrange[-max(a,b,c):max(a,b,c)]
set yrange[-max(a,b,c):max(a,b,c)]
set zrange[-max(a,b,c):max(a,b,c)]
set offset 0.1,0.1,0.1,0.1
set samples 2000
set size ratio 1
set ticslevel 0
set view 60, 330
check(x, y, z) = (((x/a)**2 + (y/b)**2 + (z/c)**2) <= 1)
unset key
splot '+' using (x = 2*a*(rand(0)-0.5), \
y = 2*b*(rand(0)-0.5), \
z=2*c*(rand(0)-0.5), \
check(x,y,z) ? x*cos(phi)-y*sin(phi) : 1/0):\
(x*sin(phi)+y*cos(phi)):(z) pt 7 ps 0.5
with the result:
I didn't find a method to reuse the rand(0) in the parametric plot example that you showed, but with an internal call to command line tools, you can do that with some modifications:
unset key
a=3
b=2
set xrange [-a:a]
set yrange [-b:b]
set style function dots
plot "<seq 1000 | awk '{print rand(), rand()}'" using (a*(2*$1-1)):(b*(sqrt(1-((2*$1-1))**2))*(2*$2-1))
To convert this to 3D is left as an exercise to the reader (just continue on these expressions)

Plotting a function with discrete x values in gnuplot

I need to plot a function f(x), where x is discrete set of values (in my case positive integers). I couldn't find a way to specify a step-size when using the range option and samples doesn't seem to be the right solution. Finally, I would like to approximate f(x) with a smooth function.
I don't quite understand why samples is not the solution to your problem.
If I want to plot sin(x) on an interval between 0 and 10 with a point at every integer I use
set xrange [0:10]
set sample 11
plot sin(x) w p
Obviously the number of samples is xmax-xmin+1 (10 - 0 + 1 = 11).
Finally to tackle the approximation problem have a look at this website which discusses linear least squares fitting. For simple linear interpolation use lp instead of p.
Or alternatively, play around with the ceil(x) or floor(x) functions.
Maybe have a look at this example:
http://gnuplot.sourceforge.net/demo/prob2.html
You can do:
plot [1:12] '+' u ($0):(f($0))
Where, $0 will be replaced by 1, 2, ..., 12. You can even do a smooth on this. For instance:
f(x)=sin(2*x)
plot [1:12] f(x) t 'the function'\
, '+' u ($0):(f($0)) t 'the points'\
, '+' u ($0):(f($0)) smooth cspline t 'the smooth'

Resources