From a13cc1ec858539d3097d0cefbd9427aed0371525 Mon Sep 17 00:00:00 2001 From: Peter Yoachim Date: Tue, 5 Dec 2023 09:42:13 -0800 Subject: [PATCH] IntRounded throw an error if it gets a NaN --- .../basis_functions/basis_functions.py | 19 +++++++++++-------- .../scheduler/schedulers/core_scheduler.py | 13 +++++++------ rubin_scheduler/scheduler/utils/utils.py | 5 +++++ 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/rubin_scheduler/scheduler/basis_functions/basis_functions.py b/rubin_scheduler/scheduler/basis_functions/basis_functions.py index a054785b..015c06a8 100644 --- a/rubin_scheduler/scheduler/basis_functions/basis_functions.py +++ b/rubin_scheduler/scheduler/basis_functions/basis_functions.py @@ -874,12 +874,15 @@ def __init__(self, nside=None, max_airmass=2.5, penalty=np.nan): def _calc_value(self, conditions, indx=None): result = self.result.copy() + valid_airmass = np.isfinite(conditions.airmass) good_pix = np.where( - (conditions.airmass >= 1.0) - & (IntRounded(conditions.airmass) < self.max_airmass) - & (IntRounded(np.abs(conditions.az_to_sun)) < IntRounded(np.pi / 2.0)) + (conditions.airmass[valid_airmass] >= 1.0) + & (IntRounded(conditions.airmass[valid_airmass]) < self.max_airmass) + & (IntRounded(np.abs(conditions.az_to_sun[valid_airmass])) < IntRounded(np.pi / 2.0)) + ) + result[valid_airmass][good_pix] = ( + conditions.airmass[valid_airmass][good_pix] / self.max_airmass.initial ) - result[good_pix] = conditions.airmass[good_pix] / self.max_airmass.initial return result @@ -921,15 +924,15 @@ def _calc_value(self, conditions, indx=None): if indx is None: indx = np.arange(result.size) diff = conditions.mjd - self.survey_features["Last_observed"].feature[indx] + mask = np.isnan(diff) + # remove NaNs from diff, but save mask so we exclude those values later. + diff[mask] = 0.0 ir_diff = IntRounded(diff) - # Note! There is something afoot where different platforms evaluate - # nan's differently. Thus adding in the (~np.isnan(diff) term - # to make sure things are evaluated correctly. good = np.where( (ir_diff >= self.gap_min) & (ir_diff <= self.gap_max) & (self.survey_features["Pair_in_night"].feature[indx] < self.npairs) - & (~np.isnan(diff)) + & (~mask) )[0] result[indx[good]] += 1.0 return result diff --git a/rubin_scheduler/scheduler/schedulers/core_scheduler.py b/rubin_scheduler/scheduler/schedulers/core_scheduler.py index 38bdf6c5..109f39de 100644 --- a/rubin_scheduler/scheduler/schedulers/core_scheduler.py +++ b/rubin_scheduler/scheduler/schedulers/core_scheduler.py @@ -240,12 +240,13 @@ def request_observation(self, mjd=None): ) obs_pa = _approx_altaz2pa(alt, az, self.conditions.site.latitude_rad) rot_tel_pos_expected = (obs_pa - observation["rotSkyPos"]) % (2.0 * np.pi) - if (IntRounded(rot_tel_pos_expected) > IntRounded(self.rotator_limits[0])) & ( - IntRounded(rot_tel_pos_expected) < IntRounded(self.rotator_limits[1]) - ): - diff = np.abs(self.rotator_limits - rot_tel_pos_expected) - limit_indx = np.min(np.where(diff == np.min(diff))[0]) - observation["rotSkyPos"] = (obs_pa - self.rotator_limits[limit_indx]) % (2.0 * np.pi) + if np.isfinite(observation["rotSkyPos"]): + if (IntRounded(rot_tel_pos_expected) > IntRounded(self.rotator_limits[0])) & ( + IntRounded(rot_tel_pos_expected) < IntRounded(self.rotator_limits[1]) + ): + diff = np.abs(self.rotator_limits - rot_tel_pos_expected) + limit_indx = np.min(np.where(diff == np.min(diff))[0]) + observation["rotSkyPos"] = (obs_pa - self.rotator_limits[limit_indx]) % (2.0 * np.pi) return observation def _fill_queue(self): diff --git a/rubin_scheduler/scheduler/utils/utils.py b/rubin_scheduler/scheduler/utils/utils.py index 38c99acf..407895bb 100644 --- a/rubin_scheduler/scheduler/utils/utils.py +++ b/rubin_scheduler/scheduler/utils/utils.py @@ -72,6 +72,9 @@ class IntRounded: Class to help force comparisons be made on scaled up integers, preventing machine precision issues cross-platforms + Note that casting a NaN to an int can have different behaviours + cross-platforms, so will throw an error if attempted. + Parameters ---------- inval : number-like thing @@ -81,6 +84,8 @@ class IntRounded: """ def __init__(self, inval, scale=1e5): + if np.any(~np.isfinite(inval)): + raise ValueError("IntRounded can only take finite values.") self.initial = inval self.value = np.round(inval * scale).astype(int) self.scale = scale