2

With a set of data files. I would like to performs series of operations on each file (such as fitting) and stack the resulting curves continiously along with my analysis (to see how each curves fit on the bigger picture). I wrote the following code snippet

reset
PATH = 'XRP_'
nmin = 1
nmax = 20

f(x) = log10(x); h(x) = a*x + b 
name(i) = sprintf(PATH.'%04d/data_main_ddnls_twod_mlce.dat', i)
set xrange [0:7]
start = 0
set fit 
do for [i=nmin:nmax]{
    fit [4:] h(x) name(i) using (f($1)):(f($4)) via a, b 
    if (start==0){
        plot name(i) using (f($1)):(f($4)) w l title sprintf("%04d", i)
    } else {
    replot name(i) using (f($1)):(f($4)) w l title sprintf("%04d", i)
}
start = start + 1
pause -1
}
# Add the slope 
replot (1./5.)*x  + 0.5 lc 'black' lw 3 dt 2
unset fit 
# pause -1

Instead of stacking all the previous curves + the current one, it plots only the current curve i-times (see loop of code). For instance, after 10 iterations it plots only the 10th datafile, 10 times (see legends on picture)

enter image description here

How can I fix this?

Many
  • 383
  • 4
  • 15

2 Answers2

3

The reason your plot behaves the way it does, and example (1) from theozh does also, is that "replot f(x)" acts by tacking ", f(x)" onto the end of the previous plot command. By putting it in a loop you are basically creating the successive commands

 plot f(x,i)
 plot f(x,i), f(x,i)
 plot f(x,i), f(x,i), f(x,i)
 ...

Yes the value of i might change each time, but nevertheless each plot command produces multiple copies of the same thing.

Alternative solution: I don't normally recommend multiplot mode for creating a single output, but in this case it may be the best option.

# force identical margins even if the range changes
set margins screen 0.1, screen 0.9, screen 0.1, screen 0.9

# ... same prelimary stuff as shown in the question

# revised loop using multiplot rather than replot
set multiplot
do for [i=nmin:nmax]{
    fit [4:] h(x) name(i) using (f($1)):(f($4)) via a, b 
    plot name(i) using (f($1)):(f($4)) w l \
        title sprintf("%04d", i) at screen 0.9, screen 1.0 - 0.02*i
    unset tics
}
unset multiplot

Note that you cannot use auto-generated title placement because each of the multiplot iterations will put the title in the same place. So instead we use the form "title foo at ". Similarly it is better to turn off tic generation after the first pass so that you don't redraw the tics and labels each time through the loop.

Ethan
  • 13,715
  • 2
  • 12
  • 21
  • 1
    Interesting. Learned again something. Could you maybe explain why the Version 3 of my examples with `eval` behave "as expected"? – theozh Jan 08 '19 at 21:09
  • 1
    Yes. In your 3rd example the substitution for the current value of "i" occurs when the sprintf() function is evaluated. The result of that evaluation is appended to the previous plot command. Therefore the growing plot command never contains "i" as a variable; instead it contains component strings that were created by sprintf at different times (when "i" had different values). – Ethan Jan 09 '19 at 05:16
1

Indeed, a strange behaviour which I also would not have expected. See the minimal examples below.

  • Version 1: basically your attempt. Not the expected result. I also don't know why.
  • Version 2: the expected result. Basically the same but not in a loop.
  • Version 3: the expected result, although in a loop but using eval.

Not very satisfying but at least some solution. Hopefully, others will have better solutions or explanations.

### plotting in a loop
reset session
set colorsequence classic

# Version 1
set title "Version 1"
do for [i=1:5] {
    if (i==1) { plot x**i }
    else { replot x**i noautoscale }
}
pause -1

# Version 2
set title "Version 2"
plot x**1
replot x**2 noautoscale
replot x**3 noautoscale
replot x**4 noautoscale
replot x**5 noautoscale
pause -1

# Version 3
set title "Version 3"
do for [i=1:5] {
    if (i==1) { cmd = sprintf("plot x**%d",i) }
    else { cmd = sprintf("replot x**%d noautoscale",i) }
    eval cmd
}
### end of code

enter image description here

theozh
  • 22,244
  • 5
  • 28
  • 72
  • I have just included the command `eval` into my workflow. I realized that this post is great too. Worth checking.Thank you @theozth. – Many Jul 16 '20 at 06:32