Coverage for python/lsst/sims/downtimeModel/unscheduledDowntimeData.py : 17%

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 builtins import object
2from collections import OrderedDict
3import numpy as np
4from astropy.time import Time, TimeDelta
5import random
8__all__ = ['UnscheduledDowntimeData']
11class UnscheduledDowntimeData(object):
12 """Handle (and create) the unscheduled downtime information.
14 Parameters
15 ----------
16 start_time : astropy.time.Time
17 The time of the start of the simulation.
18 The cloud database will be assumed to start on Jan 01 of the same year.
19 seed : int, opt
20 The random seed for creating the random nights of unscheduled downtime. Default 1516231120.
21 start_of_night_offset : float, opt
22 The fraction of a day to offset from MJD.0 to reach the defined start of a night ('noon' works).
23 Default 0.16 (UTC midnight in Chile) - 0.5 (minus half a day) = -0.34
24 survey_length : int, opt
25 The number of nights in the total survey. Default 3650*2.
26 """
28 MINOR_EVENT = {'P': 0.0137, 'length': 1, 'level': "minor event"}
29 INTERMEDIATE_EVENT = {'P': 0.00548, 'length': 3, 'level': "intermediate event"}
30 MAJOR_EVENT = {'P': 0.00137, 'length': 7, 'level': "major event"}
31 CATASTROPHIC_EVENT = {'P': 0.000274, 'length': 14, 'level': "catastrophic event"}
33 def __init__(self, start_time, seed=1516231120, start_of_night_offset=-0.34, survey_length=3650*2):
34 self.seed = seed
35 self.survey_length = survey_length
36 year_start = start_time.datetime.year
37 self.night0 = Time('%d-01-01' % year_start, format='isot', scale='tai') + start_of_night_offset
39 # Scheduled downtime data is a np.ndarray of start / end / activity for each scheduled downtime.
40 self.downtime = None
41 self.make_data()
43 def __call__(self):
44 """Return the array of unscheduled downtimes.
46 Parameters
47 ----------
48 time : astropy.time.Time
49 Time in the simulation for which to find the current downtime.
51 Returns
52 -------
53 np.ndarray
54 The array of all unscheduled downtimes, with keys for 'start', 'end', 'activity',
55 corresponding to astropy.time.Time, astropy.time.Time, and str.
56 """
57 return self.downtime
59 def _downtimeStatus(self, time):
60 """Look behind the scenes at the downtime status/next values
61 """
62 next_start = self.downtime['start'].searchsorted(time, side='right')
63 next_end = self.downtime['end'].searchsorted(time, side='right')
64 if next_start > next_end:
65 current = self.downtime[next_end]
66 else:
67 current = None
68 future = self.downtime[next_start:]
69 return current, future
71 def make_data(self):
72 """Configure the set of unscheduled downtimes.
74 This function creates the unscheduled downtimes based on a set of probabilities
75 of the downtime type occurance.
77 The random downtime is calculated using the following probabilities:
79 minor event
80 remainder of night and next day = 5/365 days e.g. power supply failure
81 intermediate
82 3 nights = 2/365 days e.g. repair filter mechanism, rotator, hexapod, or shutter
83 major event
84 7 nights = 1/2*365 days
85 catastrophic event
86 14 nights = 1/3650 days e.g. replace a raft
87 """
88 random.seed(self.seed)
90 starts = []
91 ends = []
92 acts = []
93 night = 0
94 while night < self.survey_length:
95 prob = random.random()
96 if prob < self.CATASTROPHIC_EVENT['P']:
97 start_night = self.night0 + TimeDelta(night, format='jd')
98 starts.append(start_night)
99 end_night = start_night + TimeDelta(self.CATASTROPHIC_EVENT['length'], format='jd')
100 ends.append(end_night)
101 acts.append(self.CATASTROPHIC_EVENT['level'])
102 night += self.CATASTROPHIC_EVENT['length'] + 1
103 continue
104 else:
105 prob = random.random()
106 if prob < self.MAJOR_EVENT['P']:
107 start_night = self.night0 + TimeDelta(night, format='jd')
108 starts.append(start_night)
109 end_night = start_night + TimeDelta(self.MAJOR_EVENT['length'], format='jd')
110 ends.append(end_night)
111 acts.append(self.MAJOR_EVENT['level'])
112 night += self.MAJOR_EVENT['length'] + 1
113 continue
114 else:
115 prob = random.random()
116 if prob < self.INTERMEDIATE_EVENT['P']:
117 start_night = self.night0 + TimeDelta(night, format='jd')
118 starts.append(start_night)
119 end_night = start_night + TimeDelta(self.INTERMEDIATE_EVENT['length'], format='jd')
120 ends.append(end_night)
121 acts.append(self.INTERMEDIATE_EVENT['level'])
122 night += self.INTERMEDIATE_EVENT['length'] + 1
123 continue
124 else:
125 prob = random.random()
126 if prob < self.MINOR_EVENT['P']:
127 start_night = self.night0 + TimeDelta(night, format='jd')
128 starts.append(start_night)
129 end_night = start_night + TimeDelta(self.MINOR_EVENT['length'], format='jd')
130 ends.append(end_night)
131 acts.append(self.MINOR_EVENT['level'])
132 night += self.MINOR_EVENT['length'] + 1
133 night += 1
134 self.downtime = np.array(list(zip(starts, ends, acts)),
135 dtype=[('start', 'O'), ('end', 'O'), ('activity', 'O')])
137 def config_info(self):
138 """Report information about configuration of this data.
140 Returns
141 -------
142 OrderedDict
143 """
144 config_info = OrderedDict()
145 config_info['Survey start'] = self.night0.isot
146 config_info['Survey end'] = (self.night0 + TimeDelta(self.survey_length)).isot
147 config_info['Total unscheduled downtime (days)'] = self.total_downtime()
148 config_info['Random seed'] = self.seed
149 config_info['Unscheduled Downtimes'] = self.downtime
150 return config_info
152 def total_downtime(self):
153 """Return total downtime (in days).
155 Returns
156 -------
157 int
158 Total number of downtime days.
159 """
160 total = 0
161 for td in (self.downtime['end'] - self.downtime['start']):
162 total += td.jd
163 return total