diff --git a/docs/obs/obs_scheduling.rst b/docs/obs/obs_scheduling.rst index 71b58c6..abce052 100644 --- a/docs/obs/obs_scheduling.rst +++ b/docs/obs/obs_scheduling.rst @@ -106,6 +106,20 @@ The schedule visualization displays such reserved blocks as hatched grey time wi Empty planning with a reserved block inserted. +The reverse operation can also be perfomed thanks to the :meth:`~nenupy.schedule.schedule.Schedule.set_free_slots` method which sets the whole schedule as unavailable except for the time intervals given as inputs: + +.. code-block:: python + + >>> schedule = Schedule( + >>> time_min=Time('2021-01-11 00:00:00'), + >>> time_max=Time('2021-01-15 00:00:00'), + >>> dt=TimeDelta(3600, format='sec') + >>> ) + >>> schedule.set_free_slots( + >>> start_times=Time(['2021-01-12 10:00:00', '2021-01-14 08:32:00']), + >>> stop_times=Time(['2021-01-13 03:30:00', '2021-01-15 00:00:00']) + >>> ) + Virtual Control Room bookings ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -132,6 +146,9 @@ This file can then be used to instantiates a :class:`~nenupy.schedule.obsblocks. Five-days NenuFAR planning for which all the active allocated time as been set as 'unavailable for further observation planning'. +The same file can also be used to globally set the schedule slots to unavailable except those belonging to a given Science Key Project. +The method :meth:`~nenupy.schedule.schedule.Schedule.match_booking` allows one to define a schedule that matches the time slots allocated to a NenuFAR KP. + .. _observation_request_sec: @@ -208,8 +225,10 @@ Available constraints are: ~nenupy.schedule.constraints.ElevationCnst ~nenupy.schedule.constraints.MeridianTransitCnst ~nenupy.schedule.constraints.AzimuthCnst + ~nenupy.schedule.constraints.LocalSiderealTimeCnst ~nenupy.schedule.constraints.LocalTimeCnst ~nenupy.schedule.constraints.TimeRangeCnst + ~nenupy.schedule.constraints.NightTimeCnst Adding constraints diff --git a/nenupy/schedule/constraints.py b/nenupy/schedule/constraints.py index f7bcf3d..c1f63f1 100644 --- a/nenupy/schedule/constraints.py +++ b/nenupy/schedule/constraints.py @@ -167,14 +167,13 @@ from abc import ABC import numpy as np -from functools import lru_cache from astropy.time import Time, TimeDelta from astropy.coordinates import Angle, Longitude import pytz import matplotlib.pyplot as plt from copy import copy -from nenupy.schedule.targets import _Target, SSTarget +from nenupy.schedule.targets import _Target import logging log = logging.getLogger(__name__) diff --git a/nenupy/schedule/obsblocks.py b/nenupy/schedule/obsblocks.py index 43bdc79..701a716 100644 --- a/nenupy/schedule/obsblocks.py +++ b/nenupy/schedule/obsblocks.py @@ -400,6 +400,9 @@ def target(self, src): raise TypeError( f'`target` should be of type {_Target}.' ) + elif src._lst is not None: + # Clear the target from previous computations + src.reset() self._target = src diff --git a/nenupy/schedule/schedule.py b/nenupy/schedule/schedule.py index 27e5f89..790d25f 100644 --- a/nenupy/schedule/schedule.py +++ b/nenupy/schedule/schedule.py @@ -645,11 +645,14 @@ class Schedule(_TimeSlots): .. autosummary:: + ~Schedule.set_free_slots + ~Schedule.match_booking ~Schedule.insert ~Schedule.plot + ~Schedule.plot_range ~Schedule.book ~Schedule.export - + .. rubric:: Attributes and Methods Documentation """ @@ -1107,7 +1110,7 @@ def book(self, optimize=False, **kwargs): def fine_tune(self, max_it: int = 1000) -> None: - """ + """ """ log.info("(Fine tunning) Launching...") @@ -1266,23 +1269,54 @@ def export(self, score_min=0): def plot_range(self, start_time: Time, stop_time: Time, **kwargs) -> None: - """ """ + """ Plots the current schedule. + + .. rubric:: Data display keywords + + :param start_time: + Minimal time to display. + :type start_time: + :class:`~astropy.time.Time` + :param stop_time: + Maximal time to display. + :type stop_time: + :class:`~astropy.time.Time` + + .. rubric:: Plotting layout keywords + + :param grid: + If set to ``True``, the time slots are separated by vertical lines. + Default is ``True``. + :type grid: + `bool` + :param figname: + Name of the file (absolute or relative path) to save the figure. + Default is ``''`` (i.e., only show the figure). + :type figname: + `str` + :param figsize: + Set the figure size. + Default is ``(15, 3)``. + :type figsize: + `tuple` + + """ import matplotlib.pyplot as plt import matplotlib.dates as mdates # Initialize the figure - fig, ax = plt.subplots( - figsize=kwargs.get('figsize', (15, 3)) + _, ax = plt.subplots( + figsize=kwargs.get("figsize", (15, 3)) ) # Display granularity - if kwargs.get('grid', True): + if kwargs.get("grid", True): time_mask = (self._startsJD >= start_time.jd)*(self._stopsJD <= stop_time.jd) for slot_start in self.starts[time_mask]: ax.axvline( slot_start.datetime, - color='gray', - linestyle='-', + color="gray", + linestyle="-", linewidth=0.5 ) @@ -1309,22 +1343,22 @@ def plot_range(self, start_time: Time, stop_time: Time, **kwargs) -> None: # Formating ax.yaxis.set_visible(False) - h_fmt = mdates.DateFormatter('%y-%m-%d\n%H') + h_fmt = mdates.DateFormatter("%y-%m-%d\n%H") ax.xaxis.set_major_formatter(h_fmt) # Save or show the figure - figname = kwargs.get('figname', '') - if figname != '': + figname = kwargs.get("figname", "") + if figname != "": plt.savefig( figname, dpi=300, - bbox_inches='tight', + bbox_inches="tight", transparent=True ) log.info(f"Figure '{figname}' saved.") else: plt.show() - plt.close('all') + plt.close("all") def plot(self, days_per_line=1, **kwargs): diff --git a/nenupy/schedule/targets.py b/nenupy/schedule/targets.py index 4f68cef..62c4713 100644 --- a/nenupy/schedule/targets.py +++ b/nenupy/schedule/targets.py @@ -118,6 +118,15 @@ def azimuth(self): # --------------------------------------------------------- # # ------------------------ Methods ------------------------ # + def reset(self) -> None: + """ Clear the Target instance from previous computations. """ + self._lst = None + self._fk5 = None + self._hourAngle = None + self._elevation = None + self._azimuth = None + + def computePosition(self, time): """ """