def __call__(self, md, exposureId): """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 (except TIMESYS, because it may apply to other keywords). exposureId : `int` exposure ID Notes ----- The basic implementation sets `date` and `exposureTime` using typical values found in FITS files and logs a warning if neither can be set. """ argDict = dict(exposureId=exposureId) self.setArgDict(md, argDict) 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 testMultiPlaneFitsReaders(self): """Run tests for MaskedImageFitsReader and ExposureFitsReader. """ metadata = PropertyList() metadata.add("FIVE", 5) metadata.add("SIX", 6.0) wcs = makeSkyWcs(Point2D(2.5, 3.75), SpherePoint(40.0 * degrees, 50.0 * degrees), np.array([[1E-5, 0.0], [0.0, -1E-5]])) defineFilter("test_readers_filter", lambdaEff=470.0) calib = PhotoCalib(2.5E4) psf = GaussianPsf(21, 21, 8.0) polygon = Polygon(Box2D(self.bbox)) apCorrMap = ApCorrMap() visitInfo = VisitInfo(exposureTime=5.0) transmissionCurve = TransmissionCurve.makeIdentity() coaddInputs = CoaddInputs(ExposureTable.makeMinimalSchema(), ExposureTable.makeMinimalSchema()) detector = DetectorWrapper().detector record = coaddInputs.ccds.addNew() record.setWcs(wcs) record.setPhotoCalib(calib) record.setPsf(psf) record.setValidPolygon(polygon) record.setApCorrMap(apCorrMap) record.setVisitInfo(visitInfo) record.setTransmissionCurve(transmissionCurve) record.setDetector(detector) for n, dtypeIn in enumerate(self.dtypes): with self.subTest(dtypeIn=dtypeIn): exposureIn = Exposure(self.bbox, dtype=dtypeIn) shape = exposureIn.image.array.shape exposureIn.image.array[:, :] = np.random.randint(low=1, high=5, size=shape) exposureIn.mask.array[:, :] = np.random.randint(low=1, high=5, size=shape) exposureIn.variance.array[:, :] = np.random.randint(low=1, high=5, size=shape) exposureIn.setMetadata(metadata) exposureIn.setWcs(wcs) exposureIn.setFilter(Filter("test_readers_filter")) exposureIn.setFilterLabel( FilterLabel(physical="test_readers_filter")) exposureIn.setPhotoCalib(calib) exposureIn.setPsf(psf) exposureIn.getInfo().setValidPolygon(polygon) exposureIn.getInfo().setApCorrMap(apCorrMap) exposureIn.getInfo().setVisitInfo(visitInfo) exposureIn.getInfo().setTransmissionCurve(transmissionCurve) exposureIn.getInfo().setCoaddInputs(coaddInputs) exposureIn.setDetector(detector) with lsst.utils.tests.getTempFilePath(".fits") as fileName: exposureIn.writeFits(fileName) self.checkMaskedImageFitsReader(exposureIn, fileName, self.dtypes[n:]) self.checkExposureFitsReader(exposureIn, fileName, self.dtypes[n:])
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 @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, "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 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 __call__(self, md, exposureId): """Construct a VisitInfo and strip associated data from the metadata @param[in,out] md metadata, as an lsst.daf.base.PropertyList or PropertySet; items that are used are stripped from the metadata (except TIMESYS, because it may apply to more than one other keyword). @param[in] exposureId exposure ID The basic implementation sets date and exposureTime using typical values found in FITS files and logs a warning if neither can be set. """ argDict = dict(exposureId=exposureId) self.setArgDict(md, argDict) 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 setUp(self): self.camera = CameraWrapper().camera self.detector = DetectorWrapper().detector self.crpix = lsst.geom.Point2D(50, 100) self.crval = lsst.geom.SpherePoint(36, 71, lsst.geom.degrees) scale = 1.0 * lsst.geom.arcseconds self.cdMatrix = afwGeom.makeCdMatrix(scale=scale) self.wcs = afwGeom.makeSkyWcs(crpix=self.crpix, crval=self.crval, cdMatrix=self.cdMatrix) self.bbox = lsst.geom.Box2I(lsst.geom.Point2I(-10, 10), lsst.geom.Extent2I(1000, 1022)) self.exposure = ExposureF(self.bbox) # set the few items of ExposureInfo needed by IsrTask.run # when only adding a distortion model exposureInfo = ExposureInfo(photoCalib=PhotoCalib(1.0), detector=self.detector, visitInfo=VisitInfo(exposureTime=1.0), wcs=self.wcs) self.exposure.setInfo(exposureInfo)
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 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 setUp(self): """Constructs a CCD with two amplifiers and prepares for ISR""" np.random.seed(12345) baseValue = 100.0 gain = 1.0 readNoise = 123456789.0 saturation = 987654321.0 height = 234 imageSize = Extent2I(123, height) overscanSize = Extent2I(16, height) self.sigma = 1.234 # Set up the various regions overscan1 = Box2I(Point2I(0, 0), overscanSize) image1 = Box2I(Point2I(overscanSize[0], 0), imageSize) image2 = Box2I(Point2I(overscanSize[0] + imageSize[0], 0), imageSize) overscan2 = Box2I(Point2I(overscanSize[0] + 2 * imageSize[0], 0), overscanSize) leftBox = Box2I( overscan1.getMin(), Extent2I(overscan1.getWidth() + image1.getWidth(), height)) rightBox = Box2I( image2.getMin(), Extent2I(image2.getWidth() + overscan2.getWidth(), height)) target1 = Box2I(Point2I(0, 0), imageSize) target2 = Box2I(Point2I(image1.getWidth(), 0), imageSize) # Set the pixels exposure = ExposureF( Box2I(Point2I(0, 0), Extent2I(imageSize[0] * 2 + overscanSize[0] * 2, height))) yy = np.arange(0, height, 1, dtype=np.float32) leftImage = ExposureF(exposure, leftBox) leftImage.image.array[:] = baseValue + yy[:, np.newaxis] rightImage = ExposureF(exposure, rightBox) rightImage.image.array[:] = baseValue - yy[:, np.newaxis] leftOverscan = ExposureF(exposure, overscan1) leftOverscan.image.array += np.random.normal( 0.0, self.sigma, leftOverscan.image.array.shape) rightOverscan = ExposureF(exposure, overscan2) rightOverscan.image.array += np.random.normal( 0.0, self.sigma, leftOverscan.image.array.shape) exposure.mask.array[:] = 0.0 exposure.variance.array[:] = np.nan # Construct the detectors amp1 = makeAmplifier("left", target1, image1, overscan1, gain, readNoise, saturation) amp2 = makeAmplifier("right", target2, image2, overscan2, gain, readNoise, saturation) ccdBox = Box2I(Point2I(0, 0), Extent2I(image1.getWidth() + image2.getWidth(), height)) camBuilder = cameraGeom.Camera.Builder("fakeCam") detBuilder = camBuilder.add("detector", 1) detBuilder.setSerial("det1") detBuilder.setBBox(ccdBox) detBuilder.setPixelSize(Extent2D(1.0, 1.0)) detBuilder.setOrientation(cameraGeom.Orientation()) detBuilder.append(amp1) detBuilder.append(amp2) cam = camBuilder.finish() exposure.setDetector(cam.get('detector')) header = PropertyList() header.add("EXPTIME", 0.0) exposure.getInfo().setVisitInfo(VisitInfo(header)) self.exposure = exposure self.config = IsrTask.ConfigClass() # Disable everything we don't care about self.config.doBias = False self.config.doDark = False self.config.doFlat = False self.config.doFringe = False self.config.doDefect = False self.config.doWrite = False self.config.expectWcs = False self.config.doLinearize = False self.config.doCrosstalk = False self.config.doBrighterFatter = False self.config.doAttachTransmissionCurve = False self.config.doAssembleCcd = False self.config.doNanMasking = False self.config.doInterpolate = False self.config.maskNegativeVariance = False # This runs on mocks. # Set the things that match our test setup self.config.overscan.fitType = "CHEB" self.config.overscan.order = 1 self.config.doEmpiricalReadNoise = True self.task = IsrTask(config=self.config)
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)