Commit 198132303d731ebe7a310c5a0780ce287b60c0de

Authored by Alain Klotz
1 parent be9ae145
Exists in dev

New DATA structure in two Agents.

config/pyros_observatory/general/schemas/schema_observatory-2.0.yml
... ... @@ -135,6 +135,20 @@ schema;schema_FN_CONTEXTS:
135 135 type: map
136 136 required: False
137 137 mapping:
  138 + pyros_cat:
  139 + type: map
  140 + required: False
  141 + mapping:
  142 + root_dir:
  143 + type: str
  144 + description:
  145 + type: str
  146 + extension:
  147 + type: str
  148 + naming:
  149 + type: str
  150 + pathnaming:
  151 + type: str
138 152 pyros_skd:
139 153 type: map
140 154 required: False
... ...
src/core/pyros_django/img_process/A_ImgProcessor.py
... ... @@ -58,7 +58,7 @@ class A_ImgProcessor(Agent):
58 58 "do_stop_current_processing" : (60, Agent.EXEC_MODE.SEQUENTIAL, ''),
59 59 }
60 60  
61   - # Scenario to be executed
  61 + # Test scenario to be executed (option -t)
62 62 # "self do_stop_current_processing"
63 63 # AgentCmd.CMD_STATUS_CODE.CMD_EXECUTED
64 64 _TEST_COMMANDS_LIST = [
... ... @@ -119,13 +119,16 @@ class A_ImgProcessor(Agent):
119 119 log.info(f"{longitude=}")
120 120 self._ima.longitude(longitude)
121 121  
122   - # === Copy the channel file contexts into the Ima object
  122 + # === Copy and update the channel file contexts into the Ima object
123 123 self._ima.fcontext_replace(self._fn)
124 124 log.info(f"=== List of file name contexts available for the channel {channel['name']} ({channel['symbol']})")
125 125 for fcname in self._ima.fcontexts:
126 126 self._ima.fcontext = fcname
  127 + if self.is_in_test_mode():
  128 + self._ima.rootdir = os.path.abspath(self._ima.rootdir.replace("/PRODUCTS/","/PRODUCTS/TESTS/"))
  129 + os.makedirs(self._ima.rootdir, exist_ok=True)
127 130 log.info(f"{fcname} : {self._ima.fdescription} {self._ima.rootdir}/[{self._ima.pathing()}]/[{self._ima.naming()}]{self._ima.extension}")
128   -
  131 +
129 132 # === Status of routine processing
130 133 self._routine_running = self.RUNNING_NOTHING
131 134 log.info("Init done with success")
... ... @@ -514,7 +517,8 @@ class A_ImgProcessor(Agent):
514 517 log.info(f"Test image night: {datedict['night']}")
515 518 # --- Get other infos
516 519 filter_symbol = "C"
517   - id_sequence = 123456789
  520 + kid = 110
  521 + id_sequence = int("999" + f"{kid:07d}")
518 522  
519 523 # --- Rename the image file name when copying to be compatible with the img_L0 file context
520 524 try:
... ... @@ -647,7 +651,8 @@ class A_ImgProcessor(Agent):
647 651 att = at
648 652 # --- Get other infos
649 653 filter_symbol = "C"
650   - id_sequence = 123452789
  654 + kid = 210
  655 + id_sequence = int("999" + f"{kid:07d}")
651 656  
652 657 # --- Save the image file name to be compatible with the img_L0 file context
653 658 try:
... ...
src/core/pyros_django/scheduling/A_Scheduler.py
... ... @@ -53,7 +53,7 @@ import numpy as np
53 53  
54 54 class A_Scheduler(Agent):
55 55  
56   - DPRINT = False
  56 + DPRINT = True
57 57  
58 58 # - Sampling of the night arrays (bins/night)
59 59 BINS_NIGHT = 86400
... ... @@ -85,13 +85,13 @@ class A_Scheduler(Agent):
85 85 "do_create_seq_1" : (60, Agent.EXEC_MODE.SEQUENTIAL, ''),
86 86 }
87 87  
88   - # Scenario to be executed
  88 + # Test scenario to be executed (option -t)
