diff --git a/src/core/pyros_django/scheduling/A_Scheduler.py b/src/core/pyros_django/scheduling/A_Scheduler.py index 9ba0243..0490688 100755 --- a/src/core/pyros_django/scheduling/A_Scheduler.py +++ b/src/core/pyros_django/scheduling/A_Scheduler.py @@ -5,6 +5,9 @@ # Linux console: # cd /srv/develop/pyros/docker # ./PYROS_DOCKER_START.sh +# ./PYROS_RUN_WEBSERVER_ONLY -o tnc -fg +# cd .. +# ./PYROS start -o tnc -fg -a A_Scheduler # # Launch from Power Shell: # To go from docker to Powershell: pyros_user@ORION:~/app$ exit (or Ctrl+d) @@ -29,6 +32,7 @@ import argparse import os import pickle import socket +import yaml pwd = os.environ['PROJECT_ROOT_PATH'] if pwd not in sys.path: @@ -44,6 +48,7 @@ for short_path in short_paths: from majordome.agent.Agent import Agent, build_agent, log, parse_args from seq_submit.models import Sequence from user_mgmt.models import Period, ScientificProgram, SP_Period +from scp_mgmt.models import Quota from scheduling.models import PredictiveSchedule, EffectiveSchedule # = Specials import glob @@ -54,6 +59,8 @@ from decimal import Decimal import zoneinfo import numpy as np +from pyros_api import PyrosAPI + class A_Scheduler(Agent): DPRINT = True @@ -223,7 +230,7 @@ class A_Scheduler(Agent): """ - def update_db_quota_sequence(sequence_id, quota_attributes): + def update_db_quota_sequence(self, sequence_id, quota_attributes): sequence = Sequence.objects.get(id=sequence_id) new_quota = Quota() new_quota.set_attributes_and_save(quota_attributes) @@ -249,13 +256,14 @@ class A_Scheduler(Agent): # --- Get the night night = info['night'] # --- Get ephemeris informations of the night and initialize quotas - night_info = self.update_sun_moon_ephems() - quota_total_period = night_info['total'][1] - quota_total_night_start = night_info[night][0] - quota_total_night_end = night_info[night][1] - self.dprint(f"{quota_total_period=}") - self.dprint(f"{quota_total_night_start=}") - self.dprint(f"{quota_total_night_end=}") + self.update_sun_moon_ephems() + + # Get quota for night + + oquota = Quota.objects.get(id_period=info["operiod"].id, night_id=info["night"]) + + + # --- Build the wildcard to list the sequences wildcard = os.path.join(rootdir, subdir, "*.p") self.dprint(f"{wildcard=}") @@ -329,6 +337,7 @@ class A_Scheduler(Agent): eph_info = pickle.load(open(ephfile,"rb")) #print("="*20 + "\n" + f"{eph_info=}") # --- + self._fn.fcontext = "pyros_seq" param = self._fn.naming_get(seqfile) sequence_info['id'] = int(param['id_seq']) # --- scientific_program_id is an integer @@ -351,14 +360,18 @@ class A_Scheduler(Agent): sequence_info['visibility_duration'] = visibility_duration # total slots - duration sequence_info['duration'] = seq_info['sequence']['duration'] sequence_info['scientific_program_id'] = scientific_program_id + sequence_info["period"] = seq_info["sequence"]["period"] + sequence_info["night_id"] = seq_info["sequence"]["night_id"] self.dprint(f" {scientific_program_id=} range to start={len(kobss)}") if scientific_program_id not in scientific_program_ids: scientific_program_ids.append(scientific_program_id) # --- TODO quota_attributes = {} - quota_attributes["total"] = sequence_info["duration"] - quota_attributes["schedule"] = sequence_info["duration"] - update_db_quota_sequence(sequence_info["id"], quota_attributes) + quota_attributes["d_total"] = int(np.ceil(sequence_info["duration"])) + quota_attributes["d_schedule"] = int(np.ceil(sequence_info["duration"])) + quota_attributes["night_id"] = sequence_info["night_id"] + quota_attributes["id_period"] = sequence_info["period"] + self.update_db_quota_sequence(seq_info["sequence"]["id"], quota_attributes) else: sequence_info['error'] = f"File {ephfile} not exists" sequence_infos.append(sequence_info) @@ -556,9 +569,12 @@ class A_Scheduler(Agent): log.info(f"_compute_schedule_1 finished in {time.time() - t0:.2f} seconds") def _create_seq_1(self, nb_seq: int): + # delete all previous test seq + Sequence.objects.filter(id__gte=9990000000).delete() t0 = time.time() self.dprint("Debut _create_seq_1") - seq_template = {'sequence': {'id': 4, 'start_expo_pref': 'IMMEDIATE', 'pyros_user': 2, 'scientific_program': 1, 'name': 'seq_20230628T102140', 'desc': None, 'last_modified_by': 2, 'is_alert': False, 'status': 'TBP', 'with_drift': False, 'priority': None, 'analysis_method': None, 'moon_min': None, 'alt_min': None, 'type': None, 'img_current': None, 'img_total': None, 'not_obs': False, 'obsolete': False, 'processing': False, 'flag': None, 'period': 1, 'start_date': datetime.datetime(2023, 6, 28, 10, 21, 40, tzinfo=zoneinfo.ZoneInfo(key='UTC')), 'end_date': datetime.datetime(2023, 6, 28, 10, 21, 40, 999640, tzinfo=datetime.timezone.utc), 'jd1': Decimal('0E-8'), 'jd2': Decimal('0E-8'), 'tolerance_before': '1s', 'tolerance_after': '1min', 'duration': -1.0, 'overhead': Decimal('0E-8'), 'submitted': False, 'config_attributes': {'tolerance_before': '1s', 'tolerance_after': '1min', 'target': 'RADEC 0H10M -15D', 'conformation': 'WIDE', 'layout': 'Altogether'}, 'ra': None, 'dec': None, 'complete': True, 'night_id': '20230627'}, 'albums': {'Altogether': {'plans': [{'id': 4, 'album': 4, 'duration': 0.0, 'nb_fnges': 1, 'config_attributes': {'binnings': {'binxy': [1, 1], 'readouttime': 6}, 'exposuretime': 1.0}, 'complete': True}]}}} + seq_template = yaml.safe_load(open("scheduler_seq_template.yml","r")) + #{"simplified":True, 'sequence': {'id': 4, 'start_expo_pref': 'IMMEDIATE', 'pyros_user': 2, 'scientific_program': 1, 'name': 'seq_20230628T102140', 'desc': None, 'last_modified_by': 2, 'is_alert': False, 'status': 'TBP', 'with_drift': False, 'priority': None, 'analysis_method': None, 'moon_min': None, 'alt_min': None, 'type': None, 'img_current': None, 'img_total': None, 'not_obs': False, 'obsolete': False, 'processing': False, 'flag': None, 'period': 1, 'start_date': datetime.datetime(2023, 6, 28, 10, 21, 40, tzinfo=zoneinfo.ZoneInfo(key='UTC')), 'end_date': datetime.datetime(2023, 6, 28, 10, 21, 40, 999640, tzinfo=datetime.timezone.utc), 'tolerance_before': '1s', 'tolerance_after': '1min', 'duration': -1.0, 'submitted': False, 'config_attributes': {'tolerance_before': '1s', 'tolerance_after': '1min', 'target': 'RADEC 0H10M -15D', 'conformation': 'WIDE', 'layout': 'Altogether'}, 'ra': None, 'dec': None, 'complete': True, 'night_id': '20230627'}, 'albums': {'Altogether': {'plans': [{'id': 4, 'album': 4, 'duration': 0.0, 'nb_fnges': 1, 'config_attributes': {'binnings': {'binxy': [1, 1], 'readouttime': 6}, 'exposuretime': 1.0}, 'complete': True}]}}} # decode general variables info a dict info info = self.get_infos() rootdir = info['rootdir'] @@ -603,35 +619,54 @@ class A_Scheduler(Agent): # --- Create new sequences for k in range(nb_seq): #print("B"*20 + f" {info['operiod'].id} {info['night']} {k}") + if k < nb_seq/2: + scientific_program = 0 + else: + scientific_program = 1 + time.sleep(1) seq = seq_template.copy() - seq['sequence']['period'] = info['operiod'].id # int - seq['sequence']['night_id'] = info['night'] # str - seq['sequence']['config_attributes']['target'] = k # int + print(f"{seq}") + #seq['sequence']['config_attributes']['target'] = k # int # --- - start_expo_pref = "BESTELEV" #"IMMEDIATE" - scientific_program = int(k/2) - start_date = datetime.datetime(2023, 6, 28, 10, 21, 40) - end_date = datetime.datetime(2023, 6, 28, 10, 21, 40, 999640, tzinfo=datetime.timezone.utc) + #start_expo_pref = "BESTELEV" #"IMMEDIATE" + start_expo_pref = 0 # for bestelev 1, for immediate 0 + start_date,_ = self._fn.night2date(info["night"]) + start_date = start_date + 0.25 + (0.5*k) + start_date_to_datetime = guitastro.Date(start_date).iso() + #start_date = datetime.datetime(2023, 6, 28, 10, 21, 40) + #end_date = datetime.datetime(2023, 6, 28, 10, 21, 40, 999640, tzinfo=datetime.timezone.utc) jd1 = Decimal('0E-8') jd2 = Decimal('0E-8') tolerance_before = '1s' - tolerance_after = '1min' + tolerance_after = '5min' duration = 3000.0 target = f"RADEC {k}h {10+2*k}d" # --- seq['sequence']['start_expo_pref'] = start_expo_pref seq['sequence']['scientific_program'] = scientific_program - seq['sequence']['start_date'] = start_date - seq['sequence']['end_date'] = end_date - seq['sequence']['jd1'] = jd1 - seq['sequence']['jd2'] = jd2 + seq['sequence']['start_date'] = start_date_to_datetime + # seq['sequence']['jd1'] = jd1 + # seq['sequence']['jd2'] = jd2 seq['sequence']['tolerance_before'] = tolerance_before seq['sequence']['tolerance_after'] = tolerance_after - seq['sequence']['duration'] = duration - seq['sequence']['config_attributes']['target'] = target + seq['sequence']['target'] = target # --- Build the path and file name of the sequence file - fn_param["id_seq"] = int("999" + f"{k:07d}") + seq["sequence"]["id"] = int("999" + f"{k:07d}") + seq["sequence"]["name"] = "seq_"+str(seq["sequence"]["id"]) + # Add sequence to db + # with pyros_api script + pyros_api = PyrosAPI(None) + self._fn.fcontext = "pyros_seq_tmp" + self._fn.extension = ".json" + seq_fname = self._fn.join(str(seq["sequence"]["id"])) + seq_file = open(seq_fname,"w") + seq_file.write(yaml.dump(seq, sort_keys=False)) + seq_file.close() + response = pyros_api.submit_sequence_file(seq_fname) + log.info(f"{response}") + + """ self.dprint(f"{k} : {self._fn.fcontext=}") self._fn.fname = self._fn.naming_set(fn_param) self.dprint(f"{k} : {self._fn.fname=}") @@ -658,6 +693,7 @@ class A_Scheduler(Agent): pickle.dump(seq, open(seq_file,"wb")) #dprint(f"{errors=}") #dprint("C"*20) + """ log.info(f"_create_seq_1 finished in {time.time() - t0:.2f} seconds") def load_sequence(self): diff --git a/src/core/pyros_django/scheduling/scheduler_seq_template.yml b/src/core/pyros_django/scheduling/scheduler_seq_template.yml new file mode 100644 index 0000000..4196d51 --- /dev/null +++ b/src/core/pyros_django/scheduling/scheduler_seq_template.yml @@ -0,0 +1,19 @@ +simplified: True +sequence: + scientific_program: 0 + name: seq_20231019T153204 + start_date: '2023-10-19T15:32:04.000000' + tolerance_before: 1s + tolerance_after: 1min + start_expo_pref: 0 + target: RADEC 0H10M -15D + conformation: 0 + layout: 0 + ALBUMS: + - Album: + name: Altogether + Plans: + - Plan: + nb_images: 100 + exposuretime: 10 + binnings: 0 -- libgit2 0.21.2