GNUplot - draw line using window coordinate system

喜你入骨 提交于 2021-01-29 07:59:59

问题


I try to plot two horizontal lines in a coordinate system using GNUPlot. The two lines represent average values in two datasets. Each dataset has the following constants: max, min and average. The same logic is to be applied to both datasets, so we can simply focus at one of them.

The output should be a 800 x 800 PNG image. They share the X axis, but their Y axis is different from each other in terms of the ranges' values and unit of measurement. Naturally, the numerical values of the two lines can vary arbitrarily. More precisely, I need to plot the two lines at, say, y = 300 and y = 500 in pixel coordinates, regardless of the value of average.

As far I as can tell, there is no way to tell GNUPlot to plot something at a specific pixel coordinate. However, I do believe it is possible to to it indirectly by adjusting the ranges to appropriate values. After poking around in GNUPlot, I managed to find proper values. When the proper range values are set, I think the datapoints in the set should be plotted nicely such that they fit into the graph. Now I need a general approach for any values.

I have the following GNUPlot script with arbitrary values for two horizontal lines:

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"

Use it like this: gnuplot -p script > plot.png

I need two procedure that looks something like this:

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

The ranges is put into set yrange in GNUPlot. The green line must be at y = 500 and the blue line must be at y = 300 (this is the pixel_target_y patameter). Any help is greatly appreciated!


回答1:


Let me try to repeat in my words if I understood your question correctly: You want to plot two datasets where the average (or mean) of each datasets have a fixed y-pixel-(or screen) position within the output graph (independent of data values and graph margins), correct?

For this you need the gnuplot variables GPVAL_TERM_YMIN and GPVAL_TERM_YMAX. In order to get these values you have to plot a dummy graph first. Then you need to do some calculations to get the proper range. As you can see in the result from 3 different plots: the green and blue lines are independent of x-labels or graph titles.

Code:

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

Result:



来源:https://stackoverflow.com/questions/58270397/gnuplot-draw-line-using-window-coordinate-system

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!