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
Related
In Matlab, we would first use [x, y] = meshgrid to generate the grid, then use mesh(x, y, z) to plot the 3D plot. I want to use the same funtionality in Julia Plots.jl, which API should I use? And how can I achieve that?
Thanks a lot in advance!!!
use surface
using Plots
xs = range(-2, stop=2, length=100)\
ys = range(-pi, stop=pi, length=100)
f(x,y) = x*sin(y)
surface(xs, ys, f)
In modern Julia, v1.17, the approach is to create x and y ranges. Julia has changed over the years, and used to have linspace - it doesn't anymore.
There are three ways to create a range:
x = start:step:end
x = range(start,end,step=step)
x = range(start,end,length=npts)
You will also need Plots. If you precompile it, it takes less time to load.
]
pkg > add Plots
pkg > precompile
pkg > Ctrl-C
You need to select your backend for Plots. Choices are:
pyplot() to select PyPlot (also requires Python's MatPlotLib)
plotly() to select Plotly (displays in web browser)
gr() to select GR, the default
Finally, you need to use surface to draw the surface. The function surface can take either a function or a matrix of z values. The function takes two parameters, x and y. Either the function is supplied directly, or it is applied to the ranges:
z = f.(x',y);
One of the ranges is transposed with ', and output suppressed with ;
Surface also takes optional parameters:
fill = :fillname
legend = true | false
size = (width,height)
clims = (lowlimit,highlimit)
An example:
using Plots
plotly()
x=range(-5,5,length=101)
y=range(-5,5,length=101)
function f(x,y)
r = sqrt(x^2+y^2)
sinc(r)
end
z = f.(x',y);
surface(x,y,z,size=(1600,1000),fill=:greens,legend=false)
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 wanted to fit a geometric mapping parameter with some input/output (x,y) points. The model is very simple:
xp = x .+ k.*x.*(x.^2+y.^2)
yp = y .+ k.*y.*(x.^2+y.^2)
k is the only parameter, (x,y) is an input point and (xp,yp) is an output point.
I formulated the input/output data array as:
x = [x for x=-2.:2. for y=-2.:2.]
y = [y for x=-2.:2. for y=-2.:2.]
in_data = [x y]
out_data = [xp yp]
However I'm confused about how to turn this into the LsqFit model, I tried:
k0=[0.]
#. model(x,p) = [x[:,1]+p[1]*x[:,1]*(x[:,1]^2+x[:,2]^2) x[:,2]+p[1]*x[:,2]*(x[:,1]^2+x[:,2]^2)]
ret = curve_fit(model, in_data, out_data, k0)
but got an error:
DimensionMismatch("dimensions must match: a has dims (Base.OneTo(25),
Base.OneTo(2)), must have singleton at dim 2")
So the question is: is it possible to use LsqFit for multi-variate output? (even though this particular problem can be solved analytically)
OK Just figured out the correct way to do this. The vector output variable needs to be stacked together to form a 1D array. So the only changes needed is:
out_data = [xp; yp]
I could not find a viable solution to this problem (and I am a beginner in R).
I have an equation as shown below
where n and K are constants. a and b are the variables.
How do I generate a 2-dimensional plot for the above in R?
Thanks in advance.
factorialfunction <-function(a,b, n, K){
K*(b^a)*((2+b)^(n+a))
}
Klist = c(1,5,10,50,100,200)
nlist = c(1,5,10,50,100,200)
#note that the n and K values are recycled, make them whatever you wish, they are constants,
#while a and b take on any values, here 100 values between zero and one
res <- mapply(factorialfunction,a = seq(.01,1,by=.01),
b=seq(.01,1,by=.01), n = rep(nlist,each = 100), K=rep(Klist, each=100))
#Then you can plot this six times.
#allow six plots on the panel if you want
par(mfrow = c(3,2))
#loop through different plots
for (i in 1:6)
plot(1:100,res[1:100 + (i-1)*100])
Note In this code I chose a and b to be between zero and one, I am not familiar with this function but It looks like some type of Beta.
You can generate more than 6 plots by changing klist and nlist and your par and for loop parameters.
Here is what you get, note this code is customizable to produce the plots for the values of n, K, a, and b that you want.
I'm trying a problem but first I have to plot in r
(x+1)(x+2)...(x+n),
with n being a fixed integer.
Any idea how to create this routine?
Provided x is greater than -1, this might be most efficiently computed by exploiting the relationship
(x + 1)*(x + 2)* ... *(x + n) = Gamma(x+n+1) / Gamma(x+1).
Gammas are computed internally in terms of their logarithms, so use these logs in the form of lgamma:
f <- function(x, n) exp(lgamma(x+n+1) - lgamma(x+1))
A plot can then be obtained via curve, for instance, as in
curve(f(x,3), 0, pi)
You want something like this?
f <- function(x, n) {
return(prod(1/(x+(1:n))))
}