Гнуплот заполнил кривые откидные оси
Существует стиль для заполнения пространства между двумя функциями 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
Результат: (одинаково для обоих скриптов):