1
$\begingroup$

I have complex data and which I am fitting to a complex formula. In order to use NonlinearModelFit I split the formula and the data into real and imaginary parts.

As usual NonlinearModelFit is sensitive to initial conditions so I have a DynamicModule to help me find these. My problem is that when inside a DynamicModule NonlinearModelFit keeps running and never stops.

I have made a reduced version of the DynamicModule below to show the effect. The local variable numbers never stop increasing.

Why is this? I feel it should just do one operation and stop.

The data is:

data = {{267.761, 0.666697 - 0.117395 I}, {267.794, 0.720659 - 0.140544 I}, 
        {267.827, 0.78293 - 0.165958 I}, {267.861, 0.850505 - 0.19637 I},
        {267.894, 0.933982 - 0.239532 I}, {267.927, 1.04094 - 0.303451 I},
        {267.96, 1.15656 - 0.382384 I}, {267.994, 1.30706 - 0.505816 I}, 
        {268.027, 1.48614 - 0.684103 I}, {268.06, 1.69699 - 0.969217 I}, 
        {268.094, 1.89745 - 1.43193 I}, {268.127,1.9794 - 2.19671 I}, 
        {268.16, 1.49939 - 3.27732 I}, {268.193, 0.0979582 - 4.0018 I}, 
        {268.227, -1.38062 - 3.44199 I}, {268.26, -1.96791 - 2.37086 I}, 
        {268.293, -1.95989 - 1.55105 I}, {268.327, -1.77203 - 1.04211 I},
        {268.36, -1.572 - 0.722879 I}, {268.393, -1.37354 - 0.5245 I}, 
        {268.427, -1.21688 - 0.402393 I}, {268.46, -1.08912 - 0.310994 I},
        {268.493, -0.983056 - 0.249877 I}, {268.526, -0.897219 - 0.205772 I}, 
        {268.56, -0.823682 - 0.173521 I}, {268.593, -0.758923 - 0.150585 I}, 
        {268.626, -0.7049 - 0.127326 I}};

The fitting module is

ClearAll[nlmFit];
nlmFit::usage =  "nlmFit[data,{fnest,\[Zeta]est}] uses nonlinear model fit to get \
                values for constant (h0r,h0i), residue (gr,gi), natural frequency \
                (fn) and damping ratio (\[Zeta]). All data is fitted. Output is the \
                standard NonLinearModelFit";

 nlmFit[data0_, {fnest_, \[Zeta]est_}] := Module[
      {nn, ff, hh, data, model, y, f, hr, hi, rr, ri, fn, \[Zeta]}
  ,
  ff = data0[[All, 1]];
  hh = data0[[All, 2]];
  nn = Length[ff];
  data = Join[
              Transpose[{ff, ConstantArray[0, nn], Re[hh]}],
              Transpose[{ff, ConstantArray[1, nn], Im[hh]}]
             ];

 model = (1 - y) (( f^2 hr + f (rr - 2 fn hr Sqrt[1 - \[Zeta]^2]) + 
   fn (fn hr - ri \[Zeta] - rr Sqrt[1 - \[Zeta]^2]))/( f^2 + fn^2 - 2 f fn Sqrt[1 -
   \[Zeta]^2])) + y ((f^2 hi + f (ri - 2 fn hi Sqrt[1 - \[Zeta]^2]) +  fn (fn hi + 
   rr \[Zeta] - ri Sqrt[1 - \[Zeta]^2]))/(f^2 + fn^2 - 2 f fn Sqrt[1 - \[Zeta]^2]));

 NonlinearModelFit[data, 
                   model, 
                   {{fn, fnest}, {\[Zeta], \[Zeta]est}, rr, ri, hr, hi}, 
                   {f, y}]

 ]

The DynamicModule is

ClearAll[dfit];

dfit[data_, {fn_, \[Zeta]e_}] := DynamicModule[{fitdata},

 Dynamic[fitdata = nlmFit[data, {fn, \[Zeta]e}];

 fitdata["ParameterConfidenceIntervalTable"]]
 ]

To run the DynamicModule

dfit[data, {268, 0.0003}]

...and the output never stops changing. Why is the code running again and again? Thanks

$\endgroup$
  • 1
    $\begingroup$ Your example boils down to: DynamicModule[{a}, Dynamic[a = RandomReal[]; a] ]. I'd move assignment outside Dynamic. $\endgroup$ – Kuba Dec 14 '14 at 12:38
  • $\begingroup$ @Kuba If I understand the Q, the OP cannot move the assignment outside. Initial conditions are manually set inside Dynamic but that code has been removed. Based on my understanding, what the OP needs is TrackedSymbols (and possibly Refresh). $\endgroup$ – Michael E2 Dec 14 '14 at 13:31
  • $\begingroup$ @MichaelE2 I suppose it is the problem with the scheme. If those fn and ZetaE are changed with Slider or something, then there is not need to keep the assignment inside the same Dynamic as the table is. And if it is some kind of automatic loop, Dynamic itself is not really the solution and still I imagine it can be split. However, I do often miss the point of the question ;P $\endgroup$ – Kuba Dec 14 '14 at 13:36
  • 1
    $\begingroup$ @Hugh You might look at the links in my previous comment just above this one. The solution to your Q is Dynamic[<code>, TrackedSymbols :> {}] or Dynamic[<code>, TrackedSymbols :> {x, y,...}] where x, y,... are your slider variables, but not fitdata. The reason is explained (imo) in some answers to the linked questions. $\endgroup$ – Michael E2 Dec 14 '14 at 14:45
  • 1
    $\begingroup$ @Hugh You could (and should) post the solution as an answer. (We actually encourage it.) $\endgroup$ – Michael E2 Dec 14 '14 at 15:24
2
$\begingroup$

I am answering my own question after a suggestion by MichaelE2

Here is a second version of dfit (dfit4) which has Sliders and TrackedSymbols. The sliders are a method of finding appropriate initial conditions. The solution to the problem is to include TrackedSymbols in the Dynamic that calculates the NonLinearModelFit.

 ClearAll[dfit4];
  dfit4[data_] := DynamicModule[{fitdata, fn = 268, \[Zeta]e = 0.0001},
   Column[{
   Row[{"Estimate frequency ", Slider[Dynamic[fn], {0, 400}], 
   Dynamic[fn]}],
   Row[{"Damping ratio ", Slider[Dynamic[\[Zeta]e], {0, 0.001}], 
   Dynamic[\[Zeta]e]}],
    Dynamic[
     fitdata = nlmFit[data, {fn, \[Zeta]e}];
     fitdata["ParameterConfidenceIntervalTable"],
     TrackedSymbols :> {fn, \[Zeta]e}]
   }]
   ]

Thanks to MichaelE2

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.