def _preparePlugin(self, numCoaddInputs): """ Prepare a SingleFrameInputCountPlugin for running. Sets up an InputCount plugin to run on an empty catalog together with a synthetic, content-free Exposure. @param[in] numCoaddInputs Number of coadd inputs for use in synthetic exposure. @returns tuple of (initialized plugin, empty catalog, synthetic exposure) """ exp = afwImage.ExposureF() if numCoaddInputs > 0: exp.getInfo().setCoaddInputs( afwImage.CoaddInputs(*[ afwTable.ExposureTable.makeMinimalSchema() for _ in range(numCoaddInputs) ])) schema = afwTable.SourceTable.makeMinimalSchema() measBase.SingleFramePeakCentroidPlugin( measBase.SingleFramePeakCentroidConfig(), "centroid", schema, None) schema.getAliasMap().set("slot_Centroid", "centroid") inputCount = measBase.SingleFrameInputCountPlugin( measBase.SingleFrameInputCountConfig(), "inputCount", schema, None) catalog = afwTable.SourceCatalog(schema) return inputCount, catalog, exp
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 testTicket2861(self): with lsst.utils.tests.getTempFilePath(".fits") as tmpFile: exposure1 = afwImage.ExposureF(100, 100, self.wcs) exposure1.setPsf(self.psf) schema = afwTable.ExposureTable.makeMinimalSchema() coaddInputs = afwImage.CoaddInputs(schema, schema) exposure1.getInfo().setCoaddInputs(coaddInputs) exposure2 = afwImage.ExposureF(exposure1, True) self.assertIsNotNone(exposure2.getInfo().getCoaddInputs()) exposure2.writeFits(tmpFile) exposure3 = afwImage.ExposureF(tmpFile) self.assertIsNotNone(exposure3.getInfo().getCoaddInputs())
def testTicket2861(self): filename = "testTicket2861.fits" exposure1 = afwImage.ExposureF(100, 100, self.wcs) exposure1.setPsf(self.psf) schema = afwTable.ExposureTable.makeMinimalSchema() coaddInputs = afwImage.CoaddInputs(schema, schema) exposure1.getInfo().setCoaddInputs(coaddInputs) exposure2 = afwImage.ExposureF(exposure1, True) self.assertIsNotNone(exposure2.getInfo().getCoaddInputs()) exposure2.writeFits(filename) exposure3 = afwImage.ExposureF(filename) self.assertIsNotNone(exposure3.getInfo().getCoaddInputs()) os.remove(filename)
def _preparePlugin(self, addCoaddInputs): """Prepare a `SingleFrameInputCountPlugin` for running. Sets up the plugin to run on an empty catalog together with a synthetic, content-free `~lsst.afw.image.ExposureF`. Parameters ---------- addCoaddInputs : `bool` Should we add the coadd inputs? Returns ------- inputCount : `SingleFrameInputCountPlugin` Initialized measurement plugin. catalog : `lsst.afw.table.SourceCatalog` Empty Catalog. exp : `lsst.afw.image.ExposureF` Synthetic exposure. """ exp = afwImage.ExposureF(20, 20) scale = 1.0e-5 * lsst.geom.degrees wcs = afwGeom.makeSkyWcs(crpix=lsst.geom.Point2D(0, 0), crval=lsst.geom.SpherePoint( 0.0, 0.0, lsst.geom.degrees), cdMatrix=afwGeom.makeCdMatrix(scale=scale)) exp.setWcs(wcs) if addCoaddInputs: exp.getInfo().setCoaddInputs( afwImage.CoaddInputs( afwTable.ExposureTable.makeMinimalSchema(), afwTable.ExposureTable.makeMinimalSchema())) ccds = exp.getInfo().getCoaddInputs().ccds record = ccds.addNew() record.setWcs(wcs) record.setBBox(exp.getBBox()) record.setValidPolygon( afwGeom.Polygon(lsst.geom.Box2D(exp.getBBox()))) schema = afwTable.SourceTable.makeMinimalSchema() measBase.SingleFramePeakCentroidPlugin( measBase.SingleFramePeakCentroidConfig(), "centroid", schema, None) schema.getAliasMap().set("slot_Centroid", "centroid") inputCount = measBase.SingleFrameInputCountPlugin( measBase.InputCountConfig(), "inputCount", schema, None) catalog = afwTable.SourceCatalog(schema) return inputCount, catalog, exp
def _preparePlugin(self, addCoaddInputs): """ Prepare a SingleFrameInputCountPlugin for running. Sets up an InputCount plugin to run on an empty catalog together with a synthetic, content-free Exposure. @param[in] addCoaddInputs Should we add the coadd inputs? @returns tuple of (initialized plugin, empty catalog, synthetic exposure) """ exp = afwImage.ExposureF(20, 20) scale = 1.0e-5 * afwGeom.degrees wcs = afwGeom.makeSkyWcs(crpix=afwGeom.Point2D(0, 0), crval=afwGeom.SpherePoint( 0.0, 0.0, afwGeom.degrees), cdMatrix=afwGeom.makeCdMatrix(scale=scale)) exp.setWcs(wcs) if addCoaddInputs: exp.getInfo().setCoaddInputs( afwImage.CoaddInputs( afwTable.ExposureTable.makeMinimalSchema(), afwTable.ExposureTable.makeMinimalSchema())) ccds = exp.getInfo().getCoaddInputs().ccds record = ccds.addNew() record.setWcs(wcs) record.setBBox(exp.getBBox()) record.setValidPolygon( afwGeom.Polygon(afwGeom.Box2D(exp.getBBox()))) schema = afwTable.SourceTable.makeMinimalSchema() measBase.SingleFramePeakCentroidPlugin( measBase.SingleFramePeakCentroidConfig(), "centroid", schema, None) schema.getAliasMap().set("slot_Centroid", "centroid") inputCount = measBase.SingleFrameInputCountPlugin( measBase.InputCountConfig(), "inputCount", schema, None) catalog = afwTable.SourceCatalog(schema) return inputCount, catalog, exp
def testInputCounts(self, showPlot=False): # Generate a simulated coadd of four overlapping-but-offset CCDs. # Populate it with three sources. # Demonstrate that we can correctly recover the number of images which # contribute to each source. size = 20 # Size of images (pixels) value = 100.0 # Source flux ccdPositions = [ lsst.geom.Point2D(8, 0), lsst.geom.Point2D(10, 10), lsst.geom.Point2D(-8, -8), lsst.geom.Point2D(-8, 8) ] # Represent sources by a tuple of position and expected number of # contributing CCDs (based on the size/positions given above). Source = namedtuple("Source", ["pos", "count"]) sources = [ Source(pos=lsst.geom.Point2D(6, 6), count=2), Source(pos=lsst.geom.Point2D(10, 10), count=3), Source(pos=lsst.geom.Point2D(14, 14), count=1) ] # These lines are used in the creation of WCS information scale = 1.0e-5 * lsst.geom.degrees cdMatrix = afwGeom.makeCdMatrix(scale=scale) crval = lsst.geom.SpherePoint(0.0, 0.0, lsst.geom.degrees) # Construct the info needed to set the exposure object imageBox = lsst.geom.Box2I(lsst.geom.Point2I(0, 0), lsst.geom.Extent2I(size, size)) wcsRef = afwGeom.makeSkyWcs(crpix=lsst.geom.Point2D(0, 0), crval=crval, cdMatrix=cdMatrix) # Create the exposure object, and set it up to be the output of a coadd exp = afwImage.ExposureF(size, size) exp.setWcs(wcsRef) exp.getInfo().setCoaddInputs( afwImage.CoaddInputs(afwTable.ExposureTable.makeMinimalSchema(), afwTable.ExposureTable.makeMinimalSchema())) # Set the fake CCDs that "went into" making this coadd, using the # differing wcs objects created above. ccds = exp.getInfo().getCoaddInputs().ccds for pos in ccdPositions: record = ccds.addNew() record.setWcs( afwGeom.makeSkyWcs(crpix=pos, crval=crval, cdMatrix=cdMatrix)) record.setBBox(imageBox) record.setValidPolygon(afwGeom.Polygon(lsst.geom.Box2D(imageBox))) # Configure a SingleFrameMeasurementTask to run InputCounts. measureSourcesConfig = measBase.SingleFrameMeasurementConfig() measureSourcesConfig.plugins.names = [ "base_PeakCentroid", "base_InputCount" ] measureSourcesConfig.slots.centroid = "base_PeakCentroid" measureSourcesConfig.slots.psfFlux = None measureSourcesConfig.slots.apFlux = None measureSourcesConfig.slots.modelFlux = None measureSourcesConfig.slots.gaussianFlux = None measureSourcesConfig.slots.calibFlux = None measureSourcesConfig.slots.shape = None measureSourcesConfig.validate() schema = afwTable.SourceTable.makeMinimalSchema() task = measBase.SingleFrameMeasurementTask(schema, config=measureSourcesConfig) catalog = afwTable.SourceCatalog(schema) # Add simulated sources to the measurement catalog. for src in sources: spans = afwGeom.SpanSet.fromShape(1) spans = spans.shiftedBy(int(src.pos.getX()), int(src.pos.getY())) foot = afwDetection.Footprint(spans) peak = foot.getPeaks().addNew() peak.setFx(src.pos[0]) peak.setFy(src.pos[1]) peak.setPeakValue(value) catalog.addNew().setFootprint(foot) task.run(catalog, exp) for src, rec in zip(sources, catalog): self.assertEqual(rec.get("base_InputCount_value"), src.count) if display: ccdVennDiagram(exp)
def makeCoaddInputs(self): """Create a CoaddInputs object with schemas defined by the task configuration""" return afwImage.CoaddInputs(self.visitSchema, self.ccdSchema)
def run(self, patchRef, selectDataList=[]): """ Task to import external data and transform it into LSST exposure object. The task also performs PSF measurement """ # --------------------------------------------- # # output images for tests # --------------------------------------------- # if self.config.test: coadd = patchRef.get(self.config.coaddName + "Coadd_calexp") self.writeTest(coadd, dirName=".") return if self.config.imgInName == "": raise ValueError('You must provide an input image (imgInName)') if self.config.varInName == "": raise ValueError( 'You must provide an input variance image (varInName)') import numpy as np self.log.info("Processing %s" % (patchRef.dataId)) # --------------------------------------------- # # wcs info # --------------------------------------------- # skyInfo = self.getSkyInfo(patchRef) # --------------------------------------------- # # load image # --------------------------------------------- # imgIn = afwImage.ImageF(self.config.imgInName) # --------------------------------------------- # # load variance # --------------------------------------------- # varIn = afwImage.ImageF(self.config.varInName) # if weight map provided # variance = inverse weight if self.config.weight: varIn.getArray()[:] = 1.0 / varIn.getArray()[:] # get pixels with 0 or non finite variance (= no data observed) noDataIn = (varIn.getArray()[:] == 0) \ | (np.logical_not(np.isfinite(varIn.getArray()[:]))) # --------------------------------------------- # # load mask or build one from scratch # --------------------------------------------- # if self.config.mskInName != "": #mskIn = afwImage.ImageU(self.config.mskInName) # not tested mskIn = afwImage.Mask(self.config.mskInName) # not tested else: # create mask array self.log.info("Creating new mask") mskIn = afwImage.Mask(skyInfo.bbox) # set NO_DATA bit to mask # where noDataIn mask_labels = mskIn.getMaskPlaneDict() self.log.info("Mask labels: {}".format(mask_labels)) noDataBit = mask_labels["NO_DATA"] # check if not already set in ref mask # (no longer used) # nopatchRefNotSet = mskIn.getArray()[:]&(1<<noDataBit) == 0 mskIn.getArray()[noDataIn] += 2**noDataBit # needed for multiband mskIn.addMaskPlane('CLIPPED') mskIn.addMaskPlane('CROSSTALK') mskIn.addMaskPlane('INEXACT_PSF') mskIn.addMaskPlane('NOT_DEBLENDED') mskIn.addMaskPlane('REJECTED') mskIn.addMaskPlane('SENSOR_EDGE') mskIn.addMaskPlane('UNMASKEDNAN') # --------------------------------------------- # # create exposure # --------------------------------------------- # self.log.info("Creating exposure") # exposure object exposure = afwImage.ExposureF(skyInfo.bbox, skyInfo.wcs) maskedImage = afwImage.MaskedImageF(imgIn, mskIn, varIn) exposure.setMaskedImage(maskedImage) # set dummy coadd info expSchema = afwTable.ExposureTable.makeMinimalSchema() coaddInputs = afwImage.CoaddInputs(expSchema, expSchema) exposure.getInfo().setCoaddInputs(coaddInputs) # set filter filter = afwImage.Filter(patchRef.dataId['filter']) exposure.setFilter(filter) # set calib object fluxMag0 = pow(10.0, +0.4 * self.config.mag0) calib = afwImage.Calib() calib.setFluxMag0(fluxMag0) exposure.setCalib(calib) # --------------------------------------------- # # add bright object mask # --------------------------------------------- # if self.config.doMaskBrightObjects: brightObjectMasks = self.readBrightObjectMasks(patchRef) self.setBrightObjectMasks(exposure, patchRef.dataId, brightObjectMasks) # ---------------------------------------------- # # Do PSF measurement on coadd # ---------------------------------------------- # results = self.charImage.characterize(exposure) exposure = results.exposure """ if False: self.log.info("Measuring PSF") self.installInitialPsf(exposure) # prepare table idFactory = afwTable.IdFactory.makeSimple() table = afwTable.SourceTable.make(self.schema, idFactory) table.setMetadata(self.algMetadata) # detect sources detRet = self.detection.makeSourceCatalog(table, exposure) sources = detRet.sources # measure moments self.measurement.measure(sources, exposure) # measure psf psfRet = self.measurePsf.run(exposure, sources, expId=0, matches=None) cellSet = psfRet.cellSet psf = psfRet.psf displayPsf = False if displayPsf: measAlg.utils.showPsf(psf, frame=1) sigma = psf.computeShape().getDeterminantRadius() print(sigma) # seems to be broken (?) # measAlg.utils.showPsfMosaic(exposure, psf, frame=1, showFwhm=True) # set PSF exposure.setPsf(psf) """ # ---------------------------------------------- # # write exposure # ---------------------------------------------- # butler = patchRef.butlerSubset.butler butler.put(exposure, self.config.coaddName + 'Coadd', patchRef.dataId) return exposure
def setUp(self): tract = 0 band = 'r' patch = 0 visits = [100, 101] # Good to test crossing 0. ra_center = 0.0 dec_center = -45.0 pixel_scale = 0.2 coadd_zp = 27.0 # Generate a mock skymap with one patch config = DiscreteSkyMap.ConfigClass() config.raList = [ra_center] config.decList = [dec_center] config.radiusList = [150 * pixel_scale / 3600.] config.patchInnerDimensions = (350, 350) config.patchBorder = 50 config.tractOverlap = 0.0 config.pixelScale = pixel_scale sky_map = DiscreteSkyMap(config) visit_summaries = [ makeMockVisitSummary(visit, ra_center=ra_center, dec_center=dec_center) for visit in visits ] visit_summary_refs = [ MockVisitSummaryReference(visit_summary, visit) for visit_summary, visit in zip(visit_summaries, visits) ] self.visit_summary_dict = { visit: ref.get() for ref, visit in zip(visit_summary_refs, visits) } # Generate an input map. Note that this does not need to be consistent # with the visit_summary projections, we're just tracking values. input_map = hsp.HealSparseMap.make_empty( nside_coverage=256, nside_sparse=32768, dtype=hsp.WIDE_MASK, wide_mask_maxbits=len(visits) * 2) patch_poly = afwGeom.Polygon( geom.Box2D(sky_map[tract][patch].getOuterBBox())) sph_pts = sky_map[tract].getWcs().pixelToSky( patch_poly.convexHull().getVertices()) patch_poly_radec = np.array([(sph.getRa().asDegrees(), sph.getDec().asDegrees()) for sph in sph_pts]) poly = hsp.Polygon(ra=patch_poly_radec[:-1, 0], dec=patch_poly_radec[:-1, 1], value=[0]) poly_pixels = poly.get_pixels(nside=input_map.nside_sparse) # The input map has full coverage for bits 0 and 1 input_map.set_bits_pix(poly_pixels, [0]) input_map.set_bits_pix(poly_pixels, [1]) input_map_ref = MockInputMapReference(input_map, patch=patch, tract=tract) self.input_map_dict = {patch: input_map_ref} coadd = afwImage.ExposureF(sky_map[tract][patch].getOuterBBox(), sky_map[tract].getWcs()) instFluxMag0 = 10.**(coadd_zp / 2.5) pc = afwImage.makePhotoCalibFromCalibZeroPoint(instFluxMag0) coadd.setPhotoCalib(pc) # Mock the coadd input ccd table schema = afwTable.ExposureTable.makeMinimalSchema() schema.addField("ccd", type="I") schema.addField("visit", type="I") schema.addField("weight", type="F") ccds = afwTable.ExposureCatalog(schema) ccds.resize(2) ccds['id'] = np.arange(2) ccds['visit'][0] = visits[0] ccds['visit'][1] = visits[1] ccds['ccd'][0] = 0 ccds['ccd'][1] = 1 ccds['weight'] = 10.0 for ccd_row in ccds: summary = self.visit_summary_dict[ccd_row['visit']].find( ccd_row['ccd']) ccd_row.setWcs(summary.getWcs()) ccd_row.setPsf(summary.getPsf()) ccd_row.setBBox(summary.getBBox()) ccd_row.setPhotoCalib(summary.getPhotoCalib()) inputs = afwImage.CoaddInputs() inputs.ccds = ccds coadd.getInfo().setCoaddInputs(inputs) coadd_ref = MockCoaddReference(coadd, patch=patch, tract=tract) self.coadd_dict = {patch: coadd_ref} self.tract = tract self.band = band self.sky_map = sky_map self.input_map = input_map
def testCountInputs(self): num = 3 # Number of images size = 10 # Size of images (pixels) shift = 4 # Shift to apply between images (pixels) value = 100.0 # Value to give objects offset = 12345 # x0,y0 cdMatrix = (1.0e-5, 0.0, 0.0, 1.0e-5) crval = afwCoord.Coord(0.0 * afwGeom.degrees, 0.0 * afwGeom.degrees) positions = [ afwGeom.Point2D(size // 2 + shift * (i - num // 2) + offset, size // 2 + shift * (i - num // 2) + offset) for i in range(num) ] wcsList = [ afwImage.makeWcs(crval, pos - afwGeom.Extent2D(offset, offset), *cdMatrix) for pos in positions ] imageBox = afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(size, size)) wcsRef = afwImage.makeWcs(crval, afwGeom.Point2D(offset, offset), *cdMatrix) exp = afwImage.ExposureF(size, size) exp.setXY0(afwGeom.Point2I(offset, offset)) exp.setWcs(wcsRef) exp.setPsf(measAlg.DoubleGaussianPsf(5, 5, 1.0)) exp.getInfo().setCoaddInputs( afwImage.CoaddInputs(afwTable.ExposureTable.makeMinimalSchema(), afwTable.ExposureTable.makeMinimalSchema())) ccds = exp.getInfo().getCoaddInputs().ccds for wcs in wcsList: record = ccds.addNew() record.setWcs(wcs) record.setBBox(imageBox) record.setValidPolygon(Polygon(afwGeom.Box2D(imageBox))) exp.getMaskedImage().getImage().set(0) exp.getMaskedImage().getMask().set(0) exp.getMaskedImage().getVariance().set(1.0) for pp in positions: x, y = map(int, pp) exp.getMaskedImage().getImage().set0(x, y, value) exp.getMaskedImage().getMask().set(x - offset, y - offset, value) measureSourcesConfig = measAlg.SourceMeasurementConfig() measureSourcesConfig.algorithms.names = [ "centroid.naive", "countInputs" ] measureSourcesConfig.slots.centroid = "centroid.naive" measureSourcesConfig.slots.psfFlux = None measureSourcesConfig.slots.apFlux = None measureSourcesConfig.slots.modelFlux = None measureSourcesConfig.slots.instFlux = None measureSourcesConfig.slots.calibFlux = None measureSourcesConfig.slots.shape = None measureSourcesConfig.validate() schema = afwTable.SourceTable.makeMinimalSchema() ms = measureSourcesConfig.makeMeasureSources(schema) catalog = afwTable.SourceCatalog(schema) measureSourcesConfig.slots.setupTable(catalog.getTable()) for pp in positions: foot = afwDetection.Footprint(afwGeom.Point2I(pp), 1.0) peak = foot.getPeaks().addNew() peak.setIx(int(pp[0])) peak.setIy(int(pp[1])) peak.setFx(pp[0]) peak.setFy(pp[1]) peak.setPeakValue(value) source = catalog.addNew() source.setFootprint(foot) ms.applyWithPeak(source, exp) number = sum( afwGeom.Box2D(imageBox).contains( wcs.skyToPixel(wcsRef.pixelToSky(pp))) for wcs in wcsList) self.assertEqual(source.get("countInputs"), number)