Пример #1
0
    def __init__(self, butler=None, schema=None, initInputs=None, **kwargs):
        # Make PipelineTask-only wording less transitional after cmdlineTask is removed
        """!
        @brief Initialize the merge detections task.

        A @ref FootprintMergeList_ "FootprintMergeList" will be used to
        merge the source catalogs.

        @param[in] schema     the schema of the detection catalogs used as input to this one
        @param[in] butler     a butler used to read the input schema from disk, if schema is None
        @param[in] initInputs This a PipelineTask-only argument that holds all inputs passed in
                              through the PipelineTask middleware
        @param[in] **kwargs   keyword arguments to be passed to CmdLineTask.__init__

        The task will set its own self.schema attribute to the schema of the output merged catalog.
        """
        super().__init__(**kwargs)
        if initInputs is not None:
            schema = initInputs['schema'].schema

        self.makeSubtask("skyObjects")
        self.schema = self.getInputSchema(butler=butler, schema=schema)

        filterNames = [
            getShortFilterName(name) for name in self.config.priorityList
        ]
        filterNames += [self.config.skyFilterName]
        self.merged = afwDetect.FootprintMergeList(self.schema, filterNames)
        self.outputSchema = afwTable.SourceCatalog(self.schema)
        self.outputPeakSchema = afwDetect.PeakCatalog(
            self.merged.getPeakSchema())
Пример #2
0
    def getSchemaCatalogs(self):
        """!
        Return a dict of empty catalogs for each catalog dataset produced by this task.

        @param[out] dictionary of empty catalogs
        """
        mergeDet = afwTable.SourceCatalog(self.schema)
        peak = afwDetect.PeakCatalog(self.merged.getPeakSchema())
        return {self.config.coaddName + "Coadd_mergeDet": mergeDet,
                self.config.coaddName + "Coadd_peak": peak}
Пример #3
0
    def setPeakSignificance(self, exposure, footprints, threshold, negative=False):
        """Set the significance of each detected peak to the pixel value divided
        by the appropriate standard-deviation for ``config.thresholdType``.

        Only sets significance for "stdev" and "pixel_stdev" thresholdTypes;
        we leave it undefined for "value" and "variance" as it does not have a
        well-defined meaning in those cases.

        Parameters
        ----------
        exposure : `lsst.afw.image.Exposure`
            Exposure that footprints were detected on, likely the convolved,
            local background-subtracted image.
        footprints : `lsst.afw.detection.FootprintSet`
            Footprints detected on the image.
        threshold : `lsst.afw.detection.Threshold`
            Threshold used to find footprints.
        negative : `bool`, optional
            Are we calculating for negative sources?
        """
        if footprints is None or footprints.getFootprints() == []:
            return footprints
        polarity = -1 if negative else 1

        # All incoming footprints have the same schema.
        mapper = afwTable.SchemaMapper(footprints.getFootprints()[0].peaks.schema)
        mapper.addMinimalSchema(footprints.getFootprints()[0].peaks.schema)
        mapper.addOutputField("significance", type=float,
                              doc="Ratio of peak value to configured standard deviation.")

        # Copy the old peaks to the new ones with a significance field.
        # Do this independent of the threshold type, so we always have a
        # significance field.
        newFootprints = afwDet.FootprintSet(footprints)
        for old, new in zip(footprints.getFootprints(), newFootprints.getFootprints()):
            newPeaks = afwDet.PeakCatalog(mapper.getOutputSchema())
            newPeaks.extend(old.peaks, mapper=mapper)
            new.getPeaks().clear()
            new.setPeakCatalog(newPeaks)

        # Compute the significance values.
        if self.config.thresholdType == "pixel_stdev":
            for footprint in newFootprints.getFootprints():
                footprint.updatePeakSignificance(exposure.variance, polarity)
        elif self.config.thresholdType == "stdev":
            sigma = threshold.getValue() / self.config.thresholdValue
            for footprint in newFootprints.getFootprints():
                footprint.updatePeakSignificance(polarity*sigma)
        else:
            for footprint in newFootprints.getFootprints():
                for peak in footprint.peaks:
                    peak["significance"] = 0

        return newFootprints
