Filledcurves with multiple functions in gnuplot - gnuplot

I am currently working on a project where I need to plot a set of functions and fill the area between them.
I have tried different things, but I cannot really get it to work.
Here is a simplified version of the gnuplot script:
f(x) = 80
g(x) = 0.35*x - 7.5
h(x) = -1.96629*x + 710
i(x) = -80
j(x) = -0.35*x + 7.5
k(x) = 1.96629*x -710
set xzeroaxis
set xtics axis
set xrange [0:500]
set yzeroaxis
set ytics axis
set yrange [-200:200]
set border 0
plot f(x) with lines ls 1 lt rgb "red", \
g(x) with lines ls 1 lt rgb "red", \
h(x) with lines ls 1 lt rgb "red", \
i(x) with lines ls 1 lt rgb "blue", \
j(x) with lines ls 1 lt rgb "blue", \
k(x) with lines ls 1 lt rgb "blue"
This produces the following plot:
I have tried different things and this link got me some of the way, but I am running out of ideas.
So my question goes: is it possible to fill the area between the red and blue lines (I.e the convex space that the functions form)?

You can do it easily if you already know which curves are lower bounds and which are upper bounds:
max(a,b)=(a>b)?a:b
min(a,b)=(a<b)?a:b
lowerb(x)=max(max(i(x),j(x)),k(x))
upperb(x)=min(min(f(x),g(x)),h(x))
plot "+" using 1:((lowerb($1)<upperb($1))?lowerb($1):1/0):(upperb($1)) with filledcurves
The ternary operator in the plot command allows to plot only { lowerb(x)< y <upperb(x)} and not { lowerb(x) > y > upperb(x)}
If you have a very long list of functions, it should be possible to automate the construction of lowerb and upperb using a macro.

Use the ternary operator to define piece wise the red function. Call it f1. Plot f1 and -f1 with filledcurves. I think that approach should do it.

Related

Bubble graphs - how to use?

