2

There is a style to fill the space between two functions of x. Examples of such plots can be found e.g. at http://gnuplot.sourceforge.net/demo/fillbetween.html Is there any way to make similar plot, but with flipped x and y axes? Here is the desired shape of a curve (without rotated/mirrored labels, titles and legends, of course)...

Approximate desired look

It could be done with closed contour (like last example here http://www.gnuplot.info/demo_svg_cvs/fillcrvs.html), but this would require reshuffling the data file. Any other options?

Thank you!

Roux
  • 435
  • 3
  • 12
  • Technically, the drawing above is no longer a function of x. Are you actually plotting functions or are you plotting from data files? It also helps if you include code that is close to what you want. Functions are harder, you need to invert your functions. Data files would be easier. Look into actually rotating the tic marks and place the 'title' as a rotated label. Legend is tougher. But with what you have above, have a blank title (title "") in the plot command. If you need a legend, [check this out](https://stackoverflow.com/questions/39334702/gnuplot-rotate-key). – Dan Sp. Jun 04 '18 at 15:02
  • Thank you! I try to plot a datafile. Probably, it is indeed easier to use filledcurves closed and tweaked data file... – Roux Jun 08 '18 at 07:07

3 Answers3

2

You can't do this directly. From help filledcurves:

The third variant fills the area between two curves sampled at the same set of x coordinates. It requires three columns of input data (x, y1, y2).

I don't think you can specify (y, x1, x2) directly. As a workaround you can the area between the y axis and the larger function in some color, and then fill the area between the y axis and the smaller function in white:

x1(y) = cos(y)+1
x2(y) = cos(y)+2
xmax(y) = (x1(y) > x2(y) ? x1(y) : x2(y))
xmin(y) = (x1(y) < x2(y) ? x1(y) : x2(y))

plot '+' using (xmax($1)):1 with filledcurve y1, \
     '+' using (xmin($1)):1 with filledcurve y1 fillcolor rgb "white"

enter image description here

This probably has to be tweaked a little if one or both of the two functions can be negative.

user8153
  • 4,049
  • 1
  • 9
  • 18
  • Thanks! Nice tweak! In my case, it is even simpler, since individual lines are percentiles.. – Roux Jun 08 '18 at 07:15
  • Well, this is a possible workaround if you don't have other options. To my opinion, a "clean" solution would not plot something and then cover some parts with the background color. What if you want a transparent background? – theozh Aug 23 '22 at 10:45
1

With gnuplot >=5.2 it could be tweaked even further because it allows arrays. The following code shows a workaround how filled curves between vertically oriented curves can be realized. You can even use transparency. If you download the attached PNG you will notice that it actually has a transparent background. The basic idea behind this workaround is to make closed areas and fill them. For this, you need to reverse one border, concatenate the borders and plot them filled. Unfortunately, gnuplot has no function to reverse datapoints in a column, so you have to do it in a special procedure yourself.

The code:

### "Vertical" filledcurves
reset session

# create some dummy data
N = 50
set samples N
set xrange [-5:5]
set table $Data
    plot '+' u (sin($1)):1:(rand(0)*0.3+1) with table
unset table

# put Borders into arrays
stats $Data nooutput
RowCount = STATS_records
array BorderX1[RowCount]
array BorderX2[RowCount]
array BorderY[RowCount]
set table $Dummy
    plot $Data u (BorderX1[$0+1]=$1-$3):(BorderX2[$0+1]=$1+$3):(BorderY[$0+1]=$2) with table
unset table

# reverse BorderX2 and merge borders
set samples RowCount
set table $Border
    plot '+' u (BorderX1[$0+1]):(BorderY[$0+1]) with table
    plot '+' u (BorderX2[RowCount-$0]):(BorderY[RowCount-$0]) with table
unset table

# make the plot
set object 1 rect at 0,-3 size 10,0.5 fs solid 1.0 fc rgb "black" back
set yrange[-5:5]
plot \
    $Border u 1:2 w filledcurves fc rgb "#AA00FF00" not,\
    $Border u ($1*1.5):2 w filledcurves fc rgb "#AAFFFF00" not,\
    $Data u ($1+2.5):2 w filledcurves y2 fc rgb "brown" not,\
    $Data u 1:2 w l lw 8 lc rgb "blue" not,\
    '+' u 1:(cos($1)-0.5):(cos($1)+0.5) w filledcurves lc rgb "grey" not,\
    '+' u 1:(cos($1)):(1) w l lw 3 dt 2 lc rgb "white" not
### end of code

The result:

enter image description here

theozh
  • 22,244
  • 5
  • 28
  • 72
0

Update: These are two alternative and simpler approaches compared to my first answer. One of them works even with gnuplot 5.0.

The plotting style filledcurves (so far) can only fill between two y-curves with identical x-values. However, gnuplot can fill closed curves. So, make the curve closed. Like in my first answer, you can do this if you reverse one curve and add it to the other one.

The assumption for both scripts is that the data has a common y-column, i.e. is organized in 3 columns, e.g. here: y x1 x2

Data: SO50676753.dat (same as OP's data, from silver.dat in the gnuplot demo directory)

# y    x1    x2     
  10   280   16.7332
  20   191   13.8203
  30   152   12.3288
  40   150   12.2474
  50   104   10.1980
  60    77    8.7750
  70    69    8.3066
  80    60    7.7460
  90    60    7.7460
 100    51    7.1414
 110    41    6.4031
 120    34    5.8310
 130    35    5.9161
 140    34    5.8310
 150    24    4.8990
 160    24    4.8990
 170    19    4.3589
 180    21    4.5826
 190    20    4.4721
 200    18    4.2426
 210    21    4.5826
 220    15    3.8730
 230    19    4.3589
 240    12    3.4641
 250    20    4.4721
 260    20    4.4721
 270    18    4.2426
 280    18    4.2426
 290    20    4.4721
 300    12    3.4641
 310    26    5.0990
 320    17    4.1231
 330     8    2.8284
 340     6    2.4495
 350     8    2.8284
 360    10    3.1623
 370    20    4.4721
 380    14    3.7417
 390     8    2.8284
 400    10    3.1623
 410     9    3.0000
 420     8    2.8284
 430    10    3.1623
 440    13    3.6056
 450     9    3.0000
 460     5    2.2361
 470     7    2.6458
 480    11    3.3166
 500     7    2.6458
 510     9    3.0000
 520    12    3.4641
 530     4    2.0000
 540     7    2.6458
 550    10    3.1623
 560     9    3.0000
 580     8    2.8284
 590     9    3.0000
 600     5    2.2361

Script 1: (works with gnuplot>=5.0.0)

Here you assume that you have monotonic and unique y-values. With this you can use the option smooth unique (available at least in gnuplot 4.x versions) to reverse one curve. However, since this solution here uses datablocks and plotting style with table it requires at least gnuplot 5.0.0. Maybe with some workarounds and temporary files you can also get it to work with some 4.6 versions.

### fill between vertical curves
reset session

FILE = "SO50676753.dat"

set table $Temp
    plot FILE u 1:2
    plot FILE u (-$1):3 smooth unique
set table $Data
    plot $Temp u 2:1     index 0 w table, \
            '' u 2:(-$1) index 1 w table
unset table

set style fill solid 0.3
set grid x,y

plot $Data u 1:2 w filledcurves
### end of script

Script 2: (works with gnuplot>=5.2.0)

With this solution there are no special assumptions about the data, but since it uses indexing of datablocks it requires gnuplot>=5.2.0.

### fill between vertical curves
reset session

FILE = "SO50676753.dat"

set table $Temp1
    plot FILE u 2:1 w table
set table $Temp2
    plot FILE u 3:1 w table
unset table

set print $Data
    do for [i=1:|$Temp1|]    { print $Temp1[i] }
    do for [i=|$Temp2|:1:-1] { print $Temp2[i] }  # reverse data
set print

set style fill solid 0.3
set grid x,y

plot $Data u 1:2 w filledcurves
### end of script

Result: (same for both scripts):

enter image description here

theozh
  • 22,244
  • 5
  • 28
  • 72