LSST Applications g070148d5b3+33e5256705,g0d53e28543+25c8b88941,g0da5cf3356+2dd1178308,g1081da9e2a+62d12e78cb,g17e5ecfddb+7e422d6136,g1c76d35bf8+ede3a706f7,g295839609d+225697d880,g2e2c1a68ba+cc1f6f037e,g2ffcdf413f+853cd4dcde,g38293774b4+62d12e78cb,g3b44f30a73+d953f1ac34,g48ccf36440+885b902d19,g4b2f1765b6+7dedbde6d2,g5320a0a9f6+0c5d6105b6,g56b687f8c9+ede3a706f7,g5c4744a4d9+ef6ac23297,g5ffd174ac0+0c5d6105b6,g6075d09f38+66af417445,g667d525e37+2ced63db88,g670421136f+2ced63db88,g71f27ac40c+2ced63db88,g774830318a+463cbe8d1f,g7876bc68e5+1d137996f1,g7985c39107+62d12e78cb,g7fdac2220c+0fd8241c05,g96f01af41f+368e6903a7,g9ca82378b8+2ced63db88,g9d27549199+ef6ac23297,gabe93b2c52+e3573e3735,gb065e2a02a+3dfbe639da,gbc3249ced9+0c5d6105b6,gbec6a3398f+0c5d6105b6,gc9534b9d65+35b9f25267,gd01420fc67+0c5d6105b6,geee7ff78d7+a14128c129,gf63283c776+ede3a706f7,gfed783d017+0c5d6105b6,w.2022.47
LSST Data Management Base Package
Loading...
Searching...
No Matches
aggregates.cc
Go to the documentation of this file.
1// -*- lsst-c++ -*-
2/*
3 * LSST Data Management System
4 * Copyright 2008-2014 LSST Corporation.
5 *
6 * This product includes software developed by the
7 * LSST Project (http://www.lsst.org/).
8 *
9 * This program is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the LSST License Statement and
20 * the GNU General Public License along with this program. If not,
21 * see <http://www.lsstcorp.org/LegalNotices/>.
22 */
23
25#include "lsst/geom/Box.h"
28
29namespace lsst {
30namespace afw {
31namespace table {
32
33//============ PointKey =====================================================================================
34
35template <typename T>
37 std::string const &unit) {
38 Key<T> xKey = schema.addField<T>(schema.join(name, "x"), doc, unit);
39 Key<T> yKey = schema.addField<T>(schema.join(name, "y"), doc, unit);
40 return PointKey<T>(xKey, yKey);
41}
42
43template <typename T>
45 return lsst::geom::Point<T, 2>(record.get(_x), record.get(_y));
46}
47
48template <typename T>
49void PointKey<T>::set(BaseRecord &record, lsst::geom::Point<T, 2> const &value) const {
50 record.set(_x, value.getX());
51 record.set(_y, value.getY());
52}
53
54template class PointKey<int>;
55template class PointKey<double>;
56
57//============ Point3Key ====================================================================================
58
59template <typename T>
61 std::string const &unit) {
62 Key<T> xKey = schema.addField<T>(schema.join(name, "x"), doc, unit);
63 Key<T> yKey = schema.addField<T>(schema.join(name, "y"), doc, unit);
64 Key<T> zKey = schema.addField<T>(schema.join(name, "z"), doc, unit);
65 return Point3Key<T>(xKey, yKey, zKey);
66}
67
68template <typename T>
70 return lsst::geom::Point<T, 3>(record.get(_x), record.get(_y), record.get(_z));
71}
72
73template <typename T>
74void Point3Key<T>::set(BaseRecord &record, lsst::geom::Point<T, 3> const &value) const {
75 record.set(_x, value.getX());
76 record.set(_y, value.getY());
77 record.set(_z, value.getZ());
78}
79
80template class Point3Key<int>;
81template class Point3Key<double>;
82
83//============ BoxKey =====================================================================================
84
85template <typename Box>
87 std::string const &unit) {
88 auto minKey = PointKey<Element>::addFields(schema, schema.join(name, "min"), doc + " (minimum)", unit);
89 auto maxKey = PointKey<Element>::addFields(schema, schema.join(name, "max"), doc + " (maximum)", unit);
90 return BoxKey<Box>(minKey, maxKey);
91}
92
93template <typename Box>
94Box BoxKey<Box>::get(BaseRecord const &record) const {
95 return Box(record.get(_min), record.get(_max), /*invert=*/false);
96}
97
98template <typename Box>
99void BoxKey<Box>::set(BaseRecord &record, Box const &value) const {
100 _min.set(record, value.getMin());
101 _max.set(record, value.getMax());
102}
103
104template class BoxKey<lsst::geom::Box2I>;
105template class BoxKey<lsst::geom::Box2D>;
106
107//============ CoordKey =====================================================================================
108
110 Key<lsst::geom::Angle> ra = schema.addField<lsst::geom::Angle>(schema.join(name, "ra"), doc);
111 Key<lsst::geom::Angle> dec = schema.addField<lsst::geom::Angle>(schema.join(name, "dec"), doc);
112 return CoordKey(ra, dec);
113}
114
116 return lsst::geom::SpherePoint(record.get(_ra), record.get(_dec));
117}
118
119void CoordKey::set(BaseRecord &record, lsst::geom::SpherePoint const &value) const {
120 record.set(_ra, value.getLongitude());
121 record.set(_dec, value.getLatitude());
122}
123
124//============ QuadrupoleKey ================================================================================
125
127 CoordinateType coordType) {
128 std::string unit = coordType == CoordinateType::PIXEL ? "pixel^2" : "rad^2";
129
130 Key<double> xxKey = schema.addField<double>(schema.join(name, "xx"), doc, unit);
131 Key<double> yyKey = schema.addField<double>(schema.join(name, "yy"), doc, unit);
132 Key<double> xyKey = schema.addField<double>(schema.join(name, "xy"), doc, unit);
133 return QuadrupoleKey(xxKey, yyKey, xyKey);
134}
135
137 return geom::ellipses::Quadrupole(record.get(_ixx), record.get(_iyy), record.get(_ixy));
138}
139
141 record.set(_ixx, value.getIxx());
142 record.set(_iyy, value.getIyy());
143 record.set(_ixy, value.getIxy());
144}
145
146//============ EllipseKey ================================================================================
147
149 std::string const &unit) {
152 return EllipseKey(qKey, pKey);
153}
154
156 return geom::ellipses::Ellipse(record.get(_qKey), record.get(_pKey));
157}
158
159void EllipseKey::set(BaseRecord &record, geom::ellipses::Ellipse const &value) const {
160 _qKey.set(record, value.getCore());
161 _pKey.set(record, value.getCenter());
162}
163
164//============ CovarianceMatrixKey ==========================================================================
165
166template <typename T, int N>
168 NameArray const &names,
169 std::string const &unit, bool diagonalOnly) {
170 NameArray units(names.size(), unit);
171 return addFields(schema, prefix, names, units, diagonalOnly);
172}
173
174template <typename T, int N>
176 NameArray const &names, NameArray const &units,
177 bool diagonalOnly) {
178 if (N != Eigen::Dynamic) {
180 "Size of names array (%d) does not match template argument (%d)");
182 "Size of units array (%d) does not match template argument (%d)");
183 }
184 ErrKeyArray err;
186 err.reserve(names.size());
187 for (std::size_t i = 0; i < names.size(); ++i) {
188 err.push_back(schema.addField<T>(schema.join(prefix, names[i] + "Err"),
189 "1-sigma uncertainty on " + names[i], units[i]));
190 }
191 if (!diagonalOnly) {
192 cov.reserve((names.size() * (names.size() - 1)) / 2);
193 for (std::size_t i = 0; i < names.size(); ++i) {
194 for (std::size_t j = 0; j < i; ++j) {
195 // We iterate over the lower-triangular part of the matrix in row-major order,
196 // but we use the upper-triangular names (i.e. we switch the order of i and j, below).
197 // That puts the elements in the order expected by the constructor we call below,
198 // while creating the field names users would expect from the ordering of their name
199 // vector (i.e. _a_b_Cov instead of _b_a_Cov if names=[a, b]).
200 cov.push_back(schema.addField<T>(
201 schema.join(prefix, names[j], names[i], "Cov"),
202 "uncertainty covariance between " + names[j] + " and " + names[i],
203 units[j] + (units[j].empty() || units[i].empty() ? "" : " ") + units[i]));
204 }
205 }
206 }
207 return CovarianceMatrixKey<T, N>(err, cov);
208}
209
210template <typename T, int N>
212
213template <typename T, int N>
215 : _err(err), _cov(cov) {
216 if (N != Eigen::Dynamic) {
218 "Size of err array (%d) does not match template argument (%d)");
219 }
220 if (!cov.empty()) {
221 LSST_THROW_IF_NE(cov.size(), err.size() * (err.size() - 1) / 2, pex::exceptions::LengthError,
222 "Size of cov array (%d) is does not match with size inferred from err array (%d)");
223 bool haveCov = false;
224 for (typename CovarianceKeyArray::const_iterator i = _cov.begin(); i != _cov.end(); ++i) {
225 if (i->isValid()) haveCov = true;
226 }
227 if (!haveCov) _cov.resize(0);
228 }
229}
230
231template <typename T, int N>
233 : _err(names.size()), _cov(names.size() * (names.size() - 1) / 2) {
234 int const n = names.size();
235 int k = 0;
236 bool haveCov = false;
237 for (int i = 0; i < n; ++i) {
238 _err[i] = s[names[i] + "Err"];
239 for (int j = 0; j < i; ++j, ++k) {
240 try {
241 _cov[k] = s[names[i] + "_" + names[j] + "_Cov"];
242 haveCov = true;
244 try {
245 _cov[k] = s[names[j] + "_" + names[i] + "_Cov"];
246 haveCov = true;
248 }
249 }
250 }
251 }
252 if (!haveCov) _cov.resize(0);
253}
254
255template <typename T, int N>
257template <typename T, int N>
259template <typename T, int N>
261template <typename T, int N>
263template <typename T, int N>
265
266// these are workarounds for the fact that Eigen has different constructors for
267// dynamic-sized matrices and fixed-size matrices, but we don't want to have to
268// partial-specialize the entire template just to change one line
269namespace {
270
271template <typename T, int N>
272Eigen::Matrix<T, N, N> makeZeroMatrix(int n, CovarianceMatrixKey<T, N> const *) {
273 return Eigen::Matrix<T, N, N>::Zero();
274}
275
276template <typename T>
277Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> makeZeroMatrix(
279 return Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>::Zero(n, n);
280}
281
282} // namespace
283
284template <typename T, int N>
285Eigen::Matrix<T, N, N> CovarianceMatrixKey<T, N>::get(BaseRecord const &record) const {
286 Eigen::Matrix<T, N, N> value = makeZeroMatrix(_err.size(), this);
287 int const n = _err.size();
288 int k = 0;
289 for (int i = 0; i < n; ++i) {
290 T err = record.get(_err[i]);
291 value(i, i) = err * err;
292 if (!_cov.empty()) {
293 for (int j = 0; j < i; ++j, ++k) {
294 if (_cov[k].isValid()) {
295 value(i, j) = value(j, i) = record.get(_cov[k]);
296 }
297 }
298 }
299 }
300 return value;
301}
302
303template <typename T, int N>
304void CovarianceMatrixKey<T, N>::set(BaseRecord &record, Eigen::Matrix<T, N, N> const &value) const {
305 int const n = _err.size();
306 int k = 0;
307 for (int i = 0; i < n; ++i) {
308 record.set(_err[i], std::sqrt(value(i, i)));
309 if (!_cov.empty()) {
310 for (int j = 0; j < i; ++j, ++k) {
311 if (_cov[k].isValid()) {
312 record.set(_cov[k], value(i, j));
313 }
314 }
315 }
316 }
317}
318
319template <typename T, int N>
321 int const n = _err.size();
322 if (n < 1) return false;
323 for (int i = 0; i < n; ++i) {
324 if (!_err[i].isValid()) return false;
325 }
326 return true;
327}
328
329template <typename T, int N>
331 if (_err.size() != other._err.size()) {
332 return false;
333 }
334 if (_cov.size() != other._cov.size()) {
335 return false;
336 }
337 int const n = _err.size();
338 int k = 0;
339 for (int i = 0; i < n; ++i) {
340 if (_err[i] != other._err[i]) {
341 return false;
342 }
343 if (!_cov.empty()) {
344 for (int j = 0; j < i; ++j, ++k) {
345 if (_cov[k] != other._cov[k]) {
346 return false;
347 }
348 }
349 }
350 }
351 return true;
352}
353
354template <typename T, int N>
356 // Completely arbitrary seeds, different to avoid any weird degeneracies/interactions
357 return utils::hashCombine(17, utils::hashIterable(19, _err.begin(), _err.end()),
358 utils::hashIterable(23, _cov.begin(), _cov.end()));
359}
360
361template <typename T, int N>
362T CovarianceMatrixKey<T, N>::getElement(BaseRecord const &record, int i, int j) const {
363 if (i == j) {
364 T err = record.get(_err[i]);
365 return err * err;
366 }
367 if (_cov.empty()) {
368 return 0.0;
369 }
370 Key<T> key = (i < j) ? _cov[j * (j - 1) / 2 + i] : _cov[i * (i - 1) / 2 + j];
371 return key.isValid() ? record.get(key) : 0.0;
372}
373
374template <typename T, int N>
375void CovarianceMatrixKey<T, N>::setElement(BaseRecord &record, int i, int j, T value) const {
376 if (i == j) {
377 record.set(_err[i], std::sqrt(value));
378 } else {
379 if (_cov.empty()) {
380 throw LSST_EXCEPT(
382 (boost::format("Cannot set covariance element %d,%d; no fields for covariance") % i % j)
383 .str());
384 }
385 Key<T> key = (i < j) ? _cov[j * (j - 1) / 2 + i] : _cov[i * (i - 1) / 2 + j];
386 if (!key.isValid()) {
387 throw LSST_EXCEPT(
389 (boost::format("Cannot set covariance element %d,%d; no field for this element") % i % j)
390 .str());
391 }
392 record.set(key, value);
393 }
394}
395
396template class CovarianceMatrixKey<float, 2>;
397template class CovarianceMatrixKey<float, 3>;
398template class CovarianceMatrixKey<float, 4>;
399template class CovarianceMatrixKey<float, 5>;
401template class CovarianceMatrixKey<double, 2>;
402template class CovarianceMatrixKey<double, 3>;
403template class CovarianceMatrixKey<double, 4>;
404template class CovarianceMatrixKey<double, 5>;
406} // namespace table
407} // namespace afw
408} // namespace lsst
table::Key< std::string > name
Definition: Amplifier.cc:116
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition: Exception.h:48
double dec
Definition: Match.cc:41
std::string prefix
Definition: SchemaMapper.cc:72
table::Schema schema
Definition: python.h:134
#define LSST_THROW_IF_NE(N1, N2, EXC_CLASS, MSG)
Check whether the given values are equal, and throw an LSST Exception if they are not.
Definition: asserts.h:38
T begin(T... args)
An ellipse defined by an arbitrary BaseCore and a center point.
Definition: Ellipse.h:51
lsst::geom::Point2D const & getCenter() const
Return the center point.
Definition: Ellipse.h:62
BaseCore const & getCore() const
Return the ellipse core.
Definition: Ellipse.h:71
An ellipse core with quadrupole moments as parameters.
Definition: Quadrupole.h:47
Base class for all records.
Definition: BaseRecord.h:31
Field< T >::Value get(Key< T > const &key) const
Return the value of a field for the given key.
Definition: BaseRecord.h:151
void set(Key< T > const &key, U const &value)
Set value of a field for the given key.
Definition: BaseRecord.h:164
A FunctorKey used to get or set a lsst::geom::Box2I or Box2D from a (min, max) pair of Point3Keys.
Definition: aggregates.h:206
Box get(BaseRecord const &record) const override
Get a Box from the given record.
Definition: aggregates.cc:94
static BoxKey addFields(Schema &schema, std::string const &name, std::string const &doc, std::string const &unit)
Add _min_x, _min_y, _max_x, _max_y fields to a Schema, and return a BoxKey that points to them.
Definition: aggregates.cc:86
void set(BaseRecord &record, Box const &value) const override
Set a Box in the given record.
Definition: aggregates.cc:99
A FunctorKey used to get or set celestial coordinates from a pair of lsst::geom::Angle keys.
Definition: aggregates.h:290
static CoordKey addFields(afw::table::Schema &schema, std::string const &name, std::string const &doc)
Add a pair of _ra, _dec fields to a Schema, and return a CoordKey that points to them.
Definition: aggregates.cc:109
CoordKey() noexcept
Default constructor; instance will not be usable unless subsequently assigned to.
Definition: aggregates.h:303
void set(BaseRecord &record, lsst::geom::SpherePoint const &value) const override
Set an lsst::geom::SpherePoint in the given record.
Definition: aggregates.cc:119
lsst::geom::SpherePoint get(BaseRecord const &record) const override
Get an lsst::geom::SpherePoint from the given record.
Definition: aggregates.cc:115
bool operator==(CovarianceMatrixKey const &other) const noexcept
Compare the FunctorKey for equality with another, using its constituent Keys.
Definition: aggregates.cc:330
CovarianceMatrixKey()
Construct an invalid instance; must assign before subsequent use.
Eigen::Matrix< T, N, N > get(BaseRecord const &record) const override
Get a covariance matrix from the given record.
Definition: aggregates.cc:285
void setElement(BaseRecord &record, int i, int j, T value) const
Set the element in row i and column j.
Definition: aggregates.cc:375
T getElement(BaseRecord const &record, int i, int j) const
Return the element in row i and column j.
Definition: aggregates.cc:362
void set(BaseRecord &record, Eigen::Matrix< T, N, N > const &value) const override
Set a covariance matrix in the given record (uses only the lower triangle of the given matrix)
Definition: aggregates.cc:304
~CovarianceMatrixKey() noexcept override
static CovarianceMatrixKey addFields(Schema &schema, std::string const &prefix, NameArray const &names, std::string const &unit, bool diagonalOnly=false)
Add covariance matrix fields to a Schema, and return a CovarianceMatrixKey to manage them.
Definition: aggregates.cc:167
std::size_t hash_value() const noexcept
Return a hash of this object.
Definition: aggregates.cc:355
bool isValid() const noexcept
Return True if all the constituent error Keys are valid.
Definition: aggregates.cc:320
CovarianceMatrixKey & operator=(CovarianceMatrixKey const &)
A FunctorKey used to get or set a geom::ellipses::Ellipse from an (xx,yy,xy,x,y) tuple of Keys.
Definition: aggregates.h:440
void set(BaseRecord &record, geom::ellipses::Ellipse const &value) const override
Set an Ellipse in the given record.
Definition: aggregates.cc:159
static EllipseKey addFields(Schema &schema, std::string const &name, std::string const &doc, std::string const &unit)
Add a set of _xx, _yy, _xy, _x, _y fields to a Schema, and return an EllipseKey that points to them.
Definition: aggregates.cc:148
geom::ellipses::Ellipse get(BaseRecord const &record) const override
Get an Ellipse from the given record.
Definition: aggregates.cc:155
EllipseKey() noexcept
Default constructor; instance will not be usable unless subsequently assigned to.
Definition: aggregates.h:456
A class used as a handle to a particular field in a table.
Definition: Key.h:53
bool isValid() const noexcept
Return true if the key was initialized to valid offset.
Definition: Key.h:97
A FunctorKey used to get or set a lsst::geom::Point3 from an (x,y,z) tuple of int or double Keys.
Definition: aggregates.h:124
void set(BaseRecord &record, lsst::geom::Point< T, 3 > const &value) const override
Set a Point in the given record.
Definition: aggregates.cc:74
static Point3Key addFields(Schema &schema, std::string const &name, std::string const &doc, std::string const &unit)
Add a pair of _x, _y, _z fields to a Schema, and return a Point3Key that points to them.
Definition: aggregates.cc:60
lsst::geom::Point< T, 3 > get(BaseRecord const &record) const override
Get a Point from the given record.
Definition: aggregates.cc:69
A FunctorKey used to get or set a lsst::geom::Point from an (x,y) pair of int or double Keys.
Definition: aggregates.h:49
void set(BaseRecord &record, lsst::geom::Point< T, 2 > const &value) const override
Set a Point in the given record.
Definition: aggregates.cc:49
static PointKey addFields(Schema &schema, std::string const &name, std::string const &doc, std::string const &unit)
Add a pair of _x, _y fields to a Schema, and return a PointKey that points to them.
Definition: aggregates.cc:36
lsst::geom::Point< T, 2 > get(BaseRecord const &record) const override
Get a Point from the given record.
Definition: aggregates.cc:44
A FunctorKey used to get or set a geom::ellipses::Quadrupole from a tuple of constituent Keys.
Definition: aggregates.h:362
geom::ellipses::Quadrupole get(BaseRecord const &record) const override
Get a Quadrupole from the given record.
Definition: aggregates.cc:136
QuadrupoleKey() noexcept
Default constructor; instance will not be usable unless subsequently assigned to.
Definition: aggregates.h:379
void set(BaseRecord &record, geom::ellipses::Quadrupole const &value) const override
Set a Quadrupole in the given record.
Definition: aggregates.cc:140
static QuadrupoleKey addFields(Schema &schema, std::string const &name, std::string const &doc, CoordinateType coordType=CoordinateType::PIXEL)
Add a set of quadrupole subfields to a schema and return a QuadrupoleKey that points to them.
Definition: aggregates.cc:126
Defines the fields and offsets for a table.
Definition: Schema.h:51
A proxy type for name lookups in a Schema.
Definition: Schema.h:367
A class representing an angle.
Definition: Angle.h:128
A coordinate class intended to represent absolute positions.
Definition: Point.h:169
Point in an unspecified spherical coordinate system.
Definition: SpherePoint.h:57
Angle getLatitude() const noexcept
The latitude of this point.
Definition: SpherePoint.h:190
Angle getLongitude() const noexcept
The longitude of this point.
Definition: SpherePoint.h:178
Reports attempts to exceed implementation-defined length limits for some classes.
Definition: Runtime.h:76
Reports errors in the logical structure of the program.
Definition: Runtime.h:46
Reports attempts to access elements using an invalid key.
Definition: Runtime.h:151
T empty(T... args)
T end(T... args)
bool isValid
Definition: fits.cc:400
CoordinateType
Enum used to set units for geometric FunctorKeys.
Definition: aggregates.h:357
std::size_t hashCombine(std::size_t seed) noexcept
Combine hashes.
Definition: hashCombine.h:35
std::size_t hashIterable(std::size_t seed, InputIterator begin, InputIterator end) noexcept
Combine hashes in an iterable.
Definition: hashCombine.h:93
T push_back(T... args)
T reserve(T... args)
T resize(T... args)
T size(T... args)
T sqrt(T... args)