0
$\begingroup$

I am using a loop to run run multiple fits. If a fit fails, I don't want it to either appear in my data or to affect later fits so I am using the Check[] function to catch if any errors occurred (I'm especially looking out for the "Failed to converge to the requested accuracy or precision..." message).

So the code I have is (I know Do loops are frowned upon, but it's easier for me to read; I'm not really a Mathematica programmer):

klist = Import["klist.dat", "List"]
sklist = Import["sk.dat", "List"]
phiprime[w_, wL2_, wk2_, t_, \[Gamma]_] := (wL2 - \[Gamma]*wk2)*t*Exp[-t^2*w^2/Pi]
phidprime[w_, wL2_, wk2_, t_, \[Gamma]_] := 2*t/Sqrt[Pi]*(wL2 - \[Gamma]*wk2)*DawsonF[t*w/Sqrt[Pi]]

foo[w_, wL2_, wk2_, t_, sk_] := sk/Pi*wk2*phiprime[w, wL2, wk2, t, 1]/((w^2 - wk2 - w*phidprime[w, wL2, wk2, t, 1])^2 + (w*phiprime[w, wL2, wk2, t, 1])^2)

fit1[sk_, dat_, wL20_, wk20_, t0_] := NonlinearModelFit[dat, foo[w, wL2, wk2, t, sk], {{wL2, wL20}, {wk2, wk20}, {t, t0}}, w]

inputs = Import["inputs.dat", "Table"]
tau = 900
outputs = {}

Do[
 k = klist[[i]];
 sk = sklist[[i]];
 skwdata = Import["skw.k_" <> StringTrim[ToString[PaddedForm[k, {4, 3}]]] <> ".new.dat", "Table"];
 Check[temp = Transpose[fit1[sk, skwdata, inputs[[i]][[2]], inputs[[i]] [[3]], tau]["BestFitParameters"] /. Rule -> List][[2]];
  outputs = AppendTo[outputs, temp];
  tau = temp[[3]],
  AppendTo[outputs, {0, 0, 0}]],
 {i, 1, Length[klist]}
 ]

Here fit1 is a defined function that uses NonlinearModelFit, so temp will end up being a list of the the three best fit parameters.

What I imagined the Check statement thus implemented would do was, if everything went smoothly, return the first three statements, and if not (instead of writing the best-fit parameters) write zeroes to the list outputs. Instead, it doesn't seem to do anything special when the "Failed to converge..." message is thrown. {0,0,0} is indeed added to ouputs, but the three fitting parameters for the failed fit are still written to outputs and tau is still changed.

What needs to be changed to make this work?

$\endgroup$
  • 1
    $\begingroup$ Please provide a complete, minimal, working (even if that means with problems noted), with some data example. $\endgroup$ – ciao Apr 21 '15 at 21:30
  • 1
    $\begingroup$ My guess is that you meant to use AppendTo[outputs, {0, 0, 0}] as Append will not change outputs. $\endgroup$ – Mr.Wizard Apr 21 '15 at 21:33
  • $\begingroup$ I will happily upload the rest of the code and some data. How do I upload data though? $\endgroup$ – mikefallopian Apr 21 '15 at 21:57
  • $\begingroup$ I should have caught the AppendTo/Append error, but strangely output was indeed changed as intended. $\endgroup$ – mikefallopian Apr 21 '15 at 21:58
3
$\begingroup$

Since there's no data source in OP, can't work with it, but I believe your issue boils down to incorrect use of Check: It does not short-ciruit remaining parts of the compound expression, so you'll still get to the Append within even when a message was generated.

You need to do the desired append outside of the check, e.g.:

res = {};

Do[AppendTo[res, Quiet@Check[(r = 10/x), "Failed"]],{x, {1, 2, 3, 0, 1, 2, 3}}]

(* {10, 5, 10/3, "Failed", 10, 5, 10/3} *)
$\endgroup$
  • $\begingroup$ As I said above, I'd be happy to provide data but I'm not sure how to do so. My only problem with this solution is I still don't see a good way to also handle the exception for the statement "tau = temp[[3]]". If I extend the logic of your answer I can't come up with anything that doesn't involve evaluating Check[fit1,...] again, which seems horribly inefficient. $\endgroup$ – mikefallopian Apr 21 '15 at 23:12
  • $\begingroup$ To be clear, I want tau to be reassigned if and only if the fit succeeds, since it is passed as a guess to the next fit. $\endgroup$ – mikefallopian Apr 21 '15 at 23:13
  • $\begingroup$ @mikefallopian: Yes, the above is just an example, so in your case, you'd return appropriate values (or failure), then use that to append/set/etc. $\endgroup$ – ciao Apr 21 '15 at 23:29
  • $\begingroup$ So would the following work? Say in the fail expression for Check i set a boolean to True, and then after Check I execute an if statement that says if the boolean is False, change tau and append the outputs, and otherwise (do other thing). $\endgroup$ – mikefallopian Apr 21 '15 at 23:35
  • $\begingroup$ @mikefallopian: Yep, that would do it... $\endgroup$ – ciao Apr 21 '15 at 23:39

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.