def setUp(self): maskedImage = afwImage.MaskedImageF(inFilePathSmall) maskedImageMD = readMetadata(inFilePathSmall) self.smallExposure = afwImage.ExposureF(inFilePathSmall) self.width = maskedImage.getWidth() self.height = maskedImage.getHeight() self.wcs = afwGeom.makeSkyWcs(maskedImageMD, False) self.md = maskedImageMD self.psf = DummyPsf(2.0) self.detector = DetectorWrapper().detector self.extras = {"misc": DummyPsf(3.5)} self.exposureBlank = afwImage.ExposureF() self.exposureMiOnly = afwImage.makeExposure(maskedImage) self.exposureMiWcs = afwImage.makeExposure(maskedImage, self.wcs) # n.b. the (100, 100, ...) form self.exposureCrWcs = afwImage.ExposureF(100, 100, self.wcs) # test with ExtentI(100, 100) too self.exposureCrOnly = afwImage.ExposureF(lsst.geom.ExtentI(100, 100)) afwImage.Filter.reset() afwImage.FilterProperty.reset() defineFilter("g", 470.0)
def X_standardizeCalib(self, dataset, item, dataId): """Standardize a calibration image read in by the butler Some calibrations are stored on disk as Images instead of MaskedImages or Exposures. Here, we convert it to an Exposure. @param dataset Dataset type (e.g., "bias", "dark" or "flat") @param item The item read by the butler @param dataId The data identifier (unused, included for future flexibility) @return standardized Exposure """ mapping = self.calibrations[dataset] if "MaskedImage" in mapping.python: exp = afwImage.makeExposure(item) elif "Image" in mapping.python: if hasattr(item, "getImage"): # For DecoratedImageX item = item.getImage() exp = afwImage.makeExposure(afwImage.makeMaskedImage(item)) elif "Exposure" in mapping.python: exp = item else: raise RuntimeError("Unrecognised python type: %s" % mapping.python) parent = super(CameraMapper, self) if hasattr(parent, "std_" + dataset): return getattr(parent, "std_" + dataset)(exp, dataId) return self._standardizeExposure(mapping, exp, dataId)
def standardizeCalib(self, dataset, item, dataId): """Standardize a calibration image read in by the butler Some calibrations are stored on disk as Images instead of MaskedImages or Exposures. Here, we convert it to an Exposure. @param dataset Dataset type (e.g., "bias", "dark" or "flat") @param item The item read by the butler @param dataId The data identifier (unused, included for future flexibility) @return standardized Exposure """ mapping = self.calibrations[dataset] if "MaskedImage" in mapping.python: exp = afwImage.makeExposure(item) elif "Image" in mapping.python: if hasattr(item, "getImage"): # For DecoratedImageX item = item.getImage() exp = afwImage.makeExposure(afwImage.makeMaskedImage(item)) elif "Exposure" in mapping.python: exp = item else: raise RuntimeError("Unrecognised python type: %s" % mapping.python) parent = super(PfsMapper, self) if hasattr(parent, "std_" + dataset): return getattr(parent, "std_" + dataset)(exp, dataId) return self._standardizeExposure(mapping, exp, dataId)
def setUp(self): maskedImage = afwImage.MaskedImageF(inFilePathSmall) maskedImageMD = afwImage.readMetadata(inFilePathSmall) self.smallExposure = afwImage.ExposureF(inFilePathSmall) self.width = maskedImage.getWidth() self.height = maskedImage.getHeight() self.wcs = afwImage.makeWcs(maskedImageMD) self.psf = DummyPsf(2.0) self.detector = DetectorWrapper().detector self.exposureBlank = afwImage.ExposureF() self.exposureMiOnly = afwImage.makeExposure(maskedImage) self.exposureMiWcs = afwImage.makeExposure(maskedImage, self.wcs) self.exposureCrWcs = afwImage.ExposureF( 100, 100, self.wcs) # n.b. the (100, 100, ...) form self.exposureCrOnly = afwImage.ExposureF(afwGeom.ExtentI( 100, 100)) # test with ExtentI(100, 100) too afwImage.Filter.reset() afwImage.FilterProperty.reset() filterPolicy = pexPolicy.Policy() filterPolicy.add("lambdaEff", 470.0) afwImage.Filter.define(afwImage.FilterProperty("g", filterPolicy))
def exposureFromImage(image, dataId=None, mapper=None, logger=None, setVisitInfo=True): """Generate an Exposure from an image-like object If the image is a DecoratedImage then also set its WCS and metadata (Image and MaskedImage are missing the necessary metadata and Exposure already has those set) Parameters ---------- image : Image-like object Can be one of lsst.afw.image.DecoratedImage, Image, MaskedImage or Exposure. Returns ------- `lsst.afw.image.Exposure` Exposure containing input image. """ metadata = None if isinstance(image, afwImage.MaskedImage): exposure = afwImage.makeExposure(image) elif isinstance(image, afwImage.DecoratedImage): exposure = afwImage.makeExposure(afwImage.makeMaskedImage(image.getImage())) metadata = image.getMetadata() try: wcs = afwGeom.makeSkyWcs(metadata, strip=True) exposure.setWcs(wcs) except pexExcept.TypeError as e: # raised on failure to create a wcs (and possibly others) if logger is None: logger = lsstLog.Log.getLogger("CameraMapper") logger.warn("wcs set to None; insufficient information found in metadata to create a valid wcs: " "%s", e.args[0]) exposure.setMetadata(metadata) elif isinstance(image, afwImage.Exposure): # Exposure exposure = image metadata = exposure.getMetadata() else: # Image exposure = afwImage.makeExposure(afwImage.makeMaskedImage(image)) # # set VisitInfo if we can # if setVisitInfo and exposure.getInfo().getVisitInfo() is None: if metadata is not None: if mapper is None: if not logger: logger = lsstLog.Log.getLogger("CameraMapper") logger.warn("I can only set the VisitInfo if you provide a mapper") else: exposureId = mapper._computeCcdExposureId(dataId) visitInfo = mapper.makeRawVisitInfo(md=metadata, exposureId=exposureId) exposure.getInfo().setVisitInfo(visitInfo) return exposure
def std_raw(self, item, dataId): md = item.getMetadata() md.set("LSSTAMP", "%(raft)s %(sensor)s %(channel)s" % dataId) newItem = afwImage.makeExposure( afwImage.makeMaskedImage(item.getImage())) newItem.setMetadata(md) return newItem
def makeExposure(bbox, scale, psfFwhm, flux): """Make a fake exposure @param bbox: Bounding box for image (Box2I) @param scale: Pixel scale (Angle) @param psfFwhm: PSF FWHM (arcseconds) @param flux: PSF flux (ADU) @return Exposure, source center """ image = afwImage.ImageF(bbox) image.set(0) center = afwGeom.Box2D(bbox).getCenter() psfSigma = psfFwhm/SIGMA_TO_FWHM/scale.asArcseconds() psfWidth = 2*int(4.0*psfSigma) + 1 psf = afwDetection.GaussianPsf(psfWidth, psfWidth, psfSigma) psfImage = psf.computeImage(center).convertF() psfFlux = psfImage.getArray().sum() psfImage *= flux/psfFlux subImage = afwImage.ImageF(image, psfImage.getBBox(afwImage.PARENT), afwImage.PARENT) subImage += psfImage exp = afwImage.makeExposure(afwImage.makeMaskedImage(image)) exp.setPsf(psf) exp.getMaskedImage().getVariance().set(1.0) exp.getMaskedImage().getMask().set(0) exp.setWcs(afwImage.makeWcs(afwCoord.Coord(0.0*afwGeom.degrees, 0.0*afwGeom.degrees), center, scale.asDegrees(), 0.0, 0.0, scale.asDegrees())) return exp, center
def createFringe(width, height, xFreq, xOffset, yFreq, yOffset): """Create a fringe frame. Parameters ---------- width, height : `int` Size of image. xFreq, yFreq : `float` Frequency of sinusoids in x and y. xOffset, yOffset : `float` Phase of sinusoids in x and y. Returns ------- exp : `lsst.afw.image.ExposureF` Fringe frame. """ image = afwImage.ImageF(width, height) array = image.getArray() x, y = np.indices(array.shape) array[x, y] = np.sin(xFreq*x + xOffset) + np.sin(yFreq*y + yOffset) mi = afwImage.makeMaskedImage(image) exp = afwImage.makeExposure(mi) exp.setFilter(afwImage.Filter('FILTER')) return exp
def testMultiple(self, pedestal=0.0): """Test subtraction of multiple fringe frames Paramters --------- pedestal : `float`, optional Pedestal to add into fringe frame. """ xFreqList = [0.1, 0.13, 0.06] xOffsetList = [0.0, 0.1, 0.2] yFreqList = [0.09, 0.12, 0.07] yOffsetList = [0.3, 0.2, 0.1] fringeList = [createFringe(self.size, self.size, xFreq, xOffset, yFreq, yOffset) for xFreq, xOffset, yFreq, yOffset in zip(xFreqList, xOffsetList, yFreqList, yOffsetList)] for fringe in fringeList: fMi = fringe.getMaskedImage() fMi += pedestal # Generate science frame scales = [0.33, 0.33, 0.33] image = afwImage.ImageF(self.size, self.size) image.set(0) for s, f in zip(scales, fringeList): image.scaledPlus(s, f.getMaskedImage().getImage()) mi = afwImage.makeMaskedImage(image) exp = afwImage.makeExposure(mi) exp.setFilter(afwImage.Filter('FILTER')) task = FringeTask(name="multiFringe", config=self.config) self.checkFringe(task, exp, fringeList, stddevMax=1.0e-2)
def readFull(self, parameters=None): """Read the full Exposure object. Parameters ---------- parameters : `dict`, optional If specified, a dictionary of slicing parameters that overrides those in the `fileDescriptor` attribute. Returns ------- exposure : `~lsst.afw.image.Exposure` Complete in-memory exposure. """ from lsst.afw.image import makeExposure, makeMaskedImage full = makeExposure(makeMaskedImage(self.readImage())) mask = self.readMask() if mask is not None: full.setMask(mask) variance = self.readVariance() if variance is not None: full.setVariance(variance) full.setDetector(self.getDetector(self.observationInfo.detector_num)) info = full.getInfo() info.setFilter(self.makeFilter()) info.setVisitInfo(self.makeVisitInfo()) info.setWcs(self.makeWcs(info.getVisitInfo(), info.getDetector())) # We don't need to call stripMetadata() here because it has already # been stripped during creation of the ObservationInfo, WCS, etc. full.setMetadata(self.metadata) return full
def createFringe(width, height, xFreq, xOffset, yFreq, yOffset): """Create a fringe frame. Parameters ---------- width, height : `int` Size of image. xFreq, yFreq : `float` Frequency of sinusoids in x and y. xOffset, yOffset : `float` Phase of sinusoids in x and y. Returns ------- exp : `lsst.afw.image.ExposureF` Fringe frame. """ image = afwImage.ImageF(width, height) array = image.getArray() x, y = np.indices(array.shape) array[x, y] = np.sin(xFreq * x + xOffset) + np.sin(yFreq * y + yOffset) mi = afwImage.makeMaskedImage(image) exp = afwImage.makeExposure(mi) exp.setFilter(afwImage.FilterLabel(band='y', physical='FILTER')) return exp
def run(self, inputExp, camera): """Bin input image, attach associated detector. Parameters ---------- inputExp : `lsst.afw.image.Exposure` Input exposure data to bin. camera : `lsst.afw.cameraGeom.Camera` Input camera to use for mosaic geometry. Returns ------- output : `lsst.pipe.base.Struct` Results struct with attribute: ``outputExp`` Binned version of input image (`lsst.afw.image.Exposure`). """ if inputExp.getDetector() is None: detectorId = inputExp.getMetadata().get( self.config.detectorKeyword) if detectorId is not None: inputExp.setDetector(camera[detectorId]) binned = inputExp.getMaskedImage() binned = afwMath.binImage(binned, self.config.binning) outputExp = afwImage.makeExposure(binned) outputExp.setInfo(inputExp.getInfo()) return pipeBase.Struct(outputExp=outputExp, )
def makeExposure(self, im, mask=None, variance=None): """Method for constructing an exposure object from an image and the information contained in this class to construct the Detector. Parameters ---------- im : `lsst.afw.image.Image` Image used to construct the exposure. mask : `lsst.afw.image.MaskU` Optional mask plane. variance : `lsst.afw.image.Image` Optional variance plance as an image of the same type as im. Returns ------- exposure : `lsst.afw.image.Exposure` Constructed exposure (specific type will match that of ``im``). """ if mask is None: mask = afwImage.Mask(im.getDimensions()) if variance is None: variance = im mi = afwImage.makeMaskedImage(im, mask, variance) detector = self.buildDetector() exp = afwImage.makeExposure(mi) exp.setDetector(detector) return exp
def testMeasureCentroid(self): """Test that we can use our silly centroid through the usual Tasks""" algorithms.AlgorithmRegistry.register("centroid.silly", testLib.SillyCentroidControl) x, y = 10, 20 im = afwImage.MaskedImageF(afwGeom.ExtentI(512, 512)) im.set(0) arr = im.getImage().getArray() arr[y,x] = 1 exp = afwImage.makeExposure(im) schema = afwTable.SourceTable.makeMinimalSchema() detConfig = algorithms.SourceDetectionConfig() detConfig.thresholdValue = 0.5 detConfig.thresholdType = "value" measConfig = algorithms.SourceMeasurementConfig() measConfig.algorithms.names.add("centroid.silly") measConfig.slots.centroid = "centroid.silly" measConfig.algorithms["centroid.silly"].param = 5 measConfig.doReplaceWithNoise = False det = algorithms.SourceDetectionTask(schema=schema, config=detConfig) meas = algorithms.SourceMeasurementTask(schema, config=measConfig) table = afwTable.SourceTable.make(schema) sources = det.makeSourceCatalog(table, exp, doSmooth=False, sigma=1.0).sources self.assertEqual(len(sources), 1) meas.run(exp, sources) self.assertEqual(len(sources), 1) self.assertEqual(sources[0].getY(), y + 5)
def process(self): clipboard = self.inputQueue.getNextDataset() metadataPolicy = self._policy.getPolicy("metadata") datatypePolicy = self._policy.getPolicy("datatype") imageKeys = self._policy.getStringArray("calibImageKey") if self._policy.exists("suffix"): suffix = self._policy.get("suffix") else: suffix = "Keyword" for imageKey in imageKeys: exposureKey = re.sub(r'Image', 'Exposure', imageKey) dImage = clipboard.get(imageKey) mask = afwImage.MaskU(dImage.getDimensions()) mask.set(0) var = afwImage.ImageF(dImage.getDimensions()) var.set(0) maskedImage = afwImage.makeMaskedImage(dImage.getImage(), mask, var) metadata = dImage.getMetadata() exposure = afwImage.makeExposure(maskedImage) exposure.setMetadata(metadata) clipboard.put(exposureKey, exposure) self.outputQueue.addDataset(clipboard)
def makeExposure(bbox, scale, psfFwhm, flux): """Make a fake exposure @param bbox: Bounding box for image (Box2I) @param scale: Pixel scale (Angle) @param psfFwhm: PSF FWHM (arcseconds) @param flux: PSF flux (ADU) @return Exposure, source center """ image = afwImage.ImageF(bbox) image.set(0) center = afwGeom.Box2D(bbox).getCenter() psfSigma = psfFwhm / SIGMA_TO_FWHM / scale.asArcseconds() psfWidth = 2 * int(4.0 * psfSigma) + 1 psf = afwDetection.GaussianPsf(psfWidth, psfWidth, psfSigma) psfImage = psf.computeImage(center).convertF() psfFlux = psfImage.getArray().sum() psfImage *= flux / psfFlux subImage = afwImage.ImageF(image, psfImage.getBBox(afwImage.PARENT), afwImage.PARENT) subImage += psfImage exp = afwImage.makeExposure(afwImage.makeMaskedImage(image)) exp.setPsf(psf) exp.getMaskedImage().getVariance().set(1.0) exp.getMaskedImage().getMask().set(0) exp.setWcs( afwImage.makeWcs( afwCoord.Coord(0.0 * afwGeom.degrees, 0.0 * afwGeom.degrees), center, scale.asDegrees(), 0.0, 0.0, scale.asDegrees())) return exp, center
def setUp(self): self.nx = 64 self.ny = 64 self.kwid = 15 self.sky = 100.0 self.val = 10000.0 self.sigma = 4.0 coordList = [[self.nx / 2, self.ny / 2, self.val, self.sigma]] # exposure with gaussian bbox = afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(self.nx, self.ny)) self.expGaussPsf = plantSources(bbox, self.kwid, self.sky, coordList, addPoissonNoise=False) # just plain sky (ie. a constant) self.mimg = afwImage.MaskedImageF(afwGeom.ExtentI(self.nx, self.ny)) self.mimg.set(self.sky, 0x0, self.sky) self.expSky = afwImage.makeExposure(self.mimg) if display > 1: ds9.mtv(self.expGaussPsf)
def readFull(self, fileDescriptor, parameters=None): """Read the full Exposure object. Parameters ---------- fileDescriptor : `FileDescriptor` Identifies the file to read and parameters to be used for reading. parameters : `dict`, optional If specified a dictionary of slicing parameters that overrides those in ``fileDescriptor`. Returns ------- exposure : `~lsst.afw.image.Exposure` Complete in-memory exposure. """ from lsst.afw.image import makeExposure, makeMaskedImage full = makeExposure(makeMaskedImage(self.readImage(fileDescriptor))) mask = self.readMask(fileDescriptor) if mask is not None: full.setMask(mask) variance = self.readVariance(fileDescriptor) if variance is not None: full.setVariance(variance) metadata = self.readMetadata(fileDescriptor) info = full.getInfo() info.setWcs(self.makeWcs(metadata)) info.setFilter(self.makeFilter(metadata)) info.setVisitInfo(self.makeVisitInfo(metadata)) # We shouldn't have to call stripMetadata() here because that should # have been done by makeVisitInfo and makeWcs (or by subclasses that # strip metadata for other components when constructing them). full.setMetadata(metadata) return full
def _standardizeMasterCal(self, datasetType, item, dataId, setFilter=False): """Standardize a MasterCal image obtained from NOAO archive into Exposure These MasterCal images are MEF files with one HDU for each detector. Some WCS header, eg CTYPE1, exists only in the zeroth extensionr, so info in the zeroth header need to be copied over to metadata. @param datasetType: Dataset type ("bias" or "flat") @param item: The image read by the butler @param dataId: Data identifier @param setFilter: Whether to set the filter in the Exposure @return (lsst.afw.image.Exposure) the standardized Exposure """ mi = afwImage.makeMaskedImage(item.getImage()) md = item.getMetadata() masterCalMap = getattr(self, "map_" + datasetType) masterCalPath = masterCalMap(dataId).getLocations()[0] headerPath = re.sub(r'[\[](\d+)[\]]$', "[0]", masterCalPath) md0 = afwImage.readMetadata(headerPath) for kw in ('CTYPE1', 'CTYPE2', 'CRVAL1', 'CRVAL2', 'CUNIT1', 'CUNIT2', 'CD1_1', 'CD1_2', 'CD2_1', 'CD2_2'): if kw in md0.paramNames() and kw not in md.paramNames(): md.add(kw, md0.get(kw)) wcs = afwImage.makeWcs(md, True) exp = afwImage.makeExposure(mi, wcs) exp.setMetadata(md) return self._standardizeExposure(self.calibrations[datasetType], exp, dataId, filter=setFilter)
def testMeasureCentroid(self): """Test that we can use our silly centroid through the usual Tasks""" algorithms.AlgorithmRegistry.register("centroid.silly", testLib.SillyCentroidControl) x, y = 10, 20 im = afwImage.MaskedImageF(afwGeom.ExtentI(512, 512)) im.set(0) arr = im.getImage().getArray() arr[y, x] = 1 exp = afwImage.makeExposure(im) schema = afwTable.SourceTable.makeMinimalSchema() detConfig = algorithms.SourceDetectionConfig() detConfig.thresholdValue = 0.5 detConfig.thresholdType = "value" measConfig = algorithms.SourceMeasurementConfig() measConfig.algorithms.names.add("centroid.silly") measConfig.slots.centroid = "centroid.silly" measConfig.algorithms["centroid.silly"].param = 5 measConfig.doReplaceWithNoise = False det = algorithms.SourceDetectionTask(schema=schema, config=detConfig) meas = algorithms.SourceMeasurementTask(schema, config=measConfig) table = afwTable.SourceTable.make(schema) sources = det.makeSourceCatalog(table, exp, doSmooth=False, sigma=1.0).sources self.assertEqual(len(sources), 1) meas.run(exp, sources) self.assertEqual(len(sources), 1) self.assertEqual(sources[0].getY(), y + 5)
def readRawFile(fileName, dataId={}, detector=None): """Read a raw file from fileName, assembling it nicely. Parameters ---------- filename : `str` The fully-qualified filename. dataId : `lsst.daf.persistence.DataId` If provided, used to look up e.g. the filter. detector : `lsst.afw.cameraGeom.Detector` If provided, add this detector to the returned Exposure Returns ------- exposure : `lsst.afw.image.Exposure` The assembled exposure from the supplied filename. """ class Info(): def __init__(self, obj): self.obj = obj amps = [] for hdu in range(1, 16+1): exp = afwImage.makeExposure(afwImage.makeMaskedImage(afwImage.ImageF(fileName, hdu=hdu))) exp.setDetector(detector) amps.append(exp) component_info = {} component_info["raw_hdu"] = Info(afwImage.readMetadata(fileName, hdu=0)) component_info["raw_amp"] = Info(amps) exp = assemble_raw(dataId, component_info, None) return exp
def backgroundToExposure(self, statsImage, bbox): """Convert a background model to an exposure Calibs need to be persisted as an Exposure, so we need to convert the background model to an Exposure. Parameters ---------- statsImage : `lsst.afw.image.MaskedImageF` Background model's statistics image. bbox : `lsst.afw.geom.Box2I` Bounding box for image. Returns ------- exp : `lsst.afw.image.Exposure` Background model in Exposure format. """ exp = afwImage.makeExposure(statsImage) header = exp.getMetadata() header.set("BOX.MINX", bbox.getMinX()) header.set("BOX.MINY", bbox.getMinY()) header.set("BOX.MAXX", bbox.getMaxX()) header.set("BOX.MAXY", bbox.getMaxY()) header.set("ALGORITHM", self.config.background.algorithm) return exp
def testCircularApertureMeasure(self): mi = afwImage.MaskedImageF(afwGeom.ExtentI(100, 200)) mi.set(10) # # Create our measuring engine # radii = ( 1.0, 5.0, 10.0) # radii to use control = measBase.ApertureFluxControl() control.radii = radii exp = afwImage.makeExposure(mi) x0, y0 = 1234, 5678 exp.setXY0(afwGeom.Point2I(x0, y0)) plugin, cat = makePluginAndCat(measBase.CircularApertureFluxAlgorithm, "test", control, True, centroid="centroid") source = cat.makeRecord() source.set("centroid_x", 30+x0) source.set("centroid_y", 50+y0) plugin.measure(source, exp) for r in radii: currentFlux = source.get("%s_flux" % measBase.CircularApertureFluxAlgorithm.makeFieldPrefix("test", r)) self.assertAlmostEqual(10.0*math.pi*r*r/currentFlux, 1.0, places=4)
def testMultiple(self, pedestal=0.0): """Test subtraction of multiple fringe frames Paramters --------- pedestal : `float`, optional Pedestal to add into fringe frame. """ xFreqList = [0.1, 0.13, 0.06] xOffsetList = [0.0, 0.1, 0.2] yFreqList = [0.09, 0.12, 0.07] yOffsetList = [0.3, 0.2, 0.1] fringeList = [ createFringe(self.size, self.size, xFreq, xOffset, yFreq, yOffset) for xFreq, xOffset, yFreq, yOffset in zip( xFreqList, xOffsetList, yFreqList, yOffsetList) ] for fringe in fringeList: fMi = fringe.getMaskedImage() fMi += pedestal # Generate science frame scales = [0.33, 0.33, 0.33] image = afwImage.ImageF(self.size, self.size) image.set(0) for s, f in zip(scales, fringeList): image.scaledPlus(s, f.getMaskedImage().getImage()) mi = afwImage.makeMaskedImage(image) exp = afwImage.makeExposure(mi) exp.setFilter(afwImage.FilterLabel(physical='FILTER')) task = FringeTask(name="multiFringe", config=self.config) self.checkFringe(task, exp, fringeList, stddevMax=1.0e-2)
def makeTestImage(xsize=200, ysize=100, nCR=15): randArr = numpy.random.poisson(1000., xsize * ysize) randArr = numpy.array(randArr.reshape(ysize, xsize), dtype=numpy.float32) # force to ImageF factory = measAlg.GaussianPsfFactory() factory.addWing = False psf = factory.apply(4) # FWHM in pixels img = afwImage.makeImageFromArray(randArr) var = afwImage.ImageF(img, True) # copy constructor mask = afwImage.Mask(xsize, ysize) xind = numpy.random.randint(0, xsize, nCR) yind = numpy.random.randint(0, ysize, nCR) # set some CRs for xi, yi in zip(xind, yind): xi, yi = int(xi), int(yi) img.set(xi, yi, 1e6) mi = afwImage.makeMaskedImage(img, mask, var) exp = afwImage.makeExposure(mi) exp.setPsf(psf) return exp
def testCircularApertureMeasure(self): mi = afwImage.MaskedImageF(afwGeom.ExtentI(100, 200)) mi.set(10) # # Create our measuring engine # radii = (1.0, 5.0, 10.0) # radii to use control = measBase.ApertureFluxControl() control.radii = radii exp = afwImage.makeExposure(mi) x0, y0 = 1234, 5678 exp.setXY0(afwGeom.Point2I(x0, y0)) plugin, cat = makePluginAndCat(measBase.CircularApertureFluxAlgorithm, "test", control, True, centroid="centroid") source = cat.makeRecord() source.set("centroid_x", 30 + x0) source.set("centroid_y", 50 + y0) plugin.measure(source, exp) for r in radii: currentFlux = source.get( "%s_flux" % measBase.CircularApertureFluxAlgorithm.makeFieldPrefix( "test", r)) self.assertAlmostEqual(10.0 * math.pi * r * r / currentFlux, 1.0, places=4)
def testApplyCentroid(self): """Test that we can instantiate and play with SillyMeasureCentroid. """ for imageFactory in ( afwImage.MaskedImageF, ): im = imageFactory(lsst.geom.ExtentI(100, 100)) exp = afwImage.makeExposure(im) for offset in (0, 1, 2): control = testLib.SillyCentroidControl() control.param = offset x, y = 10, 20 schema = afwTable.SourceTable.makeMinimalSchema() schema.addField("centroid_x", type=np.float64) schema.addField("centroid_y", type=np.float64) schema.getAliasMap().set("slot_Centroid", "centroid") plugin = testLib.SillyCentroidAlgorithm(control, "test", schema) measCat = afwTable.SourceCatalog(schema) source = measCat.makeRecord() source.set("centroid_x", x) source.set("centroid_y", y) plugin.measure(source, exp) self.assertEqual(x, source.get("test_x") - offset) self.assertEqual(y, source.get("test_y") - offset)
def testApertureMeasure(self): mi = afwImage.MaskedImageF(afwGeom.ExtentI(100, 200)) mi.set(10) # # Create our measuring engine # radii = (1.0, 5.0, 10.0) # radii to use fluxes = [50.0, 810.0, 3170.0] # corresponding correct fluxes control = measAlg.ApertureFluxControl() control.radii = radii exp = afwImage.makeExposure(mi) x0, y0 = 1234, 5678 exp.setXY0(afwGeom.Point2I(x0, y0)) schema = afwTable.SourceTable.makeMinimalSchema() mp = measAlg.MeasureSourcesBuilder().addAlgorithm(control).build( schema) table = afwTable.SourceTable.make(schema) source = table.makeRecord() mp.apply(source, exp, afwGeom.Point2D(30 + x0, 50 + y0)) measured = source[control.name] for i, f in enumerate(fluxes): self.assertEqual(f, measured[i])
def createDipole(w, h, xc, yc, scaling=100.0, fracOffset=1.2): # Make random noise image: set image plane to normal distribution image = afwImage.MaskedImageF(w, h) image.set(0) array = image.getImage().getArray() array[:, :] = np.random.randn(w, h) # Set variance to 1.0 var = image.getVariance() var.set(1.0) if display: ds9.mtv(image, frame=1, title="Original image") ds9.mtv(image.getVariance(), frame=2, title="Original variance") # Create Psf for dipole creation and measurement psfSize = 17 psf = measAlg.DoubleGaussianPsf(psfSize, psfSize, 2.0, 3.5, 0.1) psfFwhmPix = sigma2fwhm * psf.computeShape().getDeterminantRadius() psfim = psf.computeImage().convertF() psfim *= scaling / psf.computePeak() psfw, psfh = psfim.getDimensions() psfSum = np.sum(psfim.getArray()) # Create the dipole, offset by fracOffset of the Psf FWHM (pixels) offset = fracOffset * psfFwhmPix // 2 array = image.getImage().getArray() xp, yp = xc - psfw // 2 + offset, yc - psfh // 2 + offset array[yp:yp + psfh, xp:xp + psfw] += psfim.getArray() xn, yn = xc - psfw // 2 - offset, yc - psfh // 2 - offset array[yn:yn + psfh, xn:xn + psfw] -= psfim.getArray() if display: ds9.mtv(image, frame=3, title="With dipole") # Create an exposure, detect positive and negative peaks separately exp = afwImage.makeExposure(image) exp.setPsf(psf) config = measAlg.SourceDetectionConfig() config.thresholdPolarity = "both" config.reEstimateBackground = False schema = afwTable.SourceTable.makeMinimalSchema() task = measAlg.SourceDetectionTask(schema, config=config) table = afwTable.SourceTable.make(schema) results = task.makeSourceCatalog(table, exp) if display: ds9.mtv(image, frame=4, title="Detection plane") # Merge them together assert (len(results.sources) == 2) fpSet = results.fpSets.positive fpSet.merge(results.fpSets.negative, 0, 0, False) sources = afwTable.SourceCatalog(table) fpSet.makeSources(sources) assert (len(sources) == 1) s = sources[0] assert (len(s.getFootprint().getPeaks()) == 2) return psf, psfSum, exp, s
def createDipole(w, h, xc, yc, scaling = 100.0, fracOffset = 1.2): # Make random noise image: set image plane to normal distribution image = afwImage.MaskedImageF(w,h) image.set(0) array = image.getImage().getArray() array[:,:] = np.random.randn(w,h) # Set variance to 1.0 var = image.getVariance() var.set(1.0) if display: ds9.mtv(image, frame=1, title="Original image") ds9.mtv(image.getVariance(), frame=2, title="Original variance") # Create Psf for dipole creation and measurement psfSize = 17 psf = measAlg.DoubleGaussianPsf(psfSize, psfSize, 2.0, 3.5, 0.1) psfFwhmPix = sigma2fwhm * psf.computeShape().getDeterminantRadius() psfim = psf.computeImage().convertF() psfim *= scaling / psf.computePeak() psfw, psfh = psfim.getDimensions() psfSum = np.sum(psfim.getArray()) # Create the dipole, offset by fracOffset of the Psf FWHM (pixels) offset = fracOffset * psfFwhmPix // 2 array = image.getImage().getArray() xp, yp = xc - psfw//2 + offset, yc - psfh//2 + offset array[yp:yp+psfh, xp:xp+psfw] += psfim.getArray() xn, yn = xc - psfw//2 - offset, yc - psfh//2 - offset array[yn:yn+psfh, xn:xn+psfw] -= psfim.getArray() if display: ds9.mtv(image, frame=3, title="With dipole") # Create an exposure, detect positive and negative peaks separately exp = afwImage.makeExposure(image) exp.setPsf(psf) config = measAlg.SourceDetectionConfig() config.thresholdPolarity = "both" config.reEstimateBackground = False schema = afwTable.SourceTable.makeMinimalSchema() task = measAlg.SourceDetectionTask(schema, config=config) table = afwTable.SourceTable.make(schema) results = task.makeSourceCatalog(table, exp) if display: ds9.mtv(image, frame=4, title="Detection plane") # Merge them together assert(len(results.sources) == 2) fpSet = results.fpSets.positive fpSet.merge(results.fpSets.negative, 0, 0, False) sources = afwTable.SourceCatalog(table) fpSet.makeSources(sources) assert(len(sources) == 1) s = sources[0] assert(len(s.getFootprint().getPeaks()) == 2) return psf, psfSum, exp, s
def std_dark(self, item, dataId): exp = afwImage.makeExposure(afwImage.makeMaskedImage(item)) rawPath = self.map_raw(dataId).getLocations()[0] headerPath = re.sub(r'[\[](\d+)[\]]$', "[0]", rawPath) md0 = afwImage.readMetadata(headerPath) visitInfo = self.makeRawVisitInfo(md0) exp.getInfo().setVisitInfo(visitInfo) return self._standardizeExposure(self.calibrations["dark"], exp, dataId, filter=False)
def setUp(self): width, height = 100, 300 self.mi = afwImage.MaskedImageF(afwGeom.ExtentI(width, height)) self.mi.set(0) self.mi.getVariance().set(10) self.mi.getMask().addMaskPlane("DETECTED") self.FWHM = 5 self.ksize = 25 # size of desired kernel self.exposure = afwImage.makeExposure(self.mi) psf = roundTripPsf(2, algorithms.DoubleGaussianPsf(self.ksize, self.ksize, self.FWHM/(2*sqrt(2*log(2))), 1, 0.1)) self.exposure.setPsf(psf) for x, y in [(20, 20), #(30, 35), (50, 50), (60, 20), (60, 210), (20, 210)]: flux = 10000 - 0*x - 10*y sigma = 3 + 0.01*(y - self.mi.getHeight()/2) psf = roundTripPsf(3, algorithms.DoubleGaussianPsf(self.ksize, self.ksize, sigma, 1, 0.1)) im = psf.computeImage().convertF() im *= flux smi = self.mi.getImage().Factory(self.mi.getImage(), afwGeom.BoxI(afwGeom.PointI(x - self.ksize/2, y - self.ksize/2), afwGeom.ExtentI(self.ksize)), afwImage.LOCAL) if False: # Test subtraction with non-centered psfs im = afwMath.offsetImage(im, 0.5, 0.5) smi += im del psf; del im; del smi psf = roundTripPsf(4, algorithms.DoubleGaussianPsf(self.ksize, self.ksize, self.FWHM/(2*sqrt(2*log(2))), 1, 0.1)) self.cellSet = afwMath.SpatialCellSet(afwGeom.BoxI(afwGeom.PointI(0, 0), afwGeom.ExtentI(width, height)), 100) ds = afwDetection.FootprintSet(self.mi, afwDetection.Threshold(10), "DETECTED") # # Prepare to measure # msConfig = algorithms.SourceMeasurementConfig() msConfig.load("tests/config/MeasureSources.py") schema = afwTable.SourceTable.makeMinimalSchema() measureSources = msConfig.makeMeasureSources(schema) catalog = afwTable.SourceCatalog(schema) msConfig.slots.calibFlux = None msConfig.slots.setupTable(catalog.table) ds.makeSources(catalog) for i, source in enumerate(catalog): measureSources.applyWithPeak(source, self.exposure) self.cellSet.insertCandidate(algorithms.makePsfCandidate(source, self.exposure))
def testFailures(self): """Test deblender failure flagging (#2871) We create a good source which is expected to pass and a bad source which is expected to fail because its footprint goes off the image. This latter case may not happen in practise, but it is useful for checking the plumbing of the deblender. """ import lsst.meas.deblender as measDeb self.checkDeblender() xGood, yGood = 57, 86 # Required to be in image so we can evaluate the PSF; will put neighbour just outside xBad, yBad = 0, 0 flux = 100.0 dims = afwGeom.Extent2I(128, 128) mi = afwImage.MaskedImageF(dims) mi.getVariance().set(1.0) image = mi.getImage() image.set(0) image[xGood, yGood, afwImage.LOCAL] = flux exposure = afwImage.makeExposure(mi) psf = algorithms.DoubleGaussianPsf(21, 21, 3.) exposure.setPsf(psf) schema = afwTable.SourceTable.makeMinimalSchema() config = measDeb.SourceDeblendConfig() config.catchFailures = True task = measDeb.SourceDeblendTask(schema, config=config) catalog = afwTable.SourceCatalog(schema) def makeSource(x, y, offset=-2, size=3.0): """Make a source in the catalog Two peaks are created: one at the specified position, and one offset in x,y. The footprint is of the nominated size. """ src = catalog.addNew() spans = afwGeom.SpanSet.fromShape(int(size), offset=(x, y)) foot = afwDetection.Footprint(spans) foot.addPeak(x, y, flux) foot.addPeak(x + offset, y + offset, flux) src.setFootprint(foot) return src good = makeSource(xGood, yGood) bad = makeSource(xBad, yBad) task.run(exposure, catalog) self.assertFalse(good.get('deblend_failed')) self.assertTrue(bad.get('deblend_failed'))
def getExposure(self): """Construct a test exposure. The test exposure has a simple WCS set, as well as a list of unlikely header keywords that can be removed during ISR processing to exercise that code. Returns ------- exposure : `lsst.afw.exposure.Exposure` Construct exposure containing masked image of the appropriate size. """ camera = self.getCamera() detector = camera[self.config.detectorIndex] image = afwUtils.makeImageFromCcd(detector, isTrimmed=self.config.isTrimmed, showAmpGain=False, rcMarkSize=0, binSize=1, imageFactory=afwImage.ImageF) var = afwImage.ImageF(image.getDimensions()) mask = afwImage.Mask(image.getDimensions()) image.assign(0.0) maskedImage = afwImage.makeMaskedImage(image, mask, var) exposure = afwImage.makeExposure(maskedImage) exposure.setDetector(detector) exposure.setWcs(self.getWcs()) visitInfo = afwImage.VisitInfo(exposureTime=self.config.expTime, darkTime=self.config.darkTime) exposure.getInfo().setVisitInfo(visitInfo) metadata = exposure.getMetadata() metadata.add("SHEEP", 7.3, "number of sheep on farm") metadata.add("MONKEYS", 155, "monkeys per tree") metadata.add("VAMPIRES", 4, "How scary are vampires.") ccd = exposure.getDetector() newCcd = ccd.rebuild() newCcd.clear() for amp in ccd: newAmp = amp.rebuild() newAmp.setLinearityCoeffs((0., 1., 0., 0.)) newAmp.setLinearityType("Polynomial") newAmp.setGain(self.config.gain) newAmp.setSuspectLevel(25000.0) newAmp.setSaturation(32000.0) newCcd.append(newAmp) exposure.setDetector(newCcd.finish()) exposure.image.array[:] = np.zeros(exposure.getImage().getDimensions()).transpose() exposure.mask.array[:] = np.zeros(exposure.getMask().getDimensions()).transpose() exposure.variance.array[:] = np.zeros(exposure.getVariance().getDimensions()).transpose() return exposure
def makeExpFromIm(im, detector): wcs = makeFakeWcs() var = afwImage.ImageF(im) mask = afwImage.MaskU(im.getDimensions()) mi = afwImage.makeMaskedImage(im, mask, var) exp = afwImage.makeExposure(mi) exp.setDetector(detector) exp.setWcs(wcs) return exp
def standardizeCalib(self, dataset, item, dataId): mapping = self.calibrations[dataset] if "Image" in mapping.python: exp = afwImage.makeMaskedImage(item) exp = afwImage.makeExposure(exp) exp = self._standardizeExposure(mapping, exp, \ dataId, filter=False, trimmed=False) return exp
def testFailures(self): """Test deblender failure flagging (#2871) We create a good source which is expected to pass and a bad source which is expected to fail because its footprint goes off the image. This latter case may not happen in practise, but it is useful for checking the plumbing of the deblender. """ import lsst.meas.deblender as measDeb self.checkDeblender() xGood, yGood = 57, 86 # Required to be in image so we can evaluate the PSF; will put neighbour just outside xBad, yBad = 0, 0 flux = 100.0 dims = geom.Extent2I(128, 128) mi = afwImage.MaskedImageF(dims) mi.getVariance().set(1.0) image = mi.getImage() image.set(0) image[xGood, yGood, afwImage.LOCAL] = flux exposure = afwImage.makeExposure(mi) psf = algorithms.DoubleGaussianPsf(21, 21, 3.) exposure.setPsf(psf) schema = afwTable.SourceTable.makeMinimalSchema() config = measDeb.SourceDeblendConfig() config.catchFailures = True task = measDeb.SourceDeblendTask(schema, config=config) catalog = afwTable.SourceCatalog(schema) def makeSource(x, y, offset=-2, size=3.0): """Make a source in the catalog Two peaks are created: one at the specified position, and one offset in x,y. The footprint is of the nominated size. """ src = catalog.addNew() spans = afwGeom.SpanSet.fromShape(int(size), offset=(x, y)) foot = afwDetection.Footprint(spans) foot.addPeak(x, y, flux) foot.addPeak(x + offset, y + offset, flux) src.setFootprint(foot) return src good = makeSource(xGood, yGood) bad = makeSource(xBad, yBad) task.run(exposure, catalog) self.assertFalse(good.get('deblend_failed')) self.assertTrue(bad.get('deblend_failed'))
def make_exposure(*args): """ Create an Exposure object from the supplied arguments. exposure = make_exposure(mi) """ # Convert the argument list to swig arguments as required newargs = h.swigify(args) _swig_object = afwImage.makeExposure(*newargs) return Exposure(_external=_swig_object)
def plantSources(bbox, kwid, sky, coordList, addPoissonNoise=True): """Make an exposure with stars (modelled as Gaussians) @param bbox: parent bbox of exposure @param kwid: kernel width (and height; kernel is square) @param sky: amount of sky background (counts) @param coordList: a list of [x, y, counts, sigma], where: * x,y are relative to exposure origin * counts is the integrated counts for the star * sigma is the Gaussian sigma in pixels @param addPoissonNoise: add Poisson noise to the exposure? """ # make an image with sources img = afwImage.ImageD(bbox) meanSigma = 0.0 for coord in coordList: x, y, counts, sigma = coord meanSigma += sigma # make a single gaussian psf psf = SingleGaussianPsf(kwid, kwid, sigma) # make an image of it and scale to the desired number of counts thisPsfImg = psf.computeImage(afwGeom.PointD(x, y)) thisPsfImg *= counts # bbox a window in our image and add the fake star image psfBox = thisPsfImg.getBBox() psfBox.clip(bbox) if psfBox != thisPsfImg.getBBox(): thisPsfImg = thisPsfImg[psfBox, afwImage.PARENT] imgSeg = img[psfBox, afwImage.PARENT] imgSeg += thisPsfImg meanSigma /= len(coordList) img += sky # add Poisson noise if (addPoissonNoise): np.random.seed(seed=1) # make results reproducible imgArr = img.getArray() imgArr[:] = np.random.poisson(imgArr) # bundle into a maskedimage and an exposure mask = afwImage.Mask(bbox) var = img.convertFloat() img -= sky mimg = afwImage.MaskedImageF(img.convertFloat(), mask, var) exposure = afwImage.makeExposure(mimg) # insert an approximate psf psf = SingleGaussianPsf(kwid, kwid, meanSigma) exposure.setPsf(psf) return exposure
def runMeasurement(self, algorithmName, imageid, x, y, v): """Run the measurement algorithm on an image""" # load the test image imgFile = os.path.join(self.dataDir, "image.%d.fits" % imageid) img = afwImage.ImageF(imgFile) img -= self.bkgd nx, ny = img.getWidth(), img.getHeight() msk = afwImage.Mask(geom.Extent2I(nx, ny), 0x0) var = afwImage.ImageF(geom.Extent2I(nx, ny), v) mimg = afwImage.MaskedImageF(img, msk, var) msk.getArray()[:] = np.where(np.fabs(img.getArray()) < 1.0e-8, msk.getPlaneBitMask("BAD"), 0) # Put it in a bigger image, in case it matters big = afwImage.MaskedImageF(self.offset + mimg.getDimensions()) big.getImage().set(0) big.getMask().set(0) big.getVariance().set(v) subBig = afwImage.MaskedImageF(big, geom.Box2I(big.getXY0() + self.offset, mimg.getDimensions())) subBig <<= mimg mimg = big mimg.setXY0(self.xy0) exposure = afwImage.makeExposure(mimg) cdMatrix = np.array([1.0/(2.53*3600.0), 0.0, 0.0, 1.0/(2.53*3600.0)]) cdMatrix.shape = (2, 2) exposure.setWcs(afwGeom.makeSkyWcs(crpix=geom.Point2D(1.0, 1.0), crval=geom.SpherePoint(0, 0, geom.degrees), cdMatrix=cdMatrix)) # load the corresponding test psf psfFile = os.path.join(self.dataDir, "psf.%d.fits" % imageid) psfImg = afwImage.ImageD(psfFile) psfImg -= self.bkgd kernel = afwMath.FixedKernel(psfImg) kernelPsf = algorithms.KernelPsf(kernel) exposure.setPsf(kernelPsf) # perform the shape measurement msConfig = base.SingleFrameMeasurementConfig() alg = base.SingleFramePlugin.registry[algorithmName].PluginClass.AlgClass control = base.SingleFramePlugin.registry[algorithmName].PluginClass.ConfigClass().makeControl() msConfig.algorithms.names = [algorithmName] # Note: It is essential to remove the floating point part of the position for the # Algorithm._apply. Otherwise, when the PSF is realised it will have been warped # to account for the sub-pixel offset and we won't get *exactly* this PSF. plugin, table = makePluginAndCat(alg, algorithmName, control, centroid="centroid") center = geom.Point2D(int(x), int(y)) + geom.Extent2D(self.offset + geom.Extent2I(self.xy0)) source = table.makeRecord() source.set("centroid_x", center.getX()) source.set("centroid_y", center.getY()) source.setFootprint(afwDetection.Footprint(afwGeom.SpanSet(exposure.getBBox(afwImage.PARENT)))) plugin.measure(source, exposure) return source
def testMaskedImage(self): scale = (1.0*afwGeom.arcseconds).asDegrees() wcs = afwImage.makeWcs(afwCoord.Coord(0.0*afwGeom.degrees, 0.0*afwGeom.degrees), afwGeom.Point2D(0.0, 0.0), scale, 0.0, 0.0, scale) for MaskedImage in (afwImage.MaskedImageF, afwImage.MaskedImageD, ): image = self.createMaskedImage(MaskedImage) self.checkImages(image) exposure = afwImage.makeExposure(image, wcs) self.checkExposures(exposure)
def setUp(self): maskedImage = afwImage.MaskedImageF(inFilePathSmall) maskedImageMD = afwImage.readMetadata(inFilePathSmall + "_img.fits") self.smallExposure = afwImage.ExposureF(inFilePathSmall) self.width = maskedImage.getWidth() self.height = maskedImage.getHeight() self.wcs = afwImage.makeWcs(maskedImageMD) self.exposureBlank = afwImage.ExposureF() self.exposureMiOnly = afwImage.makeExposure(maskedImage) self.exposureMiWcs = afwImage.makeExposure(maskedImage, self.wcs) self.exposureCrWcs = afwImage.ExposureF(100, 100, self.wcs) # n.b. the (100, 100, ...) form self.exposureCrOnly = afwImage.ExposureF(afwGeom.ExtentI(100, 100)) # test with ExtentI(100, 100) too afwImage.Filter.reset() afwImage.FilterProperty.reset() filterPolicy = pexPolicy.Policy() filterPolicy.add("lambdaEff", 470.0) afwImage.Filter.define(afwImage.FilterProperty("g", filterPolicy))
def makeGalaxy(width, height, flux, a, b, theta, dx=0.0, dy=0.0, xy0=None, xcen=None, ycen=None): """Make a fake galaxy image. """ gal = afwImage.ImageF(width, height) if xcen is None: xcen = 0.5*width + dx if ycen is None: ycen = 0.5*height + dy I0 = flux/(2*math.pi*a*b) if xy0 is not None: gal.setXY0(xy0) c, s = math.cos(math.radians(theta)), math.sin(math.radians(theta)) ii, iuu, ivv = 0.0, 0.0, 0.0 for y in range(height): for x in range(width): dx, dy = x + gal.getX0() - xcen, y + gal.getY0() - ycen if math.hypot(dx, dy) < 10.5: nsample = 5 subZ = np.linspace(-0.5*(1 - 1/nsample), 0.5*(1 - 1/nsample), nsample) else: nsample = 1 subZ = [0.0] val = 0 for sx in subZ: for sy in subZ: u = c*(dx + sx) + s*(dy + sy) v = -s*(dx + sx) + c*(dy + sy) val += I0*math.exp(-0.5*((u/a)**2 + (v/b)**2)) if val < 0: val = 0 gal[afwGeom.Point2I(x, y), afwImage.LOCAL] = val/nsample**2 ii += val iuu += val*u**2 ivv += val*v**2 iuu /= ii ivv /= ii exp = afwImage.makeExposure(afwImage.makeMaskedImage(gal)) exp.getMaskedImage().getVariance().set(1.0) scale = 1.0e-4*afwGeom.degrees cdMatrix = afwGeom.makeCdMatrix(scale=scale, flipX=True) exp.setWcs(afwGeom.makeSkyWcs(crpix=afwGeom.Point2D(0.0, 0.0), crval=afwGeom.SpherePoint(0.0, 0.0, afwGeom.degrees), cdMatrix=cdMatrix)) # add a dummy Psf. The new SdssCentroid needs one exp.setPsf(afwDetection.GaussianPsf(11, 11, 0.01)) return exp
def runMeasurement(self, algorithmName, imageid, x, y, v): """Run the measurement algorithm on an image""" # load the test image imgFile = os.path.join(self.dataDir, "image.%d.fits" % imageid) img = afwImage.ImageF(imgFile) img -= self.bkgd nx, ny = img.getWidth(), img.getHeight() msk = afwImage.MaskU(afwGeom.Extent2I(nx, ny), 0x0) var = afwImage.ImageF(afwGeom.Extent2I(nx, ny), v) mimg = afwImage.MaskedImageF(img, msk, var) msk.getArray()[:] = np.where(np.fabs(img.getArray()) < 1.0e-8, msk.getPlaneBitMask("BAD"), 0) # Put it in a bigger image, in case it matters big = afwImage.MaskedImageF(self.offset + mimg.getDimensions()) big.getImage().set(0) big.getMask().set(0) big.getVariance().set(v) subBig = afwImage.MaskedImageF(big, afwGeom.Box2I(big.getXY0() + self.offset, mimg.getDimensions())) subBig <<= mimg mimg = big mimg.setXY0(self.xy0) exposure = afwImage.makeExposure(mimg) exposure.setWcs(afwImage.makeWcs(afwCoord.makeCoord(afwCoord.ICRS, 0. * afwGeom.degrees, 0. * afwGeom.degrees), afwGeom.Point2D(1.0,1.0), 1.0/(2.53*3600.0), 0.0, 0.0, 1.0/(2.53*3600.0))) # load the corresponding test psf psfFile = os.path.join(self.dataDir, "psf.%d.fits" % imageid) psfImg = afwImage.ImageD(psfFile) psfImg -= self.bkgd kernel = afwMath.FixedKernel(psfImg) kernelPsf = algorithms.KernelPsf(kernel) exposure.setPsf(kernelPsf) # perform the shape measurement msConfig = base.SingleFrameMeasurementConfig() alg = base.SingleFramePlugin.registry[algorithmName].PluginClass.AlgClass control = base.SingleFramePlugin.registry[algorithmName].PluginClass.ConfigClass().makeControl() msConfig.algorithms.names = [algorithmName] # Note: It is essential to remove the floating point part of the position for the # Algorithm._apply. Otherwise, when the PSF is realised it will have been warped # to account for the sub-pixel offset and we won't get *exactly* this PSF. plugin, table = makePluginAndCat(alg, algorithmName, control, centroid="centroid") center = afwGeom.Point2D(int(x), int(y)) + afwGeom.Extent2D(self.offset + afwGeom.Extent2I(self.xy0)) source = table.makeRecord() source.set("centroid_x", center.getX()) source.set("centroid_y", center.getY()) source.setFootprint(afwDetection.Footprint(exposure.getBBox(afwImage.PARENT))) plugin.measure(source, exposure) return source
def testMaskedImage(self): scale = 1.0*lsst.geom.arcseconds wcs = afwGeom.makeSkyWcs(crval=lsst.geom.SpherePoint(0.0*lsst.geom.degrees, 0.0*lsst.geom.degrees), crpix=lsst.geom.Point2D(0.0, 0.0), cdMatrix=afwGeom.makeCdMatrix(scale=scale)) for MaskedImage in (afwImage.MaskedImageF, afwImage.MaskedImageD, ): image = self.createMaskedImage(MaskedImage) self.checkMaskedImages(image) exposure = afwImage.makeExposure(image, wcs) self.checkExposures(exposure)
def do_testAstrometry(self, alg, bkgd, control): """Test that we can instantiate and play with a centroiding algorithms""" schema = afwTable.SourceTable.makeMinimalSchema() schema.getAliasMap().set("slot_Centroid", "test") centroider = alg(control, "test", schema) table = afwTable.SourceCatalog(schema) x0, y0 = 12345, 54321 for imageFactory in (afwImage.MaskedImageF,): im = imageFactory(afwGeom.ExtentI(100, 100)) im.setXY0(afwGeom.Point2I(x0, y0)) # This fixed DoubleGaussianPsf replaces a computer generated one. # The values are not anything in particular, just a reasonable size. psf = lsst.afw.detection.GaussianPsf(15, 15, 3.0) exp = afwImage.makeExposure(im) exp.setPsf(psf) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- im.set(bkgd) x, y = 30, 20 im.set(x, y, (1010,)) source = table.addNew() foot = afwDetection.Footprint(exp.getBBox(afwImage.LOCAL)) foot.addPeak(x + x0, y + y0, 1010) source.setFootprint(foot) centroider.measure(source, exp) self.assertClose(x + x0, source.getX(), rtol=.00001) self.assertClose(y + y0, source.getY(), rtol=.00001) self.assertFalse(source.get("test_flag")) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- im.set(bkgd) im.set(10, 20, (1010,)) im.set(10, 21, (1010,)) im.set(11, 20, (1010,)) im.set(11, 21, (1010,)) x, y = 10.5 + x0, 20.5 + y0 source = table.addNew() source.set('test_x', x) source.set('test_y', y) centroider.measure(source, exp) self.assertClose(x, source.getX(), rtol=.00001) self.assertClose(y, source.getY(), rtol=.00001) self.assertFalse(source.get("test_flag"))
def plantSources(bbox, kwid, sky, coordList, addPoissonNoise=True): """Make an exposure with stars (modelled as Gaussians) @param bbox: parent bbox of exposure @param kwid: kernel width (and height; kernel is square) @param sky: amount of sky background (counts) @param coordList: a list of [x, y, counts, sigma], where: * x,y are relative to exposure origin * counts is the integrated counts for the star * sigma is the Gaussian sigma in pixels @param addPoissonNoise: add Poisson noise to the exposure? """ # make an image with sources img = afwImage.ImageD(bbox) meanSigma = 0.0 for coord in coordList: x, y, counts, sigma = coord meanSigma += sigma # make a single gaussian psf psf = afwDetection.GaussianPsf(kwid, kwid, sigma) # make an image of it and scale to the desired number of counts thisPsfImg = psf.computeImage(afwGeom.PointD(int(x), int(y))) thisPsfImg *= counts # bbox a window in our image and add the fake star image imgSeg = img.Factory(img, thisPsfImg.getBBox()) imgSeg += thisPsfImg meanSigma /= len(coordList) img += sky # add Poisson noise if (addPoissonNoise): numpy.random.seed(seed=1) # make results reproducible imgArr = img.getArray() imgArr[:] = numpy.random.poisson(imgArr) # bundle into a maskedimage and an exposure mask = afwImage.MaskU(bbox) var = img.convertFloat() img -= sky mimg = afwImage.MaskedImageF(img.convertFloat(), mask, var) exposure = afwImage.makeExposure(mimg) # insert an approximate psf psf = afwDetection.GaussianPsf(kwid, kwid, meanSigma) exposure.setPsf(psf) return exposure
def testWcs(self): """Test round-tripping an empty Wcs""" mi = afwImage.MaskedImageF(afwGeom.Extent2I(10, 20)) wcs = afwImage.Wcs() exp = afwImage.makeExposure(mi, wcs) tmpFile = "foo.fits" exp.writeFits(tmpFile) exp2 = type(exp)(tmpFile) self.assertFalse(exp2.getWcs()) os.remove(tmpFile)
def setUp(self): self.mi = afwImage.MaskedImageF(afwGeom.ExtentI(100, 100)) self.mi.set(0, 0x0, 1) self.exp = afwImage.makeExposure(self.mi) builder = measAlgorithms.MeasureSourcesBuilder() for conf in (measAlgorithms.NaiveFluxConfig(radius=10.0), measAlgorithms.PsfFluxConfig(), measAlgorithms.SincFluxConfig(radius2=3.0), ): builder.addAlgorithm(conf.makeControl()) self.schema = afwTable.SourceTable.makeMinimalSchema() self.measurePhotom = builder.build(self.schema)
def do_testAstrometry(self, control, bkgd): """Test that we can instantiate and play with a centroiding algorithms""" x0, y0 = 12345, 54321 for imageFactory in (afwImage.MaskedImageF, afwImage.MaskedImageD, ): im = imageFactory(afwGeom.ExtentI(100, 100)) im.setXY0(afwGeom.Point2I(x0, y0)) psf = testLib.makeTestPsf(im) exp = afwImage.makeExposure(im) exp.setPsf(psf) schema = afwTable.SourceTable.makeMinimalSchema() centroider = algorithms.MeasureSourcesBuilder().addAlgorithm(control).build(schema) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- im.set(bkgd) x, y = 30, 20 im.set(x, y, (1010,)) table = afwTable.SourceTable.make(schema) table.defineCentroid(control.name) source = table.makeRecord() foot = afwDetection.Footprint(exp.getBBox()) source.setFootprint(foot) centroider.apply(source, exp, afwGeom.Point2D(x + x0, y + y0)) self.assertEqual(x + x0, source.getX()) self.assertEqual(y + y0, source.getY()) self.assertFalse(source.get(control.name + ".flags")) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- im.set(bkgd) im.set(10, 20, (1010,)) im.set(10, 21, (1010,)) im.set(11, 20, (1010,)) im.set(11, 21, (1010,)) x, y = 10.5 + x0, 20.5 + y0 centroider.apply(source, exp, afwGeom.Point2D(x + 0.123, y - 0.123)) self.assertEqual(x, source.getX()) self.assertEqual(y, source.getY()) self.assertFalse(source.get(control.name + ".flags"))
def makeGalaxy(width, height, flux, a, b, theta, dx=0.0, dy=0.0, xy0=None, xcen=None, ycen=None): """Make a fake galaxy image""" gal = afwImage.ImageF(width, height) if xcen is None: xcen = 0.5*width + dx if ycen is None: ycen = 0.5*height + dy I0 = flux/(2*math.pi*a*b) if xy0 is not None: gal.setXY0(xy0) c, s = math.cos(math.radians(theta)), math.sin(math.radians(theta)) I, Iuu, Ivv = 0.0, 0.0, 0.0 for y in range(height): for x in range(width): dx, dy = x + gal.getX0() - xcen, y + gal.getY0() - ycen if math.hypot(dx, dy) < 10.5: nsample = float(5) subZ = np.linspace(-0.5*(1 - 1/nsample), 0.5*(1 - 1/nsample), nsample) else: nsample = 1 subZ = [0.0] val = 0 for sx in subZ: for sy in subZ: u = c*(dx + sx) + s*(dy + sy) v = -s*(dx + sx) + c*(dy + sy) val += I0*math.exp(-0.5*((u/a)**2 + (v/b)**2)) if val < 0: val = 0 gal.set(x, y, val/nsample**2) I += val Iuu += val*u**2 Ivv += val*v**2 Iuu /= I; Ivv /= I exp = afwImage.makeExposure(afwImage.makeMaskedImage(gal)) exp.getMaskedImage().getVariance().setXY0(exp.getXY0()) # workaround #2577 exp.getMaskedImage().getVariance().set(1.0) exp.setWcs(afwImage.makeWcs(afwCoord.Coord(0.0*afwGeom.degrees, 0.0*afwGeom.degrees), afwGeom.Point2D(0.0, 0.0), 1.0e-4, 0.0, 0.0, 1.0e-4)) # add a dummy Psf. The new SdssCentroid needs one exp.setPsf(afwDetection.GaussianPsf(11, 11, 0.01)) return exp
def getExposure(self): r"""Construct a test exposure. The test exposure has a simple WCS set, as well as a list of unlikely header keywords that can be removed during ISR processing to exercise that code. Returns ------- exposure : `lsst.afw.exposure.Exposure` Construct exposure containing masked image of the appropriate size. """ camera = self.getCamera() detector = camera[self.config.detectorIndex] image = afwUtils.makeImageFromCcd(detector, isTrimmed=self.config.isTrimmed, showAmpGain=False, rcMarkSize=0, binSize=1, imageFactory=afwImage.ImageF) var = afwImage.ImageF(image.getDimensions()) mask = afwImage.Mask(image.getDimensions()) image.assign(0.0) maskedImage = afwImage.makeMaskedImage(image, mask, var) exposure = afwImage.makeExposure(maskedImage) exposure.setDetector(detector) exposure.setWcs(self.getWcs()) visitInfo = afwImage.VisitInfo(exposureTime=self.config.expTime, darkTime=self.config.darkTime) exposure.getInfo().setVisitInfo(visitInfo) metadata = exposure.getMetadata() metadata.add("SHEEP", 7.3, "number of sheep on farm") metadata.add("MONKEYS", 155, "monkeys per tree") metadata.add("VAMPIRES", 4, "How scary are vampires.") for amp in exposure.getDetector(): amp.setLinearityCoeffs((0., 1., 0., 0.)) amp.setLinearityType("Polynomial") amp.setGain(self.config.gain) exposure.image.array[:] = np.zeros(exposure.getImage().getDimensions()).transpose() exposure.mask.array[:] = np.zeros(exposure.getMask().getDimensions()).transpose() exposure.variance.array[:] = np.zeros(exposure.getVariance().getDimensions()).transpose() return exposure
def testBrighterFatterInterface(self): """Test brighter fatter correction interface using a delta function kernel on a flat image""" image = afwImage.ImageF(100, 100) image.set(100) ref_image = afwImage.ImageF(image, True) mi = afwImage.makeMaskedImage(image) exp = afwImage.makeExposure(mi) with open(self.filename, 'rb') as f: bfKernel = pickle.load(f) isrFunctions.brighterFatterCorrection(exp, bfKernel, 5, 100, False) self.assertImagesEqual(ref_image, image)
def setUp(self): maskedImage = afwImage.MaskedImageF(inFilePathSmall) maskedImageMD = readMetadata(inFilePathSmall) self.smallExposure = afwImage.ExposureF(inFilePathSmall) self.width = maskedImage.getWidth() self.height = maskedImage.getHeight() self.wcs = afwGeom.makeSkyWcs(maskedImageMD, False) self.md = maskedImageMD self.psf = DummyPsf(2.0) self.detector = DetectorWrapper().detector self.exposureBlank = afwImage.ExposureF() self.exposureMiOnly = afwImage.makeExposure(maskedImage) self.exposureMiWcs = afwImage.makeExposure(maskedImage, self.wcs) # n.b. the (100, 100, ...) form self.exposureCrWcs = afwImage.ExposureF(100, 100, self.wcs) # test with ExtentI(100, 100) too self.exposureCrOnly = afwImage.ExposureF(lsst.geom.ExtentI(100, 100)) afwImage.Filter.reset() afwImage.FilterProperty.reset() defineFilter("g", 470.0)
def test1(self): task = measAlg.ReplaceWithNoiseTask() schema = afwTable.SourceTable.makeMinimalSchema() table = afwTable.SourceTable.make(schema) sources = afwTable.SourceCatalog(table) im = afwImage.ImageF(200, 50) seed = 42 rand = afwMath.Random(afwMath.Random.MT19937, seed) afwMath.randomGaussianImage(im, rand) s = sources.addNew() s.setId(1) fp = afwDet.Footprint() y,x0,x1 = (10, 10, 190) im.getArray()[y, x0:x1] = 10 fp.addSpan(y, x0, x1) s.setFootprint(fp) s = sources.addNew() s.setId(2) fp = afwDet.Footprint() y,x0,x1 = (40, 10, 190) im.getArray()[y, x0:x1] = 10 fp.addSpan(y, x0, x1) s.setFootprint(fp) mi = afwImage.MaskedImageF(im) exposure = afwImage.makeExposure(mi) self._save(mi, 'a') task.begin(exposure, sources) self._save(mi, 'b') sourcei = 0 task.insertSource(exposure, sourcei) self._save(mi, 'c') # do something task.removeSource(exposure, sources, sources[sourcei]) self._save(mi, 'd') sourcei = 1 task.insertSource(exposure, sourcei) self._save(mi, 'e') # do something task.removeSource(exposure, sources, sources[sourcei]) self._save(mi, 'f') task.end(exposure, sources) self._save(mi, 'g')
def setUp(self): FWHM = 5 psf = algorithms.DoubleGaussianPsf(15, 15, FWHM/(2*math.sqrt(2*math.log(2)))) mi = afwImage.MaskedImageF(lsst.geom.ExtentI(100, 100)) self.xc, self.yc, self.instFlux = 45, 55, 1000.0 mi.image[self.xc, self.yc, afwImage.LOCAL] = self.instFlux cnvImage = mi.Factory(mi.getDimensions()) afwMath.convolve(cnvImage, mi, psf.getKernel(), afwMath.ConvolutionControl()) self.exp = afwImage.makeExposure(cnvImage) self.exp.setPsf(psf) if display and False: afwDisplay.Display(frame=0).mtv(self.exp, title=self._testMethodName + ": image")