def setUp(self): self.testDir = os.path.dirname(__file__) def computeLstHA(data): """Return LST, Hour Angle, computed from VisitInfoData.""" localEra = data.era + data.observatory.getLongitude() hourAngle = localEra - data.boresightRaDec[0] return localEra, hourAngle fields = [ 'exposureId', 'exposureTime', 'darkTime', 'date', 'ut1', 'era', 'boresightRaDec', 'boresightAzAlt', 'boresightAirmass', 'boresightRotAngle', 'rotType', 'observatory', 'weather' ] VisitInfoData = collections.namedtuple("VisitInfoData", fields) data1 = VisitInfoData( exposureId=10313423, exposureTime=10.01, darkTime=11.02, date=DateTime(65321.1, DateTime.MJD, DateTime.TAI), ut1=12345.1, era=45.1 * degrees, boresightRaDec=SpherePoint(23.1 * degrees, 73.2 * degrees), boresightAzAlt=SpherePoint(134.5 * degrees, 33.3 * degrees), boresightAirmass=1.73, boresightRotAngle=73.2 * degrees, rotType=afwImage.RotType.SKY, observatory=Observatory(11.1 * degrees, 22.2 * degrees, 0.333), weather=Weather(1.1, 2.2, 34.5), ) self.data1 = data1 self.localEra1, self.hourAngle1 = computeLstHA(data1) data2 = VisitInfoData( exposureId=1, exposureTime=15.5, darkTime=17.8, date=DateTime(55321.2, DateTime.MJD, DateTime.TAI), ut1=312345.1, era=25.1 * degrees, boresightRaDec=SpherePoint(2.1 * degrees, 33.2 * degrees), boresightAzAlt=SpherePoint(13.5 * degrees, 83.3 * degrees), boresightAirmass=2.05, boresightRotAngle=-53.2 * degrees, rotType=afwImage.RotType.HORIZON, observatory=Observatory(22.2 * degrees, 33.3 * degrees, 0.444), weather=Weather(2.2, 3.3, 44.4), ) self.data2 = data2 self.localEra2, self.hourAngle2 = computeLstHA(data2)
def defaultWeather(altitude): """Set default local weather conditions if they are missing. Parameters ---------- weather : `lsst.afw.coord.Weather` Class containing the measured temperature, pressure, and humidity at the observatory during an observation altitude : `astropy.units.Quantity` The altitude of the observatory, in meters. Returns ------- `lsst.afw.coord.Weather` Updated Weather class with any `nan` values replaced by defaults. """ if isinstance(altitude, units.quantity.Quantity): altitude2 = altitude else: altitude2 = altitude * units.meter p0 = 101325. * units.pascal # sea level air pressure g = 9.80665 * units.meter / units.second**2 # typical gravitational acceleration at sea level R0 = 8.31447 * units.Joule / (units.mol * units.Kelvin) # gas constant T0 = 19. * units.Celsius # Typical sea-level temperature lapseRate = -6.5 * units.Celsius / units.km # Typical rate of change of temperature with altitude M = 0.0289644 * units.kg / units.mol # molar mass of dry air temperature = T0 + lapseRate * altitude2 temperatureK = temperature.to(units.Kelvin, equivalencies=units.temperature()) pressure = p0 * np.exp(-(g * M * altitude2) / (R0 * temperatureK)) humidity = 40. # Typical humidity at many observatory sites. weather = Weather((temperature / units.Celsius).value, (pressure / units.pascal).value, humidity) return weather
def setArgDict(self, md, argDict): """Set an argument dict for VisitInfo and pop associated metadata @param[in,out] md metadata, as an lsst.daf.base.PropertyList or PropertySet @param[in,out] argdict a dict of arguments """ MakeRawVisitInfo.setArgDict(self, md, argDict) argDict["darkTime"] = self.popFloat(md, "DARKTIME") argDict["boresightAzAlt"] = Coord( self.popAngle(md, "AZ"), self.altitudeFromZenithDistance(self.popAngle(md, "ZD")), ) argDict["boresightRaDec"] = IcrsCoord( self.popAngle(md, "TELRA", units=astropy.units.h), self.popAngle(md, "TELDEC"), ) argDict["boresightAirmass"] = self.popFloat(md, "AIRMASS") argDict["observatory"] = Observatory( self.popAngle(md, "OBS-LONG"), self.popAngle(md, "OBS-LAT"), self.popFloat(md, "OBS-ELEV"), ) argDict["weather"] = Weather( self.popFloat(md, "OUTTEMP"), self.pascalFromMmHg(self.popFloat(md, "PRESSURE")), self.popFloat(md, "HUMIDITY")) longitude = argDict["observatory"].getLongitude() argDict['era'] = self.decamGetEra(md, argDict["boresightRaDec"][0], longitude)
def setArgDict(self, md, argDict): """Set an argument dict for VisitInfo and pop associated metadata @param[in,out] md metadata, as an lsst.daf.base.PropertyList or PropertySet @param[in,out] argdict a dict of arguments """ MakeRawVisitInfo.setArgDict(self, md, argDict) argDict["darkTime"] = self.popFloat(md, "DARKTIME") argDict["boresightAzAlt"] = Coord( self.popAngle(md, "TELAZ"), self.popAngle(md, "TELALT"), ) argDict["boresightRaDec"] = IcrsCoord( self.popAngle( md, "RA_DEG", ), self.popAngle(md, "DEC_DEG"), ) argDict["boresightAirmass"] = self.popFloat(md, "AIRMASS") argDict["observatory"] = Observatory( self.popAngle(md, "LONGITUD"), self.popAngle(md, "LATITUDE"), 4204, # from Wikipedia ) argDict["weather"] = Weather( self.popFloat(md, "TEMPERAT"), self.popFloat(md, "PRESSURE") * 100.0, # 100 Pascal per millibar self.popFloat(md, "RELHUMID"), ) # Using LST to compute ERA until we get UT1 (see: DM-8053) LST = self.popAngle(md, "LST-OBS", units=astropy.units.h) argDict['era'] = self.eraFromLstAndLongitude( LST, argDict["observatory"].getLongitude())
def testVisitInfoFitsPersistence(self): """Test saving an exposure to FITS and reading it back in preserves (some) VisitInfo fields""" exposureId = 5 exposureTime = 12.3 boresightRotAngle = 45.6 * lsst.geom.degrees weather = Weather(1.1, 2.2, 0.3) visitInfo = afwImage.VisitInfo( exposureId=exposureId, exposureTime=exposureTime, boresightRotAngle=boresightRotAngle, weather=weather, ) photoCalib = afwImage.PhotoCalib(3.4, 5.6) exposureInfo = afwImage.ExposureInfo() exposureInfo.setVisitInfo(visitInfo) exposureInfo.setPhotoCalib(photoCalib) exposureInfo.setDetector(self.detector) gFilter = afwImage.Filter("g") exposureInfo.setFilter(gFilter) maskedImage = afwImage.MaskedImageF(inFilePathSmall) exposure = afwImage.ExposureF(maskedImage, exposureInfo) with lsst.utils.tests.getTempFilePath(".fits") as tmpFile: exposure.writeFits(tmpFile) rtExposure = afwImage.ExposureF(tmpFile) rtVisitInfo = rtExposure.getInfo().getVisitInfo() self.assertEqual(rtVisitInfo.getWeather(), weather) self.assertEqual(rtExposure.getPhotoCalib(), photoCalib) self.assertEqual(rtExposure.getFilter(), gFilter)
def setArgDict(self, md, argDict): """Set an argument dict for VisitInfo and pop associated metadata @param[in,out] md metadata, as an lsst.daf.base.PropertyList or PropertySet @param[in,out] argdict a dict of arguments """ MakeRawVisitInfo.setArgDict(self, md, argDict) argDict["boresightRaDec"] = IcrsCoord( self.popAngle(md, "RA2000", units=astropy.units.h), self.popAngle(md, "DEC2000"), ) argDict["boresightAzAlt"] = Coord( self.popAngle(md, "AZIMUTH"), self.popAngle(md, "ALTITUDE"), ) argDict["boresightAirmass"] = self.popFloat(md, "AIRMASS") argDict["observatory"] = self.observatory argDict["weather"] = Weather( self.centigradeFromKelvin(self.popFloat(md, "OUT-TMP")), self.pascalFromMmHg(self.popFloat(md, "OUT-PRS")), self.popFloat(md, "OUT-HUM"), ) LST = self.popAngle(md, "LST-STR", units=astropy.units.h) argDict['era'] = self.eraFromLstAndLongitude( LST, self.observatory.getLongitude()) argDict['darkTime'] = argDict['exposureTime'] # Rotation angle formula determined empirically from visual inspection # of HSC images. See DM-9111. rotAngle = (270.0 * degrees - self.popAngle(md, "INST-PA")).wrap() argDict['boresightRotAngle'] = rotAngle argDict['rotType'] = RotType.SKY
def setArgDict(self, md, argDict): """Set an argument dict for makeVisitInfo and pop associated metadata @param[in,out] md metadata, as an lsst.daf.base.PropertyList or PropertySet @param[in,out] argdict a dict of arguments """ MakeRawVisitInfo.setArgDict(self, md, argDict) argDict["boresightRaDec"] = IcrsCoord( self.popAngle(md, "RA2000", units=astropy.units.h), self.popAngle(md, "DEC2000"), ) # argDict["boresightAzAlt"] = Coord( # self.popAngle(md, "AZIMUTH"), # self.popAngle(md, "ALTITUDE"), # ) argDict["boresightAirmass"] = self.popFloat(md, "AIRMASS") argDict["observatory"] = self.observatory argDict["weather"] = Weather( self.centigradeFromKelvin(self.popFloat(md, "OUT-TMP")), self.pascalFromMmHg(self.popFloat(md, "OUT-PRS")), self.popFloat(md, "OUT-HUM"), ) LST = self.popAngle(md, "LST-STR", units=astropy.units.h) argDict['era'] = self.eraFromLstAndLongitude( LST, self.observatory.getLongitude()) argDict['darkTime'] = argDict['exposureTime']
def setArgDict(self, md, argDict): """Set an argument dict for makeVisitInfo and pop associated metadata @param[in,out] md metadata, as an lsst.daf.base.PropertyList or PropertySet @param[in,out] argdict a dict of arguments """ MakeRawVisitInfo.setArgDict(self, md, argDict) argDict["darkTime"] = self.popFloat(md, "DARKTIME") argDict["boresightAzAlt"] = Coord( self.popAngle(md, "AZIMUTH"), self.altitudeFromZenithDistance(self.popAngle(md, "ZENITH")), ) argDict["boresightRaDec"] = IcrsCoord( self.popAngle(md, "RA_DEG"), self.popAngle(md, "DEC_DEG"), ) argDict["boresightAirmass"] = self.popFloat(md, "AIRMASS") argDict["boresightRotAngle"] = 90 * degrees - self.popAngle( md, "ROTANG") argDict["rotType"] = RotType_SKY argDict["observatory"] = self.observatory argDict["weather"] = Weather( self.popFloat(md, "TEMPERA"), self.pascalFromMmHg(self.popFloat(md, "PRESS")), float("nan"), ) return makeVisitInfo(**argDict)
def setArgDict(self, md, argDict): """Set an argument dict for VisitInfo and pop associated metadata @param[in,out] md metadata, as an lsst.daf.base.PropertyList or PropertySet @param[in,out] argdict a dict of arguments """ MakeRawVisitInfo.setArgDict(self, md, argDict) argDict["darkTime"] = self.popFloat(md, "DARKTIME") argDict["boresightAzAlt"] = Coord( self.popAngle(md, "AZIMUTH"), self.altitudeFromZenithDistance(self.popAngle(md, "ZENITH")), ) argDict["boresightRaDec"] = IcrsCoord( self.popAngle(md, "RA_DEG"), self.popAngle(md, "DEC_DEG"), ) argDict["boresightAirmass"] = self.popFloat(md, "AIRMASS") argDict["boresightRotAngle"] = -self.popAngle(md, "ROTANG") argDict["rotType"] = RotType.SKY argDict["observatory"] = self.observatory argDict["weather"] = Weather( self.popFloat(md, "TEMPERA"), self.pascalFromMmHg(self.popFloat(md, "PRESS")), float("nan"), ) # phosim doesn't supply LST, HA, or UT1, and the alt/az/ra/dec/time can be inconsistent. # We will leave ERA as NaN until a better answer is available. return VisitInfo(**argDict)
def setArgDict(self, md, argDict): """Set an argument dict for VisitInfo and pop associated metadata Parameters ---------- md : `lsst.daf.base.PropertyList` or `lsst.daf.base.PropertySet` Metadata to extract from. Extracted values are removed. argdict : `dict` A dict of arguments to add to values to. """ MakeRawVisitInfo.setArgDict(self, md, argDict) argDict["darkTime"] = self.popFloat(md, "DARKTIME") argDict["boresightAzAlt"] = SpherePoint( self.popAngle(md, "TELAZ"), self.popAngle(md, "TELALT"), ) argDict["boresightRaDec"] = SpherePoint( self.popAngle(md, "RA_DEG",), self.popAngle(md, "DEC_DEG"), ) argDict["boresightAirmass"] = self.popFloat(md, "AIRMASS") argDict["observatory"] = Observatory( self.popAngle(md, "LONGITUD"), self.popAngle(md, "LATITUDE"), 4204, # from Wikipedia ) argDict["weather"] = Weather( self.popFloat(md, "TEMPERAT"), self.popFloat(md, "PRESSURE")*100.0, # 100 Pascal per millibar self.popFloat(md, "RELHUMID"), ) # Using LST to compute ERA until we get UT1 (see: DM-8053) LST = self.popAngle(md, "LST-OBS", units=astropy.units.h) argDict['era'] = self.eraFromLstAndLongitude(LST, argDict["observatory"].getLongitude())
def createVisitInfo(): return lsst.afw.image.VisitInfo( 10313423, 10.01, 11.02, DateTime(65321.1, DateTime.MJD, DateTime.TAI), 12345.1, 45.1 * degrees, SpherePoint(23.1 * degrees, 73.2 * degrees), SpherePoint(134.5 * degrees, 33.3 * degrees), 1.73, 73.2 * degrees, lsst.afw.image.RotType.SKY, Observatory(11.1 * degrees, 22.2 * degrees, 0.333), Weather(1.1, 2.2, 34.5), "testCam")
def setUp(self): """Define parameters used by every test.""" lsstLat = -30.244639 * degrees lsstLon = -70.749417 * degrees lsstAlt = 2663. lsstTemperature = 20. * units.Celsius # in degrees Celsius lsstHumidity = 10. # in percent lsstPressure = 73892. * units.pascal # 1 atmosphere. np.random.seed(5) self.weather = Weather(lsstTemperature / units.Celsius, lsstPressure / units.pascal, lsstHumidity) self.observatory = Observatory(lsstLon, lsstLat, lsstAlt)
def testBasics(self): prevWeather = None for temp, pressure in ((1.1, 2.2), (100.1, 200.2)): # arbitrary values # 0 and greater, including supersaturation for humidity in (0.0, 10.1, 100.0, 120.5): weather = Weather(temp, pressure, humidity) self.assertEqual(weather.getAirTemperature(), temp) self.assertEqual(weather.getAirPressure(), pressure) self.assertEqual(weather.getHumidity(), humidity) # test copy constructor weatherCopy = Weather(weather) self.assertEqual(weatherCopy.getAirTemperature(), temp) self.assertEqual(weatherCopy.getAirPressure(), pressure) self.assertEqual(weatherCopy.getHumidity(), humidity) # test == (using a copy, to make sure the test is not based on # identity) and != self.assertEqual(weather, weatherCopy) if prevWeather is not None: self.assertNotEqual(weather, prevWeather) prevWeather = weather
def test_getWeather(self): def test_weather(w1, w2): """Test equality of two Weather objects @param[in] w1 First Weather object @param[in] w2 Second Weather object """ humid_bool = np.isnan(w1.getHumidity()) and np.isnan(w2.getHumidity()) if not humid_bool: humid_bool = (w1.getHumidity() == w2.getHumidity()) self.assertTrue(w1.getAirPressure() == w2.getAirPressure() and w1.getAirTemperature() == w2.getAirTemperature() and humid_bool) weather = Weather(20, 69327.64145580001, np.nan) test_weather(weather, self.visit_info.getWeather())
def makeVisitInfo(): """Return a non-NaN visitInfo.""" return afwImage.VisitInfo(exposureId=10313423, exposureTime=10.01, darkTime=11.02, date=dafBase.DateTime(65321.1, dafBase.DateTime.MJD, dafBase.DateTime.TAI), ut1=12345.1, era=45.1*afwGeom.degrees, boresightRaDec=afwGeom.SpherePoint(23.1, 73.2, afwGeom.degrees), boresightAzAlt=afwGeom.SpherePoint(134.5, 33.3, afwGeom.degrees), boresightAirmass=1.73, boresightRotAngle=73.2*afwGeom.degrees, rotType=afwImage.RotType.SKY, observatory=Observatory(11.1*afwGeom.degrees, 22.2*afwGeom.degrees, 0.333), weather=Weather(1.1, 2.2, 34.5), )
def makeVisitInfo(): return lsst.afw.image.VisitInfo( 10313423, 10.01, 11.02, DateTime(65321.1, DateTime.MJD, DateTime.TAI), 12345.1, 45.1*lsst.afw.geom.degrees, lsst.afw.geom.SpherePoint(23.1, 73.2, lsst.afw.geom.degrees), lsst.afw.geom.SpherePoint(134.5, 33.3, lsst.afw.geom.degrees), 1.73, 73.2*lsst.afw.geom.degrees, lsst.afw.image.RotType.SKY, Observatory(11.1*lsst.afw.geom.degrees, 22.2*lsst.afw.geom.degrees, 0.333), Weather(1.1, 2.2, 34.5), )
def testEquals(self): weather1 = Weather(1.1, 100.1, 10.1) weather2 = Weather(2.2, 200.2, 0.0) weather3 = Weather(np.nan, np.nan, np.nan) # objects with "same" values should be equal self.assertEqual(Weather(1.1, 100.1, 10.1), Weather(1.1, 100.1, 10.1)) self.assertEqual(Weather(np.nan, np.nan, np.nan), Weather(np.nan, np.nan, np.nan)) self.assertNotEqual(weather1, weather2) self.assertNotEqual(weather3, weather2) # equality must be reflexive self.assertEqual(weather1, weather1) self.assertEqual(weather2, weather2) self.assertEqual(weather3, weather3)
def setArgDict(self, md, argDict): """Set an argument dict for VisitInfo and pop associated metadata @param[in,out] md metadata, as an lsst.daf.base.PropertyList or PropertySet @param[in,out] argdict a dict of arguments """ MakeRawVisitInfo.setArgDict(self, md, argDict) argDict["darkTime"] = self.popFloat(md, "DARKTIME") argDict["boresightAzAlt"] = Coord( self.popAngle(md, "AZIMUTH"), self.altitudeFromZenithDistance(self.popAngle(md, "ZENITH")), ) argDict["boresightRaDec"] = IcrsCoord( self.popAngle(md, "RA_DEG"), self.popAngle(md, "DEC_DEG"), ) argDict["boresightAirmass"] = self.popFloat(md, "AIRMASS") argDict["boresightRotAngle"] = -self.popAngle(md, "ROTANG") argDict["rotType"] = RotType.SKY argDict["observatory"] = self.observatory weather = defaultWeather(self.observatory.getElevation()) temperature = self.defaultMetadata(self.popFloat(md, "TEMPERA"), weather.getAirTemperature(), minimum=-10, maximum=40.) pressure = self.defaultMetadata(self.pascalFromMmHg( self.popFloat(md, "PRESS")), weather.getAirPressure(), minimum=50000., maximum=90000.) humidity = 40. # Not currently supplied by phosim, so set to a typical value. argDict["weather"] = Weather(temperature, pressure, humidity) longitude = argDict["observatory"].getLongitude() RA = argDict["boresightRaDec"][0] # phosim doesn't supply LST, HA, or UT1, and the alt/az/ra/dec/time can be inconsistent. # We will leave ERA as NaN until a better answer is available. try: # Other simulation tools don't have the same problem, and need hour angle if it is available. HA = self.popAngle(md, "HA", units=astropy.units.h) argDict['era'] = HA + RA - longitude except: self.log.warn("Hour angle missing from metadata, will be NAN") return VisitInfo(**argDict)
def setArgDict(self, md, argDict): """Set an argument dict for VisitInfo and pop associated metadata @param[in,out] md metadata, as an lsst.daf.base.PropertyList or PropertySet @param[in,out] argdict a dict of arguments """ MakeRawVisitInfo.setArgDict(self, md, argDict) argDict["darkTime"] = self.popFloat(md, "DARKTIME") argDict["boresightAzAlt"] = SpherePoint( self.popAngle(md, "AZ"), self.altitudeFromZenithDistance(self.popAngle(md, "ZD")), ) argDict["boresightRaDec"] = SpherePoint( self.popAngle(md, "TELRA", units=astropy.units.h), self.popAngle(md, "TELDEC"), ) argDict["boresightAirmass"] = self.popFloat(md, "AIRMASS") argDict["observatory"] = Observatory( self.popAngle(md, "OBS-LONG"), self.popAngle(md, "OBS-LAT"), self.popFloat(md, "OBS-ELEV"), ) # Default weather is based on typical conditions at an altitude of 2215 meters. temperature = self.defaultMetadata(self.popFloat(md, "OUTTEMP"), 10., minimum=-10., maximum=40.) pressure = self.defaultMetadata(self.pascalFromMmHg( self.popFloat(md, "PRESSURE")), 77161.1, minimum=70000., maximum=85000.) humidity = self.defaultMetadata(self.popFloat(md, "HUMIDITY"), 40., minimum=0., maximum=100.) argDict["weather"] = Weather(temperature, pressure, humidity) longitude = argDict["observatory"].getLongitude() argDict['era'] = self.decamGetEra(md, argDict["boresightRaDec"][0], longitude)
def setArgDict(self, md, argDict): """Set an argument dict for VisitInfo and pop associated metadata. Parameters ---------- md : `lsst.daf.base.PropertySet` Image metadata. argDict : `dict` A dict of arguments for the `lsst.afw.image.VisitInfo` constructor. Updated by this call. Returns ------- visitInfo : `lsst.afw.image.VisitInfo` Visit information. """ MakeRawVisitInfo.setArgDict(self, md, argDict) argDict["darkTime"] = self.popFloat(md, "DARKTIME") argDict["boresightAzAlt"] = SpherePoint( self.popAngle(md, "AZIMUTH"), self.altitudeFromZenithDistance(self.popAngle(md, "ZENITH")), ) argDict["boresightRaDec"] = SpherePoint( self.popAngle(md, "RA_DEG"), self.popAngle(md, "DEC_DEG"), ) argDict["boresightAirmass"] = self.popFloat(md, "AIRMASS") argDict["boresightRotAngle"] = -self.popAngle(md, "ROTANG") argDict["rotType"] = RotType.SKY argDict["observatory"] = self.observatory argDict["weather"] = Weather( self.popFloat(md, "TEMPERA"), self.pascalFromMmHg(self.popFloat(md, "PRESS")), float("nan"), ) return VisitInfo(**argDict)
def __call__(self, md, exposureId=None): """Construct a VisitInfo and strip associated data from the metadata. Parameters ---------- md : `lsst.daf.base.PropertyList` or `lsst.daf.base.PropertySet` Metadata to pull from. Items that are used are stripped from the metadata. exposureId : `int`, optional Ignored. Here for compatibility with `MakeRawVisitInfo`. Returns ------- visitInfo : `lsst.afw.image.VisitInfo` `~lsst.afw.image.VisitInfo` derived from the header using a `~astro_metadata_translator.MetadataTranslator`. """ argDict = dict() obsInfo = ObservationInfo(md, translator_class=self.metadataTranslator) # Strip all the cards out that were used for c in obsInfo.cards_used: del md[c] # Map the translated information into a form suitable for VisitInfo if obsInfo.exposure_time is not None: argDict["exposureTime"] = obsInfo.exposure_time.to_value("s") if obsInfo.dark_time is not None: argDict["darkTime"] = obsInfo.dark_time.to_value("s") argDict["exposureId"] = obsInfo.detector_exposure_id # VisitInfo uses the middle of the observation for the date if obsInfo.datetime_begin is not None and obsInfo.datetime_end is not None: tdelta = obsInfo.datetime_end - obsInfo.datetime_begin middle = obsInfo.datetime_begin + 0.5 * tdelta # DateTime uses nanosecond resolution, regardless of the resolution # of the original date middle.precision = 9 # isot is ISO8601 format with "T" separating date and time and no # time zone argDict["date"] = DateTime(middle.tai.isot, DateTime.TAI) # Derive earth rotation angle from UT1 (being out by a second is not # a big deal given the uncertainty over exactly what part of the # observation we are needing it for). # ERFA needs a UT1 time split into two floats # We ignore any problems with DUT1 not being defined for now. try: ut1time = middle.ut1 except iers.IERSRangeError: ut1time = middle era = erfa.era00(ut1time.jd1, ut1time.jd2) argDict["era"] = era * radians else: argDict["date"] = DateTime() # Coordinates if obsInfo.tracking_radec is not None: icrs = obsInfo.tracking_radec.transform_to("icrs") argDict["boresightRaDec"] = SpherePoint(icrs.ra.degree, icrs.dec.degree, units=degrees) altaz = obsInfo.altaz_begin if altaz is not None: argDict["boresightAzAlt"] = SpherePoint(altaz.az.degree, altaz.alt.degree, units=degrees) argDict["boresightAirmass"] = obsInfo.boresight_airmass if obsInfo.boresight_rotation_angle is not None: argDict[ "boresightRotAngle"] = obsInfo.boresight_rotation_angle.degree * degrees if obsInfo.boresight_rotation_coord is not None: rotType = RotType.UNKNOWN if obsInfo.boresight_rotation_coord == "sky": rotType = RotType.SKY argDict["rotType"] = rotType # Weather and Observatory Location temperature = float("nan") if obsInfo.temperature is not None: temperature = obsInfo.temperature.to_value( "deg_C", astropy.units.temperature()) pressure = float("nan") if obsInfo.pressure is not None: pressure = obsInfo.pressure.to_value("Pa") relative_humidity = float("nan") if obsInfo.relative_humidity is not None: relative_humidity = obsInfo.relative_humidity argDict["weather"] = Weather(temperature, pressure, relative_humidity) if obsInfo.location is not None: geolocation = obsInfo.location.to_geodetic() argDict["observatory"] = Observatory( geolocation.lon.degree * degrees, geolocation.lat.degree * degrees, geolocation.height.to_value("m")) for key in list( argDict.keys()): # use a copy because we may delete items if argDict[key] is None: self.log.warn("argDict[{}] is None; stripping".format( key, argDict[key])) del argDict[key] return VisitInfo(**argDict)
def testBadHumidity(self): """Check bad humidity handling (humidity is the only value whose range is checked)""" for humidity in (-1, -0.0001): with self.assertRaises(lsst.pex.exceptions.InvalidParameterError): Weather(1.1, 2.2, humidity)
def observationInfo2visitInfo(obsInfo, log=None): """Construct a `~lsst.afw.image.VisitInfo` from an `~astro_metadata_translator.ObservationInfo` Parameters ---------- obsInfo : `astro_metadata_translator.ObservationInfo` Information gathered from the observation metadata. log : `logging.Logger` or `lsst.log.Log`, optional Logger to use for logging informational messages. If `None` logging will be disabled. Returns ------- visitInfo : `lsst.afw.image.VisitInfo` `~lsst.afw.image.VisitInfo` derived from the supplied `~astro_metadata_translator.ObservationInfo`. """ argDict = dict() # Map the translated information into a form suitable for VisitInfo if obsInfo.exposure_time is not None: argDict["exposureTime"] = obsInfo.exposure_time.to_value("s") if obsInfo.dark_time is not None: argDict["darkTime"] = obsInfo.dark_time.to_value("s") argDict["exposureId"] = obsInfo.detector_exposure_id # VisitInfo uses the middle of the observation for the date if obsInfo.datetime_begin is not None and obsInfo.datetime_end is not None: tdelta = obsInfo.datetime_end - obsInfo.datetime_begin middle = obsInfo.datetime_begin + 0.5 * tdelta # DateTime uses nanosecond resolution, regardless of the resolution # of the original date middle.precision = 9 # isot is ISO8601 format with "T" separating date and time and no # time zone argDict["date"] = DateTime(middle.tai.isot, DateTime.TAI) # Derive earth rotation angle from UT1 (being out by a second is # not a big deal given the uncertainty over exactly what part of # the observation we are needing it for). # ERFA needs a UT1 time split into two floats # We ignore any problems with DUT1 not being defined for now. try: # Catch any warnings about the time being in the future # since there is nothing we can do about that for simulated # data and it tells us nothing for data from the past. with warnings.catch_warnings(): # If we are using the real erfa it is not an AstropyWarning # During transition period filter both warnings.simplefilter( "ignore", category=astropy.utils.exceptions.AstropyWarning) if ErfaWarning is not None: warnings.simplefilter("ignore", category=ErfaWarning) ut1time = middle.ut1 except iers.IERSRangeError: ut1time = middle era = erfa.era00(ut1time.jd1, ut1time.jd2) argDict["era"] = era * radians else: argDict["date"] = DateTime() # Coordinates if obsInfo.tracking_radec is not None: icrs = obsInfo.tracking_radec.transform_to("icrs") argDict["boresightRaDec"] = SpherePoint(icrs.ra.degree, icrs.dec.degree, units=degrees) altaz = obsInfo.altaz_begin if altaz is not None: argDict["boresightAzAlt"] = SpherePoint(altaz.az.degree, altaz.alt.degree, units=degrees) argDict["boresightAirmass"] = obsInfo.boresight_airmass if obsInfo.boresight_rotation_angle is not None: argDict[ "boresightRotAngle"] = obsInfo.boresight_rotation_angle.degree * degrees if obsInfo.boresight_rotation_coord is not None: rotType = RotType.UNKNOWN if obsInfo.boresight_rotation_coord == "sky": rotType = RotType.SKY argDict["rotType"] = rotType # Weather and Observatory Location temperature = float("nan") if obsInfo.temperature is not None: temperature = obsInfo.temperature.to_value( "deg_C", astropy.units.temperature()) pressure = float("nan") if obsInfo.pressure is not None: pressure = obsInfo.pressure.to_value("Pa") relative_humidity = float("nan") if obsInfo.relative_humidity is not None: relative_humidity = obsInfo.relative_humidity argDict["weather"] = Weather(temperature, pressure, relative_humidity) if obsInfo.location is not None: geolocation = obsInfo.location.to_geodetic() argDict["observatory"] = Observatory( geolocation.lon.degree * degrees, geolocation.lat.degree * degrees, geolocation.height.to_value("m")) for key in list( argDict.keys()): # use a copy because we may delete items if argDict[key] is None: if log is not None: log.warn("argDict[%s] is None; stripping", key) del argDict[key] return VisitInfo(**argDict)
def makeVisitInfo( exposureId=0, exposureTime=nanFloat, darkTime=nanFloat, date=DateTime(), ut1=nanFloat, era=nanAngle, boresightRaDec=IcrsCoord(nanAngle, nanAngle), boresightAzAlt=Coord(nanAngle, nanAngle), boresightAirmass=nanFloat, boresightRotAngle=nanAngle, rotType=RotType_UNKNOWN, observatory=Observatory(nanAngle, nanAngle, nanFloat), weather=Weather(nanFloat, nanFloat, nanFloat), ): """Make a VisitInfo from keyword arguments This function will be replaced by a VisitInfo constructor once we switch to pybind11 (it is too much hassle with SWIG). @param[in] exposureId exposure ID (int, defaults to 0) @param[in] exposureTime exposure duration (shutter open time); (float, sec, defaults to NaN) @param[in] darkTime time from CCD flush to readout, including shutter open time (despite the name); (float, sec, defaults to NaN) @param[in] date TAI (international atomic time) MJD date at middle of exposure (lsst.daf.base.DateTime; defaults to date of unix epoch) @param[in] ut1 UT1 (universal time) MJD date at middle of exposure (float, defaults to Nan) @param[in] era earth rotation angle at middle of exposure (lsst.afw.geom.Angle, defaults to Angle(Nan)) @param[in] boresightRaDec ICRS RA/Dec of boresight at middle of exposure (lsst.afw.coord.IcrsCoord; defaults to IcrsCoord(Nan, Nan)); other Coord types are accepted and converted to Icrs @param[in] boresightAzAlt refracted apparent topocentric Az/Alt of boresight at middle of exposure; (lsst.afw.coord.Coord; defaults to Coord(Nan, Nan)) @param[in] boresightAirmass airmass at the boresight, relative to zenith at sea level (float, defaults to Nan) @param[in] boresightRotAngle rotation angle at boresight at middle of exposure; see getBoresightRotAngle for details (lsst.afw.geom.Angle, defaults to Angle(Nan)) @param[in] rotType rotation type; one of the lsst.afw.image.RotType_ constants, defaults to RotType_UNKNOWN @param[in] observatory observatory longitude, latitude and altitude, (lsst.afw.coord.Observatory, defaults to Observatory(Angle(Nan), Angle(Nan), Nan)) @param[in] weather basic weather information for computing air mass, (lsst.afw.coord.Weather, defaults to Weather(NaN, NaN, NaN)) """ return VisitInfo( exposureId, exposureTime, darkTime, date, ut1, era, boresightRaDec.toIcrs(), boresightAzAlt, boresightAirmass, boresightRotAngle, rotType, observatory, weather, )