Гнуплот заполнил кривые откидные оси

Существует стиль для заполнения пространства между двумя функциями x. Примеры таких графиков можно найти, например, по адресу http://gnuplot.sourceforge.net/demo/fillbetween.html Есть ли способ создать аналогичный график, но с перевернутыми осями x и y? Вот желаемая форма кривой (без повернутых / зеркальных надписей, заголовков и надписей, конечно)...

Примерный желаемый вид

Это можно сделать с замкнутым контуром (как в последнем примере здесь http://www.gnuplot.info/demo_svg_cvs/fillcrvs.html), но для этого потребуется перестановка файла данных. Есть другие варианты?

Спасибо!

3 ответа

Решение

Вы не можете сделать это напрямую. От help filledcurves:

Третий вариант заполняет область между двумя кривыми, отобранными по одному и тому же набору координат х. Требуется три столбца входных данных (x, y1, y2).

Я не думаю, что вы можете указать (у, х1, х2) напрямую. В качестве обходного пути вы можете выделить область между осью y и большей функцией каким-либо цветом, а затем залить область между осью y и меньшей функцией белым цветом:

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"

Это, вероятно, нужно немного подправить, если одна или обе функции могут быть отрицательными.

При gnuplot >=5.2 его можно настроить еще больше, поскольку он допускает массивы. Следующий код показывает обходной путь, которым могут быть реализованы заполненные кривые между вертикально ориентированными кривыми. Вы даже можете использовать прозрачность. Если вы скачаете прикрепленный PNG, вы заметите, что он на самом деле имеет прозрачный фон. Основная идея этого обходного пути - создать закрытые области и заполнить их. Для этого вам нужно повернуть одну границу, объединить границы и построить их заполненными. К сожалению, gnuplot не имеет функции для обратного обращения к точкам данных в столбце, поэтому вы должны сделать это в специальной процедуре самостоятельно.

Код:

### "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

Результат:

Обновление: это два альтернативных и более простых подхода по сравнению с моим первым ответом. Один из них работает даже с gnuplot 5.0.

Стиль построенияfilledcurves(пока что) может заполнить только две y-кривые с одинаковыми значениями x. Однако gnuplot может заполнять замкнутые кривые. Итак, сделайте кривую замкнутой. Как и в моем первом ответе, вы можете сделать это, если перевернете одну кривую и добавите ее к другой.

Предположение для обоих скриптов состоит в том, что данные имеют общий столбец Y, т.е. организованы в 3 столбца, например здесь:y x1 x2

Данные: SO50676753.dat(то же, что и данные ОП, изsilver.datв демонстрационном каталоге gnuplot)

      # 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

Сценарий 1: (работает с gnuplot>=5.0.0)

Здесь вы предполагаете, что у вас есть монотонные и уникальные значения y. При этом вы можете использовать опциюsmooth unique(доступно по крайней мере в версиях gnuplot 4.x), чтобы перевернуть одну кривую. Однако, поскольку в этом решении здесь используются блоки данных и стиль построения графиковwith tableдля этого требуется как минимум gnuplot 5.0.0. Возможно, с некоторыми обходными путями и временными файлами вы также сможете заставить его работать с некоторыми версиями 4.6.

      ### 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

Сценарий 2: (работает с gnuplot>=5.2.0)

В этом решении нет особых предположений о данных, но, поскольку оно использует индексирование блоков данных, требуется 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

Результат: (одинаково для обоих скриптов):

Другие вопросы по тегам