Coverage for python/lsst/sims/featureScheduler/surveys/plan_night_survey.py : 19%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1from lsst.sims.featureScheduler.surveys import Blob_survey
2from lsst.sims.featureScheduler import features
3import lsst.sims.featureScheduler.basis_functions as bfs
4import numpy as np
5from lsst.sims.featureScheduler.utils import (empty_observation, set_default_nside)
6import healpy as hp
7import matplotlib.pylab as plt
10__all__ = ['Plan_ahead_survey']
13class Plan_ahead_survey(Blob_survey):
14 """Have a survey object that can plan ahead if it will want to observer a blob later in the night
16 Parameters
17 ----------
18 delta_mjd_tol : float
19 The tolerance to alow on when to execute scheduled observations (days)
20 minimum_sky_area : float
21 The minimum sky area to demand before making a scheduled observation (square degrees)
22 track_filters : str
23 The filter name we want to prevent long gaps on
24 in_season : float
25 The distance in RA from the meridian at midnight to consider (hours). This is the half-width
26 cadence : float
27 Ignore gaps below this length (days)
28 """
30 def __init__(self, basis_functions, basis_weights, delta_mjd_tol=0.3/24., minimum_sky_area=200.,
31 track_filters='g', in_season=2.5, cadence=9, **kwargs):
32 super(Plan_ahead_survey, self).__init__(basis_functions, basis_weights, **kwargs)
33 # note that self.night is already being used for tracking tesselation.
34 # So here's an attribute for seeing if the night has changed for cadence tracking
35 self.night_cad = -100
36 self.scheduled_obs = None
37 self.delta_mjd_tol = delta_mjd_tol
38 self.minimum_sky_area = minimum_sky_area # sq degrees
39 self.extra_features = {}
40 self.extra_features['last_observed'] = features.Last_observed(filtername=track_filters)
41 self.extra_basis_functions = {}
42 self.extra_basis_functions['moon_mask'] = bfs.Moon_avoidance_basis_function()
43 self.track_filters = track_filters
44 self.in_season = in_season/12.*np.pi # to radians
46 self.pix_area = hp.nside2pixarea(self.nside, degrees=True)
47 self.cadence = cadence
49 #def add_observation(self, observation, **kwargs):
50 # # If a relevant observation got made, recompute when we actually want to observe in the night
51 # if observation['filter'] in self.track_filters:
52 # if self.scheduled_obs is not None:
53 # # this will force a run of self.check_night on the next calc_reward_function
54 # self.night = observation['night'] - 1
55 # super(Plan_ahead_survey, self).add_observation(observation, **kwargs)
57 def check_night(self, conditions):
58 """
59 """
60 delta_mjd = conditions.mjd - self.extra_features['last_observed'].feature
61 moon_mask = self.extra_basis_functions['moon_mask'](conditions)
63 pix_to_obs = np.where((delta_mjd > self.cadence) &
64 (np.abs(conditions.az_to_antisun) < self.in_season) &
65 (moon_mask >= 0))[0]
67 area = np.size(pix_to_obs)*self.pix_area
69 # If there are going to be some observations at a given time
70 if area > self.minimum_sky_area:
71 # Maybe just calculate the mean (with angles)
72 # Via https://en.wikipedia.org/wiki/Mean_of_circular_quantities
73 mean_RA = np.arctan2(np.mean(np.sin(conditions.ra[pix_to_obs])), np.mean(np.cos(conditions.ra[pix_to_obs])))
74 if mean_RA < 0:
75 mean_RA += 2.*np.pi
77 hour_angle = conditions.lmst - mean_RA*12./np.pi
78 # This should be running -12 hours to +12 hours
80 hour_angle[np.where(hour_angle < -12)] += 24
81 hour_angle[np.where(hour_angle > 12)] -= 24
83 if hour_angle < 0:
84 self.scheduled_obs = conditions.mjd - hour_angle/24.
85 else:
86 self.scheduled_obs = conditions.mjd
87 else:
88 self.scheduled_obs = None
90 def calc_reward_function(self, conditions):
91 # Only compute if we will want to observe sometime in the night
92 self.reward = -np.inf
93 if self._check_feasibility(conditions):
94 if self.night_cad != conditions.night:
95 self.check_night(conditions)
96 self.night_cad = conditions.night + 0
98 if self.scheduled_obs is not None:
99 # If there are scheduled observations, and we are in the correct time window
100 delta_mjd = conditions.mjd - self.scheduled_obs
101 if (np.abs(delta_mjd) < self.delta_mjd_tol) & (self.scheduled_obs is not None):
102 # So, we think there's a region that has had a long gap and can be observed
103 # call the standard reward function
104 self.reward = super(Plan_ahead_survey, self).calc_reward_function(conditions)
106 return self.reward
108 def generate_observations(self, conditions):
109 observations = super(Plan_ahead_survey, self).generate_observations(conditions)
110 # We are providing observations, so clear the scheduled obs and reset the night so
111 # self.check_night will get called again in case there's another blob that should be done
112 # after this one completes
113 self.scheduled_obs = None
114 self.night_cad = conditions.night - 1
115 return observations