Source code for rubin_scheduler.scheduler.detailers.short_survey
__all__ = ("ShortExptDetailer",)
import numpy as np
import rubin_scheduler.scheduler.features as features
from rubin_scheduler.scheduler.detailers import BaseDetailer
from rubin_scheduler.scheduler.utils import HpInLsstFov
from rubin_scheduler.utils import DEFAULT_NSIDE, SURVEY_START_MJD
[docs]
class ShortExptDetailer(BaseDetailer):
"""Check if the area has been observed with a short exposure time
this year. If not, add some short exposures.
Parameters
----------
exp_time : `float` (1.)
The short exposure time to use.
nobs : `float` (2)
The number of observations to try and take per year
night_max : `float` (None)
Do not apply any changes to the observation list if the current
night is greater than night_max.
n_repeat : `int` (1)
How many short observations to do in a row.
time_scale : `bool` (False)
Should the short observations be scaled throughout the year (True),
or taken as fast as possible (False).
"""
def __init__(
self,
exp_time=1.0,
filtername="r",
nside=DEFAULT_NSIDE,
footprint=None,
nobs=2,
mjd0=SURVEY_START_MJD,
survey_name="short",
read_approx=2.0,
night_max=None,
n_repeat=1,
time_scale=False,
):
self.read_approx = read_approx
self.exp_time = exp_time
self.filtername = filtername
self.nside = nside
self.footprint = footprint
self.nobs = nobs
self.survey_name = survey_name
self.mjd0 = mjd0
self.night_max = night_max
self.n_repeat = n_repeat
self.time_scale = time_scale
self.survey_features = {}
# XXX--need a feature that tracks short exposures in the filter
self.survey_features["nobs"] = features.N_observations(
filtername=filtername, nside=nside, survey_name=self.survey_name
)
# Need to be able to look up hpids for each observation
self.obs2hpid = HpInLsstFov(nside=nside)
def __call__(self, observation_list, conditions):
# XXX--this logic would probably make more sense as a feasability
# basis function. Might consider expanding the detailer base class
# to include basis functions.
if self.night_max is not None:
if conditions.night > self.night_max:
return observation_list
out_observations = []
# Compute how many observations we should have taken by now
if self.time_scale:
n_goal = self.nobs * np.ceil(conditions.night / self.night_max)
else:
n_goal = self.nobs
time_to_add = 0.0
for observation in observation_list:
out_observations.append(observation)
if observation["filter"] == self.filtername:
hpids = self.obs2hpid(observation["RA"], observation["dec"])
# Crop off anything outside the target footprint
hpids = hpids[np.where(self.footprint[hpids] > 0)]
# Crop off things where we already have enough observation
hpids = hpids[np.where(self.survey_features["nobs"].feature[hpids] < n_goal)]
if np.size(hpids) > 0:
for i in range(0, self.n_repeat):
new_obs = observation.copy()
new_obs["exptime"] = self.exp_time
new_obs["nexp"] = 1
new_obs["scheduler_note"] = self.survey_name
out_observations.append(new_obs)
time_to_add += new_obs["exptime"] + self.read_approx
# pump up the flush time
for observation in observation_list:
observation["flush_by_mjd"] += time_to_add / 3600.0 / 24.0
return out_observations