def setDefaults(self):
     SingleFrameMeasurementConfig.setDefaults(self)
     self.plugins = [
         "base_CircularApertureFlux", "base_PixelFlags", "base_SkyCoord",
         "base_PsfFlux", "ip_diffim_NaiveDipoleCentroid",
         "ip_diffim_NaiveDipoleFlux", "ip_diffim_PsfDipoleFlux"
     ]
     self.slots.calibFlux = None
     self.slots.modelFlux = None
     self.slots.instFlux = None
     self.slots.shape = None
     self.slots.centroid = "ip_diffim_NaiveDipoleCentroid"
     self.doReplaceWithNoise = False
 def setDefaults(self):
     SingleFrameMeasurementConfig.setDefaults(self)
     self.plugins = ["base_CircularApertureFlux",
                     "base_PixelFlags",
                     "base_SkyCoord",
                     "base_PsfFlux",
                     "ip_diffim_NaiveDipoleCentroid",
                     "ip_diffim_NaiveDipoleFlux",
                     "ip_diffim_PsfDipoleFlux"]
     self.slots.calibFlux = None
     self.slots.modelFlux = None
     self.slots.instFlux = None
     self.slots.shape = None
     self.slots.centroid = "ip_diffim_NaiveDipoleCentroid"
     self.doReplaceWithNoise = False
    def test1(self):
        #exposure = afwImage.ExposureF('mini-v85408556-fr-R23-S11.fits')
        #exposure = afwImage.ExposureF('../afwdata/ImSim/calexp/v85408556-fr/R23/S11.fits')
        #bb = afwGeom.Box2I(afwGeom.Point2I(0,0), afwGeom.Point2I(511,511))
        #exposure = afwImage.ExposureF('data/goodSeeingCoadd/r/3/113,0/coadd-r-3-113,0.fits', 0, bb)
        #exposure.writeFits('mini-r-3-113,0.fits')
        fn = os.path.join(os.path.dirname(__file__), 'data',
                          'mini-r-3-113,0.fits.gz')
        print 'Reading image', fn
        exposure = afwImage.ExposureF(fn)
        exposure.setPsf(afwDetection.GaussianPsf(15, 15, 3))
        schema = afwTable.SourceTable.makeMinimalSchema()
        idFactory = afwTable.IdFactory.makeSimple()

        dconf = measAlg.SourceDetectionConfig()
        dconf.reEstimateBackground = False
        dconf.includeThresholdMultiplier = 5.

        mconf = SingleFrameMeasurementConfig()

        aconf = ANetAstrometryConfig()
        aconf.forceKnownWcs = True

        det = measAlg.SourceDetectionTask(schema=schema, config=dconf)
        meas = SingleFrameMeasurementTask(schema, config=mconf)
        astrom = ANetAstrometryTask(schema, config=aconf, name='astrom')

        astrom.log.setThreshold(pexLog.Log.DEBUG)

        inwcs = exposure.getWcs()
        print 'inwcs:', inwcs
        instr = inwcs.getFitsMetadata().toString()
        print 'inwcs:', instr
        table = afwTable.SourceTable.make(schema, idFactory)
        sources = det.makeSourceCatalog(table, exposure, sigma=1).sources
        meas.measure(exposure, sources)

        for dosip in [False, True]:
            aconf.solver.calculateSip = dosip
            ast = astrom.run(sourceCat=sources, exposure=exposure)
            outwcs = exposure.getWcs()
            outstr = outwcs.getFitsMetadata().toString()
            if dosip is False:
                self.assertEqual(inwcs, outwcs)
                self.assertEqual(instr, outstr)
            print 'inwcs:', instr
            print 'outwcs:', outstr
            print len(ast.matches), 'matches'
            self.assertTrue(len(ast.matches) > 10)
