27 #include "boost/tuple/tuple.hpp"
43 FlagDefinitionList flagDefinitions;
48 flagDefinitions.add(
"flag_unweightedBad",
"Both weighted and unweighted moments were invalid");
50 "flag_unweighted",
"Weighted moments converged to an invalid value; using unweighted moments");
52 flagDefinitions.add(
"flag_shift",
"centroid shifted by more than the maximum allowed amount");
54 flagDefinitions.add(
"flag_maxIter",
"Too many iterations in adaptive moments");
56 flagDefinitions.add(
"flag_psf",
"Failure in measuring PSF model shape");
62 typedef Eigen::Matrix<double, 4, 4, Eigen::DontAlign> Matrix4d;
80 float const sigma11W = shape.
xx;
81 float const sigma12W = shape.
xy;
82 float const sigma22W = shape.
yy;
84 double const D = sigma11W * sigma22W - sigma12W * sigma12W;
92 if (bkgd_var <= 0.0) {
94 (boost::format(
"Background variance must be positive (saw %g)") % bkgd_var).str());
96 double const F =
geom::PI * sqrt(D) / bkgd_var;
102 double fac = F * A / (4.0 * D);
104 fisher(0, 1) = fac * sigma22W;
105 fisher(1, 0) = fisher(0, 1);
106 fisher(0, 2) = fac * sigma11W;
107 fisher(2, 0) = fisher(0, 2);
108 fisher(0, 3) = -fac * 2 * sigma12W;
109 fisher(3, 0) = fisher(0, 3);
111 fac = 3.0 * F * A * A / (16.0 * D * D);
112 fisher(1, 1) = fac * sigma22W * sigma22W;
113 fisher(2, 2) = fac * sigma11W * sigma11W;
114 fisher(3, 3) = fac * 4.0 * (sigma12W * sigma12W + D / 3.0);
116 fisher(1, 2) = fisher(3, 3) / 4.0;
117 fisher(2, 1) = fisher(1, 2);
118 fisher(1, 3) = fac * (-2 * sigma22W * sigma12W);
119 fisher(3, 1) = fisher(1, 3);
120 fisher(2, 3) = fac * (-2 * sigma11W * sigma12W);
121 fisher(3, 2) = fisher(2, 3);
128 template <
typename ImageT>
129 struct ImageAdaptor {
130 typedef ImageT Image;
132 static bool const hasVariance =
false;
134 Image
const &getImage(ImageT
const &image)
const {
return image; }
139 template <
typename T>
140 struct ImageAdaptor<afw::image::MaskedImage<T> > {
143 static bool const hasVariance =
true;
145 Image
const &getImage(afw::image::MaskedImage<T>
const &mimage)
const {
return *mimage.getImage(); }
147 double getVariance(afw::image::MaskedImage<T>
const &mimage,
int ix,
int iy) {
148 return mimage.at(ix, iy).variance();
159 double const det = sigma11 * sigma22 - sigma12 * sigma12;
167 bool shouldInterp(
double sigma11,
double sigma22,
double det) {
168 float const xinterp = 0.25;
169 return (sigma11 < xinterp || sigma22 < xinterp || det < xinterp * xinterp);
175 geom::Box2I computeAdaptiveMomentsBBox(geom::Box2I
const &bbox,
180 double maxRadius = 1000
184 geom::Box2I result(geom::Box2D(center - offset, center + offset));
193 template <
bool instFluxOnly,
typename ImageT>
194 static int calcmom(ImageT
const &image,
195 float xcen,
float ycen,
199 double w11,
double w12,
double w22,
202 double *psumx,
double *psumy,
203 double *psumxx,
double *psumxy,
double *psumyy,
205 bool negative =
false) {
210 double sum, sumx, sumy, sumxx, sumyy, sumxy, sums4;
213 double wsum, wsumxx, wsumxy, wsumyy;
215 wsum = wsumxx = wsumxy = wsumyy = 0;
219 if (
fabs(w11) > 1e6 ||
fabs(w12) > 1e6 ||
fabs(w22) > 1e6) {
223 sum = sumx = sumy = sumxx = sumxy = sumyy = sums4 = 0;
225 int const ix0 =
bbox.getMinX();
226 int const ix1 =
bbox.getMaxX();
227 int const iy0 =
bbox.getMinY();
228 int const iy1 =
bbox.getMaxY();
230 if (ix0 < 0 || ix1 >=
image.getWidth() || iy0 < 0 || iy1 >=
image.getHeight()) {
234 for (
int i = iy0; i <= iy1; ++i) {
235 typename ImageT::x_iterator ptr =
image.x_at(ix0, i);
236 float const y = i - ycen;
237 float const y2 =
y *
y;
238 float const yl =
y - 0.375;
239 float const yh =
y + 0.375;
240 for (
int j = ix0; j <= ix1; ++j, ++ptr) {
243 float const xl =
x - 0.375;
244 float const xh =
x + 0.375;
246 float expon = xl * xl * w11 + yl * yl * w22 + 2.0 * xl * yl * w12;
247 tmp = xh * xh * w11 + yh * yh * w22 + 2.0 * xh * yh * w12;
248 expon = (expon > tmp) ? expon : tmp;
249 tmp = xl * xl * w11 + yh * yh * w22 + 2.0 * xl * yh * w12;
250 expon = (expon > tmp) ? expon : tmp;
251 tmp = xh * xh * w11 + yl * yl * w22 + 2.0 * xh * yl * w12;
252 expon = (expon > tmp) ? expon : tmp;
256 for (Y = yl;
Y <= yh;
Y += 0.25) {
257 double const interpY2 =
Y *
Y;
258 for (X = xl;
X <= xh;
X += 0.25) {
259 double const interpX2 =
X *
X;
260 double const interpXy =
X *
Y;
261 expon = interpX2 * w11 + 2 * interpXy * w12 + interpY2 * w22;
264 ymod = tmod * weight;
267 sumx += ymod * (
X + xcen);
268 sumy += ymod * (
Y + ycen);
272 tmp = interpX2 * weight;
276 tmp = interpXy * weight;
280 tmp = interpY2 * weight;
284 sumxx += interpX2 * ymod;
285 sumxy += interpXy * ymod;
286 sumyy += interpY2 * ymod;
288 sums4 += expon * expon * ymod;
296 float expon = x2 * w11 + 2 * xy * w12 + y2 * w22;
301 ymod = tmod * weight;
325 sums4 += expon * expon * ymod;
334 double const detW = std::get<1>(weights) * std::get<3>(weights) -
std::pow(std::get<2>(weights), 2);
346 if (psums4 != NULL) {
352 if (wsum > 0 && !instFluxOnly) {
353 double det = w11 * w22 - w12 * w12;
357 printf(
"%g %g %g %g %g %g\n", w22 / det, -w12 / det, w11 / det, wsumxx, wsumxy, wsumyy);
362 return (instFluxOnly || (sum < 0 && sumxx < 0 && sumyy < 0)) ? 0 : -1;
364 return (instFluxOnly || (sum > 0 && sumxx > 0 && sumyy > 0)) ? 0 : -1;
373 template <
typename ImageT>
374 bool getAdaptiveMoments(ImageT
const &mimage,
double bkgd,
double xcen,
double ycen,
double shiftmax,
375 SdssShapeResult *shape,
int maxIter,
float tol1,
float tol2,
bool negative) {
379 double sumxx, sumxy, sumyy;
381 float const xcen0 = xcen;
382 float const ycen0 = ycen;
384 double sigma11W = 1.5;
385 double sigma12W = 0.0;
386 double sigma22W = 1.5;
388 double w11 = -1, w12 = -1, w22 = -1;
389 float e1_old = 1e6, e2_old = 1e6;
390 float sigma11_ow_old = 1e6;
392 typename ImageAdaptor<ImageT>::Image
const &
image = ImageAdaptor<ImageT>().getImage(mimage);
400 bool interpflag =
false;
405 sigma11W, sigma12W, sigma22W);
407 getWeights(sigma11W, sigma12W, sigma22W);
408 if (!std::get<0>(weights).first) {
413 double const detW = std::get<0>(weights).second;
422 const double ow11 = w11;
423 const double ow12 = w12;
424 const double ow22 = w22;
426 w11 = std::get<1>(weights);
427 w12 = std::get<2>(weights);
428 w22 = std::get<3>(weights);
430 if (shouldInterp(sigma11W, sigma22W, detW)) {
434 sigma11_ow_old = 1.e6;
444 if (calcmom<false>(image, xcen, ycen, bbox, bkgd, interpflag, w11, w12, w22, &I0, &sum, &sumx, &sumy,
445 &sumxx, &sumxy, &sumyy, &sums4, negative) < 0) {
459 shape->x = sumx / sum;
460 shape->y = sumy / sum;
462 if (
fabs(shape->x - xcen0) > shiftmax ||
fabs(shape->y - ycen0) > shiftmax) {
468 float const sigma11_ow = sumxx / sum;
469 float const sigma22_ow = sumyy / sum;
470 float const sigma12_ow = sumxy / sum;
472 if (sigma11_ow <= 0 || sigma22_ow <= 0) {
477 float const d = sigma11_ow + sigma22_ow;
478 float const e1 = (sigma11_ow - sigma22_ow) / d;
479 float const e2 = 2.0 * sigma12_ow / d;
483 if (iter > 0 &&
fabs(e1 - e1_old) < tol1 &&
fabs(e2 - e2_old) < tol1 &&
484 fabs(sigma11_ow / sigma11_ow_old - 1.0) < tol2) {
490 sigma11_ow_old = sigma11_ow;
515 float ow11, ow12, ow22;
518 getWeights(sigma11_ow, sigma12_ow, sigma22_ow);
519 if (!std::get<0>(weights).first) {
524 ow11 = std::get<1>(weights);
525 ow12 = std::get<2>(weights);
526 ow22 = std::get<3>(weights);
532 weights = getWeights(n11, n12, n22);
533 if (!std::get<0>(weights).first) {
539 sigma11W = std::get<1>(weights);
540 sigma12W = std::get<2>(weights);
541 sigma22W = std::get<3>(weights);
544 if (sigma11W <= 0 || sigma22W <= 0) {
550 if (iter == maxIter) {
555 if (sumxx + sumyy == 0.0) {
563 if (calcmom<false>(image, xcen, ycen, bbox, bkgd, interpflag, w11, w12, w22, &I0, &sum, &sumx, &sumy,
564 &sumxx, &sumxy, &sumyy, NULL, negative) < 0 ||
565 (!negative && sum <= 0) || (negative && sum >= 0)) {
570 shape->xx = 1 / 12.0;
572 shape->yy = 1 / 12.0;
578 sigma11W = sumxx / sum;
579 sigma12W = sumxy / sum;
580 sigma22W = sumyy / sum;
583 shape->instFlux = I0;
584 shape->xx = sigma11W;
585 shape->xy = sigma12W;
586 shape->yy = sigma22W;
588 if (shape->xx + shape->yy != 0.0) {
592 if (ix >= 0 && ix < mimage.getWidth() && iy >= 0 && iy < mimage.getHeight()) {
593 float const bkgd_var = ImageAdaptor<ImageT>().getVariance(
596 if (bkgd_var > 0.0) {
598 Matrix4d fisher = calc_fisher(*shape, bkgd_var);
599 Matrix4d cov = fisher.inverse();
603 shape->instFluxErr =
std::sqrt(cov(0, 0));
607 shape->instFlux_xx_Cov = cov(0, 1);
608 shape->instFlux_xy_Cov = cov(0, 2);
609 shape->instFlux_yy_Cov = cov(0, 3);
610 shape->xx_yy_Cov = cov(1, 3);
611 shape->xx_xy_Cov = cov(1, 2);
612 shape->yy_xy_Cov = cov(2, 3);
624 : instFlux_xx_Cov(
std::numeric_limits<
ErrElement>::quiet_NaN()),
625 instFlux_yy_Cov(
std::numeric_limits<
ErrElement>::quiet_NaN()),
626 instFlux_xy_Cov(
std::numeric_limits<
ErrElement>::quiet_NaN()) {}
639 r._includePsf =
true;
641 schema,
schema.join(
name,
"psf"),
"adaptive moments of the PSF model at the object position");
643 r._includePsf =
false;
648 (boost::format(
"uncertainty covariance between %s and %s") %
654 (boost::format(
"uncertainty covariance between %s and %s") %
660 (boost::format(
"uncertainty covariance between %s and %s") %
679 _instFlux_xx_Cov(s[
"instFlux"][
"xx"][
"Cov"]),
680 _instFlux_yy_Cov(s[
"instFlux"][
"yy"][
"Cov"]),
681 _instFlux_xy_Cov(s[
"instFlux"][
"xy"][
"Cov"]) {
698 static_cast<FluxResult &
>(result) = record.
get(_instFluxResult);
710 return record.
get(_psfShapeResult);
714 record.
set(_shapeResult, value);
715 record.
set(_centroidResult, value);
716 record.
set(_instFluxResult, value);
728 record.
set(_psfShapeResult, value);
732 return _shapeResult == other._shapeResult && _centroidResult == other._centroidResult &&
733 _instFluxResult == other._instFluxResult && _psfShapeResult == other._psfShapeResult &&
734 _instFlux_xx_Cov == other._instFlux_xx_Cov && _instFlux_yy_Cov == other._instFlux_yy_Cov &&
735 _instFlux_xy_Cov == other._instFlux_xy_Cov;
752 template <
typename ImageT>
754 bool negative,
Control const &control) {
755 double xcen = center.getX();
756 double ycen = center.getY();
758 xcen -=
image.getX0();
759 ycen -=
image.getY0();
764 }
else if (shiftmax > 10) {
772 control.
tol1, control.
tol2, negative);
784 double epsilon = 1.0e-6;
785 if (IxxIyy < (1.0 + epsilon) * Ixy_sq)
791 (boost::format(
"computeAdaptiveMoments IxxIxy %d < (1 + eps=%d)*(Ixy^2=%d);"
792 " implying singular moments without any flag set")
793 % IxxIyy % epsilon % Ixy_sq).str());
808 result.
x +=
image.getX0();
809 result.
y +=
image.getY0();
811 if (ImageAdaptor<ImageT>::hasVariance) {
820 template <
typename ImageT>
835 if (!std::get<0>(weights).
first) {
839 double const w11 = std::get<1>(weights);
840 double const w12 = std::get<2>(weights);
841 double const w22 = std::get<3>(weights);
842 bool const interp = shouldInterp(shape.
getIxx(), shape.
getIyy(), std::get<0>(weights).second);
845 if (calcmom<true>(ImageAdaptor<ImageT>().getImage(
image), localCenter.getX(), localCenter.getY(),
bbox,
846 0.0, interp, w11, w12, w22, NULL, &sum0, NULL, NULL, NULL, NULL, NULL, NULL) < 0) {
852 if (ImageAdaptor<ImageT>::hasVariance) {
853 int ix =
static_cast<int>(center.getX() -
image.getX0());
854 int iy =
static_cast<int>(center.getY() -
image.getY0());
857 (boost::format(
"Center (%d,%d) not in image (%dx%d)") % ix % iy %
861 double var = ImageAdaptor<ImageT>().getVariance(
image, ix, iy);
872 bool negative =
false;
875 negative = measRecord.
get(measRecord.
getSchema().
find<afw::table::Flag>(
"flags_negative").key);
876 }
catch (pexExcept::Exception &e) {
902 measRecord.
set(_resultKey, result);
909 #define INSTANTIATE_IMAGE(IMAGE) \
910 template SdssShapeResult SdssShapeAlgorithm::computeAdaptiveMoments( \
911 IMAGE const &, geom::Point2D const &, bool, Control const &); \
912 template FluxResult SdssShapeAlgorithm::computeFixedMomentsFlux( \
913 IMAGE const &, afw::geom::ellipses::Quadrupole const &, geom::Point2D const &)
915 #define INSTANTIATE_PIXEL(PIXEL) \
916 INSTANTIATE_IMAGE(afw::image::Image<PIXEL>); \
917 INSTANTIATE_IMAGE(afw::image::MaskedImage<PIXEL>);
927 _transformPsf =
mapper.getInputSchema().getNames().count(
"sdssShape_flag_psf") ? true :
false;
933 if (
mapper.getInputSchema().getNames().count(
mapper.getInputSchema().join(
name, flag.
name)) == 0)
936 mapper.getInputSchema().find<afw::table::Flag>(
name +
"_" + flag.
name).key;
944 "PSF shape in celestial moments",
954 _instFluxTransform(inputCatalog, outputCatalog,
wcs,
photoCalib);
955 _centroidTransform(inputCatalog, outputCatalog,
wcs,
photoCalib);
967 for (; inSrc != inputCatalog.
end(); ++inSrc, ++outSrc) {
980 _outShapeKey.
set(*outSrc, outShape);
table::Key< std::string > name
#define LSST_EXCEPT(type,...)
#define INSTANTIATE_PIXEL(PIXEL)
table::Key< table::Array< std::uint8_t > > wcs
Transformer transform(lsst::geom::LinearTransform const &transform)
double const getIxy() const
double getDeterminant() const
double const getIxx() const
double const getIyy() const
MaskedImageT getMaskedImage()
std::shared_ptr< lsst::afw::detection::Psf const > getPsf() const
lsst::afw::image::Image< ImagePixelT > Image
void set(Key< T > const &key, U const &value)
Field< T >::Value get(Key< T > const &key) const
CatalogIterator< typename Internal::iterator > iterator
bool isValid() const noexcept
geom::ellipses::Quadrupole get(BaseRecord const &record) const override
void set(BaseRecord &record, geom::ellipses::Quadrupole const &value) const override
static QuadrupoleKey addFields(Schema &schema, std::string const &name, std::string const &doc, CoordinateType coordType=CoordinateType::PIXEL)
bool isValid() const noexcept
std::string join(std::string const &a, std::string const &b) const
SchemaItem< T > find(std::string const &name) const
typename Base::const_iterator const_iterator
A FunctorKey for CentroidResult.
virtual CentroidResult get(afw::table::BaseRecord const &record) const
Get a CentroidResult from the given record.
bool isValid() const
Return True if the centroid key is valid.
static CentroidResultKey addFields(afw::table::Schema &schema, std::string const &name, std::string const &doc, UncertaintyEnum uncertainty)
Add the appropriate fields to a Schema, and return a CentroidResultKey that manages them.
vector-type utility class to build a collection of FlagDefinitions
std::size_t size() const
return the current size (number of defined elements) of the collection
Utility class for handling flag fields that indicate the failure modes of an algorithm.
void handleFailure(afw::table::BaseRecord &record, MeasurementError const *error=nullptr) const
Handle an expected or unexpected Exception thrown by a measurement algorithm.
static FlagHandler addFields(afw::table::Schema &schema, std::string const &prefix, FlagDefinitionList const &flagDefs, FlagDefinitionList const &exclDefs=FlagDefinitionList::getEmptyList())
Add Flag fields to a schema, creating a FlagHandler object to manage them.
void setValue(afw::table::BaseRecord &record, std::size_t i, bool value) const
Set the flag field corresponding to the given flag index.
bool getValue(afw::table::BaseRecord const &record, std::size_t i) const
Return the value of the flag field corresponding to the given flag index.
bool isValid() const
Return True if both the instFlux and instFluxErr Keys are valid.
static FluxResultKey addFields(afw::table::Schema &schema, std::string const &name, std::string const &doc)
Add a pair of _instFlux, _instFluxErr fields to a Schema, and return a FluxResultKey that points to t...
Exception to be thrown when a measurement algorithm experiences a known failure mode.
static FlagDefinition const SHIFT
static FlagDefinitionList const & getFlagDefinitions()
virtual void measure(afw::table::SourceRecord &measRecord, afw::image::Exposure< float > const &exposure) const
Called to measure a single child source in an image.
static Result computeAdaptiveMoments(ImageT const &image, geom::Point2D const &position, bool negative=false, Control const &ctrl=Control())
Compute the adaptive Gaussian-weighted moments of an image.
static FlagDefinition const FAILURE
static unsigned int const N_FLAGS
static FluxResult computeFixedMomentsFlux(ImageT const &image, afw::geom::ellipses::Quadrupole const &shape, geom::Point2D const &position)
Compute the instFlux within a fixed Gaussian aperture.
static FlagDefinition const MAXITER
static FlagDefinition const UNWEIGHTED
static FlagDefinition const PSF_SHAPE_BAD
static FlagDefinition const UNWEIGHTED_BAD
SdssShapeAlgorithm(Control const &ctrl, std::string const &name, afw::table::Schema &schema)
virtual void fail(afw::table::SourceRecord &measRecord, MeasurementError *error=nullptr) const
Handle an exception thrown by the current algorithm by setting flags in the given record.
A C++ control class to handle SdssShapeAlgorithm's configuration.
double maxShift
"Maximum centroid shift, limited to 2-10" ;
int maxIter
"Maximum number of iterations" ;
float tol2
"Convergence tolerance for FWHM" ;
bool doMeasurePsf
"Whether to also compute the shape of the PSF model" ;
float tol1
"Convergence tolerance for e1,e2" ;
double background
"Additional value to add to background" ;
Result object SdssShapeAlgorithm.
ErrElement instFlux_yy_Cov
instFlux, yy term in the uncertainty covariance matrix
SdssShapeResult()
Constructor; initializes everything to NaN.
ErrElement instFlux_xy_Cov
instFlux, xy term in the uncertainty covariance matrix
std::bitset< SdssShapeAlgorithm::N_FLAGS > flags
Status flags (see SdssShapeAlgorithm).
ErrElement instFlux_xx_Cov
instFlux, xx term in the uncertainty covariance matrix
A FunctorKey that maps SdssShapeResult to afw::table Records.
FlagHandler const & getFlagHandler() const
SdssShapeResultKey()
Default constructor; instance will not be usuable unless subsequently assigned to.
virtual SdssShapeResult get(afw::table::BaseRecord const &record) const
Get an SdssShapeResult from the given record.
static SdssShapeResultKey addFields(afw::table::Schema &schema, std::string const &name, bool doMeasurePsf)
Add the appropriate fields to a Schema, and return a SdssShapeResultKey that manages them.
virtual afw::geom::ellipses::Quadrupole getPsfShape(afw::table::BaseRecord const &record) const
Get a Quadrupole for the Psf from the given record.
bool isValid() const
Return True if the key is valid.
bool operator==(SdssShapeResultKey const &other) const
Compare the FunctorKey for equality with another, using the underlying Keys.
virtual void set(afw::table::BaseRecord &record, SdssShapeResult const &value) const
Set an SdssShapeResult in the given record.
virtual void setPsfShape(afw::table::BaseRecord &record, afw::geom::ellipses::Quadrupole const &value) const
Set a Quadrupole for the Psf at the position of the given record.
A FunctorKey for ShapeResult.
static ShapeResultKey addFields(afw::table::Schema &schema, std::string const &name, std::string const &doc, UncertaintyEnum uncertainty, afw::table::CoordinateType coordType=afw::table::CoordinateType::PIXEL)
Add the appropriate fields to a Schema, and return a ShapeResultKey that manages them.
virtual ShapeResult get(afw::table::BaseRecord const &record) const
Get a ShapeResult from the given record.
bool isValid() const
Return True if the shape key is valid.
virtual void set(afw::table::BaseRecord &record, ShapeResult const &value) const
Set a ShapeResult in the given record.
int positionToIndex(double pos)
Extent< double, 2 > Extent2D
Point< double, 2 > Point2D
constexpr AngleUnit radians
@ SIGMA_ONLY
Only the diagonal elements of the covariance matrix are provided.
@ FULL_COVARIANCE
The full covariance matrix is provided.
@ NO_UNCERTAINTY
Algorithm provides no uncertainy information at all.
Eigen::Matrix< ShapeElement, 3, 3, Eigen::DontAlign > ShapeTrMatrix
ShapeTrMatrix makeShapeTransformMatrix(geom::LinearTransform const &xform)
Construct a matrix suitable for transforming second moments.
A reusable struct for centroid measurements.
CentroidElement y
y (row) coordinate of the measured position
Centroid const getCentroid() const
Return a Point object containing the measured x and y.
CentroidElement x
x (column) coordinate of the measured position
Simple class used to define and document flags The name and doc constitute the identity of the FlagDe...
A reusable result struct for instFlux measurements.
meas::base::Flux instFlux
Measured instFlux in DN.
meas::base::FluxErrElement instFluxErr
Standard deviation of instFlux in DN.
A reusable struct for moments-based shape measurements.
Shape const getShape() const
Return an afw::geom::ellipses object corresponding to xx, yy, xy.
ShapeCov const getShapeErr() const
Return the 3x3 symmetric covariance matrix, with rows and columns ordered (xx, yy,...
afw::geom::ellipses::Quadrupole getQuadrupole()
void setShape(Shape const &shape)
Set struct elements from the given Quadrupole object.
ShapeElement xy
image or model second moment for xy^2
ShapeElement xx
image or model second moment for x^2
void setShapeErr(ShapeCov const &matrix)
Set the struct standard deviation elements from the given matrix, with rows and columns ordered (xx,...
ShapeElement yy
image or model second moment for y^2