Commit 9b6af71d7acd0209c07f1e842d17fcbfc4561ea6

Authored by Alain Klotz
1 parent 8e3c40f8
Exists in dev

Update version Scheduler

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 = {}