LSST Applications g063fba187b+fee0456c91,g0f08755f38+ea96e5a5a3,g1653933729+a8ce1bb630,g168dd56ebc+a8ce1bb630,g1a2382251a+90257ff92a,g20f6ffc8e0+ea96e5a5a3,g217e2c1bcf+937a289c59,g28da252d5a+daa7da44eb,g2bbee38e9b+253935c60e,g2bc492864f+253935c60e,g3156d2b45e+6e55a43351,g32e5bea42b+31359a2a7a,g347aa1857d+253935c60e,g35bb328faa+a8ce1bb630,g3a166c0a6a+253935c60e,g3b1af351f3+a8ce1bb630,g3e281a1b8c+c5dd892a6c,g414038480c+416496e02f,g41af890bb2+afe91b1188,g599934f4f4+0db33f7991,g7af13505b9+e36de7bce6,g80478fca09+da231ba887,g82479be7b0+a4516e59e3,g858d7b2824+ea96e5a5a3,g89c8672015+f4add4ffd5,g9125e01d80+a8ce1bb630,ga5288a1d22+bc6ab8dfbd,gb58c049af0+d64f4d3760,gc28159a63d+253935c60e,gcab2d0539d+3f2b72788c,gcf0d15dbbd+4ea9c45075,gda6a2b7d83+4ea9c45075,gdaeeff99f8+1711a396fd,ge79ae78c31+253935c60e,gef2f8181fd+3031e3cf99,gf0baf85859+c1f95f4921,gfa517265be+ea96e5a5a3,gfa999e8aa5+17cd334064,w.2024.50
LSST Data Management Base Package
Loading...
Searching...
No Matches
Public Types | Public Member Functions | Static Public Member Functions | Static Public Attributes | Protected Attributes | List of all members
lsst::meas::extensions::simpleShape::SimpleShape Class Reference

#include <simpleShape.h>

Inheritance diagram for lsst::meas::extensions::simpleShape::SimpleShape:
lsst::meas::base::SimpleAlgorithm lsst::meas::base::SingleFrameAlgorithm lsst::meas::base::ForcedAlgorithm lsst::meas::base::BaseAlgorithm lsst::meas::base::BaseAlgorithm

Public Types

typedef SimpleShapeControl Control
 

Public Member Functions

 SimpleShape (Control const &ctrl, std::string const &name, afw::table::Schema &schema)
 
virtual void measure (afw::table::SourceRecord &measRecord, afw::image::Exposure< float > const &exposure) const
 Called to measure a single child source in an image.
 
virtual void fail (afw::table::SourceRecord &measRecord, lsst::meas::base::MeasurementError *error=NULL) const
 Handle an exception thrown by the current algorithm by setting flags in the given record.
 
void measureForced (afw::table::SourceRecord &measRecord, afw::image::Exposure< float > const &exposure, afw::table::SourceRecord const &refRecord, afw::geom::SkyWcs const &refWcs) const override
 Called to measure a single child source in an image.
 
void measureNForced (afw::table::SourceCatalog const &measCat, afw::image::Exposure< float > const &exposure, afw::table::SourceCatalog const &refRecord, afw::geom::SkyWcs const &refWcs) const override
 Called to simultaneously measure all children in a deblend family, in a single image.
 
virtual void measureN (afw::table::SourceCatalog const &measCat, afw::image::Exposure< float > const &exposure) const
 Called to simultaneously measure all children in a deblend family, in a single image.
 
std::string getLogName () const
 

Static Public Member Functions

static base::FlagDefinitionList const & getFlagDefinitions ()
 
template<typename T >
static SimpleShapeResult computeMoments (afw::geom::ellipses::Ellipse const &weight, afw::image::MaskedImage< T > const &image, double nSigmaRegion=3.0)
 Compute the Gaussian-weighted moments of an image.
 
static Eigen::Matrix< double, 5, 6 > convertRawMoments (Eigen::Matrix< double, 6, 1 > const &q, afw::geom::ellipses::Quadrupole &quadrupole, geom::Point2D &center)
 Convert linear raw moments into an ellipse and centroid, and return the derivative of the conversion.
 
