Commit 198132303d731ebe7a310c5a0780ce287b60c0de
1 parent
be9ae145
Exists in
dev
New DATA structure in two Agents.
Showing
3 changed files
with
102 additions
and
36 deletions
Show diff stats
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 | ... | ... |