LSSTApplications  18.0.0+106,18.0.0+50,19.0.0,19.0.0+1,19.0.0+10,19.0.0+11,19.0.0+13,19.0.0+17,19.0.0+2,19.0.0-1-g20d9b18+6,19.0.0-1-g425ff20,19.0.0-1-g5549ca4,19.0.0-1-g580fafe+6,19.0.0-1-g6fe20d0+1,19.0.0-1-g7011481+9,19.0.0-1-g8c57eb9+6,19.0.0-1-gb5175dc+11,19.0.0-1-gdc0e4a7+9,19.0.0-1-ge272bc4+6,19.0.0-1-ge3aa853,19.0.0-10-g448f008b,19.0.0-12-g6990b2c,19.0.0-2-g0d9f9cd+11,19.0.0-2-g3d9e4fb2+11,19.0.0-2-g5037de4,19.0.0-2-gb96a1c4+3,19.0.0-2-gd955cfd+15,19.0.0-3-g2d13df8,19.0.0-3-g6f3c7dc,19.0.0-4-g725f80e+11,19.0.0-4-ga671dab3b+1,19.0.0-4-gad373c5+3,19.0.0-5-ga2acb9c+2,19.0.0-5-gfe96e6c+2,w.2020.01
LSSTDataManagementBasePackage
BaseCore.cc
Go to the documentation of this file.
1 // -*- lsst-c++ -*-
2 
3 /*
4  * LSST Data Management System
5  * Copyright 2008, 2009, 2010 LSST Corporation.
6  *
7  * This product includes software developed by the
8  * LSST Project (http://www.lsst.org/).
9  *
10  * This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the LSST License Statement and
21  * the GNU General Public License along with this program. If not,
22  * see <http://www.lsstcorp.org/LegalNotices/>.
23  */
27 #include "lsst/geom/Angle.h"
28 #include <boost/format.hpp>
29 #include <map>
30 
31 namespace lsst {
32 namespace afw {
33 namespace geom {
34 namespace ellipses {
35 
36 namespace {
37 
39 
40 RegistryMap& getRegistry() {
41  static RegistryMap instance;
42  return instance;
43 }
44 
45 std::shared_ptr<BaseCore> getRegistryCopy(std::string const& name) {
46  RegistryMap::iterator i = getRegistry().find(name);
47  if (i == getRegistry().end()) {
49  (boost::format("Ellipse core with name '%s' not found in registry.") % name).str());
50  }
51  return i->second->clone();
52 }
53 
54 } // namespace
55 
57  std::shared_ptr<BaseCore> result = getRegistryCopy(name);
58  *result = Quadrupole();
59  return result;
60 }
61 
63  std::shared_ptr<BaseCore> result = getRegistryCopy(name);
64  result->setParameterVector(parameters);
65  return result;
66 }
67 
68 std::shared_ptr<BaseCore> BaseCore::make(std::string const& name, double v1, double v2, double v3) {
69  std::shared_ptr<BaseCore> result = getRegistryCopy(name);
70  result->setParameterVector(ParameterVector(v1, v2, v3));
71  return result;
72 }
73 
75  std::shared_ptr<BaseCore> result = getRegistryCopy(name);
76  *result = other;
77  return result;
78 }
79 
81  std::shared_ptr<BaseCore> result = getRegistryCopy(name);
82  other.apply(*result);
83  return result;
84 }
85 
87  std::shared_ptr<BaseCore> result = getRegistryCopy(name);
88  other.apply(*result);
89  return result;
90 }
91 
93  getRegistry()[example->getName()] = example;
94 }
95 
96 void BaseCore::grow(double buffer) {
97  double a, b, theta;
98  _assignToAxes(a, b, theta);
99  a += buffer;
100  b += buffer;
101  _assignFromAxes(a, b, theta);
102 }
103 
104 void BaseCore::scale(double factor) {
105  double a, b, theta;
106  _assignToAxes(a, b, theta);
107  a *= factor;
108  b *= factor;
109  _assignFromAxes(a, b, theta);
110 }
111 
112 double BaseCore::getArea() const {
113  double a, b, theta;
114  _assignToAxes(a, b, theta);
115  return a * b * lsst::geom::PI;
116 }
117 
119  double a, b, theta;
120  _assignToAxes(a, b, theta);
121  return std::sqrt(a * b);
122 }
123 
124 double BaseCore::getTraceRadius() const {
125  double ixx, iyy, ixy;
126  _assignToQuadrupole(ixx, iyy, ixy);
127  return std::sqrt(0.5 * (ixx + iyy));
128 }
129 
131  double a, b, theta;
132  _assignToAxes(a, b, theta);
133  double c = std::cos(theta);
134  double s = std::sin(theta);
135  c *= c;
136  s *= s;
137  b *= b;
138  a *= a;
139  lsst::geom::Extent2D dimensions(std::sqrt(b * s + a * c), std::sqrt(a * s + b * c));
140  dimensions *= 2;
141  return dimensions;
142 }
143 
145  ParameterVector r;
146  writeParameters(r.data());
147  return r;
148 }
149 
151 
152 bool BaseCore::operator==(BaseCore const& other) const {
153  return getParameterVector() == other.getParameterVector() && getName() == other.getName();
154 }
155 
157  if (&other != this) {
158  // We use Axes instead of Quadrupole here because it allows us to copy Axes without
159  // implicitly normalizing them.
160  double a, b, theta;
161  other._assignToAxes(a, b, theta);
162  _assignFromAxes(a, b, theta);
163  }
164  return *this;
165 }
166 // Delegate to copy-constructor for backward-compatibility
168 
170  if (getName() == other.getName()) {
171  this->operator=(other);
172  return Jacobian::Identity();
173  }
174  // We use Quadrupole instead of Axes here because the ambiguity of the position angle
175  // in the circular case causes some of the Jacobians to/from Axes to be undefined for
176  // exact circles. Quadrupoles don't have that problem, and the Axes-to-Axes case is
177  // handled by the above if block.
178  double ixx, iyy, ixy;
179  Jacobian rhs = other._dAssignToQuadrupole(ixx, iyy, ixy);
180  Jacobian lhs = _dAssignFromQuadrupole(ixx, iyy, ixy);
181  return lhs * rhs;
182 }
183 
184 void BaseCore::_assignQuadrupoleToAxes(double ixx, double iyy, double ixy, double& a, double& b,
185  double& theta) {
186  double xx_p_yy = ixx + iyy;
187  double xx_m_yy = ixx - iyy;
188  double t = std::sqrt(xx_m_yy * xx_m_yy + 4 * ixy * ixy);
189  a = std::sqrt(0.5 * (xx_p_yy + t));
190  b = std::sqrt(0.5 * (xx_p_yy - t));
191  theta = 0.5 * std::atan2(2.0 * ixy, xx_m_yy);
192 }
193 
194 BaseCore::Jacobian BaseCore::_dAssignQuadrupoleToAxes(double ixx, double iyy, double ixy, double& a,
195  double& b, double& theta) {
196  double xx_p_yy = ixx + iyy;
197  double xx_m_yy = ixx - iyy;
198  double t2 = xx_m_yy * xx_m_yy + 4.0 * ixy * ixy;
199  Eigen::Vector3d dt2(2.0 * xx_m_yy, -2.0 * xx_m_yy, 8.0 * ixy);
200  double t = std::sqrt(t2);
201  a = std::sqrt(0.5 * (xx_p_yy + t));
202  b = std::sqrt(0.5 * (xx_p_yy - t));
203  theta = 0.5 * std::atan2(2.0 * ixy, xx_m_yy);
204  Jacobian m = Jacobian::Zero();
205  m(0, 0) = 0.25 * (1.0 + 0.5 * dt2[0] / t) / a;
206  m(0, 1) = 0.25 * (1.0 + 0.5 * dt2[1] / t) / a;
207  m(0, 2) = 0.25 * (0.5 * dt2[2] / t) / a;
208  m(1, 0) = 0.25 * (1.0 - 0.5 * dt2[0] / t) / b;
209  m(1, 1) = 0.25 * (1.0 - 0.5 * dt2[1] / t) / b;
210  m(1, 2) = 0.25 * (-0.5 * dt2[2] / t) / b;
211 
212  m.row(2).setConstant(1.0 / (t * t));
213  m(2, 0) *= -ixy;
214  m(2, 1) *= ixy;
215  m(2, 2) *= xx_m_yy;
216  return m;
217 }
218 
219 void BaseCore::_assignAxesToQuadrupole(double a, double b, double theta, double& ixx, double& iyy,
220  double& ixy) {
221  a *= a;
222  b *= b;
223  double c = std::cos(theta);
224  double s = std::sin(theta);
225  ixy = (a - b) * c * s;
226  c *= c;
227  s *= s;
228  ixx = c * a + s * b;
229  iyy = s * a + c * b;
230 }
231 
232 BaseCore::Jacobian BaseCore::_dAssignAxesToQuadrupole(double a, double b, double theta, double& ixx,
233  double& iyy, double& ixy) {
234  Jacobian m;
235  m.col(0).setConstant(2 * a);
236  m.col(1).setConstant(2 * b);
237  a *= a;
238  b *= b;
239  m.col(2).setConstant(a - b);
240  double c = std::cos(theta);
241  double s = std::sin(theta);
242  double cs = c * s;
243  ixy = (a - b) * c * s;
244  c *= c;
245  s *= s;
246  ixx = c * a + s * b;
247  iyy = s * a + c * b;
248  m(0, 0) *= c;
249  m(0, 1) *= s;
250  m(0, 2) *= -2.0 * cs;
251  m(1, 0) *= s;
252  m(1, 1) *= c;
253  m(1, 2) *= 2.0 * cs;
254  m(2, 0) *= cs;
255  m(2, 1) *= -cs;
256  m(2, 2) *= (c - s);
257  return m;
258 }
259 } // namespace ellipses
260 } // namespace geom
261 } // namespace afw
262 } // namespace lsst
An ellipse core with quadrupole moments as parameters.
Definition: Quadrupole.h:47
static Jacobian _dAssignQuadrupoleToAxes(double ixx, double iyy, double ixy, double &a, double &b, double &theta)
Definition: BaseCore.cc:194
Jacobian dAssign(BaseCore const &other)
Assign other to this and return the derivative of the conversion, d(this)/d(other).
Definition: BaseCore.cc:169
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:174
static Jacobian _dAssignAxesToQuadrupole(double a, double b, double theta, double &ixx, double &iyy, double &ixy)
Definition: BaseCore.cc:232
A temporary-only expression object for ellipse core transformations.
Definition: Transformer.h:49
virtual Jacobian _dAssignToQuadrupole(double &ixx, double &iyy, double &ixy) const =0
table::Key< int > b
table::Key< int > a
static void _assignQuadrupoleToAxes(double ixx, double iyy, double ixy, double &a, double &b, double &theta)
Definition: BaseCore.cc:184
ItemVariant const * other
Definition: Schema.cc:56
STL class.
lsst::geom::Extent2D computeDimensions() const
Return the size of the bounding box for the ellipse core.
Definition: BaseCore.cc:130
T atan2(T... args)
double getTraceRadius() const
Return the radius defined as the square root of one half the trace of the quadrupole matrix...
Definition: BaseCore.cc:124
STL class.
static std::shared_ptr< BaseCore > make(std::string const &name)
Definition: BaseCore.cc:56
T sin(T... args)
afw::table::PointKey< int > dimensions
Definition: GaussianPsf.cc:49
void setParameterVector(ParameterVector const &vector)
Set the core parameters from a vector.
Definition: BaseCore.cc:150
ParameterVector const getParameterVector() const
Return the core parameters as a vector.
Definition: BaseCore.cc:144
BaseCore & operator=(BaseCore const &other)
Set the parameters of this ellipse core from another.
Definition: BaseCore.cc:156
A base class for image defects.
void grow(double buffer)
Increase the major and minor radii of the ellipse core by the given buffer.
Definition: BaseCore.cc:96
Eigen::Vector3d ParameterVector
Parameter vector type.
Definition: BaseCore.h:61
virtual void _assignFromAxes(double a, double b, double theta)=0
void scale(double factor)
Scale the size of the ellipse core by the given factor.
Definition: BaseCore.cc:104
static void _assignAxesToQuadrupole(double a, double b, double theta, double &ixx, double &iyy, double &ixy)
Definition: BaseCore.cc:219
T cos(T... args)
double getArea() const
Return the area of the ellipse core.
Definition: BaseCore.cc:112
virtual void _assignToAxes(double &a, double &b, double &theta) const =0
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition: Exception.h:48
Eigen::Matrix3d Jacobian
Parameter Jacobian matrix type.
Definition: BaseCore.h:64
A base class for parametrizations of the "core" of an ellipse - the ellipticity and size...
Definition: BaseCore.h:55
virtual void readParameters(double const *iter)=0
Reports invalid arguments.
Definition: Runtime.h:66
int m
Definition: SpanSet.cc:49
virtual std::string getName() const =0
Return a string that identifies this parametrization.
T sqrt(T... args)
virtual Jacobian _dAssignFromQuadrupole(double ixx, double iyy, double ixy)=0
double getDeterminantRadius() const
Return the radius defined as the 4th root of the determinant of the quadrupole matrix.
Definition: BaseCore.cc:118
static void registerSubclass(std::shared_ptr< BaseCore > const &example)
Definition: BaseCore.cc:92
bool operator==(BaseCore const &other) const
Compare two ellipse cores for equality.
Definition: BaseCore.cc:152
virtual void _assignToQuadrupole(double &ixx, double &iyy, double &ixy) const =0
py::object result
Definition: _schema.cc:429
A temporary-only expression object for ellipse core convolution.
Definition: Convolution.h:46
int end
double constexpr PI
The ratio of a circle&#39;s circumference to diameter.
Definition: Angle.h:39
virtual void writeParameters(double *iter) const =0