Пример #4
0
    def updatePeaks(self, fpSet, image, threshold):
        """Update the Peaks in a FootprintSet by detecting new Footprints and
        Peaks in an image and using the new Peaks instead of the old ones.

        Parameters
        ----------
        fpSet : `afw.detection.FootprintSet`
            Set of Footprints whose Peaks should be updated.
        image : `afw.image.MaskedImage`
            Image to detect new Footprints and Peak in.
        threshold : `afw.detection.Threshold`
            Threshold object for detection.

        Input Footprints with fewer Peaks than self.config.nPeaksMaxSimple
        are not modified, and if no new Peaks are detected in an input
        Footprint, the brightest original Peak in that Footprint is kept.
        """
        for footprint in fpSet.getFootprints():
            oldPeaks = footprint.getPeaks()
            if len(oldPeaks) <= self.config.nPeaksMaxSimple:
                continue
            # We detect a new FootprintSet within each non-simple Footprint's
            # bbox to avoid a big O(N^2) comparison between the two sets of
            # Footprints.
            sub = image.Factory(image, footprint.getBBox())
            fpSetForPeaks = afwDet.FootprintSet(
                sub,
                threshold,
                "",  # don't set a mask plane
                self.config.minPixels
            )
            newPeaks = afwDet.PeakCatalog(oldPeaks.getTable())
            for fpForPeaks in fpSetForPeaks.getFootprints():
                for peak in fpForPeaks.getPeaks():
                    if footprint.contains(peak.getI()):
                        newPeaks.append(peak)
            if len(newPeaks) > 0:
                del oldPeaks[:]
                oldPeaks.extend(newPeaks)
            else:
                del oldPeaks[1:]
def modelToHeavy(source,
                 filters,
                 xy0=Point2I(),
                 observation=None,
                 dtype=np.float32):
    """Convert the model to a `MultibandFootprint`

    Parameters
    ----------
    source : `scarlet.Component`
        The source to convert to a `HeavyFootprint`.
    filters : `iterable`
        A "list" of names for each filter.
    xy0 : `lsst.geom.Point2I`
        `(x,y)` coordinates of the bounding box containing the
        `HeavyFootprint`.
    observation : `scarlet.Observation`
        The scarlet observation, used to convolve the image with
        the origin PSF. If `observation`` is `None` then the
        `HeavyFootprint` will exist in the model frame.
    dtype : `numpy.dtype`
        The data type for the returned `HeavyFootprint`.

    Returns
    -------
    mHeavy : `lsst.detection.MultibandFootprint`
        The multi-band footprint containing the model for the source.
    """
    if observation is not None:
        model = observation.render(source.get_model()).astype(dtype)
    else:
        model = source.get_model().astype(dtype)
    mHeavy = afwDet.MultibandFootprint.fromArrays(filters, model, xy0=xy0)
    peakCat = afwDet.PeakCatalog(source.detectedPeak.table)
    peakCat.append(source.detectedPeak)
    for footprint in mHeavy:
        footprint.setPeakCatalog(peakCat)
    return mHeavy
Пример #6
0
        def addSignificance(footprints):
            """Return a new FootprintSet with a significance field added."""
            mapper = afwTable.SchemaMapper(
                footprints.getFootprints()[0].peaks.schema)
            mapper.addMinimalSchema(footprints.getFootprints()[0].peaks.schema)
            mapper.addOutputField(
                "significance",
                type=float,
                doc="Ratio of peak value to configured standard deviation.")

            newFootprints = afwDetect.FootprintSet(footprints)
            for old, new in zip(footprints.getFootprints(),
                                newFootprints.getFootprints()):
                newPeaks = afwDetect.PeakCatalog(mapper.getOutputSchema())
                newPeaks.extend(old.peaks, mapper=mapper)
                new.getPeaks().clear()
                new.setPeakCatalog(newPeaks)

            for footprint in newFootprints.getFootprints():
                for peak in footprint.peaks:
                    peak['significance'] = 10

            return newFootprints
