I would like to draw a curve logW= a+b*logP, where a = 12, b = -0.8
R = -0.4 of this curve. I would like to use data and look how this curve fits to data. Can I do it in gnuplot?
log(f(x)) = a+b*log(P)
a = 12, b = -0.8
fit f(x) 'data.txt' u 1:2 w p via a,b
plot f(x) 'data.txt' u 1:2
Does it sounds ok?
You are close, but there are little problems everywhere. Let's try to clean it up.
1) You must define f(x) itself, not log(f(x)). It is not clear from your statement, but I assume 'P' is the independent variable x?
f(P) = exp(a + b*log(P))
2) gnuplot commands are separated by semicolons, not commas
a = 12; b = -0.8
3) 'fit' is not a plotting style, so "with points" makes no sense as part of a fit command
fit f(x) 'data.txt' using 1:2 via a,b
4) The 'plot' command has two separate pieces: the data and the curve fit to it
plot 'data.txt' using 1:2 with points, f(x) with lines
Related
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 :)
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
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
I would like to fit data with a function f(x), where f(x) = (K)(xlog(x) + (1-x)log(1-x)) + Ax*(1-x) + B*(x)*2(1-x)**2, and K, A, B are the fitted constants. And, is what I have until now, where green solid line is the fitted curve. Here is the Data and below my gnuplot script
f(x)= (K)*(x*log(x) + (1-x)*log(1-x)) + A*x*(1-x) + B*(x)**2*(1-x)**2
pl '1417.dat' u 1:2
fit f(x) '1417.dat' u 1:2 via K,A,B
Obtained K = 8116.63, A = 2.20, B=43692
I need to fit accurately at the minima regions, can anyone suggest how to fit with less deviation.
I guess something must be "wrong" with your function/model (or with your data).
If k(x), a(x), and b(x) are all symmetric functions to x=0.5, and so is f(x).
How should the sum of 3 symmetric functions give an asymmetric function?
Code:
### impossible fitting
reset session
FILE = "SO/1417.dat"
k(x) = K*(x*log(x) + (1-x)*log(1-x))
a(x) = A*x*(1-x)
b(x) = B*x**2*(1-x)**2
f(x)= k(x) + a(x) + b(x)
set fit nolog
fit f(x) FILE u 1:2 via K,A,B
plot FILE u 1:2, k(x), a(x), b(x), f(x) lw 2 lc "red"
### end of code
Result:
For example the slightly different function below allows a better fitting :
Note that ln(x)ln(1-x) is exactly equal to zero at x=0 and x=1.
I want to plot two functions in different ranges in Gnuplot. As an example, I want to plot f(x) for xrange [0:0.5] and g(x) for xrange [0.5:1], both in a same graph.
What should I do for this?
You have at least two different solutions :
1) create a "heavyside" function :
f(x) = ... define your first function
g(x) = ... define your second function
h(x) = (x<0.5)?f(x):g(x)
plot h(x)
2) if you need some control on the color of each function, you could do
plot (x<0.5?f(x):1/0) lc 1, (x>0.5?g(x):1/0) lc 2
I'm using gnuplot to fit data to a certain function with unknown coefficients. I can get gnuplot to plot the fitted function, but I can't figure out how to have gnuplot give me the actual equation of that function.
The main command is:
f(x) = a/(1+(b*(x-c)*(x-c)))
a=80
b=.001
c=70
fit f(x) "data.dat" using 1:2:3 via a,b,c
I want gnuplot to tell me the values it comes up with for a b and c. Or maybe I am misinterpreting this command and it is actually using the values I plugged in as a,b, and c. Can anyone help me out here?
After fitting the values are stored in the respective variables a, b and c
f(x) = a/(1+(b*(x-c)*(x-c)))
a=80
b=.001
c=70
fit f(x) "data.dat" using 1:2:3 via a,b,c
print a, b, c
plot "data.dat" w p, f(x) title sprintf("a=%e, b=%e, c=%e", a, b, c)
I need to plot a function f(x), where x is discrete set of values (in my case positive integers). I couldn't find a way to specify a step-size when using the range option and samples doesn't seem to be the right solution. Finally, I would like to approximate f(x) with a smooth function.
I don't quite understand why samples is not the solution to your problem.
If I want to plot sin(x) on an interval between 0 and 10 with a point at every integer I use
set xrange [0:10]
set sample 11
plot sin(x) w p
Obviously the number of samples is xmax-xmin+1 (10 - 0 + 1 = 11).
Finally to tackle the approximation problem have a look at this website which discusses linear least squares fitting. For simple linear interpolation use lp instead of p.
Or alternatively, play around with the ceil(x) or floor(x) functions.
Maybe have a look at this example:
http://gnuplot.sourceforge.net/demo/prob2.html
You can do:
plot [1:12] '+' u ($0):(f($0))
Where, $0 will be replaced by 1, 2, ..., 12. You can even do a smooth on this. For instance:
f(x)=sin(2*x)
plot [1:12] f(x) t 'the function'\
, '+' u ($0):(f($0)) t 'the points'\
, '+' u ($0):(f($0)) smooth cspline t 'the smooth'