В контурном графике cntrlabel существует отличный подход к той же проблеме, когда файл 3D-данных соответствует прямоугольной сетке.
Теперь, когда значения не привязаны к сетке (то есть разбросаны случайным образом), gnuplot необходимо интерполировать их с помощью команды set dgrid3d nx,ny, где nx и ny — количество точек вдоль осей x и y соответственно.
Я сделал это, а затем применил решение, предложенное на контурном графике cntrlabel
Лучшее, что я получил, испробовав несколько вариантов, это следующее: если несколько строк соответствуют одному и тому же значению контура, помечается только одна строка (к счастью! - только одна метка cntr). Остальные не маркированы.
Мой (сокращенный) файл данных «datos.txt» (ранее отсортированный с помощью zsort) выглядит следующим образом:
0 66 0.2
0 69 0.3
0 70 0.3
0 72 0.7
0 74 0.1
0 74.1 0.1
0 79 0.3
0 80 0.2
0 81 0.3
0.1 61 -0.1
0.1 70 0.3
0.1 74 0.7
0.1 75 0.8
0.1 75.1 0.3
0.1 78 0.2
0.2 73 0.4
0.2 75 0.5
0.3 59 0.5
0.3 74 0.4
0.3 75 0.1
0.3 76 0.6
0.3 78 0.2
0.4 71 0.3
0.4 73 0.4
0.4 74 0.6
0.5 54 1.1
0.5 69 0.2
0.5 76 0.6
0.5 84 0.3
0.6 55 0.3
0.6 67 0.3
0.6 68 0.4
0.6 76 0.4
0.6 77 0.5
0.6 79 0.2
0.6 80 0.4
0.7 68 0.2
0.7 72 0.1
0.7 73 0
0.7 76 0.4
0.7 76.1 0.4
0.7 77 0.5
0.7 77.1 0.3
0.7 81 0.2
0.8 46 1
0.8 54 0.1
0.8 63 0.5
0.8 68 0.3
0.8 73 -0.1
0.8 74 0.3
0.8 78 0.3
0.8 81 0.3
0.8 82 0.2
0.9 50 0.8
0.9 56 0.5
0.9 60 1.2
0.9 65 0.3
0.9 70 0.7
0.9 74 0.2
0.9 79 0
0.9 80 0.2
0.9 80.1 0.1
1 69 0.4
1 76 0.5
1 81 0.2
1.1 54 0.3
1.1 73 0.1
1.1 76 0.3
1.1 76.1 0.4
1.1 81 0.2
1.2 56 0
1.2 75 0.3
1.2 79 0.1
1.3 68 0.3
1.3 75 0.3
1.3 82 0.3
1.4 46 0.2
1.4 66 0.7
1.4 71 0.2
1.4 78 0
1.4 81 0.3
1.4 81.1 0.4
1.5 45 0.9
1.5 60 1.3
1.5 71 0.1
1.5 76 0.1
1.5 82 0.2
1.5 82.1 0.2
1.5 82.2 0.2
1.5 84 0.2
1.6 55 0.9
1.6 57 1.4
1.6 71 0
1.6 81 0.1
1.6 82 0.1
1.6 83 0.1
1.6 84 0.3
1.7 62 0.3
1.7 66 1
1.7 75 0.4
1.7 76 0.3
1.7 78 0.3
1.7 78.1 0.1
1.7 80 0.1
1.7 84 0.3
1.8 56 0.3
1.8 63 0.3
1.8 67 0.6
1.8 69 0.3
1.8 77 0.1
1.8 77.1 0.4
1.8 78 0.3
1.8 79 0.3
1.8 84 0.2
1.9 49 0.2
1.9 53 0.3
1.9 53.1 0.3
1.9 54 0.2
1.9 79 0.1
1.9 82 0.3
1.9 84 0.3
2 60 1
2 68 0.2
2 73 0.5
2 77 0.2
2.1 45 1
2.1 61 0.6
2.1 66 0.4
2.1 82 0.1
2.2 61 0.1
2.2 64 0.2
2.3 64 0.5
2.3 70 0.2
2.3 76 0.1
2.4 73 0.1
2.5 53 0.2
2.5 68 -0.1
2.5 74 0.1
2.5 79 0.1
2.6 43 0.9
2.6 65 0.8
2.6 70 0.1
2.8 61 0.4
2.9 61 0.5
3 54 0.4
3.1 69 0.2
3.2 57 0.3
3.2 67 0.4
3.5 65 1.1
3.8 54 0.3
3.8 60 0.2
3.9 53 0.6
3.9 65 0
4.1 46 0.9
4.1 48 0.8
4.2 56 0.8
4.3 43 1.1
4.3 45 1.1
4.6 44 1
4.7 44 0.7
4.7 46 0.9
4.7 52 0.7
5.5 44 0.9
6.6 70 -0.5
И мой код
reset session
set dgrid3d 900,900 qnorm 9 # I use large parameters because data are highly oscillatory
set table $Contour1
splot "datos.txt" u 1:2:3
unset table
set contour
set view 0,0,1
set cntrparam levels incremental -0.5,0.1,1.5
set palette rgbformulae 33,13,10
set cbrange[-0.5:1.5]
set colorbox vertical user origin 0.93,0.38 size .02,.585
set xrange [0:*]
unset surface
set table $ContourLabels
splot "datos.txt" u 1:2:3
# splot $Contour1 u 1:2:3 # THIS VARIANT YIELDS A CONTOUR PLOT WITH NUMERICAL ARTIFACTS (SEE THE 2ND PLOT BELOW)
unset table
set cntrlabel format "{/:Bold %.1f}" font "Times-New Roman, 12" # THIS HAS NO EFFECT (?)
plot $Contour1 u 1:2:3 w image notitle, \
$ContourLabels u 1:2 w l notitle lc "black", \
$ContourLabels u 1:2:3 every ::1:1:1:1 w labels notitle
Сюжет следующий (кроме надписей и мелких деталей): А в варианте (см. скрипт) это выглядит так:
Я предполагаю, что причина, по которой он отображает одну метку cntr только для одной строки среди всех строк с одинаковым значением cntr, заключается в том, что команда every (см. В конце скрипта) работает только с блоками, но не с подблоками. И у меня есть много подблоков на блок (столько, сколько контуров для одного и того же значения)
Итак, знает ли кто-нибудь какой-нибудь обходной путь для создания одной метки cntr для каждого контура? Еще лучше: одна метка управления для каждого второго контура? (это, я думаю, с every)