89 89 # "self do_stop_current_processing"
90 90 # AgentCmd.CMD_STATUS_CODE.CMD_EXECUTED
91 91 _TEST_COMMANDS_LIST = [
92 92 # Format : ("self cmd_name cmd_args", timeout, "expected_result", expected_status),
93 93 (True, "self do_create_seq_1 6", 200, '', Agent.CMD_STATUS.CMD_EXECUTED),
94   - #(True, "self do_stop asap", 500, "STOPPING", Agent.CMD_STATUS.CMD_EXECUTED),
  94 + (True, "self do_stop asap", 500, "STOPPING", Agent.CMD_STATUS.CMD_EXECUTED),
95 95 ]
96 96  
97 97 """
... ... @@ -126,11 +126,15 @@ class A_Scheduler(Agent):
126 126 # === Get home (Home object) of current unit
127 127 home = guitastro.Home(self._home)
128 128  
129   - # === Get all file contexts from pyros config
  129 + # === Get and update all file contexts from pyros config
130 130 self._fn = self.config.fn
131   -
132   - # === Select the file contextof sequence files
133   - self._fn.pathnaming("PyROS.seq.1")
  131 + log.info(f"=== List of file name contexts available for the unit")
  132 + for fcname in self._fn.fcontexts:
  133 + self._fn.fcontext = fcname
  134 + if self.is_in_test_mode():
  135 + self._fn.rootdir = os.path.abspath(self._fn.rootdir.replace("/PRODUCTS/","/PRODUCTS/TESTS/"))
  136 + os.makedirs(self._fn.rootdir, exist_ok=True)
  137 + log.info(f"{fcname} : {self._fn.fdescription} {self._fn.rootdir}/[{self._fn.pathing()}]/[{self._fn.naming()}]{self._fn.extension}")
134 138  
135 139 # === Set longitude to sequence file context to manage the night subdirectories
136 140 longitude = home.longitude
... ... @@ -167,7 +171,10 @@ class A_Scheduler(Agent):
167 171 def do_create_seq_1(self, nb_seq:int):
168 172 """Create sequences to debug
169 173 """
170   - self._create_seq_1(nb_seq)
  174 + try:
  175 + self._create_seq_1(nb_seq)
  176 + except Exception as e:
  177 + self.dprint(f"ERROR {e}")
171 178  
172 179 def do_compute_schedule_1(self):
173 180 """Compute a schedule
... ... @@ -182,7 +189,10 @@ class A_Scheduler(Agent):
182 189 Columns are defined by the enum SEQ_* (see the python code itself).
183 190  
184 191 """
185   - self._compute_schedule_1()
  192 + try:
  193 + self._compute_schedule_1()
  194 + except Exception as e:
  195 + self.dprint(f"ERROR {e}")
186 196  
187 197 """
188 198 =================================================================
... ... @@ -511,7 +521,7 @@ class A_Scheduler(Agent):
511 521 v = PredictiveSchedule.objects.last()
512 522 if v == None:
513 523 v = PredictiveSchedule()
514   - #print(f"{v=}")
  524 + #log.info(f"{v=}")
515 525 v.scheduler_matrix = ouput_matrix
516 526 v.save()
517 527 # --- Save the numpy matrix in database (via Json)
... ... @@ -522,32 +532,68 @@ class A_Scheduler(Agent):
522 532 v.save()
523 533 # --- Update the running state
524 534 self._routine_running = self.RUNNING_NOTHING
525   - print(f"_compute_schedule_1 finished in {time.time() - t0:.2f} seconds")
  535 + log.info(f"_compute_schedule_1 finished in {time.time() - t0:.2f} seconds")
526 536  
527   - def _create_seq_1(self, nb_seq):
  537 + def _create_seq_1(self, nb_seq: int):
528 538 t0 = time.time()
529 539 self.dprint("Debut _create_seq_1")
530   - 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_images': 1, 'config_attributes': {'binnings': {'binxy': [1, 1], 'readouttime': 6}, 'exposuretime': 1.0}, 'complete': True}]}}}
  540 + 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}]}}}
531 541 # decode general variables info a dict info
532 542 info = self.get_infos()
533 543 rootdir = info['rootdir']
534 544 subdir = info['subdir']
  545 +
535 546 # --- Prepare ephemeris object
536 547 # TBD duskelev a parametrer from obsconfig (yml)
537 548 duskelev = -7
538 549 eph = guitastro.Ephemeris()
539 550 eph.set_home(self.config.getHome())
540   - print(f"Debut _create_seq_1 SUN {info['night']=}")
541   - try:
  551 +
  552 + # --- Build the path and file name of the sun ephemeris
  553 + self._fn.fcontext = "pyros_eph"
  554 + fn_param = {
  555 + "period" : f"{info['period_id']}",
  556 + "date": info['night'],
  557 + "version": "1",
  558 + "unit": self.config.unit_name,
  559 + "target": "sun"
  560 + }
  561 + fname = self._fn.naming_set(fn_param)
  562 + eph_file = self._fn.joinabs(fname)
  563 + # --- Compute the sun ephemeris if needed. Save it as pickle.
  564 + if not os.path.exists(eph_file):
