Commit 9b6af71d7acd0209c07f1e842d17fcbfc4561ea6
1 parent
8e3c40f8
Exists in
dev
Update version Scheduler
Showing
2 changed files
with
98 additions
and
18 deletions
Show diff stats
src/core/pyros_django/majordome/agent/Agent.py
@@ -3482,13 +3482,13 @@ class Agent: | @@ -3482,13 +3482,13 @@ class Agent: | ||
3482 | if loginfo: | 3482 | if loginfo: |
3483 | log.info(self._oc['config'].fn.fcontexts_human()) | 3483 | log.info(self._oc['config'].fn.fcontexts_human()) |
3484 | 3484 | ||
3485 | - def ephem_target2night(self, target:str) -> dict: | 3485 | + def ephem_target2night(self, target:str, date: str="now") -> dict: |
3486 | eph = Ephemeris() | 3486 | eph = Ephemeris() |
3487 | eph.set_home(self._oc['config'].getHome()) | 3487 | eph.set_home(self._oc['config'].getHome()) |
3488 | fcontext0 = self._oc['config'].fn.fcontext | 3488 | fcontext0 = self._oc['config'].fn.fcontext |
3489 | # --- Build the path and file name of the sun ephemeris | 3489 | # --- Build the path and file name of the sun ephemeris |
3490 | self._oc['config'].fn.fcontext = "pyros_eph" | 3490 | self._oc['config'].fn.fcontext = "pyros_eph" |
3491 | - night = self._oc['config'].fn.date2night("now") | 3491 | + night = self._oc['config'].fn.date2night(date) |
3492 | operiod = Period.objects.exploitation_period() | 3492 | operiod = Period.objects.exploitation_period() |
3493 | if operiod == None: | 3493 | if operiod == None: |
3494 | log.info("No period valid in the database") | 3494 | log.info("No period valid in the database") |
@@ -3506,8 +3506,8 @@ class Agent: | @@ -3506,8 +3506,8 @@ class Agent: | ||
3506 | "unit": self._oc['config'].unit_name, | 3506 | "unit": self._oc['config'].unit_name, |
3507 | "target": target | 3507 | "target": target |
3508 | } | 3508 | } |
3509 | - fname = self._fn.naming_set(fn_param) | ||
3510 | - eph_file = self._fn.joinabs(fname) | 3509 | + fname = self._oc['config'].fn.naming_set(fn_param) |
3510 | + eph_file = self._oc['config'].fn.joinabs(fname) | ||
3511 | # --- Compute the sun ephemeris if needed. Save it as pickle. | 3511 | # --- Compute the sun ephemeris if needed. Save it as pickle. |
3512 | if not os.path.exists(eph_file): | 3512 | if not os.path.exists(eph_file): |
3513 | ephem_target = eph.target2night(target, night, None, None) | 3513 | ephem_target = eph.target2night(target, night, None, None) |
src/core/pyros_django/scheduling/A_Scheduler.py
@@ -127,6 +127,9 @@ class A_Scheduler(Agent): | @@ -127,6 +127,9 @@ class A_Scheduler(Agent): | ||
127 | self.check_contexts(True) | 127 | self.check_contexts(True) |
128 | log.info(f"{self._fn.longitude=}") | 128 | log.info(f"{self._fn.longitude=}") |
129 | 129 | ||
130 | + # TBD duskelev a parametrer from obsconfig (yml) | ||
131 | + self._duskelev = -7 | ||
132 | + | ||
130 | # === Status of routine processing | 133 | # === Status of routine processing |
131 | self._routine_running = self.RUNNING_NOTHING | 134 | self._routine_running = self.RUNNING_NOTHING |
132 | log.debug("end init()") | 135 | log.debug("end init()") |
@@ -229,6 +232,14 @@ class A_Scheduler(Agent): | @@ -229,6 +232,14 @@ class A_Scheduler(Agent): | ||
229 | subdir = info['subdir'] | 232 | subdir = info['subdir'] |
230 | # --- Get the night | 233 | # --- Get the night |
231 | night = info['night'] | 234 | night = info['night'] |
235 | + # --- Get ephemeris informations of the night and initialize quotas | ||
236 | + night_info = self.update_sun_moon_ephems() | ||
237 | + quota_total_period = night_info['total'][1] | ||
238 | + quota_total_night_start = night_info[night][0] | ||
239 | + quota_total_night_end = night_info[night][1] | ||
240 | + self.dprint(f"{quota_total_period=}") | ||
241 | + self.dprint(f"{quota_total_night_start=}") | ||
242 | + self.dprint(f"{quota_total_night_end=}") | ||
232 | # --- Build the wildcard to list the sequences | 243 | # --- Build the wildcard to list the sequences |
233 | wildcard = os.path.join(rootdir, subdir, "*.p") | 244 | wildcard = os.path.join(rootdir, subdir, "*.p") |
234 | self.dprint(f"{wildcard=}") | 245 | self.dprint(f"{wildcard=}") |
@@ -529,18 +540,16 @@ class A_Scheduler(Agent): | @@ -529,18 +540,16 @@ class A_Scheduler(Agent): | ||
529 | rootdir = info['rootdir'] | 540 | rootdir = info['rootdir'] |
530 | subdir = info['subdir'] | 541 | subdir = info['subdir'] |
531 | 542 | ||
532 | - # --- Prepare ephemeris object | ||
533 | - # TBD duskelev a parametrer from obsconfig (yml) | ||
534 | - duskelev = -7 | ||
535 | - eph = guitastro.Ephemeris() | ||
536 | - eph.set_home(self.config.getHome()) | ||
537 | - | ||
538 | - # --- Build the path and file name of the sun ephemeris | 543 | + # --- Read or create the sun ephemeris |
539 | ephem_sun = self.ephem_target2night("sun") | 544 | ephem_sun = self.ephem_target2night("sun") |
540 | 545 | ||
541 | - # --- Build the path and file name of the moon ephemeris | 546 | + # --- Read or create the moon ephemeris |
542 | ephem_moon = self.ephem_target2night("moon") | 547 | ephem_moon = self.ephem_target2night("moon") |
543 | 548 | ||
549 | + # --- Prepare ephemeris object | ||
550 | + eph = guitastro.Ephemeris() | ||
551 | + eph.set_home(self.config.getHome()) | ||
552 | + | ||
544 | # --- Horizon (TBD get from config) | 553 | # --- Horizon (TBD get from config) |
545 | self.dprint("Debut _create_seq_1 Horizon") | 554 | self.dprint("Debut _create_seq_1 Horizon") |
546 | hor = guitastro.Horizon(eph.home) | 555 | hor = guitastro.Horizon(eph.home) |
@@ -613,7 +622,7 @@ class A_Scheduler(Agent): | @@ -613,7 +622,7 @@ class A_Scheduler(Agent): | ||
613 | #print(f"{k} : TRY") | 622 | #print(f"{k} : TRY") |
614 | errors = [] | 623 | errors = [] |
615 | try: | 624 | try: |
616 | - 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) | 625 | + ephem = eph.target2night(seq["sequence"]["config_attributes"]["target"], info['night'], ephem_sun, ephem_moon, preference=seq['sequence']['start_expo_pref'], duskelev=self._duskelev, horizon=hor, duration=duration) |
617 | except ValueError: | 626 | except ValueError: |
618 | errors.append("Target value is not valid") | 627 | errors.append("Target value is not valid") |
619 | except guitastro.ephemeris.EphemerisException as ephemException: | 628 | except guitastro.ephemeris.EphemerisException as ephemException: |
@@ -630,7 +639,80 @@ class A_Scheduler(Agent): | @@ -630,7 +639,80 @@ class A_Scheduler(Agent): | ||
630 | def load_sequence(self): | 639 | def load_sequence(self): |
631 | sequence = "" | 640 | sequence = "" |
632 | return sequence | 641 | return sequence |
642 | + | ||
643 | + def update_sun_moon_ephems(self): | ||
644 | + """Update the files in the ephems folder. | ||
633 | 645 | ||
646 | + The file 'duration.pickle' contains the start, end for each night and other informations to make quota computations. | ||
647 | + | ||
648 | + Check if the file 'duration.pickle' exists in the ephem/period directory. | ||
649 | + If yes, returns the contents of the 'duration.pickle' file. | ||
650 | + If not, check each ephemeris file existance for Sun and Moon and compute them if needed. | ||
651 | + | ||
652 | + Returns: | ||
653 | + Dictionary with night string as key. Values are a list of integers: | ||
654 | + | ||
655 | + * total1: Cumulative sum of seconds of previous night durations at the start of the night. | ||
656 | + * total2: Cumulative sum of seconds of previous night durations at the end of the night. | ||
657 | + * total_night: Number of seconds available during this night. | ||
658 | + * sec1: Index of seconds for the start of the night. | ||
659 | + * sec2: Index of seconds for the end of the night. | ||
660 | + | ||
661 | + """ | ||
662 | + | ||
663 | + # --- Get the period object | ||
664 | + operiod = Period.objects.exploitation_period() | ||
665 | + | ||
666 | + # --- Get the period ID | ||
667 | + period_id = operiod.get_period_id_as_str() | ||
668 | + | ||
669 | + # --- Select the context of ephemeris | ||
670 | + fcontext0 = self._oc['config'].fn.fcontext | ||
671 | + self._oc['config'].fn.fcontext = "pyros_eph" | ||
672 | + | ||
673 | + # --- Check if durations.pickle file exists | ||
674 | + rootdir = self._oc['config'].fn.rootdir | ||
675 | + filename = os.path.join(rootdir, period_id, "durations.pickle") | ||
676 | + self.dprint(f"Read {filename=}") | ||
677 | + if os.path.exists(filename): | ||
678 | + self._oc['config'].fn.fcontext = fcontext0 | ||
679 | + return pickle.load(open(filename, "wb")) | ||
680 | + | ||
681 | + # --- Get the period limit dates jd1, jd2 | ||
682 | + self.dprint(f"{dir(operiod)=}") | ||
683 | + d = operiod.start_date.isoformat() | ||
684 | + night_start = d[0:4]+d[5:7]+d[8:10] | ||
685 | + jd1, _ = self.config.fn.night2date(night_start) | ||
686 | + d = operiod.end_date.isoformat() | ||
687 | + night_end = d[0:4]+d[5:7]+d[8:10] | ||
688 | + jd2, _ = self.config.fn.night2date(night_end) | ||
689 | + self.dprint(f"{night_start=} {night_end=}") | ||
690 | + self.dprint(f"{jd1=} {jd2=}") | ||
691 | + | ||
692 | + # --- Loop over dates of the period to create ephems | ||
693 | + targets = ['sun', 'moon'] | ||
694 | + jd = jd1 + 0.1 | ||
695 | + total1 = 0 | ||
696 | + night_info = {} | ||
697 | + while jd < jd2: | ||
698 | + night = self._oc['config'].fn.date2night(jd) | ||
699 | + for target in targets: | ||
700 | + self.dprint(f"{night=} {target=}") | ||
701 | + ephem = self.ephem_target2night(target, jd) | ||
702 | + if target == "sun": | ||
703 | + ks = np.where(ephem['alt'] < self._duskelev) | ||
704 | + total_night = len(ks[0]) | ||
705 | + total2 = total1 + total_night | ||
706 | + sec1 = ks[0][0] | ||
707 | + sec2 = ks[0][-1] | ||
708 | + night_info[night] = [int(total1), int(total2), int(total_night), sec1, sec2] | ||
709 | + total1 = total2 | ||
710 | + jd += 1 | ||
711 | + night_info['total'] = [0, int(total2), int(total2), -1, -1] | ||
712 | + self.dprint(f"Write {filename=}") | ||
713 | + pickle.dump(night_info, open(filename, "wb")) | ||
714 | + return night_info | ||
715 | + | ||
634 | def get_infos(self): | 716 | def get_infos(self): |
635 | self._fn.fcontext = "pyros_seq" | 717 | self._fn.fcontext = "pyros_seq" |
636 | rootdir = self._fn.rootdir | 718 | rootdir = self._fn.rootdir |
@@ -639,11 +721,9 @@ class A_Scheduler(Agent): | @@ -639,11 +721,9 @@ class A_Scheduler(Agent): | ||
639 | log.info("No period valid in the database") | 721 | log.info("No period valid in the database") |
640 | self._routine_running = self.RUNNING_NOTHING | 722 | self._routine_running = self.RUNNING_NOTHING |
641 | return | 723 | return |
642 | - period_id = str(operiod.id) | ||
643 | - if len(str(operiod.id)) < 3: | ||
644 | - while len(period_id) < 3: | ||
645 | - period_id = "0" + period_id | ||
646 | - period_id = "P" + period_id | 724 | + # retourne un str -> id de la période sous le format Pxxx |
725 | + period_id = operiod.get_period_id_as_str() | ||
726 | + | ||
647 | night_id = self._fn.date2night("now") | 727 | night_id = self._fn.date2night("now") |
648 | subdir = os.path.join(period_id, night_id) | 728 | subdir = os.path.join(period_id, night_id) |
649 | dico = {} | 729 | dico = {} |