Compare View
Commits (3)
Showing
2 changed files
Show diff stats
src/core/pyros_django/majordome/agent/Agent.py
... | ... | @@ -45,6 +45,7 @@ from datetime import datetime |
45 | 45 | from typing import Final, Sequence, Iterable, Mapping, MutableMapping, Dict, List, Tuple, Union, Any, Optional, Literal |
46 | 46 | import ast |
47 | 47 | from inspect import signature |
48 | +import numpy as np | |
48 | 49 | |
49 | 50 | import os |
50 | 51 | from pathlib import Path |
... | ... | @@ -3482,13 +3483,13 @@ class Agent: |
3482 | 3483 | if loginfo: |
3483 | 3484 | log.info(self._oc['config'].fn.fcontexts_human()) |
3484 | 3485 | |
3485 | - def ephem_target2night(self, target:str) -> dict: | |
3486 | + def ephem_target2night(self, target:str, date: str="now") -> dict: | |
3486 | 3487 | eph = Ephemeris() |
3487 | 3488 | eph.set_home(self._oc['config'].getHome()) |
3488 | 3489 | fcontext0 = self._oc['config'].fn.fcontext |
3489 | 3490 | # --- Build the path and file name of the sun ephemeris |
3490 | 3491 | self._oc['config'].fn.fcontext = "pyros_eph" |
3491 | - night = self._oc['config'].fn.date2night("now") | |
3492 | + night = self._oc['config'].fn.date2night(date) | |
3492 | 3493 | operiod = Period.objects.exploitation_period() |
3493 | 3494 | if operiod == None: |
3494 | 3495 | log.info("No period valid in the database") |
... | ... | @@ -3506,8 +3507,8 @@ class Agent: |
3506 | 3507 | "unit": self._oc['config'].unit_name, |
3507 | 3508 | "target": target |
3508 | 3509 | } |
3509 | - fname = self._fn.naming_set(fn_param) | |
3510 | - eph_file = self._fn.joinabs(fname) | |
3510 | + fname = self._oc['config'].fn.naming_set(fn_param) | |
3511 | + eph_file = self._oc['config'].fn.joinabs(fname) | |
3511 | 3512 | # --- Compute the sun ephemeris if needed. Save it as pickle. |
3512 | 3513 | if not os.path.exists(eph_file): |
3513 | 3514 | ephem_target = eph.target2night(target, night, None, None) |
... | ... | @@ -3517,9 +3518,80 @@ class Agent: |
3517 | 3518 | ephem_target = pickle.load(open(eph_file,"rb")) |
3518 | 3519 | self._oc['config'].fn.fcontext = fcontext0 |
3519 | 3520 | return ephem_target |
3520 | - | |
3521 | 3521 | |
3522 | - | |
3522 | + def update_sun_moon_ephems(self): | |
3523 | + """Update the files in the ephems folder. | |
3524 | + | |
3525 | + The file 'duration.pickle' contains the start, end for each night and other informations to make quota computations. | |
3526 | + | |
3527 | + Check if the file 'duration.pickle' exists in the ephem/period directory. | |
3528 | + If yes, returns the contents of the 'duration.pickle' file. | |
3529 | + If not, check each ephemeris file existance for Sun and Moon and compute them if needed. | |
3530 | + | |
3531 | + Returns: | |
3532 | + Dictionary with night string as key. Values are a list of integers: | |
3533 | + | |
3534 | + * total1: Cumulative sum of seconds of previous night durations at the start of the night. | |
3535 | + * total2: Cumulative sum of seconds of previous night durations at the end of the night. | |
3536 | + * total_night: Number of seconds available during this night. | |
3537 | + * sec1: Index of seconds for the start of the night. | |
3538 | + * sec2: Index of seconds for the end of the night. | |
3539 | + | |
3540 | + """ | |
3541 | + | |
3542 | + # --- Get the period object | |
3543 | + operiod = Period.objects.exploitation_period() | |
3544 | + | |
3545 | + # --- Get the period ID | |
3546 | + period_id = operiod.get_id_as_str() | |
3547 | + | |
3548 | + # --- Select the context of ephemeris | |
3549 | + fcontext0 = self._oc['config'].fn.fcontext | |
3550 | + self._oc['config'].fn.fcontext = "pyros_eph" | |
3551 | + | |
3552 | + # --- Check if durations.pickle file exists | |
3553 | + rootdir = self._oc['config'].fn.rootdir | |
3554 | + filename = os.path.join(rootdir, period_id, "durations.pickle") | |
3555 | + self.dprint(f"Read {filename=}") | |
3556 | + if os.path.exists(filename): | |
3557 | + self._oc['config'].fn.fcontext = fcontext0 | |
3558 | + return pickle.load(open(filename, "wb")) | |
3559 | + | |
3560 | + # --- Get the period limit dates jd1, jd2 | |
3561 | + self.dprint(f"{dir(operiod)=}") | |
3562 | + d = operiod.start_date.isoformat() | |
3563 | + night_start = d[0:4]+d[5:7]+d[8:10] | |
3564 | + jd1, _ = self.config.fn.night2date(night_start) | |
3565 | + d = operiod.end_date.isoformat() | |
3566 | + night_end = d[0:4]+d[5:7]+d[8:10] | |
3567 | + jd2, _ = self.config.fn.night2date(night_end) | |
3568 | + self.dprint(f"{night_start=} {night_end=}") | |
3569 | + self.dprint(f"{jd1=} {jd2=}") | |
3570 | + | |
3571 | + # --- Loop over dates of the period to create ephems | |
3572 | + targets = ['sun', 'moon'] | |
3573 | + jd = jd1 + 0.1 | |
3574 | + total1 = 0 | |
3575 | + night_info = {} | |
3576 | + while jd < jd2: | |
3577 | + night = self._oc['config'].fn.date2night(jd) | |
3578 | + for target in targets: | |
3579 | + self.dprint(f"{night=} {target=}") | |
3580 | + ephem = self.ephem_target2night(target, jd) | |
3581 | + if target == "sun": | |
3582 | + ks = np.where(ephem['alt'] < self._duskelev) | |
3583 | + total_night = len(ks[0]) | |
3584 | + total2 = total1 + total_night | |
3585 | + sec1 = ks[0][0] | |
3586 | + sec2 = ks[0][-1] | |
3587 | + night_info[night] = [int(total1), int(total2), int(total_night), sec1, sec2] | |
3588 | + total1 = total2 | |
3589 | + jd += 1 | |
3590 | + night_info['total'] = [0, int(total2), int(total2), -1, -1] | |
3591 | + self.dprint(f"Write {filename=}") | |
3592 | + pickle.dump(night_info, open(filename, "wb")) | |
3593 | + return night_info | |
3594 | + | |
3523 | 3595 | """ |
3524 | 3596 | ================================================================= |
3525 | 3597 | MAIN |
... | ... | @@ -3541,7 +3613,6 @@ def parse_args(args): |
3541 | 3613 | parser = argparse.ArgumentParser(description='Start an agent.') |
3542 | 3614 | parser.add_argument("--computer",dest="computer",help='Launch agent with simulated computer hostname',action="store") |
3543 | 3615 | parser.add_argument("-t", action="store_true") |
3544 | - parser.add_argument("-d", action="store_true" ) | |
3545 | 3616 | args = vars(parser.parse_args(args)) |
3546 | 3617 | return args |
3547 | 3618 | ... | ... |
src/core/pyros_django/scheduling/A_Scheduler.py
... | ... | @@ -127,6 +127,9 @@ class A_Scheduler(Agent): |
127 | 127 | self.check_contexts(True) |
128 | 128 | log.info(f"{self._fn.longitude=}") |
129 | 129 | |
130 | + # TBD duskelev a parametrer from obsconfig (yml) | |
131 | + self._duskelev = -7 | |
132 | + | |
130 | 133 | # === Status of routine processing |
131 | 134 | self._routine_running = self.RUNNING_NOTHING |
132 | 135 | log.debug("end init()") |
... | ... | @@ -229,6 +232,14 @@ class A_Scheduler(Agent): |
229 | 232 | subdir = info['subdir'] |
230 | 233 | # --- Get the night |
231 | 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 | 243 | # --- Build the wildcard to list the sequences |
233 | 244 | wildcard = os.path.join(rootdir, subdir, "*.p") |
234 | 245 | self.dprint(f"{wildcard=}") |
... | ... | @@ -529,18 +540,16 @@ class A_Scheduler(Agent): |
529 | 540 | rootdir = info['rootdir'] |
530 | 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 | 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 | 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 | 553 | # --- Horizon (TBD get from config) |
545 | 554 | self.dprint("Debut _create_seq_1 Horizon") |
546 | 555 | hor = guitastro.Horizon(eph.home) |
... | ... | @@ -613,7 +622,7 @@ class A_Scheduler(Agent): |
613 | 622 | #print(f"{k} : TRY") |
614 | 623 | errors = [] |
615 | 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 | 626 | except ValueError: |
618 | 627 | errors.append("Target value is not valid") |
619 | 628 | except guitastro.ephemeris.EphemerisException as ephemException: |
... | ... | @@ -630,7 +639,7 @@ class A_Scheduler(Agent): |
630 | 639 | def load_sequence(self): |
631 | 640 | sequence = "" |
632 | 641 | return sequence |
633 | - | |
642 | + | |
634 | 643 | def get_infos(self): |
635 | 644 | self._fn.fcontext = "pyros_seq" |
636 | 645 | rootdir = self._fn.rootdir |
... | ... | @@ -639,11 +648,9 @@ class A_Scheduler(Agent): |
639 | 648 | log.info("No period valid in the database") |
640 | 649 | self._routine_running = self.RUNNING_NOTHING |
641 | 650 | 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 | |
651 | + # retourne un str -> id de la période sous le format Pxxx | |
652 | + period_id = operiod.get_id_as_str() | |
653 | + | |
647 | 654 | night_id = self._fn.date2night("now") |
648 | 655 | subdir = os.path.join(period_id, night_id) |
649 | 656 | dico = {} | ... | ... |