Skip to content

Commit

Permalink
unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
yoachim committed Nov 26, 2024
1 parent a9dccd0 commit b81b378
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 12 deletions.
53 changes: 45 additions & 8 deletions rubin_scheduler/scheduler/detailers/detailer.py
Original file line number Diff line number Diff line change
Expand Up @@ -331,41 +331,78 @@ def __call__(self, observation_list, conditions):


class StartFieldSequenceDetailer(BaseDetailer):
"""Append a sequence of observations to the start of a list
"""Prepend a sequence of observations to the start of a list
Parameters
----------
sequence_obs_list : `list` of rubing_scheduler.scheduler.utils.ObservationArray
List of n=1 ObservationArray objects. The observations should
have "scheduler_note" and/or "science_program" set.
ang_distance_match : `float`
How close should an observation be on the sky to be considered
matching (degrees).
time_match_hours : `float`
How close in time to demand an observation be matching (hours).
science_program : `str`
The science_program to match against. Default None.
scheduler_note : `str`
The scheduler_note to match observations against.
Default "starting_sequence".
ra : `float`
RA to match against. Default 0 (degrees). Ignored
if ang_distance_match is None.
dec : `float`
Dec to match observations against. Default 0 (degrees).
Ignored if ang_distance_match is None.
"""

def __init__(
self,
sequence_obs_list,
ang_distance_match=3.5,
time_match_hours=5,
science_program="starting_sequence",
sequence_obs_list=None,
science_program=None,
scheduler_note="starting_sequence",
ra=0,
dec=0,
):
super().__init__()
self.survey_features["last_matching"] = features.LastObservedMatching(
ang_distance_match=3.5, science_program=science_program, ra=ra, dec=dec
ang_distance_match=3.5,
science_program=science_program,
scheduler_note=scheduler_note,
ra=ra,
dec=dec,
)
self.ang_distance_match = np.radians(ang_distance_match)
self.time_match = time_match_hours / 24.0
self.science_program = science_program
self.scheduler_note = scheduler_note

if sequence_obs_list is None:
raise NotImplementedError("No default sequence yet, set sequence_obs_list")
else:
self.sequence_obs_list = sequence_obs_list
self.sequence_obs_list = sequence_obs_list

for obs in self.sequence_obs_list:
obs["science_program"] = self.science_program
obs["scheduler_note"] = self.scheduler_note

# Check that things are sensibly set
obs_array = np.concatenate(sequence_obs_list)
u_scip = np.unique(obs_array["science_program"])
u_sn = np.unique(obs_array["scheduler_note"])

if (np.size(u_scip) > 1) | (np.size(u_sn) > 1):
msg = (
"The science_program and/or scheduler_note " "values in sequence_obs_list should be the same."
)
raise ValueError(msg)

if science_program is not None:
if self.science_program != u_scip:
ValueError("science_program kwarg not equal to science_programs from sequence_obs_list")
if scheduler_note is not None:
if self.scheduler_note != u_sn:
ValueError("scheduler_note kwarg not equal to scheduler_notes from sequence_obs_list")

def __call__(self, observation_list, conditions):
# Do we need to add the opening sequence?
Expand Down
25 changes: 21 additions & 4 deletions rubin_scheduler/scheduler/features/features.py
Original file line number Diff line number Diff line change
Expand Up @@ -588,14 +588,31 @@ def __init__(self, ang_distance_match=None, science_program=None, scheduler_note
self.feature.mjd = -100000
self.science_program = science_program
self.scheduler_note = scheduler_note
self.ang_distance_match = np.radians(ang_distance_match)
if ra is not None:
if (ra is not None) | (dec is not None) | (ang_distance_match is not None):
self.ra = np.radians(ra)
if dec is not None:
self.ang_distance_match = np.radians(ang_distance_match)
self.dec = np.radians(dec)
else:
self.ang_distance_match = None

def add_observations_array(self, observations_array, observations_hpid):
raise NotImplementedError("not done yet")

if self.science_program is not None:
good = np.where(observations_array["science_program"] == self.science_program)[0]
observations_array = observations_array[good]

if self.scheduler_note is not None:
good = np.where(observations_array["scheduler_note"] == self.scheduler_note)[0]
observations_array = observations_array[good]

if self.ang_distance_match is not None:
dist = _angular_separation(observations_array["RA"], observations_array["dec"], self.ra, self.dec)
good = np.where(dist <= self.ang_distance_match)
observations_array = observations_array[good]

if np.size(observations_array) > 0:
self.feature = ObservationArray(n=1)
self.feature[0] = observations_array[-1]

def add_observation(self, observation, indx=None):
if self.science_program is not None:
Expand Down
19 changes: 19 additions & 0 deletions tests/scheduler/test_detailers.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,25 @@ def test_basics(self):
result = live_det(obs_list, conditions)
assert len(result) > 0

def test_start_field(self):

observatory = ModelObservatory()
conditions = observatory.return_conditions()

scheduler_note = "prepended"

obs_to_prepend = [ObservationArray(n=1)] * 3
for i, obs in enumerate(obs_to_prepend):
obs["RA"] = np.radians(20)
obs["filter"] = "r"
obs["scheduler_note"] = scheduler_note

obs_reg = [ObservationArray(n=1)]
det = detailers.StartFieldSequenceDetailer(obs_to_prepend, scheduler_note=scheduler_note)
obs_out = det(obs_reg, conditions)

assert len(obs_out) == 4

def test_random_filter(self):
obs = ObservationArray(1)
obs["filter"] = "r"
Expand Down
50 changes: 50 additions & 0 deletions tests/scheduler/test_features.py
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,56 @@ def test_LastObservation(self):
count_feature.add_observations_array(observations_array, observations_hpid=observations_hpid_array)
self.assertTrue(count_feature.feature["mjd"] == observations_list[-1]["mjd"])

def test_last_obs_matching(self):
"""Test the LastObservedMatching"""

feature = features.LastObservedMatching(scheduler_note="test")

# Add an observation that should count
obs = ObservationArray(n=1)
obs["scheduler_note"] = "test"
obs["mjd"] = 10
feature.add_observation(obs)

assert feature.feature["mjd"] == 10

# Add observation that should not count
obs["scheduler_note"] = "test1"
obs["mjd"] = 20
feature.add_observation(obs)

assert feature.feature["mjd"] == 10

# test add array
feature = features.LastObservedMatching(scheduler_note="test")
obs = ObservationArray(n=2)
obs["scheduler_note"] = "test"
obs["mjd"] = 20

feature.add_observations_array(obs, [])
assert feature.feature == obs[-1]

# Test distance cut
feature = features.LastObservedMatching(scheduler_note="test", ra=0, dec=0, ang_distance_match=4.0)
obs = ObservationArray(n=1)
obs["scheduler_note"] = "test"
obs["RA"] = 0
obs["dec"] = 0
obs["mjd"] = 30
feature.add_observation(obs)

assert feature.feature["mjd"] == 30

# Add observation beyond distance cut
obs = ObservationArray(n=1)
obs["scheduler_note"] = "test"
obs["RA"] = 0
obs["dec"] = np.radians(-20)
obs["mjd"] = 40
feature.add_observation(obs)

assert feature.feature["mjd"] == 30

def test_NObservations(self):
# Make some observations to count
observations_list = make_observations_list(12)
Expand Down

0 comments on commit b81b378

Please sign in to comment.