I have a big set of data (more than 800 spectra) which need to be fit with a Maxwell-Boltzmann function. Let's start with only two spectra
data1={1.53108, -0.00184597}, {1.53503, -0.00131884}, {1.539,
0.00185461}, {1.54299, -0.00419277}, {1.54701, -0.00639723}, \
{1.55104, -0.00551708}, {1.5551, -0.00800965}, {1.55917, \
-0.00677264}, {1.56327, -0.0110927}, {1.56739, -0.0103286}, {1.57153,
-0.00973164}, {1.5757, -0.0111152}, {1.57988, -0.0113855}, {1.58409,
-0.0117398}, {1.58832, -0.0127097}, {1.59257, -0.0139916}, {1.59685,
-0.014101}, {1.60115, -0.0139898}, {1.60547, -0.0118756}, {1.60981,
-0.01029}, {1.61418, -0.00805921}, {1.61858, -0.000821386}, {1.62299,
0.00466453}, {1.62743, 0.00821456}, {1.6319, 0.0171329}, {1.63639,
0.0310873}, {1.6409, 0.0413745}, {1.64544, 0.053401}, {1.65001,
0.0616692}, {1.6546, 0.0702816}, {1.65921, 0.0752915}, {1.66385,
0.0843292}, {1.66852, 0.0806191}, {1.67322, 0.0865337}, {1.67794,
0.0820241}, {1.68268, 0.0869062}, {1.68746, 0.0808511}, {1.69226,
0.0864214}, {1.69709, 0.0748011}, {1.70194, 0.0822971}, {1.70683,
0.0768256}, {1.71174, 0.0783893}, {1.71668, 0.0702391}, {1.72165,
0.0791383}, {1.72665, 0.0711978}, {1.73168, 0.0772164}, {1.73673,
0.069743}, {1.74182, 0.0742699}, {1.74693, 0.0635676}, {1.75208,
0.0705165}, {1.75726, 0.0580984}, {1.76246, 0.0649913}, {1.7677,
0.0537584}, {1.77297, 0.0561502}, {1.77827, 0.0471154}, {1.7836,
0.0636209}, {1.78897, 0.0396738}, {1.79437, 0.0417097}, {1.7998,
0.036672}, {1.80526, 0.0483584}, {1.81076, 0.0359746}, {1.81629,
0.0478157}, {1.82185, 0.0356168}, {1.82745, 0.0382669}, {1.83308,
0.0287583}, {1.83875, 0.0391059}, {1.84445, 0.0300186}, {1.85019,
0.0283772}, {1.85596, 0.0245703}, {1.86177, 0.0263533}, {1.86761,
0.0170249}, {1.8735, 0.0268241}, {1.87942, 0.0134921}, {1.88537,
0.0148601}, {1.89137, 0.00781962}, {1.8974, 0.0119102}, {1.90348,
0.00445442}, {1.90959, 0.0074297}, {1.91574, 0.00365792}, {1.92193,
0.0108381}, {1.92816, -0.00316959}, {1.93443, -0.000539258},
{1.94074, 0.0043318}, {1.9471, -0.00430929}, {1.95349,
0.00441513}, {1.95993,
0.00595201}, {1.96641, -0.00438416}, {1.97293,
0.00600895}, {1.9795, -0.0021935}, {1.98611, -0.0121693}, {1.99276,
-0.0180589}, {1.99946, -0.000531422}, {2.00621, -0.0103922}, {2.013, \
-0.0134376}, {2.01983, -0.00937648}, {2.02671, -0.0123256}, {2.03364, \
-0.0171005}, {2.04062, -0.012415}, {2.04765, -0.00842077}, {2.05472,
-0.0222206}, {2.06184, -0.0173176}, {2.06902, -0.00691508}, {2.07624,
-0.0136626}, {2.08351, -0.00384277}, {2.09084, -0.0133483}, {2.09821,
-0.0214737}, {2.10564, -0.0107265}, {2.11312, -0.0168493}, {2.12066,
-0.0148875}, {2.12824, -0.0204143}, {2.13589, -0.00490166}, {2.14358,
-0.0163762}, {2.15134, -0.0132914}, {2.15915, -0.0119276}, {2.16702,
-0.00761709}, {2.17494, -0.00623985}, {2.18292, -0.0139031},
{2.19096, -0.00510826}, {2.19906, -0.00934085}}
and
data2={1.53108, 0.00187441}, {1.53503, 0.00891081}, {1.539,
0.0111849}, {1.54299, 0.004364}, {1.54701, 0.00628025}, {1.55104,
0.00680789}, {1.5551, 0.00853707}, {1.55917, 0.00920825}, {1.56327,
0.00928874}, {1.56739, 0.0117898}, {1.57153, 0.0114837}, {1.5757,
0.0139937}, {1.57988, 0.0161987}, {1.58409, 0.0164855}, {1.58832,
0.012975}, {1.59257, 0.0112959}, {1.59685, 0.0197188}, {1.60115,
0.021546}, {1.60547, 0.024632}, {1.60981, 0.0281438}, {1.61418,
0.0310039}, {1.61858, 0.0405104}, {1.62299, 0.047554}, {1.62743,
0.0507924}, {1.6319, 0.0578233}, {1.63639, 0.0714587}, {1.6409,
0.0806594}, {1.64544, 0.092654}, {1.65001, 0.101177}, {1.6546,
0.110297}, {1.65921, 0.114115}, {1.66385, 0.123051}, {1.66852,
0.116146}, {1.67322, 0.121149}, {1.67794, 0.115578}, {1.68268,
0.119243}, {1.68746, 0.108077}, {1.69226, 0.117215}, {1.69709,
0.0994373}, {1.70194, 0.102059}, {1.70683, 0.0951892}, {1.71174,
0.0951288}, {1.71668, 0.0837428}, {1.72165, 0.0940461}, {1.72665,
0.0814388}, {1.73168, 0.084036}, {1.73673, 0.0717605}, {1.74182,
0.0774831}, {1.74693, 0.0627288}, {1.75208, 0.0652405}, {1.75726,
0.0613616}, {1.76246, 0.0609079}, {1.7677, 0.0501096}, {1.77297,
0.0564122}, {1.77827, 0.0373842}, {1.7836, 0.0519737}, {1.78897,
0.0257087}, {1.79437, 0.0319259}, {1.7998, 0.0243793}, {1.80526,
0.0278366}, {1.81076, 0.021786}, {1.81629, 0.0273007}, {1.82185,
0.0157447}, {1.82745, 0.0144138}, {1.83308, 0.0149415}, {1.83875,
0.00669958}, {1.84445, 0.00744026}, {1.85019, 0.00570051}, {1.85596,
0.00109972}, {1.86177,
0.00250912}, {1.86761, -0.00782543}, {1.8735, -0.00982973},
{1.87942, -0.00647511}, {1.88537, -0.00960983}, {1.89137,
-0.00156248}, {1.8974, -0.0115654}, {1.90348, -0.0117897}, {1.90959,
-0.0053029}, {1.91574, -0.0144718}, {1.92193, -0.00995421}, {1.92816,
-0.0120168}, {1.93443, -0.0233383}, {1.94074, -0.0168577}, {1.9471,
-0.0257402}, {1.95349, -0.0185922}, {1.95993, -0.0176849}, {1.96641,
-0.0223636}, {1.97293, -0.0259812}, {1.9795, -0.0218552}, {1.98611,
-0.0207055}, {1.99276, -0.0189714}, {1.99946, -0.0136022}, {2.00621,
-0.0232702}, {2.013, -0.0199806}, {2.01983, -0.0220758}, {2.02671,
-0.0211568}, {2.03364, -0.0200752}, {2.04062, -0.0334419}, {2.04765,
-0.0262612}, {2.05472, -0.0285296}, {2.06184, -0.0262901}, {2.06902,
-0.0148341}, {2.07624, -0.0239107}, {2.08351, -0.0229732}, {2.09084,
-0.0159384}, {2.09821, -0.0150739}, {2.10564, -0.013385}, {2.11312,
-0.014881}, {2.12066, -0.0108471}, {2.12824, -0.0180245}, {2.13589,
-0.0149589}, {2.14358, -0.01849}, {2.15134, -0.010917}, {2.15915,
-0.0111556}, {2.16702, -0.00881686}, {2.17494, -0.00877528},
{2.18292, -0.0162301}, {2.19096, -0.00540098}, {2.19906, -0.00319884}}
I first define the function (k is a constant)
f[x_, A_, Ef_, T_, d_] := A*Exp[-(x - Ef)/(k*T)] + d;
Only Ef is the shared parameter among all of these 800 spectra. As previous answer, I started from here
MultiNonlinearModelFit[datasets_, expressions_, params_,
constraints : _ : True, independents_Symbol,
opts : OptionsPattern[]] :=
MultiNonlinearModelFit[datasets, expressions, constraints,
params, {independents}, opts];
MultiNonlinearModelFit[datasets : {__?(MatrixQ[#, NumericQ] &)},
expressions_List,
constraints : _ :
True, {fitParams__Symbol}, {independents__Symbol},
opts : OptionsPattern[]] /;
Length[expressions] === Length[datasets] :=
Module[{fitfun, numSets = Length[expressions],
augmentedData =
Catenate@
MapIndexed[
Join[(*Attach indices to the data*)
ConstantArray[N[#2], Length[#1]], #1, 2] &, datasets]},
fitfun =
With[{conditions =
Map[{\[FormalN] == #, expressions[[#]]} &, N@Range[numSets]]},
Which @@ Catenate[conditions]];
NonlinearModelFit[augmentedData,
If[TrueQ[constraints],
fitfun, {fitfun, constraints}], {fitParams}, {\[FormalN],
independents},(*use dataset index as extra independent variable*)
opts]];
Then, I applied
k= 0.0000651
fit = MultiNonlinearModelFit[{data1,
data2}, {amp1 *Exp[(-x + sharedOffset)/(k*T1)]+d1,
amp2 *Exp[(-x + sharedOffset)/(k*T2)]+d2}, {amp1,amp2, T1, T2, sharedOffset, d1, d2}, {x}];
fit["BestFitParameters"];
I chose just two spectra to start. The result of the fit is totally a mess. What I am doing wrong? Few question on this approach (I am new, sorry)
1) Is it possible to choose starting parameters for all of them? This would improve the fit a lot. 2) Is it possible to extend it to 800 spectra without defining 800 times A1,A2,A3... and so on?
amp1
andd1
cannot be estimated separately. Same thing foramp2
andd2
. $\endgroup$ – JimB Jun 11 '20 at 14:14(-x+sharedOffset)^2
rather than(-x+sharedOffset)
? $\endgroup$ – JimB Jun 11 '20 at 14:55ClearAll[MultiNonlinearModelFit
before your definitions, then in the definition of the fitter function changefitParams__Symbol
to simplyfitParams__
. Finally, use the form:{{amp1, 10}, {amp2, 20}, T1, T2, sharedOffset, d1, d2}
to give initial values for certain parameters. You can mix and match, giving initial values for some but not all. $\endgroup$ – MarcoB Jun 11 '20 at 14:55amp[1]
rather thanamp1
etc). To generate those, look intoArray
: for instance, considerArray[amp,10]
. $\endgroup$ – MarcoB Jun 11 '20 at 14:59