static Eigen::Matrix< double, 5, 5 > correctWeightedMoments (afw::geom::ellipses::Quadrupole const &weight, afw::geom::ellipses::Quadrupole &ellipse, geom::Point2D &center)
 Correct moments measured with a Gaussian weight function by assuming the data was also an elliptical Gaussian, and return the derivative of the correction.
 

Static Public Attributes

static unsigned int const N_FLAGS = 1
 
static base::FlagDefinition const FAILURE = flagDefinitions.addFailureFlag()
 

Protected Attributes

std::string _logName
 

Detailed Description

Definition at line 95 of file simpleShape.h.

Member Typedef Documentation

◆ Control

Definition at line 103 of file simpleShape.h.

Constructor & Destructor Documentation

◆ SimpleShape()

lsst::meas::extensions::simpleShape::SimpleShape::SimpleShape ( Control const & ctrl,
std::string const & name,
afw::table::Schema & schema )

Definition at line 378 of file simpleShape.cc.

383 : _ctrl(ctrl),
384 _resultKey(SimpleShapeResultKey::addFields(schema, name)),
385 _centroidExtractor(schema, name)
386 {}
table::Schema schema
Definition python.h:134
static SimpleShapeResultKey addFields(afw::table::Schema &schema, std::string const &name)

Member Function Documentation

◆ computeMoments()

template<typename T >
template SimpleShapeResult lsst::meas::extensions::simpleShape::SimpleShape::computeMoments ( afw::geom::ellipses::Ellipse const & weight,
afw::image::MaskedImage< T > const & image,
double nSigmaRegion = 3.0 )
static

Compute the Gaussian-weighted moments of an image.

Parameters
[in]weightAn ellipse object of Gaussian weights to apply to the measurement.
[in]imageA Masked image instance with int float or double pixels.
[in]nSigmaRegionMaximum radius for pixels to include, in units of sigma

Definition at line 161 of file simpleShape.cc.

165 {
166 // Define the pixel region we want to accumulate over.
167 afw::geom::ellipses::Ellipse regionEllipse(weight);
168 regionEllipse.getCore().scale(nSigmaRegion);
169 afw::geom::ellipses::PixelRegion region(regionEllipse);
170 SimpleShapeResult result;
171
172 // We work in the coordinate system where the origin is the center of the weight function.
173 // This will make things easier in the various transformations we'll have to apply to the raw
174 // moments.
175
176 // All the pixel operations take place in the next two lines, when we use the above machinery
177 // to accumulate the raw moments in a single pass.
178 RawMomentAccumulator functor(weight);
179 iterateRegion(functor, image, region);
180
181 // Then we convert the raw moments to an ellipse and centroid, and propagate the uncertainty
182 // through the covariance matrix.
183 MatrixMQ dm_dq = convertRawMoments(functor.moments, result.ellipse, result.center);
184 MatrixM mCov = dm_dq * functor.covariance.selfadjointView<Eigen::Lower>() * dm_dq.adjoint();
185
186 // Next, we correct the measured moments for the fact that what we just measured was the
187 // moments of the product of the weight function and the data, and we want just the moments
188 // of the data.
189 MatrixM dc_dm = correctWeightedMoments(
190 weight.getCore().as<afw::geom::ellipses::Quadrupole>(),
191 result.ellipse,
192 result.center
193 );
194 result.covariance = dc_dm * mCov.selfadjointView<Eigen::Lower>() * dc_dm.adjoint();
195
196 // Finally, we switch back to the native image coordinate system.
197 result.center += geom::Extent2D(weight.getCenter());
198
199 return result;
200}
py::object result
Definition _schema.cc:429
static Eigen::Matrix< double, 5, 5 > correctWeightedMoments(afw::geom::ellipses::Quadrupole const &weight, afw::geom::ellipses::Quadrupole &ellipse, geom::Point2D &center)
Correct moments measured with a Gaussian weight function by assuming the data was also an elliptical ...
static Eigen::Matrix< double, 5, 6 > convertRawMoments(Eigen::Matrix< double, 6, 1 > const &q, afw::geom::ellipses::Quadrupole &quadrupole, geom::Point2D &center)
Convert linear raw moments into an ellipse and centroid, and return the derivative of the conversion.
Extent< double, 2 > Extent2D
Definition Extent.h:400
afw::table::Key< double > weight

