Coverage for python/astro_metadata_translator/properties.py: 49%

Shortcuts 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

43 statements  

1# This file is part of astro_metadata_translator. 

2# 

3# Developed for the LSST Data Management System. 

4# This product includes software developed by the LSST Project 

5# (http://www.lsst.org). 

6# See the LICENSE file at the top-level directory of this distribution 

7# for details of code ownership. 

8# 

9# Use of this source code is governed by a 3-clause BSD-style 

10# license that can be found in the LICENSE file. 

11 

12"""Properties calculated by this package. 

13 

14Defines all properties in one place so that both `ObservationInfo` and 

15`MetadataTranslator` can use them. In particular, the translator 

16base class can use knowledge of these properties to predefine translation 

17stubs with documentation attached, and `ObservationInfo` can automatically 

18define the getter methods. 

19 

20""" 

21 

22__all__ = ("PROPERTIES",) 

23 

24import astropy.coordinates 

25import astropy.time 

26import astropy.units 

27 

28 

29# Helper functions to convert complex types to simple form suitable 

30# for JSON serialization 

31# All take the complex type and return simple python form using str, float, 

32# int, dict, or list. 

33# All assume the supplied parameter is not None. 

34 

35def earthlocation_to_simple(location): 

36 """Convert EarthLocation to tuple. 

37 

38 Parameters 

39 ---------- 

40 location : `astropy.coordinates.EarthLocation` 

41 The location to simplify. 

42 

43 Returns 

44 ------- 

45 geocentric : `tuple` of (`float`, `float`, `float`) 

46 The geocentric location as three floats in meters. 

47 """ 

48 geocentric = location.to_geocentric() 

49 return tuple(c.to_value(astropy.units.m) for c in geocentric) 

50 

51 

52def simple_to_earthlocation(simple, **kwargs): 

53 """Convert simple form back to EarthLocation. 

54 """ 

55 return astropy.coordinates.EarthLocation.from_geocentric(*simple, unit=astropy.units.m) 

56 

57 

58def datetime_to_simple(datetime): 

59 """Convert Time to tuple. 

60 

61 Parameters 

62 ---------- 

63 datetime : `astropy.time.Time` 

64 The time to simplify. 

65 

66 Returns 

67 ------- 

68 mjds : `tuple` of (`float`, `float`) 

69 The two MJDs in TAI. 

70 """ 

71 tai = datetime.tai 

72 return (tai.jd1, tai.jd2) 

73 

74 

75def simple_to_datetime(simple, **kwargs): 

76 """Convert simple form back to astropy.time.Time""" 

77 return astropy.time.Time(*simple, format="jd", scale="tai") 

78 

79 

80def exptime_to_simple(exptime): 

81 """Convert exposure time Quantity to seconds.""" 

82 return exptime.to_value(astropy.units.s) 

83 

84 

85def simple_to_exptime(simple, **kwargs): 

86 """Convert simple form back to Quantity.""" 

87 return simple * astropy.units.s 

88 

89 

90def angle_to_simple(angle): 

91 """Convert Angle to degrees.""" 

92 return angle.to_value(astropy.units.deg) 

93 

94 

95def simple_to_angle(simple, **kwargs): 

96 """Convert degrees to Angle.""" 

97 return astropy.coordinates.Angle(simple * astropy.units.deg) 

98 

99 

100def temperature_to_simple(temp): 

101 """Convert temperature to kelvin.""" 

102 return temp.to(astropy.units.K, equivalencies=astropy.units.temperature()).to_value() 

103 

104 

105def simple_to_temperature(simple, **kwargs): 

106 """Convert scalar kelvin value back to quantity.""" 

107 return simple * astropy.units.K 

108 

109 

110def pressure_to_simple(press): 

111 """Convert pressure Quantity to hPa.""" 

112 return press.to_value(astropy.units.hPa) 

113 

114 

115def simple_to_pressure(simple, **kwargs): 

116 """Convert the pressure scalar back to Quantity.""" 

117 return simple * astropy.units.hPa 

118 

119 

120def skycoord_to_simple(skycoord): 

121 """Convert SkyCoord to ICRS RA/Dec tuple""" 

122 icrs = skycoord.icrs 

123 return (icrs.ra.to_value(astropy.units.deg), 

124 icrs.dec.to_value(astropy.units.deg)) 

125 

126 

127def simple_to_skycoord(simple, **kwargs): 

128 """Convert ICRS tuple to SkyCoord.""" 

129 return astropy.coordinates.SkyCoord(*simple, unit=astropy.units.deg) 

130 

131 

132def altaz_to_simple(altaz): 

133 """Convert AltAz to Alt/Az tuple. 

134 

135 Do not include obstime or location in simplification. It is assumed 

136 that those will be present from other properties. 

137 """ 

138 return (altaz.az.to_value(astropy.units.deg), 

139 altaz.alt.to_value(astropy.units.deg)) 

140 

141 

142def simple_to_altaz(simple, **kwargs): 

143 """Convert simple altaz tuple to AltAz. 

144 

145 Will look for location and datetime_begin in kwargs. 

146 """ 

147 location = kwargs.get("location") 

148 obstime = kwargs.get("datetime_begin") 