Пример #7
0
def modelToHeavy(source,
                 filters,
                 xy0=Point2I(),
                 observation=None,
                 dtype=np.float32):
    """Convert the model to a `MultibandFootprint`

    Parameters
    ----------
    source : `scarlet.Component`
        The source to convert to a `HeavyFootprint`.
    filters : `iterable`
        A "list" of names for each filter.
    xy0 : `lsst.geom.Point2I`
        `(x,y)` coordinates of the bounding box containing the
        `HeavyFootprint`. If `observation` is not `None` then
        this parameter is updated with the position of the new model
    observation : `scarlet.Observation`
        The scarlet observation, used to convolve the image with
        the origin PSF. If `observation`` is `None` then the
        `HeavyFootprint` will exist in the model frame.
    dtype : `numpy.dtype`
        The data type for the returned `HeavyFootprint`.

    Returns
    -------
    mHeavy : `lsst.detection.MultibandFootprint`
        The multi-band footprint containing the model for the source.
    """
    if observation is not None:
        # We want to convolve the model with the observed PSF,
        # which means we need to grow the model box by the PSF to
        # account for all of the flux after convolution.
        # FYI: The `scarlet.Box` class implements the `&` operator
        # to take the intersection of two boxes.

        # Get the PSF size and radii to grow the box
        py, px = observation.frame.psf.get_model().shape[1:]
        dh = py // 2
        dw = px // 2
        shape = (source.bbox.shape[0], source.bbox.shape[1] + py,
                 source.bbox.shape[2] + px)
        origin = (source.bbox.origin[0], source.bbox.origin[1] - dh,
                  source.bbox.origin[2] - dw)
        # Create the larger box to fit the model + PSf
        bbox = Box(shape, origin=origin)
        # Only use the portion of the convolved model that fits in the image
        overlap = Frame(bbox & source.frame.bbox,
                        source.frame.channels,
                        psfs=source.frame.psf)
        # Load the full multiband model in the larger box
        model = source.model_to_frame(overlap)
        # Convolve the model with the PSF in each band
        # Always use a real space convolution to limit artifacts
        model = observation.convolve(model,
                                     convolution_type="real").astype(dtype)
        # Update xy0 with the origin of the sources box
        xy0 = Point2I(overlap.origin[-1] + xy0.x, overlap.origin[-2] + xy0.y)
    else:
        model = source.get_model().astype(dtype)
    mHeavy = afwDet.MultibandFootprint.fromArrays(filters, model, xy0=xy0)
    peakCat = afwDet.PeakCatalog(source.detectedPeak.table)
    peakCat.append(source.detectedPeak)
    for footprint in mHeavy:
        footprint.setPeakCatalog(peakCat)
    return mHeavy
