0
$\begingroup$

I created a TimeSeries from TimeObjects (i.e.the list timemeting, times of the measurements) and the measured values (anglesarray). I want to fit the data to a function of time. The function contains another function (SunPosition) requiring the time in the form of a TimeObject, the same as used in making the TimeSeries. Just calling it "t" as done in the examples for fitting a timeseries does not work. Do I have to deconstruct the timeobjects to get a simpler variable and construct again when calling the function? That seems putting the horse behind the wagon.

timemeting= {DateObject[{2022, 7, 17, 7, 54, 33.}, "Instant"], 
 DateObject[{2022, 7, 17, 8, 16, 8.}, "Instant"], 
 DateObject[{2022, 7, 17, 8, 56, 4.}, "Instant"], 
 DateObject[{2022, 7, 17, 9, 36, 20.}, "Instant"], 
 DateObject[{2022, 7, 17, 10, 16, 1.}, "Instant"], 
 DateObject[{2022, 7, 17, 10, 16, 55.}, "Instant"], 
 DateObject[{2022, 7, 17, 10, 55, 51.}, "Instant"], 
 DateObject[{2022, 7, 17, 10, 56, 13.}, "Instant"], 
 DateObject[{2022, 7, 17, 11, 36, 8.}, "Instant"], 
 DateObject[{2022, 7, 17, 12, 16, 10.}, "Instant"], 
 DateObject[{2022, 7, 17, 14, 16, 21.}, "Instant"], 
 DateObject[{2022, 7, 17, 14, 57, 3.}, "Instant"], 
 DateObject[{2022, 7, 17, 15, 37, 4.}, "Instant"], 
 DateObject[{2022, 7, 17, 16, 16, 6.}, "Instant"], 
 DateObject[{2022, 7, 17, 16, 56, 3.}, "Instant"], 
 DateObject[{2022, 7, 17, 17, 36, 26.}, "Instant"], 
 DateObject[{2022, 7, 17, 18, 16, 22.}, "Instant"], 
 DateObject[{2022, 7, 17, 19, 34, 8.}, "Instant"], 
 DateObject[{2022, 7, 17, 19, 35, 44.}, "Instant"]}
anglesarray= {-83.95, -79.106, -68.979, -58.889, -49.1, -48.725, \
-38.725, -39.15, -29.31, -19.25, 10.595, 20.688, 30.924, 40.635, \
50.53, 60.993, 71.066, 90.977, 91.1841}

NonlinearModelFit[TimeSeries[Transpose[{timemeting, anglesarray}]], 
 ArcTan[Cos[#1] (Cos[#3] Sin[\[Beta]] Sin[#2] + 
         Cos[\[Beta]] Sin[#3]) + 
      Sin[#1] (-Cos[\[Gamma]] Cos[#2] Cos[#3] - 
         Sin[\[Gamma]] (Cos[\[Beta]] Cos[#3] Sin[#2] - 
            Sin[\[Beta]] Sin[#3])), -Cos[#2] Cos[#3] Sin[\[Gamma]] + 
      Cos[\[Gamma]] (Cos[\[Beta]] Cos[#3] Sin[#2] - 
         Sin[\[Beta]] Sin[#3])] & @ 
   Flatten[{gardenloc["Latitude"] Degree + \[Alpha], 
     QuantityMagnitude[SunPosition[gardenloc, t]] Degree}]/
  Degree, {\[Alpha], \[Beta], \[Gamma]}, t]
$\endgroup$
1
  • 2
    $\begingroup$ Please include your code in the question. $\endgroup$
    – Domen
    Jul 19, 2022 at 19:49

1 Answer 1

2
$\begingroup$

There is a syntax issue that needs to addressed first. You have

ArcTan[Cos[#1] (Cos[#3] Sin[β] Sin[#2] + 
         Cos[β] Sin[#3]) + 
      Sin[#1] (-Cos[γ] Cos[#2] Cos[#3] - 
         Sin[γ] (Cos[β] Cos[#3] Sin[#2] - 
            Sin[β] Sin[#3])), -Cos[#2] Cos[#3] Sin[γ] + 
      Cos[γ] (Cos[β] Cos[#3] Sin[#2] - 
         Sin[β] Sin[#3])] & @ 
   Flatten[{gardenloc["Latitude"] Degree + α, 
     QuantityMagnitude[SunPosition[gardenloc, t]] Degree}]/
  Degree

but that work work as you expect because the result of Flatten[{gardenloc["Latitude"] Degree + α, QuantityMagnitude[SunPosition[gardenloc, t]] Degree}] is going to be a List and you are sending it to a Function which is expecting 3 arguments. So you need to modify @ to @@ (Apply).

With that in mind, the main issue is that NonlinearModelFit isn't built to use TimeObjects as a point to fit data to. So you need to convert the TimeObject to a number. For example, using AbsoluteTime:

atimes = AbsoluteTime /@ timemeting - AbsoluteTime[timemeting[[1]]]

(I set the first time to be 0 so I don't have to worry too much about working with numbers with large exponents.) Now up a function to use as our model. But now we need to convert t back to the correct TimeObject for SunPosition to use). Also notice that I used the pattern t_?NumericQ to ensure that my function doesn't evaluate until I have a numeric value for t.

func[t_?NumericQ, {α_, β_, γ_}] := 
 Module[{time = FromAbsoluteTime[t + AbsoluteTime[timemeting[[1]]]]}, 
  ArcTan[Cos[#1] (Cos[#3] Sin[β] Sin[#2] + 
          Cos[β] Sin[#3]) + 
       Sin[#1] (-Cos[γ] Cos[#2] Cos[#3] - 
          Sin[γ] (Cos[β] Cos[#3] Sin[#2] - 
             Sin[β] Sin[#3])), -Cos[#2] Cos[#3] Sin[γ] + 
       Cos[γ] (Cos[β] Cos[#3] Sin[#2] - 
          Sin[β] Sin[#3])] & @@ 
    Flatten[{gardenloc["Latitude"] Degree + α, 
      QuantityMagnitude[SunPosition[gardenloc, time]] Degree}]/
   Degree 
  ]

and from here now we can use NonlinearModelFit as before (I used gardenloc = Here of course you would set it to the appropriate value for you).

nlm = NonlinearModelFit[
  TimeSeries[Transpose[{atimes,anglesarray}]], func[t, {α, β, γ}], {α, β, γ}, t];

nlm["BestFitParameters"]
(* {α -> 1.7518, β -> 3.01411, γ -> -0.062247} *)
$\endgroup$
1
  • $\begingroup$ Thank you very much! The con/deconstruction of time in this way is not as painful as I anticipated. (The @@ I realized already: I worked around the problem using FindMinimum doing a least squares with a table of the function at the measured times. With your answer I get the full information for the error bars on the parameters. Also forgot the minus sign in front of ArcTan) $\endgroup$
    – Hans W
    Jul 22, 2022 at 9:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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