Hide keyboard shortcuts

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 

8 

9 

10__all__ = ['Plan_ahead_survey'] 

11 

12 

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 

15 

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 """ 

29 

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 

45 

46 self.pix_area = hp.nside2pixarea(self.nside, degrees=True) 

47 self.cadence = cadence 

48 

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) 

56 

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) 

62 

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] 

66 

67 area = np.size(pix_to_obs)*self.pix_area 

68 

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 

76 

77 hour_angle = conditions.lmst - mean_RA*12./np.pi 

78 # This should be running -12 hours to +12 hours 

79 

80 hour_angle[np.where(hour_angle < -12)] += 24 

81 hour_angle[np.where(hour_angle > 12)] -= 24 

82 

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 

89 

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 

97 

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) 

105 

106 return self.reward 

107 

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