diff --git a/LCS/PyCommon/json_utils.py b/LCS/PyCommon/json_utils.py index 232ba7841c4d588378ab01fb192d8d25b59577bc..4b84ad903e6e0510240743901ba4b9ec7397fb49 100644 --- a/LCS/PyCommon/json_utils.py +++ b/LCS/PyCommon/json_utils.py @@ -103,6 +103,12 @@ def get_default_json_object_for_schema(schema: str) -> dict: def add_defaults_to_json_object_for_schema(json_object: dict, schema: str) -> dict: '''return a copy of the json object with defaults filled in according to the schema for all the missing properties''' copy_of_json_object = deepcopy(json_object) + + # add a $schema to the json doc if needed + if '$schema' not in copy_of_json_object and '$id' in schema: + copy_of_json_object['$schema'] = schema['$id'] + + # run validator, which populates the properties with defaults. get_validator_for_schema(schema, add_defaults=True).validate(copy_of_json_object) return copy_of_json_object diff --git a/SAS/TMSS/docker-compose-scu199.yml b/SAS/TMSS/docker-compose-scu199.yml index 85cfd2d27d6fd292129294551405937b511a07bf..227ca832e0a291a189d1f60c098439ead86ec1a8 100644 --- a/SAS/TMSS/docker-compose-scu199.yml +++ b/SAS/TMSS/docker-compose-scu199.yml @@ -7,7 +7,7 @@ services: env_file: - ./.env network_mode: "host" - command: bash -c 'source /opt/lofar/lofarinit.sh && ALLOWED_HOSTS=* tmss_test_environment -H 0.0.0.0 -P `hostname -f` -p 8008 -sSd' + command: bash -c 'source /opt/lofar/lofarinit.sh && ALLOWED_HOSTS=* tmss_test_environment -H 0.0.0.0 -P `hostname -f` -p 8008 -sSdv' ports: - "8008:8008" testprovider: diff --git a/SAS/TMSS/services/scheduling/lib/constraints/template_constraints_v1.py b/SAS/TMSS/services/scheduling/lib/constraints/template_constraints_v1.py index dd4f5451a7e844d41a5070b3e083d2cbe4f3fca2..f9e2aab204e1b49dfddbb9c2019342a9150cbf9d 100644 --- a/SAS/TMSS/services/scheduling/lib/constraints/template_constraints_v1.py +++ b/SAS/TMSS/services/scheduling/lib/constraints/template_constraints_v1.py @@ -111,7 +111,8 @@ def can_run_anywhere_within_timewindow_with_daily_constraints(scheduling_unit: m if upper_bound < lower_bound: raise ValueError("Provided upper_bound=%s is earlier than provided lower_bound=%s" % (upper_bound, lower_bound)) - stations = scheduling_unit.requirements_doc['tasks'][main_observation_task_name]['specifications_doc']['stations'] + station_groups = scheduling_unit.requirements_doc['tasks'][main_observation_task_name]['specifications_doc']["station_groups"] + stations = list(set(sum([group['stations'] for group in station_groups], []))) # flatten all station_groups to single list # check contraint and return false on first failure for station in stations: @@ -221,10 +222,13 @@ def can_run_anywhere_within_timewindow_with_sky_constraints(scheduling_unit: mod 'min_calibrator_elevation' in constraints['sky'] and task['specifications_template'] == 'calibrator observation': if task['specifications_template'] == 'calibrator observation': min_elevation = Angle(constraints['sky']['min_calibrator_elevation'], unit=astropy.units.rad) + main_observation_task_name = get_target_observation_task_name_from_requirements_doc(scheduling_unit) + station_groups = scheduling_unit.requirements_doc['tasks'][main_observation_task_name]['specifications_doc']["station_groups"] else: min_elevation = Angle(constraints['sky']['min_target_elevation'], unit=astropy.units.rad) + station_groups = task['specifications_doc']['station_groups'] + stations = list(set(sum([group['stations'] for group in station_groups], []))) # flatten all station_groups to single list timestamps = (lower_bound, upper_bound) - stations = task['specifications_doc']['stations'] # currently we only check at bounds, we probably want to add some more samples in between later on target_rise_and_set_times = coordinates_timestamps_and_stations_to_target_rise_and_set(angle1=angle1, angle2=angle2, direction_type=direction_type, timestamps=timestamps, stations=tuple(stations), angle_to_horizon=min_elevation) for station, times in target_rise_and_set_times.items(): @@ -261,7 +265,8 @@ def get_earliest_possible_start_time(scheduling_unit: models.SchedulingUnitBluep return parser.parse(constraints['time']['after'], ignoretz=True) if constraints['daily']['require_day'] or constraints['daily']['require_night'] or constraints['daily']['avoid_twilight']: - stations = scheduling_unit.requirements_doc['tasks'][main_observation_task_name]['specifications_doc']['stations'] + station_groups = scheduling_unit.requirements_doc['tasks'][main_observation_task_name]['specifications_doc']["station_groups"] + stations = list(set(sum([group['stations'] for group in station_groups], []))) # flatten all station_groups to single list all_sun_events = timestamps_and_stations_to_sun_rise_and_set(timestamps=(lower_bound,lower_bound+timedelta(days=1)), stations=tuple(stations)) start_time_per_station = {} for station in stations: diff --git a/SAS/TMSS/services/scheduling/test/t_dynamic_scheduling.py b/SAS/TMSS/services/scheduling/test/t_dynamic_scheduling.py index 343cc8925a42702dc814b06c808c68d9498f95ee..75d55fa8467b1cda9887ce2859bda2d617ff93f4 100755 --- a/SAS/TMSS/services/scheduling/test/t_dynamic_scheduling.py +++ b/SAS/TMSS/services/scheduling/test/t_dynamic_scheduling.py @@ -125,6 +125,7 @@ class TestDynamicScheduling(TestCase): # Note: we use django.test.TestCase inst scheduling_unit_spec = add_defaults_to_json_object_for_schema(strategy_template.template, strategy_template.scheduling_unit_template.schema) scheduling_unit_spec['tasks']['Observation']['specifications_doc']['duration'] = obs_duration + scheduling_unit_spec['tasks']['Observation']['specifications_doc']['station_groups'][0]['stations'] = ['CS001'] # add the scheduling_unit_doc to a new SchedulingUnitDraft instance, and were ready to use it! return models.SchedulingUnitDraft.objects.create(name=name, @@ -360,7 +361,7 @@ class TestDailyConstraints(TestCase): self.assertEqual(returned_time, self.sunrise_data['CS001']['day'][0]['start']) def test_get_earliest_possible_start_time_with_daytime_constraint_returns_day_start_of_latest_station(self): - self.scheduling_unit_blueprint.requirements_doc['tasks']['Observation']['specifications_doc']['stations'] = ['CS001', 'DE601'] + self.scheduling_unit_blueprint.requirements_doc['tasks']['Observation']['specifications_doc']['station_groups'] = [{'stations': ['CS001', 'DE601']}] self.scheduling_unit_blueprint.draft.scheduling_constraints_doc['daily']['require_day'] = True self.scheduling_unit_blueprint.save() self.sunrise_mock.return_value = self.sunrise_data_early_night @@ -452,7 +453,7 @@ class TestDailyConstraints(TestCase): self.assertEqual(returned_time, self.sunrise_data['CS001']['night'][0]['start']) def test_get_earliest_possible_start_time_with_nighttime_constraint_returns_night_start_of_latest_station(self): - self.scheduling_unit_blueprint.requirements_doc['tasks']['Observation']['specifications_doc']['stations'] = ['CS001', 'DE601'] + self.scheduling_unit_blueprint.requirements_doc['tasks']['Observation']['specifications_doc']['station_groups'] = [{'stations': ['CS001', 'DE601']}] self.scheduling_unit_blueprint.draft.scheduling_constraints_doc['daily']['require_night'] = True self.scheduling_unit_blueprint.save() timestamp = datetime(2020, 1, 1, 14, 0, 0) @@ -589,7 +590,7 @@ class TestDailyConstraints(TestCase): self.assertEqual(returned_time, self.sunrise_data['CS001']['day'][0]['start']) def test_get_earliest_possible_start_time_with_twilight_constraint_returns_day_start_of_latest_station(self): - self.scheduling_unit_blueprint.requirements_doc['tasks']['Observation']['specifications_doc']['stations'] = ['CS001', 'DE601'] + self.scheduling_unit_blueprint.requirements_doc['tasks']['Observation']['specifications_doc']['station_groups'] = [{'stations': ['CS001', 'DE601']}] self.scheduling_unit_blueprint.draft.scheduling_constraints_doc['daily']['avoid_twilight'] = True self.scheduling_unit_blueprint.save() @@ -608,7 +609,7 @@ class TestDailyConstraints(TestCase): self.assertEqual(returned_time, self.sunrise_data['CS001']['night'][0]['start']) def test_get_earliest_possible_start_time_with_twilight_constraint_returns_night_start_of_latest_station(self): - self.scheduling_unit_blueprint.requirements_doc['tasks']['Observation']['specifications_doc']['stations'] = ['CS001', 'DE601'] + self.scheduling_unit_blueprint.requirements_doc['tasks']['Observation']['specifications_doc']['station_groups'] = [{'stations': ['CS001', 'DE601']}] self.scheduling_unit_blueprint.draft.scheduling_constraints_doc['daily']['avoid_twilight'] = True self.scheduling_unit_blueprint.save() diff --git a/SAS/TMSS/src/tmss/tmssapp/schemas/simple-observation-scheduling-unit-observation-strategy.json b/SAS/TMSS/src/tmss/tmssapp/schemas/simple-observation-scheduling-unit-observation-strategy.json index cfa908a68e642538b03c398a65e6d752f2e81db2..3a9536713768ac5ff4ddb93874dcea024dcdf9ee 100644 --- a/SAS/TMSS/src/tmss/tmssapp/schemas/simple-observation-scheduling-unit-observation-strategy.json +++ b/SAS/TMSS/src/tmss/tmssapp/schemas/simple-observation-scheduling-unit-observation-strategy.json @@ -24,7 +24,9 @@ }, "antenna_set": "HBA_DUAL_INNER", "filter": "HBA_110_190", - "stations": ["CS001"], + "station_groups": [ { + "stations": ["CS002", "CS003", "CS004", "CS005", "CS006", "CS007"] + }], "tile_beam": { "direction_type": "J2000", "angle1": 0.42,