From 6355305d084045917607dbfa846f03d670c3ceaa Mon Sep 17 00:00:00 2001 From: "E. Joshua Rigler" <erigler@usgs.gov> Date: Thu, 11 Aug 2022 13:33:59 -0600 Subject: [PATCH 1/2] update interval no longer shrinks with recursion Previously, the endtime-starttime interval being processed by the `run_as_update` method would shrink by 1 (second) with each recursion. This ultimately broke `run_as_update` when processing anything other than 1-second data, but it wasn't obvious because we rarely had to actually recurse. There is a little trickery now to ensure that user- provided starttime and endtime are inclusive of the full first (most recent) update interval, while subsequent, calculated, endtimes are set equal to the prior starttime minus specified output_interval (e.g., 'second', 'minute', etc.). --- geomagio/Controller.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/geomagio/Controller.py b/geomagio/Controller.py index aa7179746..6d37c1128 100644 --- a/geomagio/Controller.py +++ b/geomagio/Controller.py @@ -426,9 +426,11 @@ class Controller(object): # check for fillable gap at start if output_gap[0] == starttime: # found fillable gap at start, recurse to previous interval - interval = endtime - starttime - recurse_starttime = starttime - interval - recurse_endtime = starttime - 1 + delta = TimeseriesUtility.get_delta_from_interval(output_interval) + recurse_starttime = ( + starttime - (endtime - starttime) - delta * bool(update_count) + ) + recurse_endtime = starttime - delta self.run_as_update( algorithm=algorithm, observatory=observatory, -- GitLab From 654364279d1342fdac1d53cca49b117a1848a8c1 Mon Sep 17 00:00:00 2001 From: Jeremy Fee <jmfee@usgs.gov> Date: Thu, 11 Aug 2022 21:32:01 -0600 Subject: [PATCH 2/2] Add get_previous_interval method and test --- geomagio/Controller.py | 30 ++++++++++++++++++++++++++---- test/Controller_test.py | 22 +++++++++++++++++++++- 2 files changed, 47 insertions(+), 5 deletions(-) diff --git a/geomagio/Controller.py b/geomagio/Controller.py index 6d37c1128..458e74e43 100644 --- a/geomagio/Controller.py +++ b/geomagio/Controller.py @@ -426,11 +426,10 @@ class Controller(object): # check for fillable gap at start if output_gap[0] == starttime: # found fillable gap at start, recurse to previous interval - delta = TimeseriesUtility.get_delta_from_interval(output_interval) - recurse_starttime = ( - starttime - (endtime - starttime) - delta * bool(update_count) + recurse_starttime, recurse_endtime = get_previous_interval( + start=starttime, + end=endtime, ) - recurse_endtime = starttime - delta self.run_as_update( algorithm=algorithm, observatory=observatory, @@ -638,6 +637,29 @@ def get_output_factory(args): return output_factory +def get_previous_interval( + start: UTCDateTime, + end: UTCDateTime, +) -> Tuple[UTCDateTime, UTCDateTime]: + """Get previous interval for given interval. + + Parameters + ---------- + start + start of interval + end + end of interval + + Returns + ------- + Previous interval of approximately the same size. + Interval is rounded to nearest second, and ends one microsecond earlier. + """ + # round to nearest second to recover removed microsecond from repeated calls + interval_size = round(end - start) + return (start - interval_size, start - 1e-6) + + def get_realtime_interval(interval_seconds: int) -> Tuple[UTCDateTime, UTCDateTime]: # calculate endtime/starttime now = UTCDateTime() diff --git a/test/Controller_test.py b/test/Controller_test.py index 2e51338a6..9acab4437 100644 --- a/test/Controller_test.py +++ b/test/Controller_test.py @@ -6,7 +6,7 @@ from geomagio.algorithm import Algorithm from geomagio.iaga2002 import IAGA2002Factory # needed to emulate geomag.py script -from geomagio.Controller import _main, parse_args +from geomagio.Controller import _main, get_previous_interval, parse_args # needed to copy SqDistAlgorithm statefile from shutil import copy @@ -290,3 +290,23 @@ def test_controller_update_sqdist(): ) expected = expected_factory.get_timeseries(starttime=starttime1, endtime=endtime6) assert_allclose(actual, expected) + + +def test_get_previous_interval(): + """Test get_previous_interval produces stable interval sizes""" + # initial interval is one hour + start = UTCDateTime("2022-01-05T00:00:00Z") + end = UTCDateTime("2022-01-05T01:00:00Z") + # previous interval starts at beginning of previous hour + previous = get_previous_interval(start=start, end=end) + assert previous == ( + UTCDateTime("2022-01-04T23:00:00"), + UTCDateTime("2022-01-04T23:59:59.999999Z"), + ) + # previous interval still starts at beginning of previous hour + # even though interval is one microsecond smaller + previous = get_previous_interval(*previous) + assert previous == ( + UTCDateTime("2022-01-04T22:00:00"), + UTCDateTime("2022-01-04T22:59:59.999999Z"), + ) -- GitLab