Source code for rubin_scheduler.site_models.scheduled_downtime_data
__all__ = ("ScheduledDowntimeData",)
import os
import sqlite3
import numpy as np
from astropy.time import Time, TimeDelta
from rubin_scheduler.data import get_data_dir
[docs]
class ScheduledDowntimeData:
"""Read the scheduled downtime data.
This class deals with the scheduled downtime information that
was previously produced for OpSim version 3.
Parameters
----------
start_time : `astropy.time.Time`
The time of the start of the simulation.
The cloud database will be assumed to start on Jan 01 of the
same year.
cloud_db : `str`, optional
The full path name for the cloud database. Default None,
which will use the database stored in the module
($SIMS_CLOUDMODEL_DIR/data/cloud.db).
start_of_night_offset : `float`, optional
The fraction of a day to offset from MJD.0 to reach the defined
start of a night ('noon' works). Default 0.16 (UTC midnight
in Chile) - 0.5 (minus half a day) = -0.34
"""
def __init__(self, start_time, scheduled_downtime_db=None, start_of_night_offset=-0.34):
self.scheduled_downtime_db = scheduled_downtime_db
if self.scheduled_downtime_db is None:
self.scheduled_downtime_db = os.path.join(get_data_dir(), "site_models", "scheduled_downtime.db")
# downtime database starts in Jan 01 of the year of the
# start of the simulation.
year_start = start_time.datetime.year
self.night0 = Time("%d-01-01" % year_start, format="isot", scale="tai") + TimeDelta(
start_of_night_offset, format="jd"
)
# Scheduled downtime data is a np.ndarray of start / end /
# activity for each scheduled downtime.
self.downtime = None
self.read_data()
[docs]
def __call__(self):
"""Return the current (if any) and any future scheduled downtimes.
Parameters
----------
time : `astropy.time.Time`
Time in the simulation for which to find the current downtime.
Returns
-------
downtime : `np.ndarray`
The array of all unscheduled downtimes, with keys for
'start', 'end', 'activity', corresponding to
astropy.time.Time, astropy.time.Time, and str.
"""
return self.downtime
def _downtime_status(self, time):
"""Look behind the scenes at the downtime status/next values"""
next_start = self.downtime["start"].searchsorted(time, side="right")
next_end = self.downtime["end"].searchsorted(time, side="right")
if next_start > next_end:
current = self.downtime[next_end]
else:
current = None
future = self.downtime[next_start:]
return current, future
[docs]
def read_data(self):
"""Read the scheduled downtime information from disk and
translate to astropy.time.Times.
This function gets the appropriate database file and creates
the set of scheduled downtimes from it. The default behavior
is to use the module stored database. However, an alternate
database file can be provided. The alternate database file needs
to have a table called *Downtime* with the following columns:
night : `int`
The night (from start of simulation) the downtime occurs.
duration : `int`
The duration (units=days) of the downtime.
activity : `str`
A description of the activity involved.
"""
# Read from database.
starts = []
ends = []
acts = []
with sqlite3.connect(self.scheduled_downtime_db) as conn:
cur = conn.cursor()
cur.execute("select * from Downtime;")
for row in cur:
start_night = int(row[0])
start_night = self.night0 + TimeDelta(start_night, format="jd")
n_down = int(row[1])
end_night = start_night + TimeDelta(n_down, format="jd")
activity = row[2]
starts.append(start_night)
ends.append(end_night)
acts.append(activity)
cur.close()
self.downtime = np.array(
list(zip(starts, ends, acts)),
dtype=[("start", "O"), ("end", "O"), ("activity", "O")],
)
[docs]
def total_downtime(self):
"""Return total downtime (in days).
Returns
-------
total : `int`
Total number of downtime days.
"""
total = 0
for td in self.downtime["end"] - self.downtime["start"]:
total += td.jd
return total