예제 #1
0
    def measure(self, measRecord, exposure):
        """Run the Veres trailed source measurement plugin.

        Parameters
        ----------
        measRecord : `lsst.afw.table.SourceRecord`
            Record describing the object being measured.
        exposure : `lsst.afw.image.Exposure`
            Pixel data to be measured.

        See also
        --------
        lsst.meas.base.SingleFramePlugin.measure
        """
        xc, yc = self.centroidExtractor(measRecord, self.flagHandler)

        # Look at measRecord for Naive measurements
        # ASSUMES NAIVE ALREADY RAN
        F = measRecord.get("ext_trailedSources_Naive_flux")
        L = measRecord.get("ext_trailedSources_Naive_length")
        theta = measRecord.get("ext_trailedSources_Naive_angle")
        if np.isnan(F) or np.isnan(L) or np.isnan(theta):
            raise MeasurementError(self.NO_NAIVE.doc, self.NO_NAIVE.number)

        # Make VeresModel
        model = VeresModel(exposure)

        # Do optimization with scipy
        params = np.array([xc, yc, F, L, theta])
        results = minimize(model,
                           params,
                           method=self.config.optimizerMethod,
                           jac=model.gradient)

        # Check if optimizer converged
        if not results.success:
            raise MeasurementError(self.NON_CONVERGE.doc,
                                   self.NON_CONVERGE.number)

        # Calculate end points and reduced chi-squared
        xc_fit, yc_fit, F_fit, L_fit, theta_fit = results.x
        a = L_fit / 2
        x0_fit = xc_fit - a * np.cos(theta_fit)
        y0_fit = yc_fit - a * np.sin(theta_fit)
        x1_fit = xc_fit + a * np.cos(theta_fit)
        y1_fit = yc_fit + a * np.sin(theta_fit)
        rChiSq = results.fun / (exposure.image.array.size - 6)

        # Set keys
        measRecord.set(self.keyXC, xc_fit)
        measRecord.set(self.keyYC, yc_fit)
        measRecord.set(self.keyX0, x0_fit)
        measRecord.set(self.keyY0, y0_fit)
        measRecord.set(self.keyX1, x1_fit)
        measRecord.set(self.keyY1, y1_fit)
        measRecord.set(self.keyFlux, F_fit)
        measRecord.set(self.keyL, L_fit)
        measRecord.set(self.keyTheta, theta_fit)
        measRecord.set(self.keyRChiSq, rChiSq)
예제 #2
0
    def testFlagHandler(self):
        """
        Standalone test to create a flaghandler and call it
        This is not a real world example, just a simple unit test
        """
        schema = lsst.afw.table.SourceTable.makeMinimalSchema()

        # This is a FlagDefinition structure like a plugin might have
        flagDefs = FlagDefinitionList()
        FAILURE = flagDefs.addFailureFlag()
        FIRST = flagDefs.add("1st error", "this is the first failure type")
        SECOND = flagDefs.add("2nd error", "this is the second failure type")
        fh = FlagHandler.addFields(schema, "test", flagDefs)
        # Check to be sure that the FlagHandler was correctly initialized
        for index in range(len(flagDefs)):
            self.assertEqual(
                flagDefs.getDefinition(index).name, fh.getFlagName(index))

        catalog = lsst.afw.table.SourceCatalog(schema)

        # Now check to be sure that all of the known failures set the bits correctly
        record = catalog.addNew()
        fh.handleFailure(record)
        self.assertTrue(fh.getValue(record, FAILURE.number))
        self.assertFalse(fh.getValue(record, FIRST.number))
        self.assertFalse(fh.getValue(record, SECOND.number))
        record = catalog.addNew()

        error = MeasurementError(FAILURE.doc, FAILURE.number)
        fh.handleFailure(record, error.cpp)
        self.assertTrue(fh.getValue(record, FAILURE.number))
        self.assertFalse(fh.getValue(record, FIRST.number))
        self.assertFalse(fh.getValue(record, SECOND.number))

        record = catalog.addNew()
        error = MeasurementError(FIRST.doc, FIRST.number)
        fh.handleFailure(record, error.cpp)
        self.assertTrue(fh.getValue(record, FAILURE.number))
        self.assertTrue(fh.getValue(record, FIRST.number))
        self.assertFalse(fh.getValue(record, SECOND.number))

        record = catalog.addNew()
        error = MeasurementError(SECOND.doc, SECOND.number)
        fh.handleFailure(record, error.cpp)
        self.assertTrue(fh.getValue(record, FAILURE.number))
        self.assertFalse(fh.getValue(record, FIRST.number))
        self.assertTrue(fh.getValue(record, SECOND.number))
