toby
toby

Reputation: 15

Gnuplot : filledcurve between smoothed curve

I have two sets of points: "test1.dat" and "test2.dat", they do not share same X-values.

I want to draw two smooth lines first due to the data is noisy, and then draw a filledcurve between the smooth lines.

I've read the tutorial, and cannot find the answer.

Upvotes: 0

Views: 3971

Answers (4)

theozh
theozh

Reputation: 25714

As @mgilson already described in his solution: reverse one dataset and let gnuplot close and fill the curve.

So, just for fun and the records. I haven't found any way to do it without the help of external tools with the gnuplot version at the time of OP's question (gnuplot 4.6.0). However, starting at least from gnuplot 5.0.3 when plotting style with table was introduced, there is a way, and even a simpler version for gnuplot>=5.2.0.

I'm aware that this is probably less efficient than with external tools, but it is gnuplot-only and hence really platform-independent!

As the OP wants to plot the noisy curves but only wants to fill the smoothed curves, simply plot the smoothed curves first into a datablock or file (as @mgilson did in his answer).

Script: (for gnuplot>=5.0.3)

Explanation:

  • the second dataset will be mirrored at the y-axis (-$1):2 and "resorted" via smooth unique and written into a third dataset, i.e. in total it is reversed in x.
  • the first dataset and the (once more) mirrored third dataset will be appended into a fourth dataset which will be used for filling.
### filledcurves for 2 datasets with different x-values
# reguires gnuplot>=5.0.3
reset session

$Data1 <<EOD
-5   5
-2   4
 0   1
 1   2
 3   5
 5   4
 7   2
 9   4
EOD

$Data2 <<EOD
-5     7
-1.0   6
 0.5   4
 1.5   6
 2.5   7
 6.5   5
 8.0   4
 9     5
EOD

set table $Data3
    plot $Data2 u (-$1):2 smooth unique
set table $Data4
    plot $Data1 u 1:2     w table, \
         $Data3 u (-$1):2 w table
unset table

set style fill solid 0.2 noborder

plot $Data4 u 1:2 w filledcurves lc "red" ti "filledcurves", \
     $Data1 u 1:2 w lp pt 7 ti "Data1", \
     $Data2 u 1:2 w lp pt 7 ti "Data2"
### end of script

Script: (for gnuplot>5.2.0)

Explanation:

  • this is feasible only since gnuplot 5.2.0 when indexing of datablocks was introduced
  • data needs to be in a datablock (see here: gnuplot: load datafile 1:1 into datablock)
  • the first dataset will be written line by line into a new dataset
  • the second dataset will be appended in reverse order
### filledcurves for 2 datasets with different x-values
# reguires gnuplot>=5.2.0
reset session

$Data1 <<EOD
-5   5
-2   4
 0   1
 1   2
 3   5
 5   4
 7   2
 9   4
EOD

$Data2 <<EOD
-5     7
-1.0   6
 0.5   4
 1.5   6
 2.5   7
 6.5   5
 8.0   4
 9     5
EOD

set print $Data3
    do for [i=1:|$Data1|]    { print $Data1[i] }
    do for [i=|$Data2|:1:-1] { print $Data2[i] }
set print

set style fill solid 0.2 noborder

plot $Data3 u 1:2 w filledcurves lc "red" ti "filledcurves", \
     $Data1 u 1:2 w lp pt 7 ti "Data1", \
     $Data2 u 1:2 w lp pt 7 ti "Data2"
### end of script

Result: (very similar for both scripts)

enter image description here

Upvotes: 0

Petr
Petr

Reputation: 11

This works for me. First fill with some color between the upper smoothed line and x axis, second fill white between the lower line and x axis, finally plot the two smoothened lines.

smooth cspline must be before with filledcurve

plot "test1.dat" using ($1):($2) notitle smooth cspline with filledcurve x1 lt rgb "#FFAAAA",\ "test2.dat" using ($1):($2) notitle smooth cspline with filledcurve x1 lt rgb "#FFFFFF",\ "test1.dat" using ($1):($2) notitle w l lw 2 lt 1 lc 0 smooth cspline,\ "test2.dat" using ($1):($2) notitle w l lw 2 lt 1 lc 1 smooth cspline

Upvotes: 1

mgilson
mgilson

Reputation: 309831

piggy-backing off of Raphael Roth's answer and looking at the gnuplot documentation, you can probably achieve this with a little shell magic for datasets that don't share X values as well.

plot '< tail -r test2.dat | cat test1.dat -' using 1:2 with filledcurves closed

One thing that I noticed when testing this out is that you should make sure that you have a newline at the end of test2.dat, otherwise tail -r won't work correctly (tac would probably work too, but it isn't installed on my Mac. This works taking the first datafile and appending the second datafile to the first one in reverse. (I am assuming the first and second datafiles are already ordered using ascending X values). In other words, as far as gnuplot is concerned, the data is ascending in x then descending in x. Since we used with filledcurves closed gnuplot treats all the points as a single polygon and then connects them. As far as smoothing the data, that is another question entirely. Just looking at the documentation, gnuplot offers a few smoothing algorithms, but they'll need to be used on your data ahead of time. The following is completely untested, but hopefully will be something similar to what you want (it will also probably only work in a unix type environment) ...

set table 'smoothed1'
plot 'test1.dat' using 1:2 smooth beizer  #beizer is just an example see "help plot datafile smooth" for more options
unset table

set table 'smoothed2'
plot 'test2.dat' using 1:2 smooth beizer
unset table

plot '< tail -r smoothed2 | cat smoothed1 -' using 1:2 with filledcurves closed

If it doesn't work, take a look at the gnuplot generated files "smoothed1" and "smoothed2" and see if that gives you any hints (e.g. are there extra newlines that should be removed?)

Upvotes: 1

Raphael Roth
Raphael Roth

Reputation: 27373

Is far as I know Gnuplot cannot make plots using data in 2 different files. In such cases I invoke a BASH program such as "paste" to merge the two file. I assume the two files contain data in the format "X Y" and they share a common X-grid (the number of datapoints must also be equal)

plot '<paste test1.dat test2.dat' u 1:2:4 w filledcurve

PS: If you are not using Linux I don't knwo how to do it....

Upvotes: 1

Related Questions