Triggered by this question, I observed something with variable definition during plot command which looks unexpected to me.
You can use the following construct to extract the maximum value (or some other value) of a column during plotting.
plot x0=y0=NaN $Data u 0:($2<y0 ? $2 : (x0=$1,y0=$2))
At the beginning of the plot command you define x0=y0=NaN
, and after plotting y0
will hold the maximum y-value and x0
the corresponding x-value of that maximum.
So, the following snippet:
plot x0=y0=NaN $Data u 0:($2<y0 ? $2 : (x0=$1,y0=$2)) w lp pt 7 lc "red", \
'+' every ::::0 u (x0):(y0):(sprintf("%g",y0)) w labels offset 0,1.0, \
y0 w l lc "web-green", \
'+' every ::::0 u (x0):(y0) w p pt 6 ps 2 lc "blue"
print sprintf("Test%d: y0 = %g",i,y0)
should do the following:
$Data
with linespoints(x0,y0)
with the value of y0
y=y0
(x0,y0)
y0
at the gnuplot consoleHere are several variations in order to find out what's going on.
Script:
### values after plotting defined during plotting
reset session
$Data <<EOD
0 0.0
1 2.3
2 9.2
3 3.4
4 4.1
5 1.0
EOD
set key noautotitle
set multiplot layout 2,3
i = 0
set title "Test ".(i=i+1)
plot x0=y0=NaN $Data u 0:($2<y0 ? $2 : (x0=$1,y0=$2)) w lp pt 7 lc "red", \
'+' every ::::0 u (x0):(y0):(sprintf("%g",y0)) w labels offset 0,1.0, \
y0 w l lc "web-green", \
'+' every ::::0 u (x0):(y0) w p pt 6 ps 2 lc "blue"
print sprintf("Test%d: y0 = %g",i,y0)
set title "Test ".(i=i+1)
plot x0=y0=NaN $Data u 0:($2<y0 ? $2 : (x0=$1,y0=$2)) w lp pt 7 lc "red", \
'+' every ::::0 u (x0):(y0):(sprintf("%g",y0)) w labels offset 0,1.0, \
9.2 w l lc "web-green", \
'+' every ::::0 u (x0):(y0) w p pt 6 ps 2 lc "blue"
print sprintf("Test%d: y0 = %g",i,y0)
set title "Test ".(i=i+1)
plot x0=y0=NaN $Data u 0:($2<y0 ? $2 : (x0=$1,y0=$2)) w lp pt 7 lc "red", \
'+' every ::::0 u (x0):(y0):(sprintf("%g",y0)) w labels offset 0,1.0, \
'+' u 1:(y0) w l lc "web-green", \
'+' every ::::0 u (x0):(y0) w p pt 6 ps 2 lc "blue"
print sprintf("Test%d: y0 = %g",i,y0)
set title "Test ".(i=i+1)
plot x0=y0=NaN $Data u 0:($2<y0 ? $2 : (x0=$1,y0=$2)) w lp pt 7 lc "red", \
'+' every ::::0 u (x0):(a0=y0):(sprintf("%g",y0)) w labels offset 0,1.0, \
y0-1 w l lc "web-green", \
a0 w l lc "web-green", \
'+' every ::::0 u (x0):(y0) w p pt 6 ps 2 lc "blue"
print sprintf("Test%d: y0 = %g, a0=%g",i,y0,a0)
set title "Test ".(i=i+1)
x0=y0=NaN
plot $Data u 0:($2<y0 ? $2 : (x0=$1,y0=$2)) w lp pt 7 lc "red", \
'+' every ::::0 u (x0):(y0):(sprintf("%g",y0)) w labels offset 0,1.0, \
y0 w l lc "web-green", \
'+' every ::::0 u (x0):(y0) w p pt 6 ps 2 lc "blue"
print sprintf("Test%d: y0 = %g",i,y0)
unset multiplot
### end of script
Result:
Test1: y0 = nan
Test2: y0 = nan
Test3: y0 = 9.2
Test4: y0 = nan, a0=9.2
Test5: y0 = 9.2
Observations:
Test1: the horizontal line at y=y0
is missing and y0
is printed as NaN
.
Test2: horziontal line is plotted because the fixed value of 9.2 is used, but y0
is again printed as NaN
.
Test3: now, '+' u 1:(y0) w l
is used to plot the horizontal line which is plotted this time at y=y0
and the printed value of y0
is now 9.2.
Test4: during plotting a0
is set equal to y0
. The plotting command y0-1
(just shifted for potential visibility) is not plotting a horizonal line, but the line at y=a0
is plotted . And after plotting again y0=NaN
, but a0=9.2
.
Test5: If I take the definition x0=y0=NaN
out of the plot command, y0=9.2
after the plotting command as expected
Some thoughts:
the blue empty circle is plotted in all cases, so the values of x0
and y0
must be known at the last plot (sub)command '+' every ::::0 u (x0):(y0) w p pt 6 ps 2 lc "blue"
if y0
are defind within a plot command, like plot x0=y0=NaN ...
maybe they are "local variables" and only accessible during that plot command? But then they should be undefined variable y0
after the plotting command. Why are they NaN
or the value they got assigned to at the beginning of the plot command?
Why is the value y0=9.2
after plotting only if I use '+' u 1:(y0) w l
instead of y0 w l
for plotting the horizontal line?
Why is the horizontal line plotted at y=a0=9.2
, but not at y=y0-1=8.2
?
I found an answer to this related question: gnuplot: variable values and definitions in plot command which explains the two pass process of a plotting command.
However, with this, I still don't understand the result of Test3 in contrast to Test1. Why is the horizontal line plotted at y=y0
and y0=9.2
after the plotting command?
Can maybe someone explain me what's going on here?
There are three key points to keep in mind.
plot y0
is a function plot. It is equivalent to f(x)=y0; plot f(x)
. In contrast to this, plot '+' using 1:(y0)
is a data plot. It is equivalent to reading a data file that contains the contstant value y0 on each line.
gnuplot accumulates values from a plot command in two passes. In each pass it steps through the entire plot command. Pass #1 handles data plots. During this pass definitions are executed; data is loaded for all the data components and used to establish limits for auto-scaling; function components are ignored. Pass #2 handles function plots. During this pass definitions are executed; data components are ignored; function components are evaluated over the range limits that were set by auto-scaling in the first pass. After both passes have completed, the program then generates a graph from the accumulated values for each component.
If there are no function components in the plot command, the second pass never happens.
Now let's see how this explains the differing outcomes from your test cases 1 and 3.
# test 1
plot y0=NaN, $Data using 1:(y0=123,$2), y0
# test 3
plot y0=NaN, $Data using 1:(y0=123,$2), '+' using 0:(y0)
Test 1 consists of a definition, a data plot, and a function plot. Gnuplot makes two passes through the plot command. During the first pass y0 is set to NaN, the values read from $Data are stored and y0 becomes 123 as a side-effect. During the second pass y0 is set to NaN, the data part is skipped, and the function f(x)=y0 is evaluated at each sampled x value. Since the function evaluates to NaN at all points it will not appear on the graph and afterwards y0 is still NaN.
Test 3 consists of a definition, a data plot, and another data plot. There are no function plots. During the first pass y0 is set to NaN, the values read from $Data are stored and y0 becomes 123 as a side-effect, then the values read from the pseudofile '+' are stored. "reading" from pseudofile '+' consists of evaluating (y0) repeatedly. There are no function components in this plot command, so no second pass is made. After the graph is generated from accumulated values, y0 is still 123.
Your test case 4 differs from case 3 by the addition of a function plot component. It doesn't matter what that function is. What matters is that the presence of a function components causes the program to execute the second processing pass, which includes the initial definition y0=NaN. That doesn't change the generated graph but it does affect the value left in y0 afterwards.