MoreTeaPlease
MoreTeaPlease

Reputation: 31

Fitting and plotting a series in gnuplot

This is similar to this question and this but my problem is that I have several hundred files that need to be simultaneously fitted and plotted on one graph. Unlike the other questions posted I'm looking for the best fits for each file, not for the global data set so cat won't work.

I was hoping to use fit.. for like I do for plot but it's not working so well. Here's what I've got so far:

f(x) = 1+d*exp(-(x-f)**2/(2*(g**2)))+a*exp((-(x-b)**2)/(2*(c**2)))

filename(n) = sprintf("rheosaxs_saxs_%005d_0001_var_rebin_div.dat", n)
fit f(x) for [n=575:584] filename(n) u 1:2 via a,b,c,d,f,g
plot for [n=575:584] filename(n) using 1:2, f(x)

the error I get is: line 60: undefined variable: for which corresponds to the fit f(x) for [n=a:b]

I know that my starting parameters are reasonable because I can plot them without the fit command and they look sensible. Similarly my plot for works ok.

Any ideas? Thank you :)

Upvotes: 2

Views: 856

Answers (1)

Christoph
Christoph

Reputation: 48390

In version 5.2 gnuplot introduces arrays, which allow you to save the results of each fit and plot those later.

A simplified example script would be

file(n) = sprintf('myfile_%d.dat', n)
f(a, x) = a*x

array A[10]
do for [i=1:10] {
    tmpA = 1
    fit f(tmpA, x) file(i) via tmpA
    A[i] = tmpA
}

plot for [i=1:10] file(i),\
     for [i=1:10] f(A[i], x)

Although gnuplots arrays are implemented as linked list of user variables, it is not possible to use A[i] directly for the fit, but I had to use a temporary variable to get it right.

A full working example, including generation of random data, with python from gnuplot, uargh ;):

# generate some random data
system("python3 -c 'import random\nfor i in range(1, 11):\n\twith open(\"output_{0}.dat\".format(i), \"w\") as f:\n\t\tf.write(chr(10).join([str(i*100 + i* x * (1 + 0.1*(random.random()-0.5))) for x in range(0,100)]))'")


file(n) = sprintf('output_%d.dat', n)

f(a, b, x) = a*x + b
array A[10]
array B[10]
do for [i=1:10] {
    tmpA = 1
    tmpB = 1
    fit f(tmpA, tmpB, x) file(i) u 0:1 via tmpA, tmpB
    A[i] = tmpA
    B[i] = tmpB
}

plot for [i = 1:10] file(i) u 0:1 with points lt i notitle, \
     for [i=1:10] f(A[i], B[i], x) with lines lt i notitle

enter image description here

BTW: There is no fit for, because that is equivalent to do for { fit }. But when plotting, plot for generates a single plot with multiple functions, whereas do for { plot } makes several plots and should be used with multiplot

Upvotes: 2

Related Questions