diff --git a/SAS/TMSS/src/tmss/tmssapp/subtasks.py b/SAS/TMSS/src/tmss/tmssapp/subtasks.py index 8cb12d96d0d99434c65dc7ae5d406e1ea6ef8698..edb4b33a3b94648c79fe24f8a968c4fe939b0411 100644 --- a/SAS/TMSS/src/tmss/tmssapp/subtasks.py +++ b/SAS/TMSS/src/tmss/tmssapp/subtasks.py @@ -28,9 +28,14 @@ def create_subtasks_from_task_blueprint(task_blueprint: TaskBlueprint) -> [Subta check_prerequities_for_subtask_creation(task_blueprint) # fixed mapping from template name to generator functions which create the list of subtask(s) for this task_blueprint - generators_mapping = {'observation schema': [create_observation_control_subtask_from_task_blueprint, - create_qafile_subtask_from_task_blueprint, - create_qaplots_subtask_from_task_blueprint], + generators_mapping = {'observation schema': [create_observation_control_subtask_from_task_blueprint_target_observation, + create_qafile_subtask_from_task_blueprint, + create_qaplots_subtask_from_task_blueprint], + 'calibrator schema': [create_observation_control_subtask_from_task_blueprint_calibrator_observation, + # skip QA for now..can not handle multiple qa plots subtasks + #create_qafile_subtask_from_task_blueprint, + #create_qaplots_subtask_from_task_blueprint + ], 'preprocessing schema': [create_preprocessing_subtask_from_task_blueprint]} template_name = task_blueprint.specifications_template.name @@ -43,7 +48,116 @@ def create_subtasks_from_task_blueprint(task_blueprint: TaskBlueprint) -> [Subta raise SubtaskCreationException('Cannot create subtasks for task id=%s because no generator exists for its schema name=%s' % (task_blueprint.pk, template_name)) -def create_observation_control_subtask_from_task_blueprint(task_blueprint: TaskBlueprint) -> Subtask: +def get_target_observation_specifications(task_spec): + """ + Retrieve the specification (station and correlator settings) from Target Observation specification + """ + lst_digital_pointings = [] + if "SAPs" in task_spec: + for sap in task_spec["SAPs"]: + lst_digital_pointings.append( + {"name": sap["name"], + "pointing": {"direction_type": sap["digital_pointing"]["direction_type"], + "angle1": sap["digital_pointing"]["angle1"], + "angle2": sap["digital_pointing"]["angle2"]}, + "subbands": sap["subbands"] + }) + + if "stations" in task_spec: + # TODO: Retrieve stations list in case of a dynamic list : ALL, SUPERTERP, CORE, REMOTE, DUTCH, INTERNATIONAL + # for now just hack one station....so also ignore the minimum for now + # could be that this is already some ticket? + if "group" in task_spec["stations"][0]: + station_list = ["CS001"] + else: + station_list = task_spec["stations"] + + # Apparently analog pointing is not required + if "tile_beam" in task_spec: + analog_pointing = {"direction_type": task_spec["tile_beam"]["direction_type"], + "angle1": task_spec["tile_beam"]["angle1"], + "angle2": task_spec["tile_beam"]["angle2"] + } + else: + analog_pointing = {} + target_observation_specifications_doc = { + "stations": {"station_list": station_list, + "antenna_set": task_spec["antenna_set"], + "filter": task_spec["filter"], + "analog_pointing": analog_pointing, + "digital_pointings": lst_digital_pointings + } + } + else: + target_observation_specifications_doc = {} + + return target_observation_specifications_doc + + +def create_observation_control_subtask_from_task_blueprint_target_observation(task_blueprint: TaskBlueprint) -> Subtask: + """ + Create an observation control subtask from task which is a Target Observation. + Determine the non-default specifications which is required for the observation control subtasks. + Therefore translate Task to SubTask settings + See https://support.astron.nl/confluence/pages/viewpage.action?spaceKey=TMSS&title=UC1+JSON + + Each Target Observation Task is split into Subtasks as follows: + * An ObsControl Subtask is created to configure the stations & COBALT: + * If any Calibrator Addon Tasks refer to this Target Observation Task using a parallel Task Scheduling Relation, + a Calibrator station beam is added to the specification. + * Subtasks are created for generating ADDR inspection plots on any correlated visibilities produced. + + :param task_blueprint: + :return: subtask + """ + logger.info("Task (id=%d) is a Target Observation" % task_blueprint.pk) + # TODO: should angle 3 als be handled by observation control? + # What todo with COBALT settings where should that come from? + # How should the observation duration fit in observation control task? + print(task_blueprint.specifications_doc) + target_observation_specifications_doc = get_target_observation_specifications(task_blueprint.specifications_doc) + subtask = create_observation_control_subtask_from_task_blueprint(task_blueprint, target_observation_specifications_doc) + return subtask + + +def create_observation_control_subtask_from_task_blueprint_calibrator_observation(task_blueprint: TaskBlueprint) -> Subtask: + """ + Create an observation control subtask from task which is a Calibrator Observation. + Determine the non-default specifications which is required for the observation control subtasks. + Therefore translate Task to SubTask settings + See https://support.astron.nl/confluence/pages/viewpage.action?spaceKey=TMSS&title=UC1+JSON + + Each Calibrator Addon Task, which has a before or after relation with an Observation Task, + is turned into the same set of Subtasks: + * An ObsControl Subtask is created, with a beam pointing at the calibrator source. + All other station & correlator settings are copied from the referenced Observation Task, + * Subtasks are created for generating ADDR inspection plots on any correlated visibilities produced. + + :param task_blueprint: + :return: subtask + """ + logger.info("Task (id=%d) is a Calibrator Addon Observation" % task_blueprint.pk) + # Get the related Target Observation Task + # TODO: + # 1) The TaskSchedulingRelationDraft should be copied to TaskSchedulingRelationBlueprint during create blueprint + # 2) Get the related blueprint_task, which should be a Target Observation + # Somehow I can not retrieve it with ......objects.get(first="Calibrator Observation 1") ...??? + related_blueprint_target_observation = TaskBlueprint.objects.get(name="Task Blueprint of Target Observation") + calibrator_spec = task_blueprint.specifications_doc + + calibrator_observation_specifications_doc = get_target_observation_specifications(related_blueprint_target_observation.specifications_doc) + + calibrator_observation_specifications_doc["stations"]["analog_pointing"] = { + "direction_type": calibrator_spec["pointing"]["direction_type"], + "angle1": calibrator_spec["pointing"]["angle1"], + "angle2": calibrator_spec["pointing"]["angle2"]} + + subtask = create_observation_control_subtask_from_task_blueprint(task_blueprint, calibrator_observation_specifications_doc) + logger.info("Subtask %d created" % subtask.pk) + return subtask + + +def create_observation_control_subtask_from_task_blueprint(task_blueprint: TaskBlueprint, extra_specifications_doc) -> Subtask: """ Create an observation control subtask . This method implements "Instantiate subtasks" step from the "Specification Flow" @@ -54,25 +168,8 @@ def create_observation_control_subtask_from_task_blueprint(task_blueprint: TaskB # step 1: create subtask in defining state subtask_template = SubtaskTemplate.objects.get(name='observationcontrol schema') - # This is some 'extra' specification to add to subtask ... where should it comes from, - # currently not defined in task ? - extra_specifications_doc = { - "stations": {"station_list": ["RS106", "RS205"], - "antenna_set": "HBA_DUAL_INNER", - "filter": "HBA_110_190", - "analog_pointing": {"direction_type": "J2000", - "angle1": 0.4262457643630986, - "angle2": 0.5787463318245085}, - "digital_pointings": [{"name": "3C48", - "pointing": {"direction_type": "J2000", - "angle1": 0.4262457643630986, - "angle1": 0.4262457643630986, - "angle2": 0.5787463318245085}, - "subbands": list(range(0, 244)) - }] - } - } + # This is some 'extra' specification to add to subtask depended on observation type specifications_doc = add_defaults_to_json_object_for_schema(extra_specifications_doc, subtask_template.schema) cluster_name = task_blueprint.specifications_doc.get("storage_cluster", "CEP4") subtask_data = { "start_time": None, diff --git a/SAS/TMSS/src/tmss/tmssapp/tasks.py b/SAS/TMSS/src/tmss/tmssapp/tasks.py index 2da600a24184f98c8158ee97768f0825e62c319c..432a1e1d7ec4168500f4632065fd117edbe9e1b5 100644 --- a/SAS/TMSS/src/tmss/tmssapp/tasks.py +++ b/SAS/TMSS/src/tmss/tmssapp/tasks.py @@ -1,6 +1,5 @@ from lofar.sas.tmss.tmss.tmssapp import models from lofar.sas.tmss.tmss.tmssapp.models.specification import TaskBlueprint, SchedulingUnitBlueprint, TaskDraft, Placement -from lofar.sas.tmss.tmss.tmssapp.subtasks import create_and_schedule_subtasks_from_task_blueprint from lofar.sas.tmss.tmss.tmssapp.models.specification import TaskBlueprint, SchedulingUnitBlueprint from lofar.sas.tmss.tmss.tmssapp.subtasks import create_and_schedule_subtasks_from_task_blueprint, \ create_subtasks_from_task_blueprint, schedule_independent_subtasks_in_task_blueprint @@ -122,7 +121,7 @@ def create_task_blueprint_from_task_draft(task_draft: models.TaskDraft) -> model specifications_template=task_draft.specifications_template ) - logger.info("Task Blueprint (id=%s) created from Task Draft (id=%s) created task_blueprint id=%s", task_blueprint.pk, task_draft.pk) + logger.info("Task Blueprint (id=%s) created from Task Draft (id=%s)", task_blueprint.pk, task_draft.pk) # now that we have a task_blueprint, its time to refresh the task_draft so we get the non-cached fields task_draft.refresh_from_db() diff --git a/SAS/TMSS/test/t_subtasks.py b/SAS/TMSS/test/t_subtasks.py index b7da9da760dd1638a93a2f70658ebc12697e6067..5e7788bcda3e4234a5696d7aef025beac5b0a412 100755 --- a/SAS/TMSS/test/t_subtasks.py +++ b/SAS/TMSS/test/t_subtasks.py @@ -41,23 +41,14 @@ from lofar.sas.tmss.tmss.tmssapp import models from lofar.sas.tmss.tmss.tmssapp.subtasks import * -# The following methods should be tested -# check_prerequities_for_subtask_creation -# create_subtasks_from_task_blueprint -# create_observation_control_subtask_from_task_blueprint -# create_qafile_subtask_from_task_blueprint -# create_qafile_subtask_from_observation_subtask -# create_qaplots_subtask_from_task_blueprint -# create_qaplots_subtask_from_qafile_subtask -# create_preprocessing_subtask_from_task_blueprint -# +# The following methods should be tested too + # schedule_subtask # check_prerequities_for_scheduling # schedule_qafile_subtask # schedule_qaplots_subtask # schedule_observation_subtask # schedule_pipeline_subtask -# # create_and_schedule_subtasks_from_task_blueprint @@ -163,7 +154,7 @@ class SubTasksCreationFromTaskBluePrint(unittest.TestCase): """ task_blueprint = self.create_task_blueprint_object() - subtask = create_observation_control_subtask_from_task_blueprint(task_blueprint) + subtask = create_observation_control_subtask_from_task_blueprint(task_blueprint,{}) self.assertEqual("defined", str(subtask.state)) self.assertEqual("observationcontrol schema", str(subtask.specifications_template.name)) self.assertEqual("observation", str(subtask.specifications_template.type)) @@ -190,7 +181,7 @@ class SubTasksCreationFromTaskBluePrint(unittest.TestCase): task_blueprint = self.create_task_blueprint_object(QA_enabled=True) task_blueprint_preprocessing = self.create_task_blueprint_object("preprocessing schema") - subtask = create_observation_control_subtask_from_task_blueprint(task_blueprint) + subtask = create_observation_control_subtask_from_task_blueprint(task_blueprint, {}) self.assertEqual("defined", str(subtask.state)) self.assertEqual("observationcontrol schema", str(subtask.specifications_template.name)) self.assertEqual("observation", str(subtask.specifications_template.type)) diff --git a/SAS/TMSS/test/t_tasks.py b/SAS/TMSS/test/t_tasks.py index 5005382e6c831e41cbd0f90d9c48afc99cce33de..b7418902b74aaa14c79b0c19fea00d5bdfb743f9 100755 --- a/SAS/TMSS/test/t_tasks.py +++ b/SAS/TMSS/test/t_tasks.py @@ -174,7 +174,6 @@ class CreationFromTaskDraft(unittest.TestCase): """ self.create_task_object("Test Target Observation 1") - task_draft = models.TaskDraft.objects.get(name="Test Target Observation 1") rest_task_draft = GET_and_assert_equal_expected_code(self, BASE_URL + '/task_draft/' + str(task_draft.id), 200) task_blueprint = create_task_blueprint_and_subtasks_and_schedule_subtasks_from_task_draft(task_draft)