Compare View

switch
from
...
to
 
Commits (3)
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 = {}
... ...