Я предполагаю, что полученный график будет легче интерпретировать, если вы присвоите отдельный цвет и/или образец штриха для каждого уровня контура, который вы хотите пометить, а затем предоставите ключ, показывающий, какой шаблон указывает на какой уровень.
Альтернативно, в версии 6 вы можете построить график with contourfill и указать отдельный цвет для каждого уровня. В этом случае контурные уровни будут идеально соответствовать цветам. Если вам нужно меньше цветов, чем контурных линий (или наоборот), это вполне возможно, отрегулировав приращение контура линий отдельно от приращения границ цветовой заливки.
set dgrid3d 900,900 qnorm 9
set view map
unset key
set palette rgbformulae 33,13,10
set cbrange[-0.5:1.5]
set colorbox vertical user origin graph 1.05, 0 size graph 0.02, 1
set xrange noextend
set yrange noextend
# These control the fill
set cbtics -0.5,0.1,1.5 font ",8"
set contourfill cbtics
# These control the lines
set contour
set cntrparam levels incremental -0.5,0.1,1.5
set cntrlabel onecolor
# Use a coarser grid when generating labels
function $smallgrid() << EOF
set dgrid3d 45,45 qnorm 9
EOF
splot 'contour.dat' with contourfill, \
'' with lines lc "black" nosurface, \
g=$smallgrid() '' with labels pointnumber 1
Смотрите также https://gnuplot.sourceforge.net/demo_6.0/contourfill.html
Пересмотренный ответ
Насколько мне известно, в настоящее время нет способа сказать gnuplot «поместить только одну метку для этого уровня контура, даже если на графике он представлен несколькими сегментами линий». Самое близкое, что я могу придумать, — это использовать более грубую сетку, чтобы контуры не разбивались на множество частей. Установка ограничения на одну метку на сегмент линии будет ближе к желаемому пределу.
Синтаксис функционального блока в gnuplot 6 можно использовать для изменения сетки внутри команды построения графика. На измененном графике ниже добавлены метки контуров на сетке 45 x 45, по одной метке на каждый сегмент линии. Хитрость заключается в том, чтобы использовать фиктивное определение g = $smallgrid(), чтобы принудительно выполнить однократное выполнение функции, которая сбрасывает параметры сетки.
@ifffam Смотрите исправленный ответ
Это уже фантастический обходной путь. Если будут какие-то очень короткие контурные линии, будет ли простой способ (я имею в виду не еще один целый скрипт) заставить gnuplot не размещать какие-либо метки cntrlabel на этих очень коротких контурных линиях? (что-то вроде «если количество точек этой контурной линии меньше n, то не размещайте на ней метку cntr)
Нет, но это хорошая идея.
@ifffam это напоминает мне этот пост. Контурные линии часто разбиваются на несколько частей. Ну, вы могли бы соединить их вместе, но (по какой-то причине, которую я не знаю) они расположены в обратном порядке, что потребует некоторых дополнительных усилий, но это можно сделать. Если данные показывают так много маленьких островков с высокой плотностью контурных линий, как в вашем случае, я не уверен, что существует автоматизированная процедура, которая всегда будет давать хорошие результаты. Поэтому может потребоваться ручная регулировка.
@theozh действительно, это тот пост, о котором я упоминал выше :) хотя этот случай был намного проще... регулярная сетка, аналитическая функция для построения графика и (в основном) одна контурная линия для каждого значения контура. Если у вас есть представление о том, как изменить последние 3 строки вашего второго сценария для данного случая (это всего лишь последние 3 строки моего сценария), я был бы очень признателен, просто для изучения, поскольку решение, предложенное @Ethan уже здорово
@ifffam ой, извини, я пропустил ссылки в твоем вопросе. Я подумаю об этом, но думаю, что с точки зрения простоты и результата решение Итана, вероятно, близко к лучшему, которое вы можете получить.
@theozh на самом деле это только последняя строка, а не последние три строки вашего второго скрипта, которые не работают в данном случае: every ::1:1:1:1 помечает только одну строку для каждого значения контура, и pointnumber 1 нельзя использовать с plot, но с splot
@Итан, извини, если это глупый вопрос... вместо splot... with contourfill я бы хотел иметь только with pm3d или with image, но ни один из них не принимается... что мне делать, чтобы цвет плавно ухудшался?
В вашем исходном сообщении показан вывод pm3d. В данном случае я бы предпочел дискретные уровни цвета, но если вы предпочитаете плавный цвет, вы можете использовать то, что у вас уже есть. Возможно, я неправильно понимаю, что вы подразумеваете под «ухудшенным» цветом.
Возможно, лучше, чем «плавно меняющийся цвет», я должен сказать «плавно меняющийся цвет». Если я воспользуюсь тем, что у меня уже есть, мне следует plot $Contour1 u 1:2:3 w image вместе с другими частями вашего сценария. Но gnuplot (насколько мне известно) не может plot и splot одновременно (если только нет обходного пути). Итак, чтобы использовать ваш скрипт, мне нужно написать splot... with pm3d, но with pm3d разрешено только с plot, а не splot.
Нет, это у вас неправильно. pm3d только в 3D. Контуринг также выполняется только в 3D. Таким образом, обе команды pm3d+contour используют splot. Ваш исходный сценарий использовал график для создания поверхности и контуров, но он сохранял выходные данные в таблицах, а не отображал график напрямую. Затем вы использовали plot, чтобы рассматривать сохраненные таблицы как 2D-данные и аппроксимировать поверхность пикселями изображения. Но этот двухэтапный процесс не является необходимым. Вы можете просто использовать splot для создания выходного графика; нет необходимости перерабатывать его через таблицы в 2D-форму.
[продолжение]. Чтобы увидеть непрерывную окраску pm3d, а не дискретные цвета уровня контура, переработайте показанный мной скрипт двумя способами. (1) Добавьте команду set pm3d explicit. (2) Измените строку splot 'contour.dat' with contourfill на splot 'contour.dat' with pm3d.
Это не только сработало идеально, но даже лучше, чем ожидалось: на самых маленьких контурах не отображается никаких надписей (что было бы немного ошеломляюще, поскольку на моем графике их много). Я думаю, это как-то связано с номерами точек сетки x и y set dgrid3d
.@Итан, я ценю ваш вклад, он определенно полезен. Однако моей основной целью было разместить только одну метку управления поверх каждого контура (для простоты давайте пока забудем размещать только один контур на альтернативных контурах. Надеюсь, я смогу сделать это сам). Как я уже сказал, сложность здесь в том, что для каждого значения контура существует несколько строк, а не одна (то есть внутри каждого блока данных есть несколько подблоков данных). Кроме того, чтобы сделать метки кнопок управления хорошо видимыми, я пробовал
set cntrlabel format "{/:Bold %.1f}" font "Times-New Roman, 12", но не получилось.