Message Boards Message Boards

Obtain each residue with MultiNonlinearModelFit global analysis

Dear All, I use the MultiNonlinearModelFit function to carry out a global analysis of several chemical kinetics (Absorbance vs. time). It works well but I would like to retrieve the residues for each kinetic separately? Is there a quick way or do I have to do it by hand for each kinetics? I tried to use "FitResiduals" (see the code below with 2 kinetics), but it gives me a single vector without the x-coordinate and I guess that corresponds to the residuals for one of the kinetics.

If you have any idea how to do this quickly (I have 15 kinetics to analyze at a time, that's a lot!), I'll be glad you share it! Thank you in advance for your advice and help. Hélène

Clear[k3, k4, ea360, eh360, ef360, ea380, eh380, ef380]
sol = ParametricNDSolve[{Derivative[1][ag][t] == -k3*ag[t], 
    Derivative[1][gox][t] == k3*ag[t], 
    Derivative[1][h][t] == k3*ag[t] - 2*k4*h[t]*h[t], 
    Derivative[1][ff][t] == 2*k4*h[t]*h[t], ag[0] == 0.000006, 
    h[0] == 0, gox[0] == 0, ff[0] == 0}, {ag, gox, h, ff}, {t, 0, 
    2000}, {k3, k4}];
{agFunc, goxFunc, hFunc, fFunc} = {ag, gox, h, ff} /. sol;
model360[k3_, k4_, ea360_, eh360_, ef360_][
   t_] := (((agFunc[k3, k4][t])*ea360) + (eh360*
      hFunc[k3, k4][t]) + (ef360*fFunc[k3, k4][t]));
model380[k3_, k4_, ea380_, eh380_, ef380_][
   t_] := (((agFunc[k3, k4][t])*ea380) + (eh380*
      hFunc[k3, k4][t]) + (ef380*fFunc[k3, k4][t]));
fit = MultiNonlinearModelFit[{Abs360, 
    Abs380}, {model360[k3, k4, ea360, eh360, ef360][t], 
    model380[k3, k4, ea380, eh380, ef380][t]}, {{k3, 0.1}, {k4, 
     450}, {ea360, 5000}, {eh360, 1500}, {ef360, 3000}, {ea380, 
     5000}, {eh380, 2000}, {ef380, 2000}}, {t}];
mle = fit["BestFitParameters"]
Show[ListPlot[{Abs360, Abs380}], 
 Plot[{model360[k3, k4, ea360, eh360, ef360][t] /. mle, 
   model380[k3, k4, ea380, eh380, ef380][t] /. mle}, {t, 0, 310}]]
residu = fit["FitResiduals"]
ListPlot[residu]
5 Replies

Dear Sjoerd, Thank you for your reply and your great help. I'm going to try to play with "repeatedTake" to see how it works.

Hélène

As for your second question:

In addition, to associate x coordinates (given by the data vector Xdata) to each residue vector, I use Timeseries like this

res360 = TimeSeries[residu360, {Xdata}] 

But isn't there another way of associating x-coordinates?

The typical way to do this would be:

res360 = Transpose[{Xdata, residu360}]

which will give you a list of pairs res360 = {{x1, res1}, {x2, res2}, ...}. This can then be easily plotted with ListPlot. There's nothing wrong with the Timeseries method, though. You can use Normal to convert the Timeseries to a list of pairs.

POSTED BY: Sjoerd Smit

Yes, if you have multiple datasets, the following function should help you to split the residuals apart again. It makes use of FoldPairList, which is a bit obscure but very powerful in some situations:

repeatedTake[list_List, lengths : {__Integer}] /; Length[list] >= Total[lengths] :=
  FoldPairList[TakeDrop, list, lengths];

(*Example usage *)
repeatedTake[Range[20], {3, 5, 10, 2}]

Out[23]= {{1, 2, 3}, {4, 5, 6, 7, 8}, {9, 10, 11, 12, 13, 14, 15, 16, 17, 18}, {19, 20}}

Essentially, this function takes a number of elements from a list and then passes the rest on to the next iteration at which point a different number of elements is extracted again. So you'd use:

repeatedTake[fit["FitResiduals"], Length /@ {Abs360, Abs380, ... (* more datasets *)}]
POSTED BY: Sjoerd Smit

Dear Sjoerd, Thank you so much for your kind help and for this very useful function. Yes I'm using your repository function! I really appreciate and this function saves me precious time!

Your solution to separate the residues is doing well. I tried to adapt it to my case where I have at least 15 kinetics and therefore 15 residues at the end. I found the following example to extract the 2nd set of residues, but I guess it should be more elegant. Note that, finally, the dimension of all the data vector is the same.

Take[fit["FitResiduals"], {Length[Abs360] + 1, 2*Length[Abs360]}]

In addition, to associate x coordinates (given by the data vector Xdata) to each residue vector, I use Timeseries like this

`res360 = TimeSeries[residu360, {Xdata}] 

But isn't there another way of associating x-coordinates?

Below, two different kinetics.

Many thanks Hélène

Abs360 = {{0.1, 0.020578}, {0.2, 0.0206772}, {0.3, 0.0201706}, {0.4, 
   0.0203716}, {0.5, 0.0201917}, {0.6, 0.0198135}, {0.7, 
   0.0199346}, {0.8, 0.0196224}, {0.9, 0.0195781}, {1, 
   0.0196144}, {1.1, 0.0192659}, {1.2, 0.0193823}, {1.3, 
   0.0191421}, {1.4, 0.0189982}, {1.5, 0.0193048}, {1.6, 
   0.0189436}, {1.7, 0.0188917}, {1.8, 0.0191417}, {1.9, 
   0.0187902}, {2, 0.0188375}, {2.1, 0.0189052}, {2.2, 
   0.0183759}, {2.3, 0.0187808}, {2.4, 0.0185128}, {2.5, 
   0.0183641}, {2.6, 0.0186758}, {2.7, 0.0184845}, {2.8, 
   0.0184009}, {2.9, 0.0185606}, {3, 0.0183937}, {3.1, 
   0.0184206}, {3.2, 0.0183251}, {3.3, 0.0183891}, {3.4, 
   0.0183389}, {3.5, 0.0183337}, {3.6, 0.018388}, {3.7, 
   0.0184438}, {3.8, 0.0182679}, {3.9, 0.0184027}, {4, 
   0.0183829}, {4.1, 0.0182594}, {4.2, 0.0184188}, {4.3, 
   0.0181372}, {4.4, 0.0182514}, {4.5, 0.0181963}, {4.6, 
   0.0181273}, {4.7, 0.0182523}, {4.8, 0.0182289}, {4.9, 
   0.0182162}, {5, 0.0184325}, {5.1, 0.0184163}, {5.2, 
   0.0181779}, {5.3, 0.0184368}, {5.4, 0.0181866}, {5.5, 
   0.0183913}, {5.6, 0.0184662}, {5.7, 0.0181838}, {5.8, 
   0.0184663}, {5.9, 0.0182806}, {6, 0.0182477}, {6.1, 
   0.018397}, {6.2, 0.0181889}, {6.3, 0.0186968}, {6.4, 
   0.0183699}, {6.5, 0.0182666}, {6.6, 0.0185456}, {6.7, 
   0.0183102}, {6.8, 0.018459}, {6.9, 0.0184074}, {7, 
   0.0183427}, {7.1, 0.0185573}, {7.2, 0.0186108}, {7.3, 
   0.0183396}, {7.4, 0.0186407}, {7.5, 0.0186582}, {7.6, 
   0.0184255}, {7.7, 0.0187252}, {7.8, 0.0184347}, {7.9, 
   0.0183682}, {8, 0.0187422}, {8.1, 0.0184937}, {8.2, 
   0.0184836}, {8.3, 0.0186525}, {8.4, 0.0182987}, {8.5, 
   0.0185847}, {8.6, 0.0186894}, {8.7, 0.0185912}, {8.8, 
   0.0186902}, {8.9, 0.018508}, {9, 0.0185523}, {9.1, 
   0.0188243}, {9.2, 0.0184394}, {9.3, 0.0187197}, {9.4, 
   0.0188471}, {9.5, 0.0185477}, {9.6, 0.0187264}, {9.7, 
   0.0187072}, {9.8, 0.0187788}, {9.9, 0.0189129}, {10, 
   0.0187566}, {12, 0.0187736}, {14, 0.0188994}, {16, 0.0190955}, {18,
    0.019202}, {20, 0.0194405}, {22, 0.0195111}, {24, 0.0197144}, {26,
    0.0198916}, {28, 0.0200099}, {30, 0.0201967}, {32, 0.020273}, {34,
    0.0204846}, {36, 0.0206786}, {38, 0.0207093}, {40, 
   0.0208471}, {42, 0.0210193}, {44, 0.0211584}, {46, 0.0212226}, {48,
    0.0214754}, {50, 0.0214993}, {52, 0.0215167}, {54, 
   0.0216675}, {56, 0.0218844}, {58, 0.0219545}, {60, 0.0220378}, {62,
    0.0221628}, {64, 0.0222014}, {66, 0.0223362}, {68, 
   0.0224844}, {70, 0.0225561}, {72, 0.02266}, {74, 0.0227757}, {76, 
   0.0228907}, {78, 0.0229685}, {80, 0.0229929}, {82, 0.0231938}, {84,
    0.0232257}, {86, 0.0233388}, {88, 0.0234633}, {90, 0.023574}, {92,
    0.023637}, {94, 0.0237275}, {96, 0.0238103}, {98, 0.023883}, {100,
    0.0239616}, {102, 0.0240022}, {104, 0.0242009}, {106, 
   0.0242503}, {108, 0.0242852}, {110, 0.0242963}, {112, 
   0.0244763}, {114, 0.0244621}, {116, 0.0246056}, {118, 
   0.0246208}, {120, 0.0246888}, {122, 0.0247914}, {124, 
   0.0249202}, {126, 0.0249675}, {128, 0.0250516}, {130, 
   0.025148}, {132, 0.0251178}, {134, 0.0251709}, {136, 
   0.0252728}, {138, 0.0253096}, {140, 0.0253722}, {142, 
   0.0253175}, {144, 0.0254264}, {146, 0.0254797}, {148, 
   0.025505}, {150, 0.025691}, {152, 0.0256809}, {154, 
   0.0256734}, {156, 0.0257156}, {158, 0.0258192}, {160, 
   0.025893}, {162, 0.0259137}, {164, 0.0259853}, {166, 
   0.0260135}, {168, 0.0260477}, {170, 0.026035}, {172, 
   0.0260938}, {174, 0.0262055}, {176, 0.0262037}, {178, 
   0.0263215}, {180, 0.026325}, {182, 0.0264696}, {184, 
   0.0265687}, {186, 0.0265805}, {188, 0.0266117}, {190, 
   0.0266924}, {192, 0.0266742}, {194, 0.0267336}, {196, 
   0.0267832}, {198, 0.0267737}, {200, 0.026911}, {202, 
   0.0269651}, {204, 0.0270751}, {206, 0.0270431}, {208, 
   0.0270912}, {210, 0.027113}, {212, 0.0272397}, {214, 
   0.0272315}, {216, 0.0272136}, {218, 0.0272959}, {220, 
   0.0273545}, {222, 0.0274866}, {224, 0.0275066}, {226, 
   0.0275655}, {228, 0.0275749}, {230, 0.0276744}, {232, 
   0.0276867}, {234, 0.0276864}, {236, 0.0277598}, {238, 
   0.0277984}, {240, 0.0277882}, {242, 0.0278638}, {244, 
   0.0278838}, {246, 0.0279382}, {248, 0.0279682}, {250, 
   0.0278752}, {252, 0.0279206}, {254, 0.0280338}, {256, 
   0.0280315}, {258, 0.0280694}, {260, 0.0279798}, {262, 
   0.0279821}, {264, 0.0279889}, {266, 0.028129}, {268, 
   0.0281517}, {270, 0.0281573}, {272, 0.0281823}, {274, 
   0.0282926}, {276, 0.0282894}, {278, 0.0282789}, {280, 
   0.0283418}, {282, 0.0283163}, {284, 0.0283835}, {286, 
   0.0283738}, {288, 0.0284595}, {290, 0.0284795}, {292, 
   0.0285648}, {294, 0.0286267}, {296, 0.0287073}, {298, 
   0.0286502}, {300, 0.0286367}, {302, 0.0287067}, {304, 
   0.0287968}, {306, 0.0288177}, {308, 0.0287733}, {310, 0.0288294}}
Abs380 = {{0.1, 0.0181389}, {0.2, 0.0184868}, {0.3, 0.0178332}, {0.4, 
   0.0177303}, {0.5, 0.0178026}, {0.6, 0.0174869}, {0.7, 
   0.0173248}, {0.8, 0.0171897}, {0.9, 0.0169962}, {1, 
   0.0169126}, {1.1, 0.0167383}, {1.2, 0.016798}, {1.3, 
   0.0165851}, {1.4, 0.0165418}, {1.5, 0.016441}, {1.6, 
   0.0162169}, {1.7, 0.0162628}, {1.8, 0.0162034}, {1.9, 
   0.0161954}, {2, 0.01608}, {2.1, 0.016113}, {2.2, 0.0157913}, {2.3, 
   0.0159812}, {2.4, 0.0160256}, {2.5, 0.0158312}, {2.6, 
   0.0159551}, {2.7, 0.0157653}, {2.8, 0.0156584}, {2.9, 
   0.015745}, {3, 0.0156091}, {3.1, 0.0157609}, {3.2, 0.01556}, {3.3, 
   0.0157248}, {3.4, 0.0157816}, {3.5, 0.0154636}, {3.6, 
   0.0157627}, {3.7, 0.0158029}, {3.8, 0.0155156}, {3.9, 
   0.0158137}, {4, 0.0155531}, {4.1, 0.015659}, {4.2, 
   0.0156929}, {4.3, 0.015593}, {4.4, 0.0156778}, {4.5, 
   0.0155809}, {4.6, 0.0154291}, {4.7, 0.0154669}, {4.8, 
   0.0154293}, {4.9, 0.015723}, {5, 0.0156523}, {5.1, 
   0.0156986}, {5.2, 0.0155511}, {5.3, 0.0157644}, {5.4, 
   0.0155238}, {5.5, 0.0156571}, {5.6, 0.015863}, {5.7, 
   0.0155556}, {5.8, 0.0158089}, {5.9, 0.0156503}, {6, 
   0.0157223}, {6.1, 0.0158217}, {6.2, 0.0155532}, {6.3, 
   0.0160364}, {6.4, 0.0157282}, {6.5, 0.0156189}, {6.6, 
   0.0157618}, {6.7, 0.0158884}, {6.8, 0.0158203}, {6.9, 0.01588}, {7,
    0.0156828}, {7.1, 0.0158321}, {7.2, 0.0160212}, {7.3, 
   0.0159493}, {7.4, 0.0161421}, {7.5, 0.0161392}, {7.6, 
   0.0158274}, {7.7, 0.0163127}, {7.8, 0.0159013}, {7.9, 
   0.0159812}, {8, 0.0163415}, {8.1, 0.0159965}, {8.2, 
   0.0160544}, {8.3, 0.0162358}, {8.4, 0.0159259}, {8.5, 
   0.0160865}, {8.6, 0.0161892}, {8.7, 0.0159022}, {8.8, 
   0.0162839}, {8.9, 0.016172}, {9, 0.0161034}, {9.1, 
   0.0161834}, {9.2, 0.0159591}, {9.3, 0.0162201}, {9.4, 
   0.0165077}, {9.5, 0.0162628}, {9.6, 0.0163246}, {9.7, 
   0.0162409}, {9.8, 0.016113}, {9.9, 0.0165561}, {10, 
   0.0163162}, {12, 0.0164887}, {14, 0.0167024}, {16, 0.0169761}, {18,
    0.0172264}, {20, 0.0175545}, {22, 0.0177088}, {24, 
   0.0180255}, {26, 0.0182986}, {28, 0.0185049}, {30, 0.0187261}, {32,
    0.0189013}, {34, 0.0192133}, {36, 0.0194547}, {38, 
   0.0195735}, {40, 0.0197712}, {42, 0.0200076}, {44, 0.0202209}, {46,
    0.0203705}, {48, 0.0206359}, {50, 0.0207846}, {52, 
   0.0208819}, {54, 0.0210565}, {56, 0.0213355}, {58, 0.0215136}, {60,
    0.0216291}, {62, 0.0218163}, {64, 0.0219576}, {66, 
   0.0221403}, {68, 0.0223647}, {70, 0.0225111}, {72, 0.0226069}, {74,
    0.022768}, {76, 0.0229539}, {78, 0.0230557}, {80, 0.0231378}, {82,
    0.0233842}, {84, 0.0234898}, {86, 0.0236244}, {88, 
   0.0238199}, {90, 0.0239548}, {92, 0.0240781}, {94, 0.0241836}, {96,
    0.0243121}, {98, 0.0244319}, {100, 0.0245564}, {102, 
   0.0246573}, {104, 0.0248724}, {106, 0.0249553}, {108, 
   0.0250335}, {110, 0.0251292}, {112, 0.0252884}, {114, 
   0.0253397}, {116, 0.0255432}, {118, 0.0255406}, {120, 
   0.0256459}, {122, 0.0258265}, {124, 0.0259592}, {126, 
   0.0260849}, {128, 0.0261496}, {130, 0.0262936}, {132, 
   0.0263212}, {134, 0.026418}, {136, 0.0265173}, {138, 
   0.0266018}, {140, 0.0266927}, {142, 0.0266983}, {144, 
   0.0268009}, {146, 0.0268993}, {148, 0.026971}, {150, 
   0.027157}, {152, 0.027201}, {154, 0.0272143}, {156, 
   0.0273452}, {158, 0.0274349}, {160, 0.0275074}, {162, 
   0.0276118}, {164, 0.0276734}, {166, 0.0277374}, {168, 
   0.0278183}, {170, 0.0278857}, {172, 0.0279445}, {174, 
   0.0280758}, {176, 0.0281244}, {178, 0.0282472}, {180, 
   0.0282469}, {182, 0.02841}, {184, 0.0285597}, {186, 
   0.0285776}, {188, 0.0286631}, {190, 0.0287524}, {192, 
   0.0287935}, {194, 0.0288491}, {196, 0.0289568}, {198, 
   0.0289707}, {200, 0.0290475}, {202, 0.0291832}, {204, 
   0.0292882}, {206, 0.0293192}, {208, 0.0293785}, {210, 
   0.0294645}, {212, 0.0295221}, {214, 0.0295769}, {216, 
   0.0295911}, {218, 0.0296945}, {220, 0.0297766}, {222, 
   0.0298977}, {224, 0.0299722}, {226, 0.0300396}, {228, 
   0.030075}, {230, 0.0301933}, {232, 0.0302031}, {234, 
   0.0302301}, {236, 0.0303071}, {238, 0.0303941}, {240, 
   0.0304433}, {242, 0.0305153}, {244, 0.0305661}, {246, 
   0.0305933}, {248, 0.0306978}, {250, 0.0306024}, {252, 
   0.0307296}, {254, 0.0308356}, {256, 0.0308429}, {258, 
   0.0308795}, {260, 0.030867}, {262, 0.0308705}, {264, 
   0.030907}, {266, 0.031066}, {268, 0.0310614}, {270, 
   0.0310895}, {272, 0.0311751}, {274, 0.0312486}, {276, 
   0.0313024}, {278, 0.0313239}, {280, 0.0313797}, {282, 
   0.0314123}, {284, 0.0314332}, {286, 0.0314901}, {288, 
   0.031552}, {290, 0.0316208}, {292, 0.0316881}, {294, 
   0.031775}, {296, 0.0318724}, {298, 0.031852}, {300, 
   0.0318658}, {302, 0.0319538}, {304, 0.0320357}, {306, 
   0.0320862}, {308, 0.0320489}, {310, 0.0321265}}

I'm going to assume that you're using my repository function, in which case I'm glad to hear that it's of use to you.

Without the exact details of the datasets, I cannot completely answer your question, but it comes down to this: MultiNonlinearModelFit internally joins all datasets together into a single one. This means that fit["FitResiduals"] has all of the residuals you need; you just need to split them up again. Concretely, you should have

Length @ fit["FitResiduals"] === Total[Length /@ {Abs360, Abs380}]

So Take[fit["FitResiduals"], Length[Abs360]] should get you the residuals for the first dataset and Drop[fit["FitResiduals"], Length[Abs360]] should give you those for the other one.

POSTED BY: Sjoerd Smit
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract