diff --git a/schedview/app/prenight/prenight.py b/schedview/app/prenight/prenight.py index 9acec741..d416303e 100644 --- a/schedview/app/prenight/prenight.py +++ b/schedview/app/prenight/prenight.py @@ -286,6 +286,20 @@ def _update_visits(self): Time(self._almanac_events.loc["sunset", "UTC"]), Time(self._almanac_events.loc["sunrise", "UTC"]), ) + if len(visits) == 0: + self.logger.info("No visits on requested night, looking for a night with visits.") + # read all visits to so we can find a central one + visits = schedview.collect.opsim.read_opsim(self.opsim_output_fname) + if len(visits) > 0: + self.logger.info("Changing night to one with visits.") + self.night = schedview.compute.astro.compute_central_night(visits) + # Setting night will trigger a call to _update_visits + # by way of _almanac_events, so we should not continue + # this execution.. + return + else: + self.logger.info("No visits found in this opsim database.") + self._visits = visits self.logger.info("Finish updating visits DataFrame.") self.logger.info("Starting to update visits ColumnDataSource.") diff --git a/schedview/compute/astro.py b/schedview/compute/astro.py index c20dd1d1..b6d68dbe 100644 --- a/schedview/compute/astro.py +++ b/schedview/compute/astro.py @@ -99,3 +99,33 @@ def night_events(night_date=None, site=None, timezone="Chile/Continental"): time_df.index.name = "event" return time_df + + +def compute_central_night(visits, site=None, timezone="Chile/Continental"): + """Compute the central night of a set of visits. + + Parameters + ---------- + visits : `pandas.DataFrame` + A DataFrame of visits. + site : `astropy.coordinates.earth.EarthLocation` + The observatory location. Defaults to Rubin observatory. + timezone: `str` + The timezone name. Defaults to 'Chile/Continental' + + Returns + ------- + central_night : `datetime.date` + The central night of the visits. + """ + central_mjd = visits["observationStartMJD"].median() + candidate_night = Time(central_mjd, format="mjd", scale="utc").datetime.date() + + # The mjd rollover can occur during the night, so the above might be offset + # by a night. Make sure the night we have is the one with a central mjd + # closest to the median visit mjd. + candidate_middle_mjd = night_events(candidate_night, site, timezone).loc["night_middle", "MJD"] + mjd_shift = np.round(central_mjd - candidate_middle_mjd) + central_night = Time(central_mjd + mjd_shift, format="mjd", scale="utc").datetime.date() + + return central_night diff --git a/tests/test_compute_astro.py b/tests/test_compute_astro.py new file mode 100644 index 00000000..ae9209de --- /dev/null +++ b/tests/test_compute_astro.py @@ -0,0 +1,25 @@ +import unittest + +import numpy as np +import pandas as pd + +from schedview.compute.astro import compute_central_night, night_events + +TEST_MJDS = [60000.6, 60000.8, 60001.2] + + +class TestComputeAstro(unittest.TestCase): + def test_compute_central_night(self): + for mjd in TEST_MJDS: + visits = pd.DataFrame( + { + "observationStartMJD": [mjd - 0.1, mjd, mjd + 0.1], + "fieldRA": [0, 0, 0], + "fieldDec": [0, 0, 0], + "filter": ["r", "i", "z"], + } + ) + computed_night = compute_central_night(visits) + computed_night_events = night_events(computed_night) + computed_night_middle_mjd = computed_night_events.loc["night_middle", "MJD"] + assert np.abs(computed_night_middle_mjd - mjd) <= 0.5