542 565 ephem_sun = eph.target2night("sun", info['night'], None, None)
543   - except Exception as e:
544   - print(f"{e.message=} {e.args=}")
545   - print(f"Debut _create_seq_1 MOON {eph.target2night=}")
546   - ephem_moon = eph.target2night("moon", info['night'], None, None)
  566 + os.makedirs(os.path.dirname(eph_file), exist_ok=True)
  567 + pickle.dump(ephem_sun, open(eph_file,"wb"))
  568 + else:
  569 + ephem_sun = pickle.load(open(eph_file,"rb"))
  570 + self._fn.fcontext = "pyros_seq"
  571 +
  572 + # --- Build the path and file name of the moon ephemeris
  573 + self._fn.fcontext = "pyros_eph"
  574 + fn_param = {
  575 + "period" : f"{info['period_id']}",
  576 + "date": info['night'],
  577 + "version": "1",
  578 + "unit": self.config.unit_name,
  579 + "target": "moon"
  580 + }
  581 + fname = self._fn.naming_set(fn_param)
  582 + eph_file = self._fn.joinabs(fname)
  583 + # --- Compute the moon ephemeris if needed. Save it as pickle.
  584 + if not os.path.exists(eph_file):
  585 + ephem_moon = eph.target2night("moon", info['night'], None, None)
  586 + os.makedirs(os.path.dirname(eph_file), exist_ok=True)
  587 + pickle.dump(ephem_moon, open(eph_file,"wb"))
  588 + else:
  589 + ephem_moon = pickle.load(open(eph_file,"rb"))
  590 + self._fn.fcontext = "pyros_seq"
  591 +
547 592 # --- Horizon (TBD get from config)
548   - print("Debut _create_seq_1 Horizon")
  593 + self.dprint("Debut _create_seq_1 Horizon")
549 594 hor = guitastro.Horizon(eph.home)
550 595 hor.horizon_altaz = [ [0,0], [360,0] ]
  596 +
551 597 # --- Delete all existing *.p and *.f files in the night directory
552 598 fn_param = {
553 599 "period" : f"{info['period_id']}",
... ... @@ -568,7 +614,8 @@ class A_Scheduler(Agent):
568 614 for seq_dfile in seq_dfiles:
569 615 #print(f":::.1 : os.remove {seq_dfile=}")
570 616 os.remove(seq_dfile)
571   - # ---
  617 +
  618 + # --- Create new sequences
572 619 for k in range(nb_seq):
573 620 #print("B"*20 + f" {info['operiod'].id} {info['night']} {k}")
574 621 time.sleep(1)
... ... @@ -599,22 +646,21 @@ class A_Scheduler(Agent):
599 646 seq['sequence']['duration'] = duration
600 647 seq['sequence']['config_attributes']['target'] = target
601 648 # --- Build the path and file name of the sequence file
602   - fn_param["id_seq"] = k
603   - print(f"{k} : {self._fn.fcontext=}")
  649 + fn_param["id_seq"] = int("999" + f"{k:07d}")
  650 + self.dprint(f"{k} : {self._fn.fcontext=}")
604 651 self._fn.fname = self._fn.naming_set(fn_param)
605   - print(f"{k} : {self._fn.fname=}")
  652 + self.dprint(f"{k} : {self._fn.fname=}")
606 653 seq_file = self._fn.join(self._fn.fname)
607   - print(f"{k} : {seq_file=}")
  654 + self.dprint(f"{k} : {seq_file=}")
608 655 # --- Build the path and file name of the ephemeris file
609 656 eph_file = f"{seq_file[:-2]}.f"
610 657 # --- Create directory if it doesn't exist
611   - print(f"{k} : {seq_file=}")
  658 + self.dprint(f"{k} : {seq_file=}")
612 659 os.makedirs(os.path.dirname(seq_file), exist_ok=True)
613 660 # --- Compute the ephemeris of the sequence and manage errors
614 661 #print(f"{k} : TRY")
615 662 errors = []
616 663 try:
617   - # TODO remplacer les none par les fichiers pickle de ephem_sun & ephem_moon
618 664 ephem = eph.target2night(seq["sequence"]["config_attributes"]["target"], info['night'], ephem_sun, ephem_moon, preference=seq['sequence']['start_expo_pref'], duskelev=duskelev, horizon=hor, duration=duration)
619 665 except ValueError:
620 666 errors.append("Target value is not valid")
... ... @@ -625,15 +671,16 @@ class A_Scheduler(Agent):
625 671 if len(errors) == 0:
626 672 pickle.dump(ephem, open(eph_file,"wb"))
627 673 pickle.dump(seq, open(seq_file,"wb"))
628   - #print(f"{errors=}")
629   - #print("C"*20)
630   - print(f"_create_seq_1 finished in {time.time() - t0:.2f} seconds")
  674 + #dprint(f"{errors=}")
  675 + #dprint("C"*20)
  676 + log.info(f"_create_seq_1 finished in {time.time() - t0:.2f} seconds")
631 677  
632 678 def load_sequence(self):
633 679 sequence = ""
634 680 return sequence
635 681  
636 682 def get_infos(self):
  683 + self._fn.fcontext = "pyros_seq"
637 684 rootdir = self._fn.rootdir
638 685 operiod = Period.objects.exploitation_period()
639 686 if operiod == None:
... ... @@ -657,7 +704,7 @@ class A_Scheduler(Agent):
657 704  
658 705 def dprint(self, *args, **kwargs):
659 706 if self.DPRINT:
660   - print(*args, **kwargs)
  707 + log.info(*args, **kwargs)
661 708  
662 709 if __name__ == "__main__":
663 710  
... ...