Пример #8
0
    def test1(self):

        # circle
        spans = afwGeom.SpanSet.fromShape(45, offset=(50, 50))
        fp = afwDet.Footprint(spans)

        #
        psfsig = 1.5
        psffwhm = psfsig * 2.35
        psf1 = measAlg.DoubleGaussianPsf(11, 11, psfsig)

        psf2 = measAlg.DoubleGaussianPsf(100, 100, psfsig)

        fbb = fp.getBBox()
        print('fbb', fbb.getMinX(), fbb.getMaxX(), fbb.getMinY(),
              fbb.getMaxY())

        fmask = afwImage.Mask(fbb)
        fmask.setXY0(fbb.getMinX(), fbb.getMinY())
        fp.spans.setMask(fmask, 1)

        sig1 = 10.

        img = afwImage.ImageF(fbb)
        A = img.getArray()
        A += np.random.normal(0, sig1, size=(fbb.getHeight(), fbb.getWidth()))
        print('img x0,y0', img.getX0(), img.getY0())
        print('BBox', img.getBBox())

        peaks = afwDet.PeakCatalog(afwDet.PeakTable.makeMinimalSchema())

        def makePeak(x, y):
            p = peaks.addNew()
            p.setFx(x)
            p.setFy(y)
            p.setIx(int(x))
            p.setIy(int(y))
            return p

        pk1 = makePeak(20., 30.)
        pk2 = makePeak(23., 33.)
        pk3 = makePeak(92., 50.)

        ibb = img.getBBox()
        iext = [ibb.getMinX(), ibb.getMaxX(), ibb.getMinY(), ibb.getMaxY()]
        ix0, iy0 = iext[0], iext[2]

        pbbs = []
        pxys = []

        fluxes = [10000., 5000., 5000.]
        for pk, f in zip(peaks, fluxes):
            psfim = psf1.computeImage(afwGeom.Point2D(pk.getFx(), pk.getFy()))
            print('psfim x0,y0', psfim.getX0(), psfim.getY0())
            pbb = psfim.getBBox()
            print('pbb', pbb.getMinX(), pbb.getMaxX(), pbb.getMinY(),
                  pbb.getMaxY())
            pbb.clip(ibb)
            print('clipped pbb', pbb.getMinX(), pbb.getMaxX(), pbb.getMinY(),
                  pbb.getMaxY())
            psfim = psfim.Factory(psfim, pbb)

            psfa = psfim.getArray()
            psfa /= psfa.sum()
            img.getArray()[pbb.getMinY() - iy0:pbb.getMaxY() + 1 - iy0,
                           pbb.getMinX() - ix0:pbb.getMaxX() + 1 -
                           ix0] += f * psfa

            pbbs.append(
                (pbb.getMinX(), pbb.getMaxX(), pbb.getMinY(), pbb.getMaxY()))
            pxys.append((pk.getFx(), pk.getFy()))

        if doPlot:
            plt.clf()
            plt.imshow(img.getArray(),
                       extent=iext,
                       interpolation='nearest',
                       origin='lower')
            ax = plt.axis()
            x0, x1, y0, y1 = fbb.getMinX(), fbb.getMaxX(), fbb.getMinY(
            ), fbb.getMaxY()
            plt.plot([x0, x0, x1, x1, x0], [y0, y1, y1, y0, y0], 'k-')
            for x0, x1, y0, y1 in pbbs:
                plt.plot([x0, x0, x1, x1, x0], [y0, y1, y1, y0, y0], 'r-')
            for x, y in pxys:
                plt.plot(x, y, 'ro')
            plt.axis(ax)
            plt.savefig('img.png')

        varimg = afwImage.ImageF(fbb)
        varimg.set(sig1**2)

        psf_chisq_cut1 = psf_chisq_cut2 = psf_chisq_cut2b = 1.5

        #pkres = PerPeak()
        pkres = DeblendedPeak(pk1, 0, None)

        loglvl = Log.INFO
        # if verbose:
        #    loglvl = Log.DEBUG
        log = Log.getLogger('tests.fit_psf')
        log.setLevel(loglvl)

        cpsf = CachingPsf(psf1)

        peaksF = [pk.getF() for pk in peaks]
        pkF = pk1.getF()

        _fitPsf(fp, fmask, pk1, pkF, pkres, fbb, peaks, peaksF, log, cpsf,
                psffwhm, img, varimg, psf_chisq_cut1, psf_chisq_cut2,
                psf_chisq_cut2b)
        for k in dir(pkres):
            if k.startswith('__'):
                continue
            print('  ', k, getattr(pkres, k))

        cpsf = CachingPsf(psf2)
        _fitPsf(fp, fmask, pk1, pkF, pkres, fbb, peaks, peaksF, log, cpsf,
                psffwhm, img, varimg, psf_chisq_cut1, psf_chisq_cut2,
                psf_chisq_cut2b)
        for k in dir(pkres):
            if k.startswith('__'):
                continue
            print('  ', k, getattr(pkres, k))

        pkF = pk3.getF()
        _fitPsf(fp, fmask, pk3, pkF, pkres, fbb, peaks, peaksF, log, cpsf,
                psffwhm, img, varimg, psf_chisq_cut1, psf_chisq_cut2,
                psf_chisq_cut2b)
        for k in dir(pkres):
            if k.startswith('__'):
                continue
            print('  ', k, getattr(pkres, k))