4

I have a script that correctly plots 100 separate data files. Now I want to do a linear fit of each plot within a for loop. However, my script crashes when it gets to the fit command with the message "Skipping unreadable file "f(x) = a100*x + b%d". Can anyone help with the correct syntax? Thank you.

plotfile = "graph.eps"
set output plotfile
n=100
filename(n) = sprintf("%d_mod.int", n)
fstr(n) = sprintf('f(x) = a%d*x + b%d ' , n)
plot for [i = 1:n] filename(i) u 1:2 title sprintf("%d", i) w lp
fit for  [i = 1:n] fstr(i) filename(i) u 1:2 via a, b
Nadia
  • 75
  • 5

1 Answers1

5

fit doesn't support iterations. Here is how you can do it, but it needs some fiddling ;)

# define the functions depending on the current number
fstr(N) = sprintf("f%d(x) = a%d*x + b%d", N, N, N)

# The fitting string for a specific file and the related function
fitstr(N) = sprintf("fit f%d(x) 'file%d.dat' via a%d,b%d", N, N, N, N)

n = 2

# Do all the fits
do for [i=1:n] {
    eval(fstr(i))
    eval(fitstr(i))
}

# construct the complete plotting string
plotstr = "plot "
do for [i=1:n] {
    plotstr = plotstr . sprintf("f%d(x), 'file%d.dat'%s ", i, i, (i == n) ? "" : ", ")
}

eval(plotstr)

This works fine for me, if I use the following two test files:

File file1.dat:

1 1
2 2.1
3 3

and file2.dat:

1 1.5
2 2.7
3 4

The result with 4.6.5 is:

enter image description here

To have the actual result of the fitting displayed in the key you must construct the plotting string plotstr as follows:

plotstr = "plot "
do for [i=1:n] {
    t = sprintf("f%d(x) = %.2f*x + %.2f", i, value(sprintf('a%d', i)), value(sprintf('b%d', i)))
    plotstr = plotstr . sprintf("f%d(x) lt %d t '%s', ", i, i, t).\
                        sprintf(" 'file%d.dat' lt %d %s ", i, i, (i == n) ? "" : ", ")
}

with the result

enter image description here

Christoph
  • 47,569
  • 8
  • 87
  • 187
  • This works perfectly for me (also using version 4.6.5). I just had to change to my file names -- exactly what I was looking for -- thank you very much! – Nadia Jun 24 '14 at 09:11
  • Can I ask one more question? How can I change the plot string so that the entire fitting function f1(x) =a1*x + b1 is plotted instead of just f1(x)? If I extend the current expression to "f%d(x) = a%d*x + b%d" I get the error message "f_sprintf: attempt to print string value with numeric format" – Nadia Jun 24 '14 at 09:53
  • `f1(x)` is the entire fitting function which is plotted. Or do you want to have `f1(x) = a1*x + b1` placed in the legend (maybe even with `a1` and `b1` replaced with the actual numbers)? – Christoph Jun 24 '14 at 10:03
  • Sorry for being inaccurate :( Yes, I meant how can I have the entire fitting function (with the actual numbers of a1 and b1) printed in the legend? I am still learning the syntax rules... – Nadia Jun 24 '14 at 10:52
  • Your comment is incomplete. Beware, that `do for ... { plot ...` is different from `plot for ...`, see e.g. [loop over array in gnuplot](http://stackoverflow.com/a/18592561/2604213). – Christoph Jun 24 '14 at 11:55
  • I wanted to plot columns 3:4 of all 100 data files and also perform the line fitting using those data. I now have correctly changed the column selection in the fit string fitstr(N) = sprintf("fit f%d(x) '%d_mod.int' u 3:4 via a%d,b%d", N, N, N, N) as well as in the plot string ...sprintf(" '%d_mod.int' u 3:4 lt %d %s ", i, i, (i == n) ? "" : ", ") and the script does what I want. Thank you again for all the help! – Nadia Jun 24 '14 at 12:40