Exemple #4
0
    def test1(self):
        fn = os.path.join(os.path.dirname(__file__), 'data',
                          'mini-r-3-113,0.fits.gz')
        print('Reading image', fn)
        exposure = afwImage.ExposureF(fn)
        exposure.setPsf(afwDetection.GaussianPsf(15, 15, 3))
        schema = afwTable.SourceTable.makeMinimalSchema()
        idFactory = afwTable.IdFactory.makeSimple()

        dconf = measAlg.SourceDetectionConfig()
        dconf.reEstimateBackground = False
        dconf.includeThresholdMultiplier = 5.

        mconf = SingleFrameMeasurementConfig()

        aconf = ANetAstrometryConfig()
        aconf.forceKnownWcs = True

        det = measAlg.SourceDetectionTask(schema=schema, config=dconf)
        meas = SingleFrameMeasurementTask(schema, config=mconf)
        astrom = ANetAstrometryTask(schema, config=aconf, name='astrom')

        astrom.log.setLevel(astrom.log.TRACE)

        inwcs = exposure.getWcs()
        print('inwcs:', inwcs)
        instr = inwcs.getFitsMetadata().toString()
        print('inwcs:', instr)
        table = afwTable.SourceTable.make(schema, idFactory)
        sources = det.makeSourceCatalog(table, exposure, sigma=1).sources
        meas.measure(sources, exposure)

        for dosip in [False, True]:
            aconf.solver.calculateSip = dosip
            ast = astrom.run(sourceCat=sources, exposure=exposure)
            outwcs = exposure.getWcs()
            outstr = outwcs.getFitsMetadata().toString()
            if not dosip:
                self.assertEqual(inwcs, outwcs)
                self.assertEqual(instr, outstr)
            print('inwcs:', instr)
            print('outwcs:', outstr)
            print(len(ast.matches), 'matches')
            self.assertGreater(len(ast.matches), 10)
    def getClumps(self, sigma=1.0, display=False):
        if self._num <= 0:
            raise RuntimeError("No candidate PSF sources")

        psfImage = self.getImage()
        #
        # Embed psfImage into a larger image so we can smooth when measuring it
        #
        width, height = psfImage.getWidth(), psfImage.getHeight()
        largeImg = psfImage.Factory(afwGeom.ExtentI(2 * width, 2 * height))
        largeImg.set(0)

        bbox = afwGeom.BoxI(afwGeom.PointI(width, height),
                            afwGeom.ExtentI(width, height))
        largeImg.assign(psfImage, bbox, afwImage.LOCAL)
        #
        # Now measure that image, looking for the highest peak.  Start by building an Exposure
        #
        msk = afwImage.MaskU(largeImg.getDimensions())
        msk.set(0)
        var = afwImage.ImageF(largeImg.getDimensions())
        var.set(1)
        mpsfImage = afwImage.MaskedImageF(largeImg, msk, var)
        mpsfImage.setXY0(afwGeom.PointI(-width, -height))
        del msk
        del var
        exposure = afwImage.makeExposure(mpsfImage)

        #
        # Next run an object detector
        #
        maxVal = afwMath.makeStatistics(psfImage, afwMath.MAX).getValue()
        threshold = maxVal - sigma * math.sqrt(maxVal)
        if threshold <= 0.0:
            threshold = maxVal

        threshold = afwDetection.Threshold(threshold)

        ds = afwDetection.FootprintSet(mpsfImage, threshold, "DETECTED")
        #
        # And measure it.  This policy isn't the one we use to measure
        # Sources, it's only used to characterize this PSF histogram
        #
        schema = SourceTable.makeMinimalSchema()
        psfImageConfig = SingleFrameMeasurementConfig()
        psfImageConfig.slots.centroid = "base_SdssCentroid"
        psfImageConfig.plugins["base_SdssCentroid"].doFootprintCheck = False
        psfImageConfig.slots.psfFlux = None  # "base_PsfFlux"
        psfImageConfig.slots.apFlux = "base_CircularApertureFlux_3_0"
        psfImageConfig.slots.modelFlux = None
        psfImageConfig.slots.instFlux = None
        psfImageConfig.slots.calibFlux = None
        psfImageConfig.slots.shape = "base_SdssShape"
        #   Formerly, this code had centroid.sdss, flux.psf, flux.naive,
        #   flags.pixel, and shape.sdss
        psfImageConfig.algorithms.names = [
            "base_SdssCentroid", "base_CircularApertureFlux", "base_SdssShape"
        ]
        psfImageConfig.algorithms["base_CircularApertureFlux"].radii = [3.0]
        psfImageConfig.validate()
        task = SingleFrameMeasurementTask(schema, config=psfImageConfig)

        sourceCat = SourceCatalog(schema)

        gaussianWidth = 1.5  # Gaussian sigma for detection convolution
        exposure.setPsf(algorithmsLib.DoubleGaussianPsf(11, 11, gaussianWidth))

        ds.makeSources(sourceCat)
        #
        # Show us the Histogram
        #
        if display:
            frame = 1
            dispImage = mpsfImage.Factory(
                mpsfImage,
                afwGeom.BoxI(afwGeom.PointI(width, height),
                             afwGeom.ExtentI(width, height)), afwImage.LOCAL)
            ds9.mtv(dispImage, title="PSF Selection Image", frame=frame)

        clumps = list()  # List of clumps, to return
        e = None  # thrown exception
        IzzMin = 1.0  # Minimum value for second moments
        IzzMax = (
            self._xSize /
            8.0)**2  # Max value ... clump radius should be < clumpImgSize/8
        apFluxes = []
        task.run(
            sourceCat,
            exposure)  # notes that this is backwards for the new framework
        for i, source in enumerate(sourceCat):
            if source.getCentroidFlag():
                continue
            x, y = source.getX(), source.getY()

            apFluxes.append(source.getApFlux())

            val = mpsfImage.getImage().get(int(x) + width, int(y) + height)

            psfClumpIxx = source.getIxx()
            psfClumpIxy = source.getIxy()
            psfClumpIyy = source.getIyy()

            if display:
                if i == 0:
                    ds9.pan(x, y, frame=frame)

                ds9.dot("+", x, y, ctype=ds9.YELLOW, frame=frame)
                ds9.dot("@:%g,%g,%g" % (psfClumpIxx, psfClumpIxy, psfClumpIyy),
                        x,
                        y,
                        ctype=ds9.YELLOW,
                        frame=frame)

            if psfClumpIxx < IzzMin or psfClumpIyy < IzzMin:
                psfClumpIxx = max(psfClumpIxx, IzzMin)
                psfClumpIyy = max(psfClumpIyy, IzzMin)
                if display:
                    ds9.dot("@:%g,%g,%g" %
                            (psfClumpIxx, psfClumpIxy, psfClumpIyy),
                            x,
                            y,
                            ctype=ds9.RED,
                            frame=frame)

            det = psfClumpIxx * psfClumpIyy - psfClumpIxy * psfClumpIxy
            try:
                a, b, c = psfClumpIyy / det, -psfClumpIxy / det, psfClumpIxx / det
            except ZeroDivisionError:
                a, b, c = 1e4, 0, 1e4

            clumps.append(
                Clump(peak=val,
                      x=x,
                      y=y,
                      a=a,
                      b=b,
                      c=c,
                      ixx=psfClumpIxx,
                      ixy=psfClumpIxy,
                      iyy=psfClumpIyy))

        if len(clumps) == 0:
            msg = "Failed to determine center of PSF clump"
            if e:
                msg += ": %s" % e
            raise RuntimeError(msg)

        # if it's all we got return it
        if len(clumps) == 1:
            return clumps

        # which clump is the best?
        # if we've undistorted the moments, stars should only have 1 clump
        # use the apFlux from the clump measurement, and take the highest
        # ... this clump has more psf star candidate neighbours than the others.

        # get rid of any that are huge, and thus poorly defined
        goodClumps = []
        for clump in clumps:
            if clump.ixx < IzzMax and clump.iyy < IzzMax:
                goodClumps.append(clump)

        # if culling > IzzMax cost us all clumps, we'll have to take what we have
        if len(goodClumps) == 0:
            goodClumps = clumps

        # use the 'brightest' clump
        iBestClump = numpy.argsort(apFluxes)[0]
        clumps = [clumps[iBestClump]]
        return clumps
    def getClumps(self, sigma=1.0, display=False):
        if self._num <= 0:
            raise RuntimeError("No candidate PSF sources")

        psfImage = self.getImage()
        #
        # Embed psfImage into a larger image so we can smooth when measuring it
        #
        width, height = psfImage.getWidth(), psfImage.getHeight()
        largeImg = psfImage.Factory(afwGeom.ExtentI(2*width, 2*height))
        largeImg.set(0)

        bbox = afwGeom.BoxI(afwGeom.PointI(width, height), afwGeom.ExtentI(width, height))
        largeImg.assign(psfImage, bbox, afwImage.LOCAL)
        #
        # Now measure that image, looking for the highest peak.  Start by building an Exposure
        #
        msk = afwImage.MaskU(largeImg.getDimensions())
        msk.set(0)
        var = afwImage.ImageF(largeImg.getDimensions())
        var.set(1)
        mpsfImage = afwImage.MaskedImageF(largeImg, msk, var)
        mpsfImage.setXY0(afwGeom.PointI(-width, -height))
        del msk
        del var
        exposure = afwImage.makeExposure(mpsfImage)

        #
        # Next run an object detector
        #
        maxVal = afwMath.makeStatistics(psfImage, afwMath.MAX).getValue()
        threshold = maxVal - sigma*math.sqrt(maxVal)
        if threshold <= 0.0:
            threshold = maxVal

        threshold = afwDetection.Threshold(threshold)

        ds = afwDetection.FootprintSet(mpsfImage, threshold, "DETECTED")
        #
        # And measure it.  This policy isn't the one we use to measure
        # Sources, it's only used to characterize this PSF histogram
        #
        schema = SourceTable.makeMinimalSchema()
        psfImageConfig = SingleFrameMeasurementConfig()
        psfImageConfig.doApplyApCorr = "no"
        psfImageConfig.slots.centroid = "base_SdssCentroid"
        psfImageConfig.slots.psfFlux = None #"base_PsfFlux"
        psfImageConfig.slots.apFlux = "base_CircularApertureFlux_3_0"
        psfImageConfig.slots.modelFlux = None
        psfImageConfig.slots.instFlux = None
        psfImageConfig.slots.calibFlux = None
        psfImageConfig.slots.shape = "base_SdssShape"
        #   Formerly, this code had centroid.sdss, flux.psf, flux.naive,
        #   flags.pixel, and shape.sdss
        psfImageConfig.algorithms.names = ["base_SdssCentroid", "base_CircularApertureFlux", "base_SdssShape"]
        psfImageConfig.algorithms["base_CircularApertureFlux"].radii = [3.0]
        psfImageConfig.validate()
        task = SingleFrameMeasurementTask(schema, config=psfImageConfig)

        sourceCat = SourceCatalog(schema)

        gaussianWidth = 1.5                       # Gaussian sigma for detection convolution
        exposure.setPsf(algorithmsLib.DoubleGaussianPsf(11, 11, gaussianWidth))

        ds.makeSources(sourceCat)
        #
        # Show us the Histogram
        #
        if display:
            frame = 1
            dispImage = mpsfImage.Factory(mpsfImage, afwGeom.BoxI(afwGeom.PointI(width, height),
                                                                  afwGeom.ExtentI(width, height)),
                                                                  afwImage.LOCAL)
            ds9.mtv(dispImage,title="PSF Selection Image", frame=frame)


        clumps = list()                 # List of clumps, to return
        e = None                        # thrown exception
        IzzMin = 1.0                    # Minimum value for second moments
        IzzMax = (self._xSize/8.0)**2   # Max value ... clump r < clumpImgSize/8
                                        # diameter should be < 1/4 clumpImgSize
        apFluxes = []
        task.run(exposure, sourceCat)   # notes that this is backwards for the new framework
        for i, source in enumerate(sourceCat):
            if source.getCentroidFlag():
                continue
            x, y = source.getX(), source.getY()

            apFluxes.append(source.getApFlux())

            val = mpsfImage.getImage().get(int(x) + width, int(y) + height)

            psfClumpIxx = source.getIxx()
            psfClumpIxy = source.getIxy()
            psfClumpIyy = source.getIyy()

            if display:
                if i == 0:
                    ds9.pan(x, y, frame=frame)

                ds9.dot("+", x, y, ctype=ds9.YELLOW, frame=frame)
                ds9.dot("@:%g,%g,%g" % (psfClumpIxx, psfClumpIxy, psfClumpIyy), x, y,
                        ctype=ds9.YELLOW, frame=frame)

            if psfClumpIxx < IzzMin or psfClumpIyy < IzzMin:
                psfClumpIxx = max(psfClumpIxx, IzzMin)
                psfClumpIyy = max(psfClumpIyy, IzzMin)
                if display:
                    ds9.dot("@:%g,%g,%g" % (psfClumpIxx, psfClumpIxy, psfClumpIyy), x, y,
                            ctype=ds9.RED, frame=frame)

            det = psfClumpIxx*psfClumpIyy - psfClumpIxy*psfClumpIxy
            try:
                a, b, c = psfClumpIyy/det, -psfClumpIxy/det, psfClumpIxx/det
            except ZeroDivisionError:
                a, b, c = 1e4, 0, 1e4

            clumps.append(Clump(peak=val, x=x, y=y, a=a, b=b, c=c,
                                ixx=psfClumpIxx, ixy=psfClumpIxy, iyy=psfClumpIyy))

        if len(clumps) == 0:
            msg = "Failed to determine center of PSF clump"
            if e:
                msg += ": %s" % e
            raise RuntimeError(msg)

        # if it's all we got return it
        if len(clumps) == 1:
            return clumps

        # which clump is the best?
        # if we've undistorted the moments, stars should only have 1 clump
        # use the apFlux from the clump measurement, and take the highest
        # ... this clump has more psf star candidate neighbours than the others.

        # get rid of any that are huge, and thus poorly defined
        goodClumps = []
        for clump in clumps:
            if clump.ixx < IzzMax and clump.iyy < IzzMax:
                goodClumps.append(clump)

        # if culling > IzzMax cost us all clumps, we'll have to take what we have
        if len(goodClumps) == 0:
            goodClumps = clumps

        # use the 'brightest' clump
        iBestClump = numpy.argsort(apFluxes)[0]
        clumps = [clumps[iBestClump]]
        return clumps