◆ convertRawMoments()

MatrixMQ lsst::meas::extensions::simpleShape::SimpleShape::convertRawMoments ( Eigen::Matrix< double, 6, 1 > const & q,
afw::geom::ellipses::Quadrupole & quadrupole,
geom::Point2D & center )
static

Convert linear raw moments into an ellipse and centroid, and return the derivative of the conversion.

Note
This function is mainly intended for internal use, and is only exposed publically so it can be unit-tested in Python.

For weight function \(w\) and data \(p\), the "raw" moments \(Q\) are defined as:

\begin{eqnarray*} Q_0 &=& \sum_n w(x_n, y_n) p_n \\ Q_{xx} &=& \sum_n w(x_n, y_n) x_n^2 p_n \\ Q_{yy} &=& \sum_n w(x_n, y_n) y_n^2 p_n \\ Q_{xy} &=& \sum_n w(x_n, y_n) x_n y_n p_n \\ Q_x &=& \sum_n w(x_n, y_n) x_n p_n \\ Q_y &=& \sum_n w(x_n, y_n) y_n p_n \end{eqnarray*}

whereas the converted ellipse and centroid moments are:

\begin{eqnarray*} M_{xx} &=& Q_{xx} / Q_0 - Q_x^2 \\ M_{xx} &=& Q_{yy} / Q_0 - Q_y^2 \\ M_{xx} &=& Q_{xy} / Q_0 - Q_x Q_y \\ M_x &=& Q_x / Q_0 \\ M_y &=& Q_y / Q_0 \end{eqnarray*}

Note the slightly unusual ordering; this is for consistency with afw::geom::ellipses::Ellipse.

Definition at line 203 of file simpleShape.cc.

207 {
208 VectorM m = q.segment<N_M>(1) / q[Q0];
209 MatrixMQ dm_dq = MatrixMQ::Zero();;
210 dm_dq.block<N_M,N_M>(0,1) = MatrixM::Identity() / q[Q0];
211 dm_dq.col(Q0) = -m / q[Q0];
212 // now we account for the centroid^2 terms in the second moments
213 m[MXX] -= m[MX] * m[MX];
214 m[MYY] -= m[MY] * m[MY];
215 m[MXY] -= m[MX] * m[MY];
216 dm_dq(MXX, QX) = -2.0 * m[MX] / q[Q0];
217 dm_dq(MYY, QY) = -2.0 * m[MY] / q[Q0];
218 dm_dq(MXY, QX) = m[MY] / q[Q0];
219 dm_dq(MXY, QY) = m[MX] / q[Q0];
220 double tmp = 2.0 / (q[Q0] * q[Q0] * q[Q0]); // == d(-Q_0^{-2})/d(Q_0)
221 dm_dq(MXX, Q0) += tmp * q[QX] * q[QX];
222 dm_dq(MYY, Q0) += tmp * q[QY] * q[QY];
223 dm_dq(MXY, Q0) += tmp * q[QX] * q[QY];
224
225 ellipse.setIxx(m[MXX]);
226 ellipse.setIyy(m[MYY]);
227 ellipse.setIxy(m[MXY]);
228 center.setX(m[MX]);
229 center.setY(m[MY]);
230
231 return dm_dq;
232}
int m
Definition SpanSet.cc:48

◆ correctWeightedMoments()

MatrixM lsst::meas::extensions::simpleShape::SimpleShape::correctWeightedMoments ( afw::geom::ellipses::Quadrupole const & weight,
afw::geom::ellipses::Quadrupole & ellipse,
geom::Point2D & center )
static

