Skip to content
31 changes: 27 additions & 4 deletions tom_observations/cadences/resume_cadence_after_failure.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from datetime import datetime, timedelta
from dateutil.parser import parse
from django.conf import settings
import logging

from tom_observations.cadence import BaseCadenceForm, CadenceStrategy
Expand Down Expand Up @@ -43,20 +44,32 @@ def run(self):

# Make a call to the facility to get the current status of the observation
facility = get_service_class(last_obs.facility)()
start_keyword, end_keyword = facility.get_start_end_keywords()
facility.update_observation_status(last_obs.observation_id) # Updates the DB record
last_obs.refresh_from_db() # Gets the record updates

# Boilerplate to get necessary properties for future calls
start_keyword, end_keyword = facility.get_start_end_keywords()
observation_payload = last_obs.parameters

# Only needs the scheduled end from the observatory
observation_payload['scheduled_end'] = last_obs.scheduled_end

# Cadence logic
# If the observation hasn't finished, do nothing
if not last_obs.terminal:
return
elif last_obs.failed: # If the observation failed
# Submit next observation to be taken as soon as possible with the same window length
window_length = parse(observation_payload[end_keyword]) - parse(observation_payload[start_keyword])
# Make the window length the cadence frequency or 24 hours, whichever is shorter.
cadence_frequency = self.dynamic_cadence.cadence_parameters.get('cadence_frequency')
if not cadence_frequency:
raise Exception(f'The {self.name} strategy requires a cadence_frequency cadence_parameter.')
if settings.OBS_WINDOW_MINIMUM:
window_length = settings.OBS_WINDOW_MINIMUM
if window_length > cadence_frequency:
window_length = cadence_frequency
else:
window_length = cadence_frequency
observation_payload[start_keyword] = datetime.now().isoformat()
observation_payload[end_keyword] = (parse(observation_payload[start_keyword]) + window_length).isoformat()
else: # If the observation succeeded
Expand Down Expand Up @@ -95,6 +108,7 @@ def run(self):
for obsr in new_observations:
facility = get_service_class(obsr.facility)()
facility.update_observation_status(obsr.observation_id)
obsr.refresh_from_db() # commit the updated observation status

return new_observations

Expand All @@ -103,9 +117,18 @@ def advance_window(self, observation_payload, start_keyword='start', end_keyword
if not cadence_frequency:
raise Exception(f'The {self.name} strategy requires a cadence_frequency cadence_parameter.')
advance_window_hours = cadence_frequency
window_length = parse(observation_payload[end_keyword]) - parse(observation_payload[start_keyword])

new_start = parse(observation_payload[start_keyword]) + timedelta(hours=advance_window_hours)
# Window length for the observation should be every 24 hours unless the frequency is less than 24
# then just the cadence frequency (24 hour window defined in the settings)
if settings.OBS_WINDOW_MINIMUM:
window_length = settings.OBS_WINDOW_MINIMUM
if window_length > cadence_frequency:
window_length = cadence_frequency
else:
window_length = cadence_frequency

# Define new start to be at the end of the previous observation + cadence in hours
new_start = parse(observation_payload['scheduled_end']) + timedelta(hours=advance_window_hours)
if new_start < datetime.now(): # Ensure that the new window isn't in the past
new_start = datetime.now()
new_end = new_start + window_length
Expand Down
12 changes: 9 additions & 3 deletions tom_observations/cadences/retry_failed_observations.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from datetime import timedelta
from dateutil.parser import parse
from django.conf import settings

from tom_observations.cadence import BaseCadenceForm, CadenceStrategy
from tom_observations.models import ObservationRecord
Expand Down Expand Up @@ -57,9 +58,14 @@ def advance_window(self, observation_payload, start_keyword='start', end_keyword
cadence_frequency = self.dynamic_cadence.cadence_parameters.get('cadence_frequency')
if not cadence_frequency:
raise Exception(f'The {self.name} strategy requires a cadence_frequency cadence_parameter.')
advance_window_hours = cadence_frequency
new_start = parse(observation_payload[start_keyword]) + timedelta(hours=advance_window_hours)
new_end = parse(observation_payload[end_keyword]) + timedelta(hours=advance_window_hours)
if settings.OBS_WINDOW_MINIMUM:
window_length = settings.OBS_WINDOW_MINIMUM
if window_length > cadence_frequency:
window_length = cadence_frequency
else:
window_length = cadence_frequency
new_start = parse(observation_payload[start_keyword]) + timedelta(hours=window_length)
new_end = parse(observation_payload[end_keyword]) + timedelta(hours=window_length)
observation_payload[start_keyword] = new_start.isoformat()
observation_payload[end_keyword] = new_end.isoformat()

Expand Down
19 changes: 17 additions & 2 deletions tom_observations/facilities/lco.py
Original file line number Diff line number Diff line change
Expand Up @@ -883,7 +883,15 @@ def clean(self):
"""
cleaned_data = super().clean()
start = cleaned_data.get('start')
cleaned_data['end'] = datetime.strftime(parse(start) + timedelta(hours=cleaned_data['cadence_frequency']),
cadence_frequency = cleaned_data['cadence_frequency']
if settings.OBS_WINDOW_MINIMUM:
window_length = settings.OBS_WINDOW_MINIMUM
if window_length > cadence_frequency:
window_length = cadence_frequency
else:
window_length = cadence_frequency

cleaned_data['end'] = datetime.strftime(parse(start) + timedelta(hours=window_length),
'%Y-%m-%dT%H:%M:%S')

return cleaned_data
Expand Down Expand Up @@ -1058,8 +1066,15 @@ def clean(self):
"""
cleaned_data = super().clean()
cleaned_data['instrument_type'] = '2M0-FLOYDS-SCICAM' # SNEx only submits spectra to FLOYDS

start = cleaned_data.get('start')
cleaned_data['end'] = datetime.strftime(parse(start) + timedelta(hours=cleaned_data['cadence_frequency']),
if settings.OBS_WINDOW_MINIMUM:
min_window = settings.OBS_WINDOW_MINIMUM
else:
min_window = 24
window_length = min_window if cleaned_data['cadence_frequency'] > min_window else cleaned_data['cadence_frequency']

cleaned_data['end'] = datetime.strftime(parse(start) + timedelta(hours=window_length),
'%Y-%m-%dT%H:%M:%S')

return cleaned_data
Expand Down
Loading