149 

150 return astropy.coordinates.AltAz(simple[0]*astropy.units.deg, simple[1]*astropy.units.deg, 

151 obstime=obstime, location=location) 

152 

153 

154# Dict of properties to tuple where tuple is: 

155# - description of property 

156# - Python type of property as a string (suitable for docstrings) 

157# - Actual python type as a type 

158# - Simplification function (can be None) 

159# - Function to convert simple form back to required type (can be None) 

160PROPERTIES = {"telescope": ("Full name of the telescope.", "str", str, None, None), 

161 "instrument": ("The instrument used to observe the exposure.", "str", str, None, None), 

162 "location": ("Location of the observatory.", "astropy.coordinates.EarthLocation", 

163 astropy.coordinates.EarthLocation, 

164 earthlocation_to_simple, simple_to_earthlocation), 

165 "exposure_id": ("Unique (with instrument) integer identifier for this observation.", "int", 

166 int, None, None), 

167 "visit_id": ("""ID of the Visit this Exposure is associated with. 

168 

169Science observations should essentially always be 

170associated with a visit, but calibration observations 

171may not be.""", "int", int, None, None), 

172 "physical_filter": ("The bandpass filter used for this observation.", "str", str, None, None), 

173 "datetime_begin": ("Time of the start of the observation.", "astropy.time.Time", 

174 astropy.time.Time, 

175 datetime_to_simple, simple_to_datetime), 

176 "datetime_end": ("Time of the end of the observation.", "astropy.time.Time", 

177 astropy.time.Time, 

178 datetime_to_simple, simple_to_datetime), 

179 "exposure_time": ("Duration of the exposure with shutter open (seconds).", 

180 "astropy.units.Quantity", astropy.units.Quantity, 

181 exptime_to_simple, simple_to_exptime), 

182 "dark_time": ("Duration of the exposure with shutter closed (seconds).", 

183 "astropy.units.Quantity", astropy.units.Quantity, 

184 exptime_to_simple, simple_to_exptime), 

185 "boresight_airmass": ("Airmass of the boresight of the telescope.", "float", float, None, None), 

186 "boresight_rotation_angle": ("Angle of the instrument in boresight_rotation_coord frame.", 

187 "astropy.coordinates.Angle", astropy.coordinates.Angle, 

188 angle_to_simple, simple_to_angle), 

189 "boresight_rotation_coord": ("Coordinate frame of the instrument rotation angle" 

190 " (options: sky, unknown).", "str", str, None, None), 

191 "detector_num": ("Unique (for instrument) integer identifier for the sensor.", "int", int, 

192 None, None), 

193 "detector_name": ("Name of the detector within the instrument (might not be unique" 

194 " if there are detector groups).", 

195 "str", str, None, None), 

196 "detector_unique_name": ("Unique name of the detector within the focal plane, generally" 

197 " combining detector_group with detector_name.", 

198 "str", str, None, None), 

199 "detector_serial": ("Serial number/string associated with this detector.", "str", str, 

200 None, None), 

201 "detector_group": ("Collection name of which this detector is a part. " 

202 "Can be None if there are no detector groupings.", "str", str, 

203 None, None), 

204 "detector_exposure_id": ("Unique integer identifier for this detector in this exposure.", 

205 "int", int, None, None), 

206 "object": ("Object of interest or field name.", "str", str, None, None), 

207 "temperature": ("Temperature outside the dome.", "astropy.units.Quantity", 

208 astropy.units.Quantity, temperature_to_simple, simple_to_temperature), 

209 "pressure": ("Atmospheric pressure outside the dome.", "astropy.units.Quantity", 

210 astropy.units.Quantity, pressure_to_simple, simple_to_pressure), 

211 "relative_humidity": ("Relative humidity outside the dome.", "float", float, None, None), 

212 "tracking_radec": ("Requested RA/Dec to track.", "astropy.coordinates.SkyCoord", 

213 astropy.coordinates.SkyCoord, 

214 skycoord_to_simple, simple_to_skycoord), 

215 "altaz_begin": ("Telescope boresight azimuth and elevation at start of observation.", 

216 "astropy.coordinates.AltAz", astropy.coordinates.AltAz, 

217 altaz_to_simple, simple_to_altaz), 

218 "science_program": ("Observing program (survey or proposal) identifier.", "str", str, 

219 None, None), 

220 "observation_type": ("Type of observation (currently: science, dark, flat, bias, focus).", 

221 "str", str, None, None), 

222 "observation_id": ("Label uniquely identifying this observation " 

223 "(can be related to 'exposure_id').", 

224 "str", str, None, None), 

225 "observation_reason": ("Reason this observation was taken, or its purpose ('science' and " 

226 "'calibration' are common values)", 

227 "str", str, None, None), 

228 "exposure_group": ("Label to use to associate this exposure with others " 

229 "(can be related to 'exposure_id').", 

230 "str", str, None, None), 

231 "observing_day": ("Integer in YYYYMMDD format corresponding to the day of observation.", 

232 "int", int, None, None), 

233 "observation_counter": ("Counter of this observation. Can be counter within observing_day " 

234 " or a global counter. Likely to be observatory specific.", 

235 "int", int, None, None), 

236 }