In the realm of TimeSeries of data with Circular Statistics, NonlinearModelFit (NLM) correctly generates reasonable Standard Error & confidence intervals for phase parameters (phaseCIs) with x-values that are integer offsets from a reference time (TRef). However, when AbsoluteTime values are utilized, resulting NLM Standard Error for phaseCIs are nonsensical. NOTE: I'm aware of FittedModel::constr warning, but still...
Questions:
- Why does NLM ignore parameter constraints Abs[phi] <= 2Pi when AbsoluteTime units are utilized?
- Is there an additional NLM tuning parameter to ensure Phi never steps outside its constrained param value?
- Is there a two-pass strategy to get reasonable phaseCIs (e.g., estimate BestFitParameters in one pass with a specific NLM Method, and then run a second NLM passing with a Method that explicitly applies parameter constraints)?
- (More generally) What other issues does NLM have with respect to TimeSeries data with Circular Statistical models?
(* Globals *)
{dayAsSeconds, lunarDayAsSeconds} =
QuantityMagnitude @
UnitConvert[Quantity[#, "Hours"], "Seconds"] & /@ {24, 24.8};
TRef = DateObject@ {2021, 1, 12, 0, 0} ;
deltaT =
QuantityMagnitude @ UnitConvert[Quantity[30, "Minutes"], "Seconds"];
(* Define xValues, one with TRef offset, the other AbsoluteTime *)
xAsOffsets = Range[5 dayAsSeconds, 20 dayAsSeconds , deltaT ];
xAsAbsoluteTime =
AbsoluteTime[TRef + Quantity[#, "Seconds"] ] & /@ xAsOffsets;
NOTE: At this point, the only difference between xAsOffsets and xAsAbsoluteTime is their IntegerLength[] size: the former are offset values from a TRef {0, 3600, ...} with IntegerLength[] <= 7 whereas the latter are AbsoluteTime values {3819830400, 3819832200, ...} whose IntegerLength[] == 10. Both are monotonically increasing by 1800.
(* Model *)
model = M + A1 Cos[2 Pi (t / tau1) + phi1] +
A2 Cos[2 Pi (t / tau2) + phi2] ;
modelSeeds = { M -> 100, A1 -> 10, tau1 -> dayAsSeconds,
phi1 -> - Pi/4, A2 -> 2, tau2 -> lunarDayAsSeconds,
phi2 -> - Pi/4};
SeedRandom[1];
rnd[dummy_] := 5 RandomReal [{-.5, .5}];
(* Generate xyPairs *)
xyAsOffset =
Table[{t, (model /. modelSeeds) + rnd[t]} , {t, xAsOffsets }];
xyAsAbsoluteTime =
Table[{t, (model /. modelSeeds) + rnd[t]} , {t, xAsAbsoluteTime }];
(* Prepare NLM wrapper *)
nlmParms = { {M}, {A1}, {tau1, dayAsSeconds}, {phi1, Pi}, {A2}, {tau2,
lunarDayAsSeconds}, {phi2, Pi}};
nlmConstraint =
Abs[phi1] <= 2 Pi && Abs[phi2] <= 2 Pi && A1 > 0 && A2 > 0;
nlm[data_, opts : OptionsPattern[NonlinearModelFit]] :=
nlm[data, opts] =
NonlinearModelFit[data, {model, nlmConstraint}, nlmParms, t, opts];
Visually verify both computed dataset Y-values are in the same phase
ListPlot[{xyAsOffset[[All, 2]], xyAsAbsoluteTime[[All, 2]]},
Joined -> True]
Visually compare phi1 and phi2 Standard Error and Confidence Intervals to see the crazy phaseCIs for xyAsAbsoluteTime.
compareCIResults[opts : OptionsPattern[NonlinearModelFit]] :=
TableForm[{#["ParameterConfidenceIntervalTable"] & /@ {nlm[
xyAsOffset, opts], nlm[xyAsAbsoluteTime, opts]}},
TableHeadings -> {{opts}, {"xAsOffsetsFromTRef",
"xAsAbsoluteTime"}}];
compareCIResults[]
xAsOffset
andxAsAbsoluteTime
asx1
andx2
withx1 = 432000 + 1800 Range[0, 720];
andx2 =x1 + 3819398400;
. The issue you raise is legit. It's just clouded by a lot of unnecessary information. And I don't think this qualifies as "circular statistics" or whatever a "circular time series" is just because cosines are involved. It's simply a regression with an additive error. $\endgroup$