Exemple #7
0
def detect_and_deblend(*, exp, log):

    log = lsst.log.Log.getLogger("LSSTMEDSifier")

    thresh = 5.0
    loglevel = 'INFO'

    # This schema holds all the measurements that will be run within the
    # stack It needs to be constructed before running anything and passed
    # to algorithms that make additional measurents.
    schema = afw_table.SourceTable.makeMinimalSchema()

    # Setup algorithms to run
    meas_config = SingleFrameMeasurementConfig()
    meas_config.plugins.names = [
        "base_SdssCentroid",
        "base_PsfFlux",
        "base_SkyCoord",
        # "modelfit_ShapeletPsfApprox",
        "modelfit_DoubleShapeletPsfApprox",
        "modelfit_CModel",
        # "base_SdssShape",
        # "base_LocalBackground",
    ]

    # set these slots to none because we aren't running these algorithms
    meas_config.slots.apFlux = None
    meas_config.slots.gaussianFlux = None
    meas_config.slots.calibFlux = None
    meas_config.slots.modelFlux = None

    # goes with SdssShape above
    meas_config.slots.shape = None

    # fix odd issue where it things things are near the edge
    meas_config.plugins['base_SdssCentroid'].binmax = 1

    meas_task = SingleFrameMeasurementTask(
        config=meas_config,
        schema=schema,
    )

    # setup detection config
    detection_config = SourceDetectionConfig()
    detection_config.reEstimateBackground = False
    detection_config.thresholdValue = thresh
    detection_task = SourceDetectionTask(config=detection_config)
    detection_task.log.setLevel(getattr(lsst.log, loglevel))

    deblend_config = SourceDeblendConfig()
    deblend_task = SourceDeblendTask(config=deblend_config, schema=schema)
    deblend_task.log.setLevel(getattr(lsst.log, loglevel))

    # Detect objects
    table = afw_table.SourceTable.make(schema)
    result = detection_task.run(table, exp)
    sources = result.sources

    # run the deblender
    deblend_task.run(exp, sources)

    # Run on deblended images
    noise_replacer_config = NoiseReplacerConfig()
    footprints = {
        record.getId(): (record.getParent(), record.getFootprint())
        for record in result.sources
    }

    # This constructor will replace all detected pixels with noise in the
    # image
    replacer = NoiseReplacer(
        noise_replacer_config,
        exposure=exp,
        footprints=footprints,
    )

    nbad = 0
    ntry = 0
    kept_sources = []

    for record in result.sources:

        # Skip parent objects where all children are inserted
        if record.get('deblend_nChild') != 0:
            continue

        ntry += 1

        # This will insert a single source into the image
        replacer.insertSource(record.getId())  # Get the peak as before

        # peak = record.getFootprint().getPeaks()[0]

        # The bounding box will be for the parent object
        # bbox = record.getFootprint().getBBox()

        meas_task.callMeasure(record, exp)

        # Remove object
        replacer.removeSource(record.getId())

        if record.getCentroidFlag():
            nbad += 1

        kept_sources.append(record)

    # Insert all objects back into image
    replacer.end()

    if ntry > 0:
        log.debug('nbad center: %d frac: %d' % (nbad, nbad / ntry))

    nkeep = len(kept_sources)
    ntot = len(result.sources)
    log.debug('kept %d/%d non parents' % (nkeep, ntot))
    return kept_sources