예제 #3
0
    def measure(self, measRecord, exposure):
        """Perform measurement.

        The measure method is called by the measurement framework when
        `run` is called. If a `MeasurementError` is raised during this method,
        the `fail` method will be called to set the error flags.
        """
        # Call the SafeCentroidExtractor to get a centroid, even if one has
        # not been supplied by the centroid slot. Normally, the centroid is
        # supplied by the centroid slot, but if that fails, the footprint is
        # used as a fallback.  If the fallback is needed, the fail flag will
        # be set on this record.
        center = self.centroidExtractor(measRecord, self.flagHandler)

        # create a square bounding box of size = config.size around the center
        centerPoint = lsst.geom.Point2I(int(center.getX()), int(center.getY()))
        bbox = lsst.geom.Box2I(centerPoint, lsst.geom.Extent2I(1, 1))
        bbox.grow(self.config.size)

        # If the measurement box falls outside the exposure, raise the edge
        # MeasurementError
        if not exposure.getBBox().contains(bbox):
            raise MeasurementError(self.EDGE.doc, self.EDGE.number)

        # Sum the pixels inside the bounding box
        instFlux = lsst.afw.image.ImageF(exposure.getMaskedImage().getImage(),
                                         bbox).getArray().sum()
        measRecord.set(self.instFluxKey, instFlux)

        # If there was a NaN inside the bounding box, the instFlux will still
        # be NaN
        if np.isnan(instFlux):
            raise MeasurementError(self.CONTAINS_NAN.doc,
                                   self.CONTAINS_NAN.number)

        if self.config.flux0 is not None:
            if self.config.flux0 == 0:
                raise ZeroDivisionError("self.config.flux0 is zero in divisor")
            mag = -2.5 * np.log10(instFlux / self.config.flux0)
            measRecord.set(self.magKey, mag)
예제 #4
0
    def measure(self, measRecord, exposure):
        """
        The measure method is called by the measurement framework when task.run is called
        If a MeasurementError is raised during this method, the fail() method will be
        called to set the error flags.
        """
        lsst.log.Log.getLogger(self.getLogName()).info("%s plugin measuring." %
                                                       (self.name, ))
        # Sum the pixels inside the bounding box
        centerPoint = lsst.afw.geom.Point2I(int(measRecord.getX()),
                                            int(measRecord.getY()))
        bbox = lsst.afw.geom.Box2I(centerPoint, lsst.afw.geom.Extent2I(1, 1))
        flux = lsst.afw.image.ImageF(exposure.getMaskedImage().getImage(),
                                     bbox).getArray().sum()
        measRecord.set(self.fluxKey, flux)

        # If there was a nan inside the bounding box, the flux will still be nan
        if numpy.isnan(flux):
            raise MeasurementError(self.CONTAINS_NAN.doc,
                                   self.CONTAINS_NAN.number)
예제 #5
0
    def measure(self, measRecord, exposure):
        """Perform measurement.

        Notes
        -----
        The `measure` method is called by the measurement framework when `run`
        is called. If a `MeasurementError` is raised during this method, the
        `fail` method will be called to set the error flags.
        """
        logging.getLogger(self.getLogName()).info("%s plugin measuring.",
                                                  self.name)
        # Sum the pixels inside the bounding box
        centerPoint = lsst.geom.Point2I(int(measRecord.getX()),
                                        int(measRecord.getY()))
        bbox = lsst.geom.Box2I(centerPoint, lsst.geom.Extent2I(1, 1))
        instFlux = lsst.afw.image.ImageF(exposure.getMaskedImage().getImage(),
                                         bbox).getArray().sum()
        measRecord.set(self.instFluxKey, instFlux)

        # If there was a NaN inside the bounding box, the instFlux will still
        # be NaN
        if numpy.isnan(instFlux):
            raise MeasurementError(self.CONTAINS_NAN.doc,
                                   self.CONTAINS_NAN.number)
예제 #6
0
 def calculate(self, measRecord):
     #  note: flagbit doesn't matter, since a FlagHandler isn't used
     raise MeasurementError("Supposed to fail", 0)
예제 #7
0
    def measure(self, measRecord, exposure):
        """Run the Naive trailed source measurement algorithm.

        Parameters
        ----------
        measRecord : `lsst.afw.table.SourceRecord`
            Record describing the object being measured.
        exposure : `lsst.afw.image.Exposure`
            Pixel data to be measured.

        See also
        --------
        lsst.meas.base.SingleFramePlugin.measure
        """
        xc, yc = self.centriodExtractor(measRecord, self.flagHandler)
        Ixx, Iyy, Ixy = measRecord.getShape().getParameterVector()
        xmy = Ixx - Iyy
        xpy = Ixx + Iyy
        xmy2 = xmy * xmy
        xy2 = Ixy * Ixy
        a = np.sqrt(0.5 * (xpy + np.sqrt((xmy)**2 + 4.0 * xy2)))
        L = 2 * a

        theta = 0.5 * np.arctan2(2.0 * Ixy, xmy)
        x0 = xc - a * np.cos(theta)
        y0 = yc - a * np.sin(theta)
        x1 = xc + a * np.cos(theta)
        y1 = yc + a * np.sin(theta)

        # For now, use the shape flux.
        F = measRecord.get("base_SdssShape_instFlux")

        # Fall back to aperture flux
        if np.isnan(F):
            if not np.isnan(measRecord.getInstApFlux()):
                F = measRecord.getInstApFlux()
            else:
                raise MeasurementError(self.NO_FLUX.doc, self.NO_FLUX.number)

        # Propagate errors from second moments
        xcErr2, ycErr2 = np.diag(measRecord.getCentroidErr())
        IxxErr2, IyyErr2, IxyErr2 = np.diag(measRecord.getShapeErr())
        desc = np.sqrt(xmy2 + 4.0 * xy2)  # Descriminant^1/2 of EV equation
        denom = 2 * np.sqrt(2.0 * (Ixx + np.sqrt(4.0 * xy2 + xmy2 + Iyy))
                            )  # Denominator for dadIxx and dadIyy
        dadIxx = (1.0 + (xmy / desc)) / denom
        dadIyy = (1.0 - (xmy / desc)) / denom
        dadIxy = (4.0 * Ixy) / (desc * denom)
        aErr2 = IxxErr2 * dadIxx * dadIxx + IyyErr2 * dadIyy * dadIyy + IxyErr2 * dadIxy * dadIxy
        thetaErr2 = ((IxxErr2 + IyyErr2) * xy2 +
                     xmy2 * IxyErr2) / (desc * desc * desc * desc)

        dxda = np.cos(theta)
        dxdt = a * np.sin(theta)
        dyda = np.sin(theta)
        dydt = a * np.cos(theta)
        xErr2 = aErr2 * dxda * dxda + thetaErr2 * dxdt * dxdt
        yErr2 = aErr2 * dyda * dyda + thetaErr2 * dydt * dydt
        x0Err = np.sqrt(xErr2 + xcErr2)  # Same for x1
        y0Err = np.sqrt(yErr2 + ycErr2)  # Same for y1

        # Set flags
        measRecord.set(self.keyX0, x0)
        measRecord.set(self.keyY0, y0)
        measRecord.set(self.keyX1, x1)
        measRecord.set(self.keyY1, y1)
        measRecord.set(self.keyFlux, F)
        measRecord.set(self.keyL, L)
        measRecord.set(self.keyAngle, theta)
        measRecord.set(self.keyX0Err, x0Err)
        measRecord.set(self.keyY0Err, y0Err)
        measRecord.set(self.keyX1Err, x0Err)
        measRecord.set(self.keyY1Err, y0Err)