Fill several sections below a curve of data in Gnuplot
Asked Answered
N

1

5

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:

example of what I want to do

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.

Nonprofit answered 4/6, 2014 at 2:9 Comment(1)
Can you post the script (or a minimal version thereof) that you used to make that example? It may be a simple modification to get what you want.Modish
R
14

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):

enter image description here

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'
Rodman answered 4/6, 2014 at 7:16 Comment(4)
Great, that works, but one more thing, I want to plot my data with smooth sbezier, but then the filled section doesn't match the curved For example replacing in the last part of plot: '' using 1:2 smooth sbezier with lines lw 3 lt 1 title 'curve' ImageNonprofit
I can also see this, but I don't know why this happens. If you use smooth csplines (for every line in the plot command), then it works fine for me.Rodman
I can't use smooth csplines in the second plot command because it throws an error Can't calculate splines, need at least 3 points . Anyway csplines doesn't approximate the curve the way I want to.Nonprofit
Please see my edited answer. The best way I know is to write the smoothed data to a temporal file and then use this with the suggested filtering and plotting.Rodman

© 2022 - 2024 — McMap. All rights reserved.