LSST Applications 26.0.0,g0265f82a02+6660c170cc,g07994bdeae+30b05a742e,g0a0026dc87+17526d298f,g0a60f58ba1+17526d298f,g0e4bf8285c+96dd2c2ea9,g0ecae5effc+c266a536c8,g1e7d6db67d+6f7cb1f4bb,g26482f50c6+6346c0633c,g2bbee38e9b+6660c170cc,g2cc88a2952+0a4e78cd49,g3273194fdb+f6908454ef,g337abbeb29+6660c170cc,g337c41fc51+9a8f8f0815,g37c6e7c3d5+7bbafe9d37,g44018dc512+6660c170cc,g4a941329ef+4f7594a38e,g4c90b7bd52+5145c320d2,g58be5f913a+bea990ba40,g635b316a6c+8d6b3a3e56,g67924a670a+bfead8c487,g6ae5381d9b+81bc2a20b4,g93c4d6e787+26b17396bd,g98cecbdb62+ed2cb6d659,g98ffbb4407+81bc2a20b4,g9ddcbc5298+7f7571301f,ga1e77700b3+99e9273977,gae46bcf261+6660c170cc,gb2715bf1a1+17526d298f,gc86a011abf+17526d298f,gcf0d15dbbd+96dd2c2ea9,gdaeeff99f8+0d8dbea60f,gdb4ec4c597+6660c170cc,ge23793e450+96dd2c2ea9,gf041782ebf+171108ac67
LSST Data Management Base Package
Loading...
Searching...
No Matches
_aggregates.cc
Go to the documentation of this file.
1/*
2 * This file is part of afw.
3 *
4 * Developed for the LSST Data Management System.
5 * This product includes software developed by the LSST Project
6 * (https://www.lsst.org).
7 * See the COPYRIGHT file at the top-level directory of this distribution
8 * for details of code ownership.
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 GNU General Public License
21 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22 */
23
24#include "pybind11/pybind11.h"
25#include "pybind11/eigen.h"
26#include "pybind11/stl.h"
27
28#include "ndarray/pybind11.h"
29
31
32#include "lsst/utils/python.h"
33#include "lsst/geom/Angle.h"
35#include "lsst/geom/Box.h"
36#include "lsst/afw/table/Key.h"
41
42namespace py = pybind11;
43using namespace pybind11::literals;
44
45namespace lsst {
46namespace afw {
47namespace table {
48
49using utils::python::WrapperCollection;
50
51namespace {
52
53// We don't expose base classes (e.g. FunctorKey) to Python, since they're just used to
54// define a CRTP interface in C++ and in Python that's just duck-typing.
55
56template <typename T>
57using PyPointKey = py::class_<PointKey<T>, std::shared_ptr<PointKey<T>>>;
58
59template <typename T>
60using PyPoint3Key = py::class_<Point3Key<T>, std::shared_ptr<Point3Key<T>>>;
61
62template <typename Box>
63using PyBoxKey = py::class_<BoxKey<Box>, std::shared_ptr<BoxKey<Box>>>;
64
65using PyCoordKey = py::class_<CoordKey, std::shared_ptr<CoordKey>>;
66
67using PyQuadrupoleKey = py::class_<QuadrupoleKey, std::shared_ptr<QuadrupoleKey>>;
68
69using PyEllipseKey = py::class_<EllipseKey, std::shared_ptr<EllipseKey>>;
70
71template <typename T, int N>
72using PyCovarianceMatrixKey =
73 py::class_<CovarianceMatrixKey<T, N>, std::shared_ptr<CovarianceMatrixKey<T, N>>>;
74
75template <typename T>
76static void declarePointKey(WrapperCollection &wrappers, std::string const &suffix) {
77 wrappers.wrapType(
78 PyPointKey<T>(wrappers.module, ("Point" + suffix + "Key").c_str()), [](auto &mod, auto &cls) {
79 cls.def(py::init<>());
80 cls.def(py::init<Key<T> const &, Key<T> const &>(), "x"_a, "y"_a);
81 cls.def(py::init<SubSchema const &>());
82 cls.def("__eq__", &PointKey<T>::operator==, py::is_operator());
83 cls.def("__ne__", &PointKey<T>::operator!=, py::is_operator());
84 cls.def("getX", &PointKey<T>::getX);
85 cls.def("getY", &PointKey<T>::getY);
86 cls.def("isValid", &PointKey<T>::isValid);
87 cls.def_static("addFields", &PointKey<T>::addFields, "schema"_a, "name"_a, "doc"_a, "unit"_a);
88 cls.def("set", [](PointKey<T> &self, BaseRecord &record,
89 lsst::geom::Point<T, 2> const &value) { return self.set(record, value); });
90 cls.def("get", &PointKey<T>::get);
91 });
92};
93
94template <typename T>
95static void declarePoint3Key(WrapperCollection &wrappers, std::string const &suffix) {
96 wrappers.wrapType(
97 PyPoint3Key<T>(wrappers.module, ("Point3" + suffix + "Key").c_str()), [](auto &mod, auto &cls) {
98 cls.def(py::init<>());
99 cls.def(py::init<Key<T> const &, Key<T> const &, Key<T> const &>(), "x"_a, "y"_a, "z"_a);
100 cls.def(py::init<SubSchema const &>());
101 cls.def("__eq__", &Point3Key<T>::operator==, py::is_operator());
102 cls.def("__ne__", &Point3Key<T>::operator!=, py::is_operator());
103 cls.def("getX", &Point3Key<T>::getX);
104 cls.def("getY", &Point3Key<T>::getY);
105 cls.def("isValid", &Point3Key<T>::isValid);
106 cls.def_static("addFields", &Point3Key<T>::addFields, "schema"_a, "name"_a, "doc"_a, "unit"_a);
107 cls.def("set", [](Point3Key<T> &self, BaseRecord &record,
108 lsst::geom::Point<T, 3> const &value) { return self.set(record, value); });
109 cls.def("get", &Point3Key<T>::get);
110 });
111};
112
113template <typename Box>
114static void declareBoxKey(WrapperCollection &wrappers, std::string const &suffix) {
115 wrappers.wrapType(
116 PyBoxKey<Box>(wrappers.module, ("Box" + suffix + "Key").c_str()), [](auto &mod, auto &cls) {
117 using Element = typename Box::Element;
118 cls.def(py::init<>());
119 cls.def(py::init<PointKey<Element> const &, PointKey<Element> const &>(), "min"_a, "max"_a);
120 cls.def(py::init<SubSchema const &>());
121 cls.def("__eq__", &BoxKey<Box>::operator==, py::is_operator());
122 cls.def("__ne__", &BoxKey<Box>::operator!=, py::is_operator());
123 cls.def("getMin", &BoxKey<Box>::getMin);
124 cls.def("getMax", &BoxKey<Box>::getMax);
125 cls.def("isValid", &BoxKey<Box>::isValid);
126 cls.def_static("addFields", &BoxKey<Box>::addFields, "schema"_a, "name"_a, "doc"_a, "unit"_a);
127 cls.def("set", &BoxKey<Box>::set);
128 cls.def("get", &BoxKey<Box>::get);
129
130 });
131};
132
133static void declareCoordKey(WrapperCollection &wrappers) {
134 wrappers.wrapType(PyCoordKey(wrappers.module, "CoordKey"), [](auto &mod, auto &cls) {
135 cls.def(py::init<>());
136 cls.def(py::init<Key<lsst::geom::Angle>, Key<lsst::geom::Angle>>(), "ra"_a, "dec"_a);
137 cls.def(py::init<SubSchema const &>());
138 cls.def("__eq__", &CoordKey::operator==, py::is_operator());
139 cls.def("__ne__", &CoordKey::operator!=, py::is_operator());
140 cls.def_static("addFields", &CoordKey::addFields, "schema"_a, "name"_a, "doc"_a);
141 cls.def("getRa", &CoordKey::getRa);
142 cls.def("getDec", &CoordKey::getDec);
143 cls.def("isValid", &CoordKey::isValid);
144 cls.def("get", [](CoordKey &self, BaseRecord const &record) { return self.get(record); });
145 cls.def("set", &CoordKey::set);
146 });
147}
148
149static void declareQuadrupoleKey(WrapperCollection &wrappers) {
150 wrappers.wrapType(PyQuadrupoleKey(wrappers.module, "QuadrupoleKey"), [](auto &mod, auto &cls) {
151 cls.def(py::init<>());
152 cls.def(py::init<Key<double> const &, Key<double> const &, Key<double> const &>(), "ixx"_a, "iyy"_a,
153 "ixy"_a);
154 cls.def(py::init<SubSchema const &>());
155 cls.def("__eq__", &QuadrupoleKey::operator==, py::is_operator());
156 cls.def("__nq__", &QuadrupoleKey::operator!=, py::is_operator());
157 cls.def_static("addFields", &QuadrupoleKey::addFields, "schema"_a, "name"_a, "doc"_a,
158 "coordType"_a = CoordinateType::PIXEL);
159 cls.def("getIxx", &QuadrupoleKey::getIxx);
160 cls.def("getIyy", &QuadrupoleKey::getIyy);
161 cls.def("getIxy", &QuadrupoleKey::getIxy);
162 cls.def("isValid", &QuadrupoleKey::isValid);
163 cls.def("set", &QuadrupoleKey::set);
164 cls.def("get", &QuadrupoleKey::get);
165 });
166}
167
168static void declareEllipseKey(WrapperCollection &wrappers) {
169 wrappers.wrapType(PyEllipseKey(wrappers.module, "EllipseKey"), [](auto &mod, auto &cls) {
170 cls.def(py::init<>());
171 cls.def(py::init<QuadrupoleKey const &, PointKey<double> const &>(), "qKey"_a, "pKey"_a);
172 cls.def(py::init<SubSchema const &>());
173 cls.def("__eq__", &EllipseKey::operator==, py::is_operator());
174 cls.def("__nq__", &EllipseKey::operator!=, py::is_operator());
175 cls.def_static("addFields", &EllipseKey::addFields, "schema"_a, "name"_a, "doc"_a, "unit"_a);
176 cls.def("get", &EllipseKey::get);
177 cls.def("set", &EllipseKey::set);
178 cls.def("isValid", &EllipseKey::isValid);
179 cls.def("getCore", &EllipseKey::getCore);
180 cls.def("getCenter", &EllipseKey::getCenter);
181 });
182}
183
184template <typename T, int N>
185static void declareCovarianceMatrixKey(WrapperCollection &wrappers, const ::std::string &suffix) {
186 wrappers.wrapType(
187 PyCovarianceMatrixKey<T, N>(wrappers.module, ("CovarianceMatrix" + suffix + "Key").c_str()),
188 [](auto &mod, auto &cls) {
189 using ErrKeyArray = std::vector<Key<T>>;
190 using CovarianceKeyArray = std::vector<Key<T>>;
191 using NameArray = std::vector<std::string>;
192
193 cls.def(py::init<>());
194 // Ordering of the next two ctor declaration matters, as a workaround for DM-8580.
195 cls.def(py::init<SubSchema const &, NameArray const &>());
196 cls.def(py::init<ErrKeyArray const &, CovarianceKeyArray const &>(), "err"_a,
197 "cov"_a = CovarianceKeyArray());
198 cls.def("__eq__", &CovarianceMatrixKey<T, N>::operator==, py::is_operator());
199 cls.def("__ne__", &CovarianceMatrixKey<T, N>::operator!=, py::is_operator());
200 cls.def_static("addFields",
201 (CovarianceMatrixKey<T, N>(*)(Schema &, std::string const &, NameArray const &,
202 std::string const &, bool)) &
203 CovarianceMatrixKey<T, N>::addFields,
204 "schema"_a, "prefix"_a, "names"_a, "unit"_a, "diagonalOnly"_a = false);
205 cls.def_static("addFields",
206 (CovarianceMatrixKey<T, N>(*)(Schema &, std::string const &, NameArray const &,
207 NameArray const &, bool)) &
208 CovarianceMatrixKey<T, N>::addFields,
209 "schema"_a, "prefix"_a, "names"_a, "units"_a, "diagonalOnly"_a = false);
210 cls.def("set", [](CovarianceMatrixKey<T, N> &cov, BaseRecord &record,
211 Eigen::Matrix<T, N, N> const &value) { return cov.set(record, value); });
212 cls.def("get", [](CovarianceMatrixKey<T, N> &cov, BaseRecord const &record) {
213 return cov.get(record);
214 });
215 cls.def("isValid", &CovarianceMatrixKey<T, N>::isValid);
216 cls.def("setElement", &CovarianceMatrixKey<T, N>::setElement);
217 cls.def("getElement", &CovarianceMatrixKey<T, N>::getElement);
218 });
219}
220
221} // namespace
222
223void wrapAggregates(WrapperCollection &wrappers) {
224 // TODO: uncomment once afw.geom uses WrapperCollection
225 // wrappers.addSignatureDependency("lsst.afw.geom.ellipses");
226
227 wrappers.wrapType(py::enum_<CoordinateType>(wrappers.module, "CoordinateType"), [](auto &mod, auto &enm) {
228 enm.value("PIXEL", CoordinateType::PIXEL);
229 enm.value("CELESTIAL", CoordinateType::CELESTIAL);
230 enm.export_values();
231 });
232
233 declarePointKey<double>(wrappers, "2D");
234 declarePointKey<int>(wrappers, "2I");
235 declarePoint3Key<double>(wrappers, "D");
236 declarePoint3Key<int>(wrappers, "I");
237
238 declareBoxKey<lsst::geom::Box2D>(wrappers, "2D");
239 declareBoxKey<lsst::geom::Box2I>(wrappers, "2I");
240
241 declareCoordKey(wrappers);
242 declareQuadrupoleKey(wrappers);
243 declareEllipseKey(wrappers);
244
245 declareCovarianceMatrixKey<float, 2>(wrappers, "2f");
246 declareCovarianceMatrixKey<float, 3>(wrappers, "3f");
247 declareCovarianceMatrixKey<float, 4>(wrappers, "4f");
248 declareCovarianceMatrixKey<float, Eigen::Dynamic>(wrappers, "Xf");
249 declareCovarianceMatrixKey<double, 2>(wrappers, "2d");
250 declareCovarianceMatrixKey<double, 3>(wrappers, "3d");
251 declareCovarianceMatrixKey<double, 4>(wrappers, "4d");
252 declareCovarianceMatrixKey<double, Eigen::Dynamic>(wrappers, "Xd");
253}
254
255} // namespace table
256} // namespace afw
257} // namespace lsst
lsst::geom::Point< T, 3 > get(BaseRecord const &record) const override
Get a Point from the given record.
Definition aggregates.cc:69
lsst::geom::Point< T, 2 > get(BaseRecord const &record) const override
Get a Point from the given record.
Definition aggregates.cc:44
void wrapAggregates(WrapperCollection &wrappers)