def writeFcr(self, dataRefList): self.log.info("Write Fcr ...") M_LN10 = math.log(10) dmag = list() for m in self.matchVec: if (m.good == True and m.mag != -9999 and m.jstar != -1 and m.mag0 != -9999 and m.mag_cat != -9999): mag = m.mag mag_cat = m.mag_cat exp_cor = -2.5*math.log10(self.fexp[m.iexp]) chip_cor = -2.5*math.log10(self.fchip[m.ichip]) gain_cor = self.ffpSet[m.iexp].eval(m.u, m.v) mag_cor = mag + exp_cor + chip_cor + gain_cor dmag.append(mag_cor - mag_cat) std, mean, n = mosaicUtils.clippedStd(numpy.array(dmag), 2.1) for dataRef in dataRefList: iexp = dataRef.dataId["visit"] ichip = dataRef.dataId["ccd"] try: x0 = self.coeffSet[iexp].x0 y0 = self.coeffSet[iexp].y0 except: x0 = 0.0 y0 = 0.0 newP = measMosaic.convertFluxFitParams(measMosaic.FluxFitParams(self.ffpSet[iexp]), self.ccdSet[ichip], x0, y0) metadata = measMosaic.metadataFromFluxFitParams(newP) exp = afwImage.ExposureI(0,0) exp.getMetadata().combine(metadata) scale = self.fexp[iexp]*self.fchip[ichip] constantPhotoCalib = afwImage.makePhotoCalibFromCalibZeroPoint(1.0/scale, 1.0/scale*std*M_LN10*0.4) exp.setPhotoCalib(constantPhotoCalib) try: dataRef.put(exp, "fcr") except Exception as e: print("failed to write fcr: %s" % (e)) # Write the flux fit (including Jacobian) as a PhotoCalib for # future compatibility with jointcal. This is redundant with # the above, and should eventually supercede it. detector = dataRef.get("camera")[dataRef.dataId["ccd"]] nQuarter = detector.getOrientation().getNQuarter() bbox = detector.getBBox() try: # Reading the Wcs we just wrote obviously isn't efficient, but # it should be in the noise of the overall runtime and it # saves us from doing a bunch of refactoring in a fragile # package with no tests. wcs = dataRef.get("jointcal_wcs") except Exception as e: print("failed to read Wcs for PhotoCalib: %s" % (e)) continue bf = measMosaic.FluxFitBoundedField(bbox, newP, wcs, zeroPoint=constantPhotoCalib.getInstFluxAtZeroMagnitude(), nQuarter=nQuarter) varyingPhotoCalib = afwImage.PhotoCalib(constantPhotoCalib.getCalibrationMean(), constantPhotoCalib.getCalibrationErr(), bf, isConstant=False) dataRef.put(varyingPhotoCalib, "jointcal_photoCalib")
def _getConstantPhotoCalib(self, zeropoint, err, offset, scaling): """ Get the PhotoCalib object from a constant zeropoint. Parameters ---------- zeropoint: `float` Zeropoint value (mag) err: `float` Error on zeropoint offset: `float` Absolute calibration offset scaling: `float` Flat scaling value from fgcmBuildStars Returns ------- photoCalib: `afwImage.PhotoCalib` """ # Take the zeropoint, apply the absolute relative calibration offset, # and whatever flat-field scaling was applied calibMean = ( (zeropoint + offset) * units.ABmag).to_value(units.nJy) * scaling calibErr = (np.log(10.) / 2.5) * calibMean * err photoCalib = afwImage.PhotoCalib(calibMean, calibErr) return photoCalib
def setUp(self): super().setUp() afwImage.Filter.reset() afwImage.FilterProperty.reset() defineFilter("g", 470.0) self.wcs = afwGeom.makeSkyWcs( lsst.geom.Point2D(0.0, 0.0), lsst.geom.SpherePoint(2.0, 34.0, lsst.geom.degrees), np.identity(2), ) self.photoCalib = afwImage.PhotoCalib(1.5) self.psf = DummyPsf(2.0) self.detector = DetectorWrapper().detector self.summaryStats = afwImage.ExposureSummaryStats(ra=100.0) self.polygon = afwGeom.Polygon( lsst.geom.Box2D(lsst.geom.Point2D(0.0, 0.0), lsst.geom.Point2D(25.0, 20.0))) self.coaddInputs = afwImage.CoaddInputs() self.apCorrMap = afwImage.ApCorrMap() self.transmissionCurve = afwImage.TransmissionCurve.makeIdentity() self.exposureInfo = afwImage.ExposureInfo() gFilter = afwImage.Filter("g") gFilterLabel = afwImage.FilterLabel(band="g") self.exposureInfo.setFilter(gFilter) self.exposureInfo.setFilterLabel(gFilterLabel)
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 testReadWriteFits(self): """Test readFits and writeFits. """ # This should pass without an exception mainExposure = afwImage.ExposureF(inFilePathSmall) mainExposure.setDetector(self.detector) subBBox = lsst.geom.Box2I(lsst.geom.Point2I(10, 10), lsst.geom.Extent2I(40, 50)) subExposure = mainExposure.Factory(mainExposure, subBBox, afwImage.LOCAL) self.checkWcs(mainExposure, subExposure) det = subExposure.getDetector() self.assertTrue(det) subExposure = afwImage.ExposureF(inFilePathSmall, subBBox, afwImage.LOCAL) self.checkWcs(mainExposure, subExposure) # This should throw an exception def getExposure(): afwImage.ExposureF(inFilePathSmallImage) self.assertRaises(FitsError, getExposure) mainExposure.setPsf(self.psf) # Make sure we can write without an exception photoCalib = afwImage.PhotoCalib(1e-10, 1e-12) mainExposure.setPhotoCalib(photoCalib) mainInfo = mainExposure.getInfo() for key, value in self.extras.items(): mainInfo.setComponent(key, value) with lsst.utils.tests.getTempFilePath(".fits") as tmpFile: mainExposure.writeFits(tmpFile) readExposure = type(mainExposure)(tmpFile) # # Check the round-tripping # self.assertEqual(mainExposure.getFilter().getName(), readExposure.getFilter().getName()) self.assertIsNotNone(mainExposure.getFilterLabel()) self.assertEqual(mainExposure.getFilterLabel(), readExposure.getFilterLabel()) self.assertEqual(photoCalib, readExposure.getPhotoCalib()) readInfo = readExposure.getInfo() for key, value in self.extras.items(): self.assertEqual(value, readInfo.getComponent(key)) psf = readExposure.getPsf() self.assertIsNotNone(psf) self.assertEqual(psf, self.psf)
def getCalibratedExposure(self, dataRef, bgSubtracted): """Return one calibrated Exposure, possibly with an updated SkyWcs. @param[in] dataRef a sensor-level data reference @param[in] bgSubtracted return calexp with background subtracted? If False get the calexp's background background model and add it to the calexp. @return calibrated exposure @raises MissingExposureError If data for the exposure is not available. If config.doApplyUberCal, the exposure will be photometrically calibrated via the `jointcal_photoCalib` dataset and have its SkyWcs updated to the `jointcal_wcs`, otherwise it will be calibrated via the Exposure's own PhotoCalib and have the original SkyWcs. """ try: exposure = dataRef.get(self.calexpType, immediate=True) except dafPersist.NoResults as e: raise MissingExposureError('Exposure not found: %s ' % str(e)) from e if not bgSubtracted: background = dataRef.get("calexpBackground", immediate=True) mi = exposure.getMaskedImage() mi += background.getImage() del mi if self.config.doApplyUberCal: if self.config.useMeasMosaic: from lsst.meas.mosaic import applyMosaicResultsExposure # NOTE: this changes exposure in-place, updating its Calib and Wcs. # Save the calibration error, as it gets overwritten with zero. calibrationErr = exposure.getPhotoCalib().getCalibrationErr() try: applyMosaicResultsExposure(dataRef, calexp=exposure) except dafPersist.NoResults as e: raise MissingExposureError( 'Mosaic calibration not found: %s ' % str(e)) from e photoCalib = afwImage.PhotoCalib( exposure.getPhotoCalib().getCalibrationMean(), calibrationErr, exposure.getBBox()) else: photoCalib = dataRef.get("jointcal_photoCalib") skyWcs = dataRef.get("jointcal_wcs") exposure.setWcs(skyWcs) else: photoCalib = exposure.getPhotoCalib() exposure.maskedImage = photoCalib.calibrateImage( exposure.maskedImage, includeScaleUncertainty=self.config.includeCalibVar) exposure.maskedImage /= photoCalib.getCalibrationMean() exposure.setPhotoCalib(photoCalib) # TODO: The images will have a calibration of 1.0 everywhere once RFC-545 is implemented. # exposure.setCalib(afwImage.Calib(1.0)) return exposure
def testNullWarpExposure(self, interpLength=10): """Test that warpExposure maps an image onto itself. Note: - NO_DATA and off-CCD pixels must be ignored - bad mask pixels get smeared out so we have to excluded all bad mask pixels from the output image when comparing masks. """ imageUtils.defineFilter("i", 748.1) originalExposure = afwImage.ExposureF(originalExposurePath) originalExposure.getInfo().setVisitInfo(makeVisitInfo()) originalFilter = afwImage.Filter("i") originalPhotoCalib = afwImage.PhotoCalib(1.0e5, 1.0e3) originalExposure.setFilter(originalFilter) originalExposure.setPhotoCalib(originalPhotoCalib) afwWarpedExposure = afwImage.ExposureF(originalExposure.getBBox(), originalExposure.getWcs()) warpingControl = afwMath.WarpingControl("lanczos4", "", 0, interpLength) afwMath.warpExposure(afwWarpedExposure, originalExposure, warpingControl) if SAVE_FITS_FILES: afwWarpedExposure.writeFits("afwWarpedExposureNull.fits") self.assertEqual(afwWarpedExposure.getFilter().getName(), originalFilter.getName()) self.assertEqual(afwWarpedExposure.getPhotoCalib(), originalPhotoCalib) self.assertEqual(afwWarpedExposure.getInfo().getVisitInfo(), originalExposure.getInfo().getVisitInfo()) afwWarpedMaskedImage = afwWarpedExposure.getMaskedImage() afwWarpedMask = afwWarpedMaskedImage.getMask() noDataBitMask = afwWarpedMask.getPlaneBitMask("NO_DATA") afwWarpedMaskedImageArrSet = afwWarpedMaskedImage.getArrays() afwWarpedMaskArr = afwWarpedMaskedImageArrSet[1] # compare all non-DATA pixels of image and variance, but relax specs a bit # because of minor noise introduced by bad pixels noDataMaskArr = afwWarpedMaskArr & noDataBitMask msg = "afw null-warped MaskedImage (all pixels, relaxed tolerance)" self.assertMaskedImagesAlmostEqual(afwWarpedMaskedImage, originalExposure.getMaskedImage(), doMask=False, skipMask=noDataMaskArr, atol=1e-5, msg=msg) # compare good pixels (mask=0) of image, mask and variance using full # tolerance msg = "afw null-warped MaskedImage (good pixels, max tolerance)" self.assertMaskedImagesAlmostEqual(afwWarpedMaskedImage, originalExposure.getMaskedImage(), skipMask=afwWarpedMask, msg=msg)
def _build_ccdImage(self, dataRef, associations, jointcalControl): """ Extract the necessary things from this dataRef to add a new ccdImage. Parameters ---------- dataRef : lsst.daf.persistence.ButlerDataRef dataRef to extract info from. associations : lsst.jointcal.Associations object to add the info to, to construct a new CcdImage jointcalControl : jointcal.JointcalControl control object for associations management Returns ------ namedtuple wcs : lsst.afw.image.TanWcs the TAN WCS of this image, read from the calexp key : namedtuple a key to identify this dataRef by its visit and ccd ids filter : str this calexp's filter """ visit = dataRef.dataId["visit"] src = dataRef.get("src", flags=lsst.afw.table.SOURCE_IO_NO_FOOTPRINTS, immediate=True) calexp = dataRef.get("calexp", immediate=True) visitInfo = calexp.getInfo().getVisitInfo() ccdname = calexp.getDetector().getId() calib = calexp.getCalib() tanWcs = calexp.getWcs() bbox = calexp.getBBox() filt = calexp.getInfo().getFilter().getName() fluxMag0 = calib.getFluxMag0() photoCalib = afwImage.PhotoCalib(fluxMag0[0], fluxMag0[1], bbox) goodSrc = self.sourceSelector.selectSources(src) if len(goodSrc.sourceCat) == 0: self.log.warn("no stars selected in ", visit, ccdname) return tanWcs self.log.info("%d stars selected in visit %d ccd %d", len(goodSrc.sourceCat), visit, ccdname) associations.addImage(goodSrc.sourceCat, tanWcs, visitInfo, bbox, filt, photoCalib, visit, ccdname, jointcalControl) Result = collections.namedtuple('Result_from_build_CcdImage', ('wcs', 'key', 'filter')) Key = collections.namedtuple('Key', ('visit', 'ccd')) return Result(tanWcs, Key(visit, ccdname), filt)
def testApplyCppTransform(self): """Test that we can apply a simple C++ transform. """ inCat = self._generateCatalog() sillyControl = testLib.SillyCentroidControl() mapper = afwTable.SchemaMapper(inCat.schema) sillyTransform = testLib.SillyTransform(sillyControl, self.pluginName, mapper) outCat = afwTable.BaseCatalog(mapper.getOutputSchema()) outCat.extend(inCat, mapper=mapper) self.assertEqual(len(inCat), len(outCat)) sillyTransform(inCat, outCat, makeWcs(), afwImage.PhotoCalib()) self._checkSillyOutputs(inCat, outCat)
def testSetMembers(self): """ Test that the MaskedImage and the WCS of an Exposure can be set. """ exposure = afwImage.ExposureF() maskedImage = afwImage.MaskedImageF(inFilePathSmall) exposure.setMaskedImage(maskedImage) exposure.setWcs(self.wcs) exposure.setDetector(self.detector) exposure.setFilter(afwImage.Filter("g")) exposure.setFilterLabel(afwImage.FilterLabel(band="g")) self.assertEqual(exposure.getDetector().getName(), self.detector.getName()) self.assertEqual(exposure.getDetector().getSerial(), self.detector.getSerial()) self.assertEqual(exposure.getFilter().getName(), "g") self.assertEqual(exposure.getFilterLabel().bandLabel, "g") self.assertEqual(exposure.getWcs(), self.wcs) # The PhotoCalib tests are in test_photoCalib.py; # here we just check that it's gettable and settable. self.assertIsNone(exposure.getPhotoCalib()) photoCalib = afwImage.PhotoCalib(511.1, 44.4) exposure.setPhotoCalib(photoCalib) self.assertEqual(exposure.getPhotoCalib(), photoCalib) # Psfs next self.assertFalse(exposure.hasPsf()) exposure.setPsf(self.psf) self.assertTrue(exposure.hasPsf()) exposure.setPsf(DummyPsf(1.0)) # we can reset the Psf # extras next info = exposure.getInfo() for key, value in self.extras.items(): self.assertFalse(info.hasComponent(key)) self.assertIsNone(info.getComponent(key)) info.setComponent(key, value) self.assertTrue(info.hasComponent(key)) self.assertEqual(info.getComponent(key), value) info.removeComponent(key) self.assertFalse(info.hasComponent(key)) # Test that we can set the MaskedImage and WCS of an Exposure # that already has both self.exposureMiWcs.setMaskedImage(maskedImage) exposure.setWcs(self.wcs)
def setUp(self): # CFHT Filters from the camera mapper. afwImageUtils.resetFilters() afwImageUtils.defineFilter('u', lambdaEff=374, alias="u.MP9301") afwImageUtils.defineFilter('g', lambdaEff=487, alias="g.MP9401") afwImageUtils.defineFilter('r', lambdaEff=628, alias="r.MP9601") afwImageUtils.defineFilter('i', lambdaEff=778, alias="i.MP9701") afwImageUtils.defineFilter('z', lambdaEff=1170, alias="z.MP9801") self.metadata = dafBase.PropertySet() self.metadata.set("SIMPLE", "T") self.metadata.set("BITPIX", -32) self.metadata.set("NAXIS", 2) self.metadata.set("NAXIS1", 1024) self.metadata.set("NAXIS2", 1153) self.metadata.set("RADECSYS", 'FK5') self.metadata.set("EQUINOX", 2000.) self.metadata.setDouble("CRVAL1", 215.604025685476) self.metadata.setDouble("CRVAL2", 53.1595451514076) self.metadata.setDouble("CRPIX1", 1109.99981456774) self.metadata.setDouble("CRPIX2", 560.018167811613) self.metadata.set("CTYPE1", 'RA---SIN') self.metadata.set("CTYPE2", 'DEC--SIN') self.metadata.setDouble("CD1_1", 5.10808596133527E-05) self.metadata.setDouble("CD1_2", 1.85579539217196E-07) self.metadata.setDouble("CD2_2", -5.10281493481982E-05) self.metadata.setDouble("CD2_1", -8.27440751733828E-07) self.wcs = afwGeom.makeSkyWcs(self.metadata) self.exposure = afwImage.makeExposure( afwImage.makeMaskedImageFromArrays(np.ones((1024, 1153))), self.wcs) detector = DetectorWrapper(id=23, bbox=self.exposure.getBBox()).detector visit = afwImage.VisitInfo(exposureId=4321, exposureTime=200., date=dafBase.DateTime(nsecs=1400000000 * 10**9)) self.exposure.setDetector(detector) self.exposure.getInfo().setVisitInfo(visit) self.exposure.setFilter(afwImage.Filter('g')) scale = 2 scaleErr = 1 self.photoCalib = afwImage.PhotoCalib(scale, scaleErr) self.exposure.setPhotoCalib(self.photoCalib) self.inputCatalogNoFlags = make_input_source_catalog(10, False) self.inputCatalog = make_input_source_catalog(10, True)
def setUp(self): self.dataDir = os.path.join(os.path.split(__file__)[0], "data") # Check the values below against what was written by comparing with # the code in `afw/tests/data/makeTestExposure.py` nx = ny = 10 image = afwImage.ImageF(np.arange(nx*ny, dtype='f').reshape(nx, ny)) variance = afwImage.ImageF(np.ones((nx, ny), dtype='f')) mask = afwImage.MaskX(nx, ny) mask.array[5, 5] = 5 self.maskedImage = afwImage.MaskedImageF(image, mask, variance) self.v0PhotoCalib = afwImage.makePhotoCalibFromCalibZeroPoint(1e6, 2e4) self.v1PhotoCalib = afwImage.PhotoCalib(1e6, 2e4)
def setUp(self): '''Create two calibs, one with a valid zero-point and one without. Use these to create two UnitSystem objects. ''' self.mag2Flux = lambda m: 10.0**(m/2.5) self.flux2Mag = lambda f: 2.5*np.log10(f) photoCalibNoZero = afwImage.PhotoCalib() photoCalibWithZero = afwImage.makePhotoCalibFromCalibZeroPoint(self.mag2Flux(25)) scale = 0.2 * geom.arcseconds wcs = afwGeom.makeSkyWcs(crpix=geom.Point2D(), crval=geom.SpherePoint(45.0, 45.0, geom.degrees), cdMatrix=afwGeom.makeCdMatrix(scale=scale)) self.unitNoZero = measModel.UnitSystem(wcs, photoCalibNoZero) self.unitWithZero = measModel.UnitSystem(wcs, photoCalibWithZero)
def testBBox(self): """Test that the default bounding box includes all warped pixels """ kernelName = "lanczos2" warper = afwMath.Warper(kernelName) originalExposure, swarpedImage, swarpedWcs = self.getSwarpedImage( kernelName=kernelName, useSubregion=True, useDeepCopy=False) imageUtils.defineFilter("i", 748.1) originalFilter = afwImage.Filter("i") originalPhotoCalib = afwImage.PhotoCalib(1.0e5, 1.0e3) originalExposure.setFilter(originalFilter) originalExposure.setPhotoCalib(originalPhotoCalib) warpedExposure1 = warper.warpExposure(destWcs=swarpedWcs, srcExposure=originalExposure) # the default size must include all good pixels, so growing the bbox # should not add any warpedExposure2 = warper.warpExposure(destWcs=swarpedWcs, srcExposure=originalExposure, border=1) # a bit of excess border is allowed, but surely not as much as 10 (in # fact it is approx. 5) warpedExposure3 = warper.warpExposure(destWcs=swarpedWcs, srcExposure=originalExposure, border=-10) # assert that warpedExposure and warpedExposure2 have the same number of non-no_data pixels # and that warpedExposure3 has fewer noDataBitMask = afwImage.Mask.getPlaneBitMask("NO_DATA") mask1Arr = warpedExposure1.getMaskedImage().getMask().getArray() mask2Arr = warpedExposure2.getMaskedImage().getMask().getArray() mask3Arr = warpedExposure3.getMaskedImage().getMask().getArray() nGood1 = (mask1Arr & noDataBitMask == 0).sum() nGood2 = (mask2Arr & noDataBitMask == 0).sum() nGood3 = (mask3Arr & noDataBitMask == 0).sum() self.assertEqual(nGood1, nGood2) self.assertLess(nGood3, nGood1) self.assertEqual(warpedExposure1.getFilter().getName(), originalFilter.getName()) self.assertEqual(warpedExposure1.getPhotoCalib(), originalPhotoCalib)
def _getChebyshevPhotoCalib(self, coefficients, err, xyMax, offset, scaling): """ Get the PhotoCalib object from a chebyshev polynomial zeropoint. Parameters ---------- coefficients: `np.array` Flattened array of chebyshev coefficients err: `float` Error on zeropoint xyMax: `list` of length 2 Maximum x and y of the chebyshev bounding box offset: `float` Absolute calibration offset scaling: `float` Flat scaling value from fgcmBuildStars Returns ------- photoCalib: `afwImage.PhotoCalib` """ orderPlus1 = self.chebyshevOrder + 1 pars = np.zeros((orderPlus1, orderPlus1)) bbox = lsst.geom.Box2I(lsst.geom.Point2I(0.0, 0.0), lsst.geom.Point2I(*xyMax)) # Take the zeropoint, apply the absolute relative calibration offset, # and whatever flat-field scaling was applied pars[:, :] = (coefficients.reshape(orderPlus1, orderPlus1) * (offset * units.ABmag).to_value(units.nJy) * scaling) field = afwMath.ChebyshevBoundedField(bbox, pars) calibMean = field.mean() calibErr = (np.log(10.) / 2.5) * calibMean * err photoCalib = afwImage.PhotoCalib(field, calibErr) return photoCalib
def setUp(self): # CFHT Filters from the camera mapper. self.filter_names = ["u", "g", "r", "i", "z"] afwImageUtils.resetFilters() afwImageUtils.defineFilter('u', lambdaEff=374, alias="u.MP9301") afwImageUtils.defineFilter('g', lambdaEff=487, alias="g.MP9401") afwImageUtils.defineFilter('r', lambdaEff=628, alias="r.MP9601") afwImageUtils.defineFilter('i', lambdaEff=778, alias="i.MP9701") afwImageUtils.defineFilter('z', lambdaEff=1170, alias="z.MP9801") # metadata taken from CFHT data # v695856-e0/v695856-e0-c000-a00.sci_img.fits self.metadata = dafBase.PropertySet() self.metadata.set("SIMPLE", "T") self.metadata.set("BITPIX", -32) self.metadata.set("NAXIS", 2) self.metadata.set("NAXIS1", 1024) self.metadata.set("NAXIS2", 1153) self.metadata.set("RADECSYS", 'FK5') self.metadata.set("EQUINOX", 2000.) self.metadata.setDouble("CRVAL1", 215.604025685476) self.metadata.setDouble("CRVAL2", 53.1595451514076) self.metadata.setDouble("CRPIX1", 1109.99981456774) self.metadata.setDouble("CRPIX2", 560.018167811613) self.metadata.set("CTYPE1", 'RA---SIN') self.metadata.set("CTYPE2", 'DEC--SIN') self.metadata.setDouble("CD1_1", 5.10808596133527E-05) self.metadata.setDouble("CD1_2", 1.85579539217196E-07) self.metadata.setDouble("CD2_2", -5.10281493481982E-05) self.metadata.setDouble("CD2_1", -8.27440751733828E-07) self.wcs = afwGeom.makeSkyWcs(self.metadata) self.calibration = 10000 self.calibrationErr = 100 self.exposureId = 1234 self.exposureTime = 200. self.imageSize = [1024, 1153] self.dateTime = "2014-05-13T17:00:00.000000000" # Make images with one source in them and distinct values and # variance for each image. # Direct Image source_image = afwImage.MaskedImageF( lsst.geom.ExtentI(self.imageSize[0] + 1, self.imageSize[1] + 1)) source_image.image[100, 100, afwImage.LOCAL] = 10 source_image.getVariance().set(1) bbox = lsst.geom.BoxI( lsst.geom.PointI(1, 1), lsst.geom.ExtentI(self.imageSize[0], self.imageSize[1])) masked_image = afwImage.MaskedImageF(source_image, bbox, afwImage.LOCAL) self.exposure = afwImage.makeExposure(masked_image, self.wcs) detector = DetectorWrapper( id=23, bbox=self.exposure.getBBox()).detector visit = afwImage.VisitInfo( exposureId=self.exposureId, exposureTime=self.exposureTime, date=dafBase.DateTime(self.dateTime, dafBase.DateTime.Timescale.TAI)) self.exposure.setDetector(detector) self.exposure.getInfo().setVisitInfo(visit) self.exposure.setFilter(afwImage.Filter('g')) self.exposure.setPhotoCalib(afwImage.PhotoCalib(self.calibration, self.calibrationErr)) # Difference Image source_image = afwImage.MaskedImageF( lsst.geom.ExtentI(self.imageSize[0] + 1, self.imageSize[1] + 1)) source_image.image[100, 100, afwImage.LOCAL] = 20 source_image.getVariance().set(2) bbox = lsst.geom.BoxI( lsst.geom.PointI(1, 1), lsst.geom.ExtentI(self.imageSize[0], self.imageSize[1])) masked_image = afwImage.MaskedImageF(source_image, bbox, afwImage.LOCAL) self.diffim = afwImage.makeExposure(masked_image, self.wcs) self.diffim.setDetector(detector) self.diffim.getInfo().setVisitInfo(visit) self.diffim.setFilter(afwImage.Filter('g')) self.diffim.setPhotoCalib(afwImage.PhotoCalib(self.calibration, self.calibrationErr)) self.expIdBits = 16 FWHM = 5 psf = measAlg.DoubleGaussianPsf(15, 15, FWHM/(2*np.sqrt(2*np.log(2)))) self.exposure.setPsf(psf) self.diffim.setPsf(psf) self.testDiaObjects = create_test_dia_objects(5, self.wcs)
def _outputZeropoints(self, camera, zptCat, visitCat, offsets, bands, physicalFilterMap, tract=None): """Output the zeropoints in fgcm_photoCalib format. Parameters ---------- camera : `lsst.afw.cameraGeom.Camera` Camera from the butler. zptCat : `lsst.afw.table.BaseCatalog` FGCM zeropoint catalog from `FgcmFitCycleTask`. visitCat : `lsst.afw.table.BaseCatalog` FGCM visitCat from `FgcmBuildStarsTask`. offsets : `numpy.array` Float array of absolute calibration offsets, one for each filter. bands : `list` [`str`] List of band names from FGCM output. physicalFilterMap : `dict` Dictionary of mappings from physical filter to FGCM band. tract: `int`, optional Tract number to output. Default is None (global calibration) Returns ------- photoCalibCatalogs : `generator` [(`int`, `lsst.afw.table.ExposureCatalog`)] Generator that returns (visit, exposureCatalog) tuples. """ # Select visit/ccds where we have a calibration # This includes ccds where we were able to interpolate from neighboring # ccds. cannot_compute = fgcm.fgcmUtilities.zpFlagDict[ 'CANNOT_COMPUTE_ZEROPOINT'] selected = (((zptCat['fgcmFlag'] & cannot_compute) == 0) & (zptCat['fgcmZptVar'] > 0.0) & (zptCat['fgcmZpt'] > FGCM_ILLEGAL_VALUE)) # Log warnings for any visit which has no valid zeropoints badVisits = np.unique(zptCat['visit'][~selected]) goodVisits = np.unique(zptCat['visit'][selected]) allBadVisits = badVisits[~np.isin(badVisits, goodVisits)] for allBadVisit in allBadVisits: self.log.warning(f'No suitable photoCalib for visit {allBadVisit}') # Get a mapping from filtername to the offsets offsetMapping = {} for f in physicalFilterMap: # Not every filter in the map will necesarily have a band. if physicalFilterMap[f] in bands: offsetMapping[f] = offsets[bands.index(physicalFilterMap[f])] # Get a mapping from "ccd" to the ccd index used for the scaling ccdMapping = {} for ccdIndex, detector in enumerate(camera): ccdMapping[detector.getId()] = ccdIndex # And a mapping to get the flat-field scaling values scalingMapping = {} for rec in visitCat: scalingMapping[rec['visit']] = rec['scaling'] if self.config.doComposeWcsJacobian: approxPixelAreaFields = computeApproxPixelAreaFields(camera) # The zptCat is sorted by visit, which is useful lastVisit = -1 zptVisitCatalog = None metadata = dafBase.PropertyList() metadata.add("COMMENT", "Catalog id is detector id, sorted.") metadata.add("COMMENT", "Only detectors with data have entries.") for rec in zptCat[selected]: # Retrieve overall scaling scaling = scalingMapping[rec['visit']][ccdMapping[rec['detector']]] # The postCalibrationOffset describe any zeropoint offsets # to apply after the fgcm calibration. The first part comes # from the reference catalog match (used in testing). The # second part comes from the mean chromatic correction # (if configured). postCalibrationOffset = offsetMapping[rec['filtername']] if self.config.doApplyMeanChromaticCorrection: postCalibrationOffset += rec['fgcmDeltaChrom'] fgcmSuperStarField = self._getChebyshevBoundedField( rec['fgcmfZptSstarCheb'], rec['fgcmfZptChebXyMax']) # Convert from FGCM AB to nJy fgcmZptField = self._getChebyshevBoundedField( (rec['fgcmfZptCheb'] * units.AB).to_value(units.nJy), rec['fgcmfZptChebXyMax'], offset=postCalibrationOffset, scaling=scaling) if self.config.doComposeWcsJacobian: fgcmField = afwMath.ProductBoundedField([ approxPixelAreaFields[rec['detector']], fgcmSuperStarField, fgcmZptField ]) else: # The photoCalib is just the product of the fgcmSuperStarField and the # fgcmZptField fgcmField = afwMath.ProductBoundedField( [fgcmSuperStarField, fgcmZptField]) # The "mean" calibration will be set to the center of the ccd for reference calibCenter = fgcmField.evaluate(fgcmField.getBBox().getCenter()) calibErr = (np.log(10.0) / 2.5) * calibCenter * np.sqrt( rec['fgcmZptVar']) photoCalib = afwImage.PhotoCalib(calibrationMean=calibCenter, calibrationErr=calibErr, calibration=fgcmField, isConstant=False) # Return full per-visit exposure catalogs if rec['visit'] != lastVisit: # This is a new visit. If the last visit was not -1, yield # the ExposureCatalog if lastVisit > -1: # ensure that the detectors are in sorted order, for fast lookups zptVisitCatalog.sort() yield (int(lastVisit), zptVisitCatalog) else: # We need to create a new schema zptExpCatSchema = afwTable.ExposureTable.makeMinimalSchema( ) zptExpCatSchema.addField('visit', type='L', doc='Visit number') # And start a new one zptVisitCatalog = afwTable.ExposureCatalog(zptExpCatSchema) zptVisitCatalog.setMetadata(metadata) lastVisit = int(rec['visit']) catRecord = zptVisitCatalog.addNew() catRecord['id'] = int(rec['detector']) catRecord['visit'] = rec['visit'] catRecord.setPhotoCalib(photoCalib) # Final output of last exposure catalog # ensure that the detectors are in sorted order, for fast lookups zptVisitCatalog.sort() yield (int(lastVisit), zptVisitCatalog)
def make_exps(band_data, show=False): """ make lsst stack exposures for each image and noise image """ from lsst.afw.cameraGeom.testUtils import DetectorWrapper exps = [] psf_exps = [] byband_exps = {} byband_psf_exps = {} for band in band_data: bdata = band_data[band] byband_exps[band] = [] byband_psf_exps[band] = [] for epoch_ind, se_obs in enumerate(bdata): wcs = se_obs.wcs pos = wcs.toImage(wcs.center) # pos = wcs.center image = se_obs.image.array bmask = se_obs.bmask.array weight = se_obs.weight.array weight = se_obs.weight.array psf_gsimage, psf_offset = se_obs.get_psf( pos.x, pos.y, center_psf=False, get_offset=True, ) psf_image = psf_gsimage.array # TODO: deal with zeros w = np.where(weight > 0) assert w[0].size == weight.size noise_var = 1.0 / weight sy, sx = image.shape masked_image = afw_image.MaskedImageF(sx, sy) masked_image.image.array[:, :] = image masked_image.variance.array[:, :] = noise_var masked_image.mask.array[:, :] = bmask # an exp for the PSF # we need to put a var here that is consistent with the # main image to get a consistent coadd. I'm not sure # what the best choice is, using median for now TODO pny, pnx = psf_image.shape pmasked_image = afw_image.MaskedImageF(pny, pnx) pmasked_image.image.array[:, :] = psf_image pmasked_image.variance.array[:, :] = np.median(noise_var) pmasked_image.mask.array[:, :] = 0 exp = afw_image.ExposureF(masked_image) psf_exp = afw_image.ExposureF(pmasked_image) zperr = 0.0 calib_mean = (ZERO_POINT * units.ABmag).to_value(units.nJy) calib_err = (np.log(10.) / 2.5) * calib_mean * zperr calib = afw_image.PhotoCalib(calib_mean, calib_err) exp.setPsf(make_stack_psf(psf_image)) exp.setWcs(make_stack_wcs(wcs)) exp.setPhotoCalib(calib) psf_exp.setWcs( make_stack_psf_wcs( dims=psf_gsimage.array.shape, jac=psf_gsimage.wcs, offset=psf_offset, world_origin=wcs.center, )) detector = DetectorWrapper().detector exp.setDetector(detector) psf_exp.setDetector(detector) if show: from espy import images images.view(exp.image.array) # show_image_and_mask(exp) # input('hit a key') exps.append(exp) byband_exps[band].append(exp) psf_exps.append(psf_exp) byband_psf_exps[band].append(psf_exp) return exps, psf_exps, byband_exps, byband_psf_exps
def _outputZeropoints(self, butler, zptCat, visitCat, offsets, tract=None): """ Output the zeropoints in fgcm_photoCalib format. Parameters ---------- butler: `lsst.daf.persistence.Butler` zptCat: `lsst.afw.table.BaseCatalog` FGCM zeropoint catalog from `FgcmFitCycleTask` visitCat: `lsst.afw.table.BaseCatalog` FGCM visitCat from `FgcmBuildStarsTask` offsets: `numpy.array` Float array of absolute calibration offsets, one for each filter tract: `int`, optional Tract number to output. Default is None (global calibration) """ if tract is None: datasetType = 'fgcm_photoCalib' else: datasetType = 'fgcm_tract_photoCalib' self.log.info("Outputting %s objects" % (datasetType)) # Select visit/ccds where we have a calibration # This includes ccds where we were able to interpolate from neighboring # ccds. cannot_compute = fgcm.fgcmUtilities.zpFlagDict[ 'CANNOT_COMPUTE_ZEROPOINT'] too_few_stars = fgcm.fgcmUtilities.zpFlagDict['TOO_FEW_STARS_ON_CCD'] selected = (((zptCat['fgcmFlag'] & cannot_compute) == 0) & (zptCat['fgcmZptVar'] > 0.0)) # We also select the "best" calibrations, avoiding interpolation. These # are only used for mapping filternames selected_best = (((zptCat['fgcmFlag'] & (cannot_compute | too_few_stars)) == 0) & (zptCat['fgcmZptVar'] > 0.0)) # Log warnings for any visit which has no valid zeropoints badVisits = np.unique(zptCat['visit'][~selected]) goodVisits = np.unique(zptCat['visit'][selected]) allBadVisits = badVisits[~np.isin(badVisits, goodVisits)] for allBadVisit in allBadVisits: self.log.warn( f'No suitable photoCalib for {self.visitDataRefName} {allBadVisit}' ) # Get the mapping from filtername to dataId filter name, empirically filterMapping = {} nFound = 0 for rec in zptCat[selected_best]: if rec['filtername'] in filterMapping: continue dataId = { self.visitDataRefName: int(rec['visit']), self.ccdDataRefName: int(rec['ccd']) } dataRef = butler.dataRef('raw', dataId=dataId) filterMapping[rec['filtername']] = dataRef.dataId['filter'] nFound += 1 if nFound == len(self.filterMap): break # Get a mapping from filtername to the offsets offsetMapping = {} for f in self.filterMap: # Not every filter in the map will necesarily have a band. if self.filterMap[f] in self.bands: offsetMapping[f] = offsets[self.bands.index(self.filterMap[f])] # Get a mapping from "ccd" to the ccd index used for the scaling camera = butler.get('camera') ccdMapping = {} for ccdIndex, detector in enumerate(camera): ccdMapping[detector.getId()] = ccdIndex # And a mapping to get the flat-field scaling values scalingMapping = {} for rec in visitCat: scalingMapping[rec['visit']] = rec['scaling'] if self.config.doComposeWcsJacobian: approxPixelAreaFields = computeApproxPixelAreaFields(camera) for rec in zptCat[selected]: # Retrieve overall scaling scaling = scalingMapping[rec['visit']][ccdMapping[rec['ccd']]] # The postCalibrationOffset describe any zeropoint offsets # to apply after the fgcm calibration. The first part comes # from the reference catalog match (used in testing). The # second part comes from the mean chromatic correction # (if configured). postCalibrationOffset = offsetMapping[rec['filtername']] if self.config.doApplyMeanChromaticCorrection: postCalibrationOffset += rec['fgcmDeltaChrom'] fgcmSuperStarField = self._getChebyshevBoundedField( rec['fgcmfZptSstarCheb'], rec['fgcmfZptChebXyMax']) # Convert from FGCM AB to nJy fgcmZptField = self._getChebyshevBoundedField( (rec['fgcmfZptCheb'] * units.AB).to_value(units.nJy), rec['fgcmfZptChebXyMax'], offset=postCalibrationOffset, scaling=scaling) if self.config.doComposeWcsJacobian: fgcmField = afwMath.ProductBoundedField([ approxPixelAreaFields[rec['ccd']], fgcmSuperStarField, fgcmZptField ]) else: # The photoCalib is just the product of the fgcmSuperStarField and the # fgcmZptField fgcmField = afwMath.ProductBoundedField( [fgcmSuperStarField, fgcmZptField]) # The "mean" calibration will be set to the center of the ccd for reference calibCenter = fgcmField.evaluate(fgcmField.getBBox().getCenter()) calibErr = (np.log(10.0) / 2.5) * calibCenter * np.sqrt( rec['fgcmZptVar']) photoCalib = afwImage.PhotoCalib(calibrationMean=calibCenter, calibrationErr=calibErr, calibration=fgcmField, isConstant=False) if tract is None: butler.put(photoCalib, datasetType, dataId={ self.visitDataRefName: int(rec['visit']), self.ccdDataRefName: int(rec['ccd']), 'filter': filterMapping[rec['filtername']] }) else: butler.put(photoCalib, datasetType, dataId={ self.visitDataRefName: int(rec['visit']), self.ccdDataRefName: int(rec['ccd']), 'filter': filterMapping[rec['filtername']], 'tract': tract }) self.log.info("Done outputting %s objects" % (datasetType))
def _build_ccdImage(self, dataRef, associations, jointcalControl): """ Extract the necessary things from this dataRef to add a new ccdImage. Parameters ---------- dataRef : lsst.daf.persistence.ButlerDataRef dataRef to extract info from. associations : lsst.jointcal.Associations object to add the info to, to construct a new CcdImage jointcalControl : jointcal.JointcalControl control object for associations management Returns ------ namedtuple wcs : lsst.afw.geom.SkyWcs the TAN WCS of this image, read from the calexp key : namedtuple a key to identify this dataRef by its visit and ccd ids filter : str this calexp's filter """ if "visit" in dataRef.dataId.keys(): visit = dataRef.dataId["visit"] else: visit = dataRef.getButler().queryMetadata("calexp", ("visit"), dataRef.dataId)[0] src = dataRef.get("src", flags=lsst.afw.table.SOURCE_IO_NO_FOOTPRINTS, immediate=True) visitInfo = dataRef.get('calexp_visitInfo') detector = dataRef.get('calexp_detector') ccdId = detector.getId() calib = dataRef.get('calexp_calib') tanWcs = dataRef.get('calexp_wcs') bbox = dataRef.get('calexp_bbox') filt = dataRef.get('calexp_filter') filterName = filt.getName() fluxMag0 = calib.getFluxMag0() photoCalib = afwImage.PhotoCalib(1.0 / fluxMag0[0], fluxMag0[1] / fluxMag0[0]**2, bbox) goodSrc = self.sourceSelector.run(src) if len(goodSrc.sourceCat) == 0: self.log.warn("No sources selected in visit %s ccd %s", visit, ccdId) else: self.log.info("%d sources selected in visit %d ccd %d", len(goodSrc.sourceCat), visit, ccdId) associations.createCcdImage(goodSrc.sourceCat, tanWcs, visitInfo, bbox, filterName, photoCalib, detector, visit, ccdId, jointcalControl) Result = collections.namedtuple('Result_from_build_CcdImage', ('wcs', 'key', 'filter')) Key = collections.namedtuple('Key', ('visit', 'ccd')) return Result(tanWcs, Key(visit, ccdId), filterName)
def _outputZeropoints(self, butler, offsets): """ Output the zeropoints in jointcal_photoCalib format. Parameters ---------- butler: lsst.daf.persistence.Butler """ self.log.info("Outputting jointcal_photoCalib objects") zptCat = butler.get('fgcmZeropoints', fgcmcycle=self.useCycle) visitCat = butler.get('fgcmVisitCatalog') # Only output those that we have a calibration selected = (zptCat['fgcmflag'] < 16) # Get the mapping from filtername to dataId filter name filterMapping = {} nFound = 0 for rec in zptCat[selected]: if rec['filtername'] in filterMapping: continue dataId = { self.visitDataRefName: int(rec['visit']), self.ccdDataRefName: int(rec['ccd']) } dataRef = butler.dataRef('raw', dataId=dataId) filterMapping[rec['filtername']] = dataRef.dataId['filter'] nFound += 1 if nFound == len(self.filterToBand): break # Get a mapping from filtername to the offsets offsetMapping = {} for f in self.filterToBand: offsetMapping[f] = offsets[self.bands.index(self.filterToBand[f])] # Get a mapping from "ccd" to the ccd index used for the scaling camera = butler.get('camera') ccdMapping = {} for ccdIndex, detector in enumerate(camera): ccdMapping[detector.getId()] = ccdIndex # And a mapping to get the flat-field scaling values scalingMapping = {} for rec in visitCat: scalingMapping[rec['visit']] = rec['scaling'] # Make a fixed variable to hold the parameters to build a ChebyshevBoundedField orderPlus1 = self.chebyshevOrder + 1 pars = np.zeros((orderPlus1, orderPlus1)) for rec in zptCat[selected]: if self.superStarSubCcd: # Spatially varying zeropoint bbox = lsst.geom.Box2I( lsst.geom.Point2I(0.0, 0.0), lsst.geom.Point2I(*rec['fgcmfzptchebxymax'])) # Take the zeropoint, apply the absolute relative calibration offset, # and whatever flat-field scaling was applied pars[:, :] = ( rec['fgcmfzptcheb'].reshape(orderPlus1, orderPlus1) * 10.**(offsetMapping[rec['filtername']] / (-2.5)) * scalingMapping[rec['visit']][ccdMapping[rec['ccd']]]) # Apply absolute relative calibration offset to 0/0 term field = afwMath.ChebyshevBoundedField(bbox, pars) calibMean = field.mean() calibErr = (np.log(10.) / 2.5) * calibMean * rec['fgcmzpterr'] photoCalib = afwImage.PhotoCalib(field, calibErr) else: # Spatially constant zeropoint # Take the zeropoint, apply the absolute relative calibration offset, # and whatever flat-field scaling was applied calibMean = ( 10.**(rec['fgcmzpt'] / (-2.5)) * 10.**(offsetMapping[rec['filtername']] / (-2.5)) * scalingMapping[rec['visit']][ccdMapping[rec['ccd']]]) calibErr = (np.log(10.) / 2.5) * calibMean * rec['fgcmzpterr'] photoCalib = afwImage.PhotoCalib(calibMean, calibErr) butler.put(photoCalib, 'jointcal_photoCalib', dataId={ self.visitDataRefName: int(rec['visit']), self.ccdDataRefName: int(rec['ccd']), 'filter': filterMapping[rec['filtername']], 'tract': 0 }) self.log.info("Done outputting jointcal_photoCalib objects")
def testComputeExposureSummary(self): """Make a fake exposure and background and compute summary. """ np.random.seed(12345) # Make an exposure with a noise image exposure = afwImage.ExposureF(100, 100) skySigma = 10.0 exposure.getImage().getArray()[:, :] = np.random.normal(0.0, skySigma, size=(100, 100)) exposure.getVariance().getArray()[:, :] = skySigma**2. # Set the visitInfo date = DateTime(date=59234.7083333334, system=DateTime.DateSystem.MJD) observatory = Observatory(-70.7366 * lsst.geom.degrees, -30.2407 * lsst.geom.degrees, 2650.) visitInfo = afwImage.VisitInfo(exposureTime=10.0, date=date, observatory=observatory) exposure.getInfo().setVisitInfo(visitInfo) # Install a Gaussian PSF psfSize = 2.0 psf = GaussianPsf(5, 5, psfSize) exposure.setPsf(psf) # Install a simple WCS scale = 0.2 * lsst.geom.arcseconds raCenter = 300.0 * lsst.geom.degrees decCenter = 0.0 * lsst.geom.degrees cdMatrix = makeCdMatrix(scale=scale) skyWcs = makeSkyWcs(crpix=exposure.getBBox().getCenter(), crval=lsst.geom.SpherePoint(raCenter, decCenter), cdMatrix=cdMatrix) exposure.setWcs(skyWcs) # Install a simple photoCalib photoCalib = afwImage.PhotoCalib(calibrationMean=0.3) zp = 2.5 * np.log10(photoCalib.getInstFluxAtZeroMagnitude()) exposure.setPhotoCalib(photoCalib) # Compute the background image bgGridSize = 10 bctrl = afwMath.BackgroundControl(afwMath.Interpolate.NATURAL_SPLINE) bctrl.setNxSample( int(exposure.getMaskedImage().getWidth() / bgGridSize) + 1) bctrl.setNySample( int(exposure.getMaskedImage().getHeight() / bgGridSize) + 1) backobj = afwMath.makeBackground(exposure.getMaskedImage().getImage(), bctrl) background = afwMath.BackgroundList() background.append(backobj) # Run the task expSummaryTask = ComputeExposureSummaryStatsTask() summary = expSummaryTask.run(exposure, None, background) # Test the outputs self.assertFloatsAlmostEqual(summary.psfSigma, psfSize) self.assertFloatsAlmostEqual(summary.psfIxx, psfSize**2.) self.assertFloatsAlmostEqual(summary.psfIyy, psfSize**2.) self.assertFloatsAlmostEqual(summary.psfIxy, 0.0) self.assertFloatsAlmostEqual(summary.psfArea, 23.088975164455444) delta = (scale * 50).asDegrees() for a, b in zip(summary.raCorners, [ raCenter.asDegrees() + delta, raCenter.asDegrees() - delta, raCenter.asDegrees() - delta, raCenter.asDegrees() + delta ]): self.assertFloatsAlmostEqual(a, b, atol=1e-10) for a, b in zip(summary.decCorners, [ decCenter.asDegrees() - delta, decCenter.asDegrees() - delta, decCenter.asDegrees() + delta, decCenter.asDegrees() + delta ]): self.assertFloatsAlmostEqual(a, b, atol=1e-10) self.assertFloatsAlmostEqual(summary.ra, raCenter.asDegrees(), atol=1e-10) self.assertFloatsAlmostEqual(summary.decl, decCenter.asDegrees(), atol=1e-10) self.assertFloatsAlmostEqual(summary.zeroPoint, zp) # Need to compare background level and noise # These are only approximately 0+/-10 because of the small image self.assertFloatsAlmostEqual(summary.skyBg, -0.079, atol=1e-3) self.assertFloatsAlmostEqual(summary.meanVar, skySigma**2.) self.assertFloatsAlmostEqual(summary.zenithDistance, 30.57112, atol=1e-5)
def setUp(self): # metadata taken from CFHT data # v695856-e0/v695856-e0-c000-a00.sci_img.fits self.metadata = dafBase.PropertySet() self.metadata.set("SIMPLE", "T") self.metadata.set("BITPIX", -32) self.metadata.set("NAXIS", 2) self.metadata.set("NAXIS1", 1024) self.metadata.set("NAXIS2", 1153) self.metadata.set("RADECSYS", 'FK5') self.metadata.set("EQUINOX", 2000.) self.metadata.setDouble("CRVAL1", 215.604025685476) self.metadata.setDouble("CRVAL2", 53.1595451514076) self.metadata.setDouble("CRPIX1", 1109.99981456774) self.metadata.setDouble("CRPIX2", 560.018167811613) self.metadata.set("CTYPE1", 'RA---SIN') self.metadata.set("CTYPE2", 'DEC--SIN') self.metadata.setDouble("CD1_1", 5.10808596133527E-05) self.metadata.setDouble("CD1_2", 1.85579539217196E-07) self.metadata.setDouble("CD2_2", -5.10281493481982E-05) self.metadata.setDouble("CD2_1", -8.27440751733828E-07) self.wcs = afwGeom.makeSkyWcs(self.metadata) self.calibration = 10000 self.calibrationErr = 100 self.exposureId = 1234 self.exposureTime = 200. self.imageSize = [1024, 1153] self.dateTime = "2014-05-13T17:00:00.000000000" # Make images with one source in them and distinct values and # variance for each image. # Direct Image source_image = afwImage.MaskedImageF( lsst.geom.ExtentI(self.imageSize[0] + 1, self.imageSize[1] + 1)) source_image.image[100, 100, afwImage.LOCAL] = 10 source_image.getVariance().set(1) bbox = lsst.geom.BoxI( lsst.geom.PointI(1, 1), lsst.geom.ExtentI(self.imageSize[0], self.imageSize[1])) masked_image = afwImage.MaskedImageF(source_image, bbox, afwImage.LOCAL) self.exposure = afwImage.makeExposure(masked_image, self.wcs) detector = DetectorWrapper( id=23, bbox=self.exposure.getBBox()).detector visit = afwImage.VisitInfo( exposureId=self.exposureId, exposureTime=self.exposureTime, date=dafBase.DateTime(self.dateTime, dafBase.DateTime.Timescale.TAI)) self.exposure.info.id = self.exposureId self.exposure.setDetector(detector) self.exposure.getInfo().setVisitInfo(visit) self.exposure.setFilter(afwImage.FilterLabel(band='g', physical='g.MP9401')) self.exposure.setPhotoCalib(afwImage.PhotoCalib(self.calibration, self.calibrationErr)) # Difference Image source_image = afwImage.MaskedImageF( lsst.geom.ExtentI(self.imageSize[0] + 1, self.imageSize[1] + 1)) source_image.image[100, 100, afwImage.LOCAL] = 20 source_image.getVariance().set(2) bbox = lsst.geom.BoxI( lsst.geom.PointI(1, 1), lsst.geom.ExtentI(self.imageSize[0], self.imageSize[1])) masked_image = afwImage.MaskedImageF(source_image, bbox, afwImage.LOCAL) self.diffim = afwImage.makeExposure(masked_image, self.wcs) self.diffim.info.id = self.exposureId self.diffim.setDetector(detector) self.diffim.getInfo().setVisitInfo(visit) self.diffim.setFilter(afwImage.FilterLabel(band='g', physical='g.MP9401')) self.diffim.setPhotoCalib(afwImage.PhotoCalib(self.calibration, self.calibrationErr)) self.expIdBits = 16 FWHM = 5 psf = measAlg.DoubleGaussianPsf(15, 15, FWHM/(2*np.sqrt(2*np.log(2)))) self.exposure.setPsf(psf) self.diffim.setPsf(psf) self.testDiaObjects = create_test_dia_objects(5, self.wcs) # Add additional diaObjects that are outside of the above difference # and calexp visit images. objects = [ (10000000, self.wcs.pixelToSky(-100000, -100000)), # xy outside (10000001, self.wcs.pixelToSky(100, -100000)), # y outside (10000002, self.wcs.pixelToSky(-100000, 100)), # x outside ] extra = pandas.DataFrame({ "diaObjectId": np.array([id for id, point in objects], dtype=np.int64), "ra": [point.getRa().asDegrees() for id, point in objects], "decl": [point.getDec().asDegrees() for id, point in objects] }) self.testDiaObjects = pd.concat([self.testDiaObjects, extra], ignore_index=True) # Ids of objects that were "updated" during "ap_association" # processing. self.updatedTestIds = np.array([1, 2, 3, 4, 10000001], dtype=np.uint64) # Expecdted number of sources is the number of updated ids plus # any that are within the CCD footprint but are not in the # above list of ids. self.expectedDiaForcedSources = 6 self.expected_n_columns = 11
def setUp(self): # CFHT Filters from the camera mapper. self.filter_names = ["u", "g", "r", "i", "z"] afwImageUtils.resetFilters() afwImageUtils.defineFilter('u', lambdaEff=374, alias="u.MP9301") afwImageUtils.defineFilter('g', lambdaEff=487, alias="g.MP9401") afwImageUtils.defineFilter('r', lambdaEff=628, alias="r.MP9601") afwImageUtils.defineFilter('i', lambdaEff=778, alias="i.MP9701") afwImageUtils.defineFilter('z', lambdaEff=1170, alias="z.MP9801") # metadata taken from CFHT data # v695856-e0/v695856-e0-c000-a00.sci_img.fits self.metadata = dafBase.PropertySet() self.metadata.set("SIMPLE", "T") self.metadata.set("BITPIX", -32) self.metadata.set("NAXIS", 2) self.metadata.set("NAXIS1", 1024) self.metadata.set("NAXIS2", 1153) self.metadata.set("RADECSYS", 'FK5') self.metadata.set("EQUINOX", 2000.) self.metadata.setDouble("CRVAL1", 215.604025685476) self.metadata.setDouble("CRVAL2", 53.1595451514076) self.metadata.setDouble("CRPIX1", 1109.99981456774) self.metadata.setDouble("CRPIX2", 560.018167811613) self.metadata.set("CTYPE1", 'RA---SIN') self.metadata.set("CTYPE2", 'DEC--SIN') self.metadata.setDouble("CD1_1", 5.10808596133527E-05) self.metadata.setDouble("CD1_2", 1.85579539217196E-07) self.metadata.setDouble("CD2_2", -5.10281493481982E-05) self.metadata.setDouble("CD2_1", -8.27440751733828E-07) self.wcs = afwGeom.makeSkyWcs(self.metadata) self.calibration = 10000 self.calibrationErr = 100 self.exposureId = 1234 self.exposureTime = 200. self.imageSize = [1024, 1153] self.dateTime = "2014-05-13T17:00:00.000000000" # Make images with one source in them and distinct values and # variance for each image. # Direct Image source_image = afwImage.MaskedImageF( lsst.geom.ExtentI(self.imageSize[0] + 1, self.imageSize[1] + 1)) source_image.image[100, 100, afwImage.LOCAL] = 10 source_image.getVariance().set(1) bbox = lsst.geom.BoxI( lsst.geom.PointI(1, 1), lsst.geom.ExtentI(self.imageSize[0], self.imageSize[1])) masked_image = afwImage.MaskedImageF(source_image, bbox, afwImage.LOCAL) self.exposure = afwImage.makeExposure(masked_image, self.wcs) detector = DetectorWrapper(id=23, bbox=self.exposure.getBBox()).detector visit = afwImage.VisitInfo(exposureId=self.exposureId, exposureTime=self.exposureTime, date=dafBase.DateTime( self.dateTime, dafBase.DateTime.Timescale.TAI)) self.exposure.setDetector(detector) self.exposure.getInfo().setVisitInfo(visit) self.exposure.setFilter(afwImage.Filter('g')) self.exposure.setPhotoCalib( afwImage.PhotoCalib(self.calibration, self.calibrationErr)) # Difference Image source_image = afwImage.MaskedImageF( lsst.geom.ExtentI(self.imageSize[0] + 1, self.imageSize[1] + 1)) source_image.image[100, 100, afwImage.LOCAL] = 20 source_image.getVariance().set(2) bbox = lsst.geom.BoxI( lsst.geom.PointI(1, 1), lsst.geom.ExtentI(self.imageSize[0], self.imageSize[1])) masked_image = afwImage.MaskedImageF(source_image, bbox, afwImage.LOCAL) self.diffim = afwImage.makeExposure(masked_image, self.wcs) self.diffim.setDetector(detector) self.diffim.getInfo().setVisitInfo(visit) self.diffim.setFilter(afwImage.Filter('g')) self.diffim.setPhotoCalib( afwImage.PhotoCalib(self.calibration, self.calibrationErr)) self.expIdBits = 16 FWHM = 5 psf = measAlg.DoubleGaussianPsf(15, 15, FWHM / (2 * np.sqrt(2 * np.log(2)))) self.exposure.setPsf(psf) self.diffim.setPsf(psf) self.testDiaObjects = create_test_dia_objects(5, self.wcs) # Add additional diaObjects that are outside of the above difference # and calexp visit images. # xy outside src = self.testDiaObjects.addNew() src['id'] = 10000000 src.setCoord(self.wcs.pixelToSky(-100000, -100000)) # y outside src = self.testDiaObjects.addNew() src['id'] = 10000001 src.setCoord(self.wcs.pixelToSky(100, -100000)) # x outside src = self.testDiaObjects.addNew() src['id'] = 10000002 src.setCoord(self.wcs.pixelToSky(-100000, 100)) # Ids of objects that were "updated" during "ap_association" # processing. self.updatedTestIds = np.array([1, 2, 3, 4, 10000001], dtype=np.uint64) # Expecdted number of sources is the number of updated ids plus # any that are within the CCD footprint but are not in the # above list of ids. self.expectedDiaForcedSources = 6 self.expected_n_columns = 11