Coverage for python/lsst/ts/observatory/model/target.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
1import math
2import numpy
3import copy
4import json
6__all__ = ["Target"]
8class Target(object):
9 """Class for gathering information for a sky target.
10 """
12 def __init__(self, targetid=0, fieldid=0, band_filter="",
13 ra_rad=0.0, dec_rad=0.0, ang_rad=0.0,
14 num_exp=0, exp_times=[]):
15 """Initialize the class.
17 Parameters
18 ----------
19 targetid : int
20 A unique identifier for the given target.
21 fieldid : int
22 The ID of the associated OpSim field for the target.
23 band_filter : str
24 The single character name of the associated band filter.
25 ra_rad : float
26 The right ascension (radians) of the target.
27 dec_rad : float
28 The declination (radians) of the target.
29 ang_rad : float
30 The sky angle (radians) of the target.
31 num_exp : int
32 The number of requested exposures for the target.
33 exp_times : list[float]
34 The set of exposure times for the target. Needs to length
35 of num_exp.
36 """
37 self.targetid = targetid
38 self.fieldid = fieldid
39 self.filter = band_filter
40 self.ra_rad = ra_rad
41 self.dec_rad = dec_rad
42 self.ang_rad = ang_rad
43 self.num_exp = num_exp
44 self.exp_times = list(exp_times)
45 self._exp_time = None # total exposure time
47 # conditions
48 self.time = 0.0
49 self.airmass = 0.0
50 self.sky_brightness = 0.0
51 self.cloud = 0.0
52 self.seeing = 0.0
54 # computed at proposal
55 self.propid = 0
56 self.need = 0.0
57 self.bonus = 0.0
58 self.value = 0.0
59 # internal proposal book-keeping
60 self.goal = 0
61 self.visits = 0
62 self.progress = 0.0
64 self.sequenceid = 0
65 self.subsequencename = ""
66 self.groupid = 0
67 self.groupix = 0
68 self.is_deep_drilling = False
69 self.is_dd_firstvisit = False
70 self.remaining_dd_visits = 0
71 self.dd_exposures = 0
72 self.dd_filterchanges = 0
73 self.dd_exptime = 0.0
75 # computed at driver
76 self.alt_rad = 0.0
77 self.az_rad = 0.0
78 self.rot_rad = 0.0
79 self.telalt_rad = 0.0
80 self.telaz_rad = 0.0
81 self.telrot_rad = 0.0
82 self.propboost = 1.0
83 self.slewtime = 0.0
84 self.cost = 0.0
85 self.rank = 0.0
87 # assembled at driver
88 self.num_props = 0
89 self.propid_list = []
90 self.need_list = []
91 self.bonus_list = []
92 self.value_list = []
93 self.propboost_list = []
94 self.sequenceid_list = []
95 self.subsequencename_list = []
96 self.groupid_list = []
97 self.groupix_list = []
98 self.is_deep_drilling_list = []
99 self.is_dd_firstvisit_list = []
100 self.remaining_dd_visits_list = []
101 self.dd_exposures_list = []
102 self.dd_filterchanges_list = []
103 self.dd_exptime_list = []
105 # stamped at observation
106 self.last_visit_time = 0.0
108 self.note = ''
110 def __str__(self):
111 """str: The string representation of the instance."""
112 return ("targetid=%d field=%d filter=%s exp_times=%s ra=%.3f "
113 "dec=%.3f ang=%.3f alt=%.3f az=%.3f rot=%.3f "
114 "telalt=%.3f telaz=%.3f telrot=%.3f "
115 "time=%.1f airmass=%.3f brightness=%.3f "
116 "cloud=%.2f seeing=%.2f "
117 "visits=%i progress=%.2f%% "
118 "seqid=%i ssname=%s groupid=%i groupix=%i "
119 "firstdd=%s ddvisits=%i "
120 "need=%.3f bonus=%.3f value=%.3f propboost=%.3f "
121 "propid=%s need=%s bonus=%s value=%s propboost=%s "
122 "slewtime=%.3f cost=%.3f rank=%.3f note=%s" %
123 (self.targetid, self.fieldid, self.filter,
124 str(self.exp_times),
125 self.ra, self.dec, self.ang,
126 self.alt, self.az, self.rot,
127 self.telalt, self.telaz, self.telrot,
128 self.time, self.airmass, self.sky_brightness,
129 self.cloud, self.seeing,
130 self.visits, 100 * self.progress,
131 self.sequenceid, self.subsequencename,
132 self.groupid, self.groupix,
133 self.is_dd_firstvisit, self.remaining_dd_visits,
134 self.need, self.bonus, self.value, self.propboost,
135 self.propid_list, numpy.round(self.need_list, 3), numpy.round(self.bonus_list, 3),
136 numpy.round(self.value_list, 3), numpy.round(self.propboost_list, 3),
137 self.slewtime, self.cost, self.rank, self.note))
139 @property
140 def alt(self):
141 """float: The altitude (degrees) of the target."""
142 return math.degrees(self.alt_rad)
144 @alt.setter
145 def alt(self, alt):
146 """
147 Set altitude given in degrees
149 Parameters
150 ----------
151 alt: float (degrees)
152 """
153 self.alt_rad = math.radians(alt)
155 @property
156 def ang(self):
157 """float: The sky angle (degrees) of the target."""
158 return math.degrees(self.ang_rad)
160 @ang.setter
161 def ang(self, ang):
162 """
163 Set camera rotation angle given in degrees
165 Parameters
166 ----------
167 ang: float (degrees)
168 """
169 self.ang_rad = math.radians(ang)
171 @property
172 def az(self):
173 """float: The azimuth (degrees) of the target."""
174 return math.degrees(self.az_rad)
176 @az.setter
177 def az(self, az):
178 """
179 Set camera rotation angle given in degrees
181 Parameters
182 ----------
183 az: float (degrees)
184 """
185 self.az_rad = math.radians(az)
187 @property
188 def dec(self):
189 """float: The declination (degrees) of the target."""
190 return math.degrees(self.dec_rad)
192 @dec.setter
193 def dec(self, dec):
194 """
195 Set declination given in degrees
197 Parameters
198 ----------
199 dec: float (degrees)
200 """
201 self.dec_rad = math.radians(dec)
203 @property
204 def ra(self):
205 """float: The right ascension (degrees) of the target."""
206 return math.degrees(self.ra_rad)
208 @ra.setter
209 def ra(self, ra):
210 """
211 Set right ascension given in degrees
213 Parameters
214 ----------
215 ra: float (degrees)
216 """
217 self.ra_rad = math.radians(ra)
219 @property
220 def rot(self):
221 """float: The rotator angle (degrees) of the target."""
222 return math.degrees(self.rot_rad)
224 @rot.setter
225 def rot(self, rot):
226 """
227 Set camera rotation angle given in degrees
229 Parameters
230 ----------
231 rot: float (degrees)
232 """
233 self.rot_rad = math.radians(rot)
235 @property
236 def telalt(self):
237 """float: The telescope altitude (degrees) for the target."""
238 return math.degrees(self.telalt_rad)
240 @telalt.setter
241 def telalt(self, telalt):
242 """
243 Set camera rotation angle given in degrees
245 Parameters
246 ----------
247 telalt: float (degrees)
248 """
249 self.telalt_rad = math.radians(telalt)
251 @property
252 def telaz(self):
253 """float: The telescope azimuth (degrees) for the target."""
254 return math.degrees(self.telaz_rad)
256 @telaz.setter
257 def telaz(self, telaz):
258 """
259 Set camera rotation angle given in degrees
261 Parameters
262 ----------
263 telaz: float (degrees)
264 """
265 self.telaz_rad = math.radians(telaz)
267 @property
268 def telrot(self):
269 """float: The telescope rotator angle (degrees) for the target."""
270 return math.degrees(self.telrot_rad)
272 @telrot.setter
273 def telrot(self, telrot):
274 """
275 Set camera rotation angle given in degrees
277 Parameters
278 ----------
279 telrot: float (degrees)
280 """
281 self.telrot_rad = math.radians(telrot)
283 @property
284 def exp_time(self):
285 """
287 Returns
288 -------
289 exp_time: float: The total exposure time in seconds.
290 """
291 if self._exp_time is None:
292 return sum(self.exp_times)
293 else:
294 self._exp_time
296 @exp_time.setter
297 def exp_time(self, exp_time):
298 """
300 Parameters
301 ----------
302 exp_time: float: The total exposure time in seconds.
304 Returns
305 -------
306 None
307 """
308 self._exp_time = exp_time
310 def copy_driver_state(self, target):
311 """Copy driver state from another target.
313 Parameters
314 ----------
315 target : :class:`.Target`
316 An instance of a target from which to get the driver state
317 information.
318 """
319 self.alt_rad = target.alt_rad
320 self.az_rad = target.az_rad
321 self.rot_rad = target.rot_rad
322 self.telalt_rad = target.telalt_rad
323 self.telaz_rad = target.telaz_rad
324 self.telrot_rad = target.telrot_rad
325 self.ang_rad = target.ang_rad
327 def get_copy(self):
328 """:class:`.Target`: Get copy of the instance."""
329 newtarget = Target()
330 newtarget.targetid = self.targetid
331 newtarget.fieldid = self.fieldid
332 newtarget.filter = self.filter
333 newtarget.ra_rad = self.ra_rad
334 newtarget.dec_rad = self.dec_rad
335 newtarget.ang_rad = self.ang_rad
336 newtarget.num_exp = self.num_exp
337 newtarget.exp_times = list(self.exp_times)
338 newtarget.time = self.time
339 newtarget.airmass = self.airmass
340 newtarget.sky_brightness = self.sky_brightness
341 newtarget.cloud = self.cloud
342 newtarget.seeing = self.seeing
343 newtarget.propid = self.propid
344 newtarget.need = self.need
345 newtarget.bonus = self.bonus
346 newtarget.value = self.value
347 newtarget.goal = self.goal
348 newtarget.visits = self.visits
349 newtarget.progress = self.progress
351 newtarget.sequenceid = self.sequenceid
352 newtarget.subsequencename = self.subsequencename
353 newtarget.groupid = self.groupid
354 newtarget.groupix = self.groupix
355 newtarget.is_deep_drilling = self.is_deep_drilling
356 newtarget.is_dd_firstvisit = self.is_dd_firstvisit
357 newtarget.remaining_dd_visits = self.remaining_dd_visits
358 newtarget.dd_exposures = self.dd_exposures
359 newtarget.dd_filterchanges = self.dd_filterchanges
360 newtarget.dd_exptime = self.dd_exptime
362 newtarget.alt_rad = self.alt_rad
363 newtarget.az_rad = self.az_rad
364 newtarget.rot_rad = self.rot_rad
365 newtarget.telalt_rad = self.telalt_rad
366 newtarget.telaz_rad = self.telaz_rad
367 newtarget.telrot_rad = self.telrot_rad
368 newtarget.propboost = self.propboost
369 newtarget.slewtime = self.slewtime
370 newtarget.cost = self.cost
371 newtarget.rank = self.rank
372 newtarget.num_props = self.num_props
373 newtarget.propid_list = list(self.propid_list)
374 newtarget.need_list = list(self.need_list)
375 newtarget.bonus_list = list(self.bonus_list)
376 newtarget.value_list = list(self.value_list)
377 newtarget.propboost_list = list(self.propboost_list)
378 newtarget.sequenceid_list = list(self.sequenceid_list)
379 newtarget.subsequencename_list = list(self.subsequencename_list)
380 newtarget.groupid_list = list(self.groupid_list)
381 newtarget.groupix_list = list(self.groupix_list)
382 newtarget.is_deep_drilling_list = list(self.is_deep_drilling_list)
383 newtarget.is_dd_firstvisit_list = list(self.is_dd_firstvisit_list)
384 newtarget.remaining_dd_visits_list = list(self.remaining_dd_visits_list)
385 newtarget.dd_exposures_list = list(self.dd_exposures_list)
386 newtarget.dd_filterchanges_list = list(self.dd_filterchanges_list)
387 newtarget.dd_exptime_list = list(self.dd_exptime_list)
389 newtarget.note = self.note
391 return newtarget
393 def to_json(self):
394 """
395 Returns a json serialization of variables in this object
396 """
397 return json.dumps(vars(self))
399 def from_json(self, jsonstr):
400 """
401 alternate __init__ method that takes a json representation as the only argument
402 """
403 mandatory_fields = ["targetid", "fieldid", "filter", "ra_rad", "dec_rad", "ang_rad", "num_exp", "exp_times"]
405 jsondict = json.loads(jsonstr)
406 for f in mandatory_fields:
407 if f not in jsondict.keys():
408 raise KeyError("json blob passed to Target()'s json constructor is missing required attribute: " + f)
411 for k in jsondict:
412 setattr(self, k, jsondict[k])
414 @classmethod
415 def from_topic(cls, topic):
416 """Alternate initializer.
418 Parameters
419 ----------
420 topic : SALPY_scheduler.targetC
421 The target topic instance.
423 Returns
424 -------
425 :class:`.Target`
426 """
427 return cls(topic.targetId, -1, topic.filter, math.radians(topic.ra),
428 math.radians(topic.decl), math.radians(topic.skyAngle), topic.numExposures,
429 topic.exposureTimes)