Skip to content
Snippets Groups Projects
Commit 9a8ff2ab authored by Jorrit Schaap's avatar Jorrit Schaap
Browse files

TMSS-2823: the problem with the specification from the...

TMSS-2823: the problem with the specification from the test_bugfix_TMSS_2823_coarse_fine_grid is that the delta-time between target transits is larger than the transit_offset window width. Made a sanity check, and apply it both in the draft and blueprint to prevent this ill specification
parent b76cbeb1
No related branches found
No related tags found
1 merge request!1187TMSS-2823
......@@ -1138,6 +1138,38 @@ class SchedulingUnitCommonPropertiesMixin:
'''return the latest possible start time for this unit's project and cycle(s)'''
return self.project.latest_possible_cycle_stop_time
def validate_scheduling_constraints(self):
'''validate the scheduling_constraints_doc against its template, and for additional consistency checks'''
if self.scheduling_constraints_template is None or self.scheduling_constraints_doc is None:
return
self.scheduling_constraints_template.validate_document(self.scheduling_constraints_doc)
if 'time' in self.scheduling_constraints_doc:
if 'between' in self.scheduling_constraints_doc['time']:
between_durations = [parser.parse(between["to"], ignoretz=True)-parser.parse(between["from"], ignoretz=True)
for between in self.scheduling_constraints_doc['time']['between']]
if any([between_duration < self.specified_main_observation_duration for between_duration in between_durations]):
raise RuleValidationException("A between constraint is shorter than the main observation's duration.")
if 'sky' in self.scheduling_constraints_doc:
if 'transit_offset' in self.scheduling_constraints_doc['sky']:
# check if the time between all target transits is not larger than the transit_window_width
transit_window_width_seconds = abs(self.scheduling_constraints_doc['sky']['transit_offset']['to'] - self.scheduling_constraints_doc['sky']['transit_offset']['from'])
# ToDo: move get_transit_offset_pointings (and similar) methods to Task/SchedulingUnit
from lofar.sas.tmss.services.scheduling.constraints import get_transit_offset_pointings
for task in self.observation_tasks:
if task.is_target_observation:
pointings = get_transit_offset_pointings(task)
transits = [p.transit_lst for p in pointings]
earliest_transit = min(transits)
latest_transit = max(transits)
delta_transit = datetime.datetime.combine(datetime.date.today(), latest_transit) - datetime.datetime.combine(datetime.date.today(), earliest_transit)
delta_transit_seconds = delta_transit.total_seconds()
if delta_transit_seconds > transit_window_width_seconds:
raise RuleValidationException("time between latest and earliest transit for targets in task id=%s name='%s' su_id=%s is larger than the transit_offset window itself: delta_transit=%dsec > transit_window_width=%ssec" % (task.id, task.name, self.id, delta_transit_seconds, transit_window_width_seconds))
class SchedulingUnitDraft(TemplateSchemaMixin, ProjectPropertyMixin, SchedulingUnitCommonPropertiesMixin, RefreshFromDbInvalidatesCachedPropertiesMixin, NamedCommon):
scheduling_set = ForeignKey('SchedulingSet', related_name='scheduling_unit_drafts', on_delete=CASCADE, help_text='Set to which this scheduling unit draft belongs.')
......@@ -1171,9 +1203,8 @@ class SchedulingUnitDraft(TemplateSchemaMixin, ProjectPropertyMixin, SchedulingU
# we intentionally do not add defaults to scheduling_constraints_doc
# because that would add default items which the user did not specify,
# and for scheduling contraints this can have unforeseen sideeffects that the user did not intent.
self.annotate_doc_using_template('scheduling_constraints_doc', 'scheduling_constraints_template')
self.validate_doc_using_template('scheduling_constraints_doc', 'scheduling_constraints_template')
# and for scheduling constraints this can have unforeseen side effects that the user did not intend.
self.validate_scheduling_constraints()
super().save(force_insert, force_update, using, update_fields)
......@@ -1336,17 +1367,9 @@ class SchedulingUnitBlueprint(ProjectPropertyMixin, TemplateSchemaMixin, Schedul
if hasattr(self, 'draft'):
setattr(self, copy_field, getattr(self.draft, copy_field))
# enforce fixed_time scheduler when time.at is given
# ToDo: do we actually want this? It seems to break some tests.
# I'm still in favor of removing the 'scheduler'='dynamic'/'fixed_time' property,
# and making it implicit: if 'time'at' is defined, then it's fixed by definition
# and if 'time'at' is not defined, then it's dynamic by definition
# if self.scheduling_constraints_doc is not None and self.scheduling_constraints_doc.get('time', {}).get('at') is not None:
# self.scheduling_constraints_doc['scheduler'] = 'fixed_time'
# we intentionally do not add defaults to scheduling_constraints_doc
# because that would add default items which the user did not specify,
# and for scheduling contraints this can have unforeseen sideeffects that the user did not intent.
# and for scheduling contraints this can have unforeseen side-effects that the user did not intent.
# but, we do check the validity of the constraints
self.validate_scheduling_constraints()
......@@ -1358,20 +1381,6 @@ class SchedulingUnitBlueprint(ProjectPropertyMixin, TemplateSchemaMixin, Schedul
super().save(force_insert, force_update, using, update_fields)
def validate_scheduling_constraints(self):
'''validate the scheduling_constraints_doc against its template, and for additional consistency checks'''
if self.scheduling_constraints_template is None or self.scheduling_constraints_doc is None:
return
self.scheduling_constraints_template.validate_document(self.scheduling_constraints_doc)
if 'time' in self.scheduling_constraints_doc:
if 'between' in self.scheduling_constraints_doc['time']:
between_durations = [parser.parse(between["to"], ignoretz=True)-parser.parse(between["from"], ignoretz=True)
for between in self.scheduling_constraints_doc['time']['between']]
if any([between_duration < self.specified_main_observation_duration for between_duration in between_durations]):
raise RuleValidationException("A between constraint is shorter than the main observation's duration.")
@property
def tasks(self) -> QuerySet:
......
......@@ -435,6 +435,9 @@ def update_task_graph_from_specifications_doc(scheduling_unit_draft: models.Sche
scheduling_unit_draft.scheduling_constraints_doc = specifications_doc['scheduling_constraints_doc']
scheduling_unit_draft.save()
# finally, check the scheduling_constraints (may raise, reverting the transaction)
scheduling_unit_draft.validate_scheduling_constraints()
scheduling_unit_draft.refresh_from_db()
return scheduling_unit_draft
......@@ -642,6 +645,9 @@ def update_task_blueprints_and_subtasks_graph_from_draft(scheduling_unit_bluepri
# and apply
update_subtasks_start_times_for_scheduling_unit(scheduling_unit_blueprint, initial_scheduled_start_time)
# finally, check the scheduling_constraints (may raise, reverting the transaction)
scheduling_unit_blueprint.validate_scheduling_constraints()
# refresh so all related fields are updated.
scheduling_unit_blueprint.refresh_from_db()
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment