GNUplot - нарисовать линию, используя оконную систему координат - PullRequest
0 голосов
/ 07 октября 2019

Я пытаюсь построить две горизонтальные линии в системе координат, используя GNUPlot. Две линии представляют средние значения в двух наборах данных. Каждый набор данных имеет следующие константы: max, min и average. Одна и та же логика должна применяться к обоим наборам данных, поэтому мы можем просто сфокусироваться на одном из них.

На выходе должно быть изображение PNG 800 x 800. Они имеют общую ось X, но их ось Y отличается друг от друга с точки зрения значений диапазонов и единиц измерения. Естественно, что числовые значения двух линий могут меняться произвольно. Точнее, мне нужно построить две линии, скажем, у = 300 и у = 500 в пиксельных координатах, независимо от значения average.

Насколько я могу судить, нетспособ сказать GNUPlot построить что-то по определенной пиксельной координате. Тем не менее, я считаю, что это возможно косвенно путем корректировки диапазонов до соответствующих значений. После поиска в GNUPlot мне удалось найти правильные значения. Когда заданы правильные значения диапазона, я думаю, что точки данных в наборе должны быть построены так, чтобы они вписывались в график. Теперь мне нужен общий подход для любых ценностей.

У меня есть следующий скрипт GNUPlot с произвольными значениями для двух горизонтальных линий:

set term png size 800, 800
set multiplot layout 1, 1

# Green line
min_green = 0
max_green = 50
set size 1,1
set ytics 20
set yrange [min_green : max_green]
avg_green = 22
plot avg_green linecolor rgb "green"

# Blue line
min_blue = 10
max_blue = 70
set size 1,1
set ytics 20
set yrange [min_blue : max_blue]
avg_blue = 14
plot avg_blue linecolor rgb "blue"

Используйте его так: gnuplot -p script > plot.png

Мне нужны две процедуры, которые выглядят как-токак это:

range_min = get_new_min_range(pixel_target_y, min, max, avg)
range_max = get_new_max_range(pixel_target_y, min, max, avg)

Диапазоны устанавливаются в заданный диапазон в GNUPlot. Зеленая линия должна быть на y = 500, а синяя линия должна быть на y = 300 (это патаметер pixel_target_y). Любая помощь с благодарностью!

1 Ответ

0 голосов
/ 08 октября 2019

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

Для этого вам нужны переменные gnuplot GPVAL_TERM_YMIN и GPVAL_TERM_YMAX. Чтобы получить эти значения, вы должны сначала построить фиктивный график. Затем вам нужно сделать некоторые расчеты, чтобы получить правильный диапазон. Как вы можете видеть в результате из 3 разных графиков: зеленые и синие линии не зависят от меток x или заголовков графиков.

Код:

### have average lines at fixed pixel position within the plot
reset session

myTermSizeX = 800
myTermSizeY = 800
set term pngcairo size myTermSizeX, myTermSizeY
myOutputFile = "Output.png"
set output myOutputFile

myFixY1 = 500
myFixY2 = 300

set title "Some graph title"
set xlabel "x-Axis title"

# create some test data
set table $Data1
    plot '+' u 1:(rand(0)*50+40) smooth bezier
unset table
set table $Data2
    plot '+' u 1:(rand(0)*40+10) smooth bezier
unset table

stats $Data1 u 2 name 'Data1' nooutput
stats $Data2 u 2 name 'Data2' nooutput
print Data1_min, Data1_mean, Data1_max
print Data2_min, Data2_mean, Data2_max

# dummy plot to get GPVAL_TERM_YMIN, GPVAL_TERM_YMAX
plot x

R_grph1 = real(myFixY1 - GPVAL_TERM_YMIN)/(GPVAL_TERM_YMAX - GPVAL_TERM_YMIN)
R_grph2 = real(myFixY2 - GPVAL_TERM_YMIN)/(GPVAL_TERM_YMAX - GPVAL_TERM_YMIN)

R_data1 = (Data1_mean - Data1_min)/(Data1_max-Data1_min)
R_data2 = (Data2_mean - Data2_min)/(Data2_max-Data2_min)

if (R_data1 > R_grph1) {
    Y1min = Data1_min
    Y1max = (Data1_mean - Data1_min)/R_grph1 + Data1_min
}
else {
    Y1max = Data1_max
    Y1min = Data1_max - (Data1_max - Data1_mean)/(1-R_grph1)
}
print Y1min,Y1max

if (R_data2 > R_grph2) {
    Y2min = Data2_min
    Y2max = (Data2_mean - Data2_min)/R_grph2 + Data2_min}
else {
    Y2max = Data2_max
    Y2min = Data2_max - (Data2_max - Data2_mean)/(1-R_grph2)
}
print Y2min,Y2max

set yrange [Y1min:Y1max]
set ytics nomirror
set y2range [Y2min:Y2max]
set y2tics nomirror

set output myOutputFile   # it seems you have to specify the output again
set key top center

plot \
    $Data1 u 1:2 axes x1y1 w lp pt 7 lc rgb "red" ti "Data1", \
    Data1_mean axes x1y1 w l lw 2 lc rgb  "green" ti "Data1 mean", \
    Data1_min axes x1y1 lt 0 not, \
    Data1_max axes x1y1 lt 0 not, \
    $Data2 u 1:2 axes x1y2 w lp pt 7 lc rgb "orange" ti "Data2", \
    Data2_mean axes x1y2 w l lw 2 lc rgb  "blue" ti "Data2 mean", \
    Data2_min axes x1y2 lt 0 not, \
    Data2_max axes x1y2 lt 0 not

set output
### end of code

Результат:

enter image description here

...