Correct moments measured with a Gaussian weight function by assuming the data was also an elliptical Gaussian, and return the derivative of the correction.

Note
This function is mainly intended for internal use, and is only exposed publically so it can be unit-tested in Python.

If we naively measure Gaussian-weighted moments, we'll measure the moments of the product of the weight function and the data. What we want is the moments of the data, as if we had measured them with no weight function (but without sacrificing the S/N benefit that comes from using a weight function). To do that, we assume the data is also an elliptical Gaussian, and "divide" the weight function from the measured moments to compute it.

If \(W\) and \(M\) are the quadruple matrices of the weight function and measurement, and \(\eta\) is the measured centroid (we work in a coordinate system where the weight function is centered at the origin), then the corrected quadrupole matrix \(C\) and centroid are \(\nu\) are:

\begin{eqnarray*} C &=& \left(M^{-1} - W^{-1}\right)^{-1} \\ \nu &=& C M^{-1} \eta \end{eqnarray*}

Definition at line 234 of file simpleShape.cc.

238 {
239 Eigen::Matrix2d wMat = weight.getMatrix();
240 Eigen::Vector2d mVec = center.asEigen();
241 Eigen::Matrix2d mMat = ellipse.getMatrix();
242 if (wMat.determinant() <= 0.0) {
243 throw LSST_EXCEPT(
244 base::MeasurementError,
245 "Weight moments matrix is singular",
247 );
248 }
249 if (mMat.determinant() <= 0.0) {
250 throw LSST_EXCEPT(
251 base::MeasurementError,
252 "Measured moments matrix is singular",
254 );
255 }
256 Eigen::Matrix2d mInv = mMat.inverse();
257 Eigen::Matrix2d cInv = mInv - wMat.inverse();
258 if (cInv.determinant() <= 0.0) {
259 throw LSST_EXCEPT(
260 base::MeasurementError,
261 "Corrected moments matrix is singular",
263 );
264 }
265 Eigen::Matrix2d cMat = cInv.inverse();
266 ellipse.setIxx(cMat(0, 0));
267 ellipse.setIyy(cMat(1, 1));
268 ellipse.setIxy(cMat(0, 1));
269 Eigen::Matrix2d cMat_mInv = cMat * mInv;
270 Eigen::Vector2d mInv_mVec = mInv * mVec;
271 Eigen::Vector2d cVec = cMat_mInv * mVec;
272 center.setX(cVec[0]);
273 center.setY(cVec[1]);
274 Eigen::Matrix2d dcMat_dmxx = cMat_mInv.col(0) * cMat_mInv.col(0).adjoint();
275 Eigen::Matrix2d dcMat_dmyy = cMat_mInv.col(1) * cMat_mInv.col(1).adjoint();
276 Eigen::Matrix2d dcMat_dmxy = cMat_mInv.col(0) * cMat_mInv.col(1).adjoint()
277 + cMat_mInv.col(1) * cMat_mInv.col(0).adjoint();
278 Eigen::Vector2d dcVec_dmxx = cMat_mInv.col(0) * mInv_mVec[0];
279 Eigen::Vector2d dcVec_dmyy = cMat_mInv.col(1) * mInv_mVec[1];
280 Eigen::Vector2d dcVec_dmxy = cMat_mInv.col(0) * mInv_mVec[1] + cMat_mInv.col(1) * mInv_mVec[0];
281 Eigen::Matrix2d const & dcVec_dmVec = cMat_mInv;
282
283 // calculations done - now we just need to put these elements back into a 5x5 matrix to return
284
285 MatrixM dc_dm = MatrixM::Zero();
286 dc_dm(MXX, MXX) = dcMat_dmxx(0, 0);
287 dc_dm(MYY, MXX) = dcMat_dmxx(1, 1);
288 dc_dm(MXY, MXX) = dcMat_dmxx(0, 1);
289 dc_dm(MXX, MYY) = dcMat_dmyy(0, 0);
290 dc_dm(MYY, MYY) = dcMat_dmyy(1, 1);
291 dc_dm(MXY, MYY) = dcMat_dmyy(0, 1);
292 dc_dm(MXX, MXY) = dcMat_dmxy(0, 0);
293 dc_dm(MYY, MXY) = dcMat_dmxy(1, 1);
294 dc_dm(MXY, MXY) = dcMat_dmxy(0, 1);
295 dc_dm(MX, MXX) = dcVec_dmxx[0];
296 dc_dm(MY, MXX) = dcVec_dmxx[1];
297 dc_dm(MX, MYY) = dcVec_dmyy[0];
298 dc_dm(MY, MYY) = dcVec_dmyy[1];
299 dc_dm(MX, MXY) = dcVec_dmxy[0];
300 dc_dm(MY, MXY) = dcVec_dmxy[1];
301 dc_dm(MX, MX) = dcVec_dmVec(0, 0);
302 dc_dm(MX, MY) = dcVec_dmVec(0, 1);
303 dc_dm(MY, MX) = dcVec_dmVec(1, 0);
304 dc_dm(MY, MY) = dcVec_dmVec(1, 1);
305
306 return dc_dm;
307}
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition Exception.h:48
EigenVector const & asEigen() const noexcept(IS_ELEMENT_NOTHROW_COPYABLE)
Return a fixed-size Eigen representation of the coordinate object.
static base::FlagDefinition const FAILURE