Is it possible to combinate "normal points" and "bubble points"? I have two sets of data - file1.txt and file2.txt and for one of them (file2.txt) I would like to use points like http://gnuplot-tricks.blogspot.com/2009/06/
How to compose this into code please? When I use the code from that webpage how to plot another data. I tried this:
f(x) = A*exp(-x*x/B/B)
rx=0.107071; ry=0.057876; A = 1; B = 0.2; C=0.5*rx; D=-0.4*ry
g(u,v) = (2*cos(u)*v*rx+C)*(2*cos(u)*v*rx+C)+(3.5*sin(u)*v*ry+D)*(3.5*sin(u)*v*ry+D)
unset key; unset colorbox; set view map
set xrange [-0.15:5.2]; set yrange [-0.7:0.95]
set parametric; set urange [0:2*pi]; set vrange [0:1]
set isosamples 20, 20; set samples 30
set palette model HSV functions 1, 1-f(gray), 1+2*f(gray)
splot cos(u)*rx*v-0.13335347,sin(u)*ry*v+2.7730389, g(u,v) w pm3d, \
cos(u)*rx*v-0.11625481,sin(u)*ry*v+3.5312312, g(u,v) w pm3d, \
cos(u)*rx*v-0.14454222,sin(u)*ry*v+3.6412394, g(u,v) w pm3d, \
cos(u)*rx*v-0.070272446,sin(u)*ry*v+3.8070912, g(u,v) w pm3d, \
cos(u)*rx*v-0.10077238,sin(u)*ry*v+4.090774, g(u,v) w pm3d, \
'file1.txt' using 2:1:(0.0):2 with points pt 7 ps 1 palette
but file2 is not splot. Thank you very much
Here is a variant of the "trick" shown in your second link. I have extracted the customized point styles into a pre-defined set of linetypes. This makes the plot command itself simpler, and it is easier to reuse the definitions in multiple plots.
set linetype 101 ps 3.0 pt 7 lc rgb "#ff0000"
set linetype 102 ps 2.6 pt 7 lc rgb "#ff2222"
set linetype 103 ps 2.2 pt 7 lc rgb "#ff4444"
set linetype 104 ps 1.8 pt 7 lc rgb "#ff6666"
set linetype 105 ps 1.4 pt 7 lc rgb "#ff8888"
set linetype 106 ps 1.0 pt 7 lc rgb "#ffaaaa"
set linetype 107 ps 0.6 pt 7 lc rgb "#ffcccc"
set linetype 108 ps 0.2 pt 7 lc rgb "#ffeeee"
set border back
plot for [LT=101:108] 'silver.dat' using 1:2 with point lt LT notitle
Please clarify what exactly what properties your plot needs to have.
(1) The term "bubble plot" usually refers to a plot in which each point is drawn as a circle with additional properties encoded by changing the size, color, or other property of the circle. Gnuplot can do that quite well. A good example can be found in the online demo collection: Hypertext bubble chart In this case the size of the circle is used to indicate relative population and additional information is encoded as hypertext (pop-up text box) attached to that point. Variable color could easily be added as well. The png version below does not include the hypertext.
(2) The example you link in the query does not appear to encode any additional information into the shape or color of the point but it does use a fancy glyph for each point rather than a simple dot or cross. Gnuplot can do that also. It depends on exactly what set of symbols or glyphs you want to use. If you can find a font providing appropriate glyphs then one way is shown here:
shape(i) = (i%4 == 0) ? "⊕" : (i%4 == 1) ? "⊙" : (i%4 == 2) ? "⊚" : "⦾"
set grid x y z vertical
splot 'silver.dat' using 1:2:3:(shape(int(column(0))) with labels textcolor "forest-green"
More complicated options are also possible but may depend on exactly what you need and what output format (gnuplot "terminal type") is acceptable.

Gnuplot columnstacked histogram with errorbars

Suppose I have the following data file, so-qn.dat:
Type on on-err off off-err
good 75 5 55 4
bad 15 2 30 3
#other 10 1 15 2
which contains values on columns 2 and 4 and corresponding error deltas on columns 3 and 5.
I can produce a columnstacked histogram:
#!/usr/bin/gnuplot
set terminal png
set output 'so-qn.png'
set linetype 1 lc rgb "blue" lw 2 pt 0
set linetype 2 lc rgb "dark-red" lw 2 pt 0
set style data histograms
set style histogram columnstacked
set style fill solid
set ylabel "% of all items"
set yrange [0:100]
set boxwidth 0.75
set xtics scale 0
set xlabel "Option"
plot 'so-qn.dat' using 2 ti col, \
'' using 4:key(1) ti col
But I can’t figure out how to add errorbars to this. The closest I got so far is with
plot 'so-qn.dat' using 2 ti col, '' using 2:3 with yerrorbars lc rgb 'black' ti col, \
'' using 4:key(1) ti col, '' using 4:5:key(1) with yerrorbars lc rgb 'black' ti col
which produces
but only one of the error bars is in the right spot (I actually have no idea where the bottom left one gets its y from), one is completely invisible (hidden behind the right stack?), and I’d like the error bars to not show up in the key.
Is it possible to combine column-stacked histograms and error bars?
You can add errorbars to column-stacked histograms by manually adding plot-commands for the errorbars. To do so, you need, however, to keep track of the y-positions.
Therefore, let's introduce two variables which store the y-position for each of the two columns' errorbars.
y1 = -2
y2 = -4
You need to initialize these variables with -(number of column)
Next, let us define two functions that update the variables y1, y2.
f1(x) = (y1 = y1+x)
f2(x) = (y2 = y2+x)
Now, generate the desired plot via
plot 'so-qn.dat' using 2 ti col, \
'' using 4:key(1) ti col, \
'' using (0):(f1($2)):3 w yerr t "", \
'' using (1):(f2($4)):5 w yerr t ""
As you can see, you can supress the errorbars in the key by assigning an empty title (t ""). This approach even gives you more flexibility in customizing the appearance of the errorbars (e.g., assign different linestyles etc.).
This being said, I personally think this visualization is rather confusing. You might want to consider another visualization:
set bars fullwidth 0
set style data histograms
set style fill solid 1 border lt -1
set style histogram errorbars gap 2 lw 2
plot 'so-qn.dat' using 2:3:xtic(1) ti columnhead(2), \
'' using 4:5:xtic(1) ti columnhead(4)

plotting fitted linear graphs at two different horizontal range values

I am plotting two graphs using gnuplot. First plot is actual data and the second one is the fitting of the data.
The script I used for plotting this is shown here below:
#!/usr/bin/gnuplot
reset
set terminal png enhanced
set terminal pngcairo enhanced color dashed
set output 'msd-maltoLyo12per-225ns.png'
##########################################
set macros
labelSIZE="font 'Arial,24'"
ticFONT="font 'Arial,16"
set key font 'Arial,14'
set key spacing 1.5 samplen 5
##########################################
set xrange [0:225]
set yrange [0:11000]
set xtic #ticFONT
set ytic #ticFONT
set xtics out nomirror
set ytics out nomirror
##############################
set style line 1 lt 1 lc rgb "red" lw 2.0
set style line 2 lt 2 lc rgb "blue" lw 2.0
set style line 3 lt 3 lc rgb "coral" lw 2.0
set style line 4 lt 4 lc rgb "green" lw 2.0
set style line 5 lt 5 lc rgb "black" lw 2.0
##############################
f(x)=a+b*x
fit [120:225] f(x) 'diff-xy-maltoLyo12per.dat' via a,b
plot 'diff-xy-maltoLyo12per.dat' using 1:2 with lines linestyle 1 title "{/Symbol b}Mal-C_{12}", f(x) lw 3.0 lc rgb 'black'
Here I plot the fitting graph from 1 to 120 as shown . Also I want to plot the same graph from range 120 to 225 as in the picture .
Now I want a single plot which contain the two black lines and the red line.
How can I achieve this?
Thanks in advance.
Working with the script you already have, you can use two functions to fit in the different ranges separately, and then use a conditional plot that selects one if x < 120 and the other one if x > 120:
f1(x)=a1+b1*x
fit [0:120] f1(x) 'diff-xy-maltoLyo12per.dat' via a1,b1
f2(x)=a2+b2*x
fit [120:225] f2(x) 'diff-xy-maltoLyo12per.dat' via a2,b2
f(x) = x < 120 ? f1(x) : f2(x)
plot 'diff-xy-maltoLyo12per.dat' using 1:2 with lines linestyle 1 title "{/Symbol b}Mal-C_{12}", f(x) lw 3.0 lc rgb 'black'
Now, the way I would go about this, would be to generate a special fitting function, whose parameters would give me the point at which the slope changes as a result of the fitting itself. Say you call that point x0 (for which the value of the function is y0), the slope at the left of it is m1 and the slope at the right m2. Then the function at the left has the form m1*(x-x0)+y0 and the function at the right has the form m2*(x-x0)+y0. The overall function can be defined in gnuplot as:
f(x) = x < x0 ? m1*(x-x0)+y0 : m2*(x-x0)+y0
and you can fit f(x) "data" via x0, m1, m2, y0. You can also generate this function without the condition using a step function:
f(x) = m1*(x-x0)*(sgn(x0-x)+1)/2 + m2*(x-x0)*(sgn(x-x0)+1)/2 + y0
After you fit, for which you might need to provide some initial values, you can print x0 and you'll get the best value (that should be close to 120 in your case, as you know) for the position of the change in slope.

Fill several sections below a curve of data in Gnuplot

I have a set of points "data" defining a curve that I want to plot with bezier smooth.
So I want to fill the area below that curve between some pairs of x values.
If I only had one pair of x values it's not that difficult because I define a new set of data and plot it with filledcu. Example:
The problem is that I want to do that several times in the same plot.
Edit: Minimal working example:
#!/usr/bin/gnuplot
set terminal wxt enhanced font 'Verdana,12'
set style fill transparent solid 0.35 noborder
plot 'data' using 1:2 smooth sbezier with lines ls 1
pause -1
Where the structure of 'data' is:
x_point y_point
And I realized that my problem is that in fact I can't fill not even one curve, it seems to be filled because the slope is almost constant there.
To fill parts below a curve, you must use the filledcurves style. With the option x1 you fill the part between the curve and the x-axis.
In order to fill only parts of the curve, you must filter your data, i.e. give the x-values a value of 1/0 (invalid data point) if they are outside of the desired range, and the correct value from the data file otherwise. At the end you plot the curve itself:
set style fill transparent solid 0.35 noborder
filter(x,min,max) = (x > min && x < max) ? x : 1/0
plot 'data' using (filter($1, -1, -0.5)):2 with filledcurves x1 lt 1 notitle,\
'' using (filter($1, 0.2, 0.8)):2 with filledcurves x1 lt 1 notitle,\
'' using 1:2 with lines lw 3 lt 1 title 'curve'
This fills the range [-1:0.5] and [0.2:0.8].
To give a working example, I use the special filename +:
set samples 100
set xrange [-2:2]
f(x) = -x**2 + 4
set linetype 1 lc rgb '#A3001E'
set style fill transparent solid 0.35 noborder
filter(x,min,max) = (x > min && x < max) ? x : 1/0
plot '+' using (filter($1, -1, -0.5)):(f($1)) with filledcurves x1 lt 1 notitle,\
'' using (filter($1, 0.2, 0.8)):(f($1)) with filledcurves x1 lt 1 notitle,\
'' using 1:(f($1)) with lines lw 3 lt 1 title 'curve'
With the result (with 4.6.4):
If you must use some kind of smoothing, the filter may affect the data curve differently, depending on the filtered part. You can first write the smoothed data to a temporary file and then use this for 'normal' plotting:
set table 'data-smoothed'
plot 'data' using 1:2 smooth bezier
unset table
set style fill transparent solid 0.35 noborder
filter(x,min,max) = (x > min && x < max) ? x : 1/0
plot 'data-smoothed' using (filter($1, -1, -0.5)):2 with filledcurves x1 lt 1 notitle,\
'' using (filter($1, 0.2, 0.8)):2 with filledcurves x1 lt 1 notitle,\
'' using 1:2 with lines lw 3 lt 1 title 'curve'

setting multiple labels at the top of the x-axis

After the answer got in my earlier post drawing vertical lines in between bezier curves, I have been trying to label the segments separated by the dotted lines. I used x2label but found out that if I use it multiple times then the data gets replaced though they are positioned in different places. Below is the script:
set term x11 persist
set title "Animation curves"
set xlabel "Time (secs.)"
set ylabel "Parameter"
set x2label "Phoneme1" offset -35
set pointsize 2
set key off
set style line 2 lt 0 lc 1 lw 2
plot [0.04:0.15] "curve.dat" u 1:2 smooth csplines ls 1, "" u 1:($2-0.2):(0):(0.3) w vectors nohead ls 2, \
"curve.dat" u 1:2 with points
The output is the following.
I want to label Phoneme1, Phoneme2...and so on.. on top of each segment. How would I do it? Also as I was suggested in my earlier post to play with the line "" u 1:($2-0.2):(0):(0.3) w vectors nohead ls 2 to get a top to bottom vertical lines. But that also did not work. How do I get the lines from top margin to bottom? Thank you.
The horizontal lines
The horizontal lines can be accomplished with setting the yrange to an explicit value. Otherwise gnuplot would try to get some space between the lines and the axis. You could choose the values
set yrange [0.3:1.2]
Then you simply modify the vector using directions like so:
"" u 1:(0.3):(0):(1.2) w vectors nohead ls 2
(see below for the complete script)
The labeling of the sections
A quick way of doing this with your set of data would be this:
set key off
set style line 2 lt 0 lc 1 lw 2
set yrange [0.3:1.2]
plot [0.04:0.15] "Data.csv" u 1:2 smooth csplines ls 1, \
"" u 1:(0.3):(0):(1.2) w vectors nohead ls 2, \
"" u ($1+0.005):(1):(sprintf("P %d", $0)) w labels
However, this will probably not look the way you want it to look. You could think of modifying your data file to also include some information about the labeling like:
#x-value y-value x-label y-label label
0.06 0.694821399177 0.65 0.1 Phoneme1
0.07 0.543022222222 0.75 0.1 Phoneme2
Then the labels line would simply look like:
"" u 3:4:5 w labels
The complete plot then looks like this:

Resources