◆ fail()

void lsst::meas::extensions::simpleShape::SimpleShape::fail ( afw::table::SourceRecord & measRecord,
lsst::meas::base::MeasurementError * error = NULL ) const
virtual

Handle an exception thrown by the current algorithm by setting flags in the given record.

fail() is called by the measurement framework when an exception is allowed to propagate out of one the algorithm's measure() methods. It should generally set both a general failure flag for the algorithm as well as a specific flag indicating the error condition, if possible. To aid in this, if the exception was an instance of MeasurementError, it will be passed in, carrying information about what flag to set.

An algorithm can also to chose to set flags within its own measure() methods, and then just return, rather than throw an exception. However, fail() should be implemented even when all known failure modes do not throw exceptions, to ensure that unexpected exceptions thrown in lower-level code are properly handled.

Implements lsst::meas::base::BaseAlgorithm.

Definition at line 399 of file simpleShape.cc.

402 {
403 _resultKey.getFlagHandler().handleFailure(measRecord, error);
404}
void handleFailure(afw::table::BaseRecord &record, MeasurementError const *error=nullptr) const
Handle an expected or unexpected Exception thrown by a measurement algorithm.
lsst::meas::base::FlagHandler const & getFlagHandler() const
Definition simpleShape.h:85

◆ getFlagDefinitions()

base::FlagDefinitionList const & lsst::meas::extensions::simpleShape::SimpleShape::getFlagDefinitions ( )
static

Definition at line 37 of file simpleShape.cc.

37 {
38 return flagDefinitions;
39}

◆ getLogName()

std::string lsst::meas::base::BaseAlgorithm::getLogName ( ) const
inlineinherited

Definition at line 66 of file Algorithm.h.

66{ return _logName; }

◆ measure()

void lsst::meas::extensions::simpleShape::SimpleShape::measure ( afw::table::SourceRecord & measRecord,
afw::image::Exposure< float > const & exposure ) const
virtual

Called to measure a single child source in an image.

Before this method is called, all neighbors will be replaced with noise, using the outputs of the deblender. Outputs should be saved in the given SourceRecord, which can also be used to obtain centroid (see SafeCentroidExtractor) and shape (see SafeShapeExtractor) information.

Implements lsst::meas::base::SingleFrameAlgorithm.

Definition at line 388 of file simpleShape.cc.

391 {
392 geom::Point2D center = _centroidExtractor(source, _resultKey.getFlagHandler());
393 afw::geom::ellipses::Ellipse weight(afw::geom::ellipses::Axes(_ctrl.sigma), center);
394 // set flags so an exception throw produces a flagged source
395 SimpleShapeResult result = computeMoments(weight, exposure.getMaskedImage(), _ctrl.nSigmaRegion);
396 source.set(_resultKey, result);
397}
double sigma
"Sigma of circular Gaussian used as weight function, in pixels" ;
Definition simpleShape.h:46
double nSigmaRegion
"Maximum radius for pixels to include, in units of sigma" ;
Definition simpleShape.h:47
static SimpleShapeResult computeMoments(afw::geom::ellipses::Ellipse const &weight, afw::image::MaskedImage< T > const &image, double nSigmaRegion=3.0)
Compute the Gaussian-weighted moments of an image.
const char * source()
Source function that allows astChannel to source from a Stream.
Definition Stream.h:224

◆ measureForced()

void lsst::meas::base::SimpleAlgorithm::measureForced ( afw::table::SourceRecord & measRecord,
afw::image::Exposure< float > const & exposure,
afw::table::SourceRecord const & refRecord,
afw::geom::SkyWcs const & refWcs ) const
inlineoverridevirtualinherited

Called to measure a single child source in an image.

Before this method is called, all neighbors will be replaced with noise, using the outputs of the deblender. Outputs should be saved in the given SourceRecord, which can also be used to obtain centroid (see SafeCentroidExtractor) and shape (see SafeShapeExtractor) information.

Implements lsst::meas::base::ForcedAlgorithm.

Reimplemented in lsst::meas::extensions::photometryKron::KronFluxAlgorithm.

Definition at line 172 of file Algorithm.h.

175 {
176 measure(measRecord, exposure);
177 }
virtual void measure(afw::table::SourceRecord &measRecord, afw::image::Exposure< float > const &exposure) const =0
Called to measure a single child source in an image.

◆ measureN()

void lsst::meas::base::SingleFrameAlgorithm::measureN ( afw::table::SourceCatalog const & measCat,
afw::image::Exposure< float > const & exposure ) const
virtualinherited

Called to simultaneously measure all children in a deblend family, in a single image.

Outputs should be saved in the given SourceCatalog, which can also be used to obtain centroid (see SafeCentroidExtractor) and shape (see SafeShapeExtractor) information.

The default implementation simply throws an exception, indicating that simultaneous measurement is not supported.

Definition at line 31 of file Algorithm.cc.

32 {
33 throw LSST_EXCEPT(pex::exceptions::LogicError, "measureN not implemented for this algorithm");
34}

◆ measureNForced()

void lsst::meas::base::SimpleAlgorithm::measureNForced ( afw::table::SourceCatalog const & measCat,
afw::image::Exposure< float > const & exposure,
afw::table::SourceCatalog const & refRecord,
afw::geom::SkyWcs const & refWcs ) const
inlineoverridevirtualinherited

Called to simultaneously measure all children in a deblend family, in a single image.

Outputs should be saved in the given SourceCatalog, which can also be used to obtain centroid (see SafeCentroidExtractor) and shape (see SafeShapeExtractor) information.

The default implementation simply throws an exception, indicating that simultaneous measurement is not supported.

Reimplemented from lsst::meas::base::ForcedAlgorithm.

Definition at line 179 of file Algorithm.h.

182 {
183 measureN(measCat, exposure);
184 }
virtual void measureN(afw::table::SourceCatalog const &measCat, afw::image::Exposure< float > const &exposure) const
Called to simultaneously measure all children in a deblend family, in a single image.
Definition Algorithm.cc:31

Member Data Documentation

◆ _logName

std::string lsst::meas::base::BaseAlgorithm::_logName
protectedinherited

Definition at line 69 of file Algorithm.h.

◆ FAILURE

base::FlagDefinition const lsst::meas::extensions::simpleShape::SimpleShape::FAILURE = flagDefinitions.addFailureFlag()
static

Definition at line 101 of file simpleShape.h.

◆ N_FLAGS

unsigned int const lsst::meas::extensions::simpleShape::SimpleShape::N_FLAGS = 1
static

Definition at line 100 of file simpleShape.h.


The documentation for this class was generated from the following files: