LSST Applications g0f08755f38+82efc23009,g12f32b3c4e+e7bdf1200e,g1653933729+a8ce1bb630,g1a0ca8cf93+50eff2b06f,g28da252d5a+52db39f6a5,g2bbee38e9b+37c5a29d61,g2bc492864f+37c5a29d61,g2cdde0e794+c05ff076ad,g3156d2b45e+41e33cbcdc,g347aa1857d+37c5a29d61,g35bb328faa+a8ce1bb630,g3a166c0a6a+37c5a29d61,g3e281a1b8c+fb992f5633,g414038480c+7f03dfc1b0,g41af890bb2+11b950c980,g5fbc88fb19+17cd334064,g6b1c1869cb+12dd639c9a,g781aacb6e4+a8ce1bb630,g80478fca09+72e9651da0,g82479be7b0+04c31367b4,g858d7b2824+82efc23009,g9125e01d80+a8ce1bb630,g9726552aa6+8047e3811d,ga5288a1d22+e532dc0a0b,gae0086650b+a8ce1bb630,gb58c049af0+d64f4d3760,gc28159a63d+37c5a29d61,gcf0d15dbbd+2acd6d4d48,gd7358e8bfb+778a810b6e,gda3e153d99+82efc23009,gda6a2b7d83+2acd6d4d48,gdaeeff99f8+1711a396fd,ge2409df99d+6b12de1076,ge79ae78c31+37c5a29d61,gf0baf85859+d0a5978c5a,gf3967379c6+4954f8c433,gfb92a5be7c+82efc23009,gfec2e1e490+2aaed99252,w.2024.46
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
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 cpputils::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_static("addErrorFields", &CoordKey::addErrorFields, "schema"_a);
142 cls.def_static("getErrorKey", &CoordKey::getErrorKey, "schema"_a);
143 cls.def("getRa", &CoordKey::getRa);
144 cls.def("getDec", &CoordKey::getDec);
145 cls.def("isValid", &CoordKey::isValid);
146 cls.def("get", [](CoordKey &self, BaseRecord const &record) { return self.get(record); });
147 cls.def("set", &CoordKey::set);
148 });
149}
150
151static void declareQuadrupoleKey(WrapperCollection &wrappers) {
152 wrappers.wrapType(PyQuadrupoleKey(wrappers.module, "QuadrupoleKey"), [](auto &mod, auto &cls) {
153 cls.def(py::init<>());
154 cls.def(py::init<Key<double> const &, Key<double> const &, Key<double> const &>(), "ixx"_a, "iyy"_a,
155 "ixy"_a);
156 cls.def(py::init<SubSchema const &>());
157 cls.def("__eq__", &QuadrupoleKey::operator==, py::is_operator());
158 cls.def("__nq__", &QuadrupoleKey::operator!=, py::is_operator());
159 cls.def_static("addFields", &QuadrupoleKey::addFields, "schema"_a, "name"_a, "doc"_a,
160 "coordType"_a = CoordinateType::PIXEL);
161 cls.def("getIxx", &QuadrupoleKey::getIxx);
162 cls.def("getIyy", &QuadrupoleKey::getIyy);
163 cls.def("getIxy", &QuadrupoleKey::getIxy);
164 cls.def("isValid", &QuadrupoleKey::isValid);
165 cls.def("set", &QuadrupoleKey::set);
166 cls.def("get", &QuadrupoleKey::get);
167 });
168}
169
170static void declareEllipseKey(WrapperCollection &wrappers) {
171 wrappers.wrapType(PyEllipseKey(wrappers.module, "EllipseKey"), [](auto &mod, auto &cls) {
172 cls.def(py::init<>());
173 cls.def(py::init<QuadrupoleKey const &, PointKey<double> const &>(), "qKey"_a, "pKey"_a);
174 cls.def(py::init<SubSchema const &>());
175 cls.def("__eq__", &EllipseKey::operator==, py::is_operator());
176 cls.def("__nq__", &EllipseKey::operator!=, py::is_operator());
177 cls.def_static("addFields", &EllipseKey::addFields, "schema"_a, "name"_a, "doc"_a, "unit"_a);
178 cls.def("get", &EllipseKey::get);
179 cls.def("set", &EllipseKey::set);
180 cls.def("isValid", &EllipseKey::isValid);
181 cls.def("getCore", &EllipseKey::getCore);
182 cls.def("getCenter", &EllipseKey::getCenter);
183 });
184}
185
186template <typename T, int N>
187static void declareCovarianceMatrixKey(WrapperCollection &wrappers, const ::std::string &suffix) {
188 wrappers.wrapType(
189 PyCovarianceMatrixKey<T, N>(wrappers.module, ("CovarianceMatrix" + suffix + "Key").c_str()),
190 [](auto &mod, auto &cls) {
191 using ErrKeyArray = std::vector<Key<T>>;
192 using CovarianceKeyArray = std::vector<Key<T>>;
193 using NameArray = std::vector<std::string>;
194
195 cls.def(py::init<>());
196 // Ordering of the next two ctor declaration matters, as a workaround for DM-8580.
197 cls.def(py::init<SubSchema const &, NameArray const &>());
198 cls.def(py::init<ErrKeyArray const &, CovarianceKeyArray const &>(), "err"_a,
199 "cov"_a = CovarianceKeyArray());
200 cls.def("__eq__", &CovarianceMatrixKey<T, N>::operator==, py::is_operator());
201 cls.def("__ne__", &CovarianceMatrixKey<T, N>::operator!=, py::is_operator());
202 cls.def_static("addFields",
203 (CovarianceMatrixKey<T, N>(*)(Schema &, std::string const &, NameArray const &,
204 std::string const &, bool)) &
205 CovarianceMatrixKey<T, N>::addFields,
206 "schema"_a, "prefix"_a, "names"_a, "unit"_a, "diagonalOnly"_a = false);
207 cls.def_static("addFields",
208 (CovarianceMatrixKey<T, N>(*)(Schema &, std::string const &, NameArray const &,
209 NameArray const &, bool)) &
210 CovarianceMatrixKey<T, N>::addFields,
211 "schema"_a, "prefix"_a, "names"_a, "units"_a, "diagonalOnly"_a = false);
212 cls.def("set", [](CovarianceMatrixKey<T, N> &cov, BaseRecord &record,
213 Eigen::Matrix<T, N, N> const &value) { return cov.set(record, value); });
214 cls.def("get", [](CovarianceMatrixKey<T, N> &cov, BaseRecord const &record) {
215 return cov.get(record);
216 });
217 cls.def("isValid", &CovarianceMatrixKey<T, N>::isValid);
218 cls.def("setElement", &CovarianceMatrixKey<T, N>::setElement);
219 cls.def("getElement", &CovarianceMatrixKey<T, N>::getElement);
220 });
221}
222
223} // namespace
224
226 // TODO: uncomment once afw.geom uses WrapperCollection
227 // wrappers.addSignatureDependency("lsst.afw.geom.ellipses");
228
229 wrappers.wrapType(py::enum_<CoordinateType>(wrappers.module, "CoordinateType"), [](auto &mod, auto &enm) {
230 enm.value("PIXEL", CoordinateType::PIXEL);
231 enm.value("CELESTIAL", CoordinateType::CELESTIAL);
232 enm.export_values();
233 });
234
235 declarePointKey<double>(wrappers, "2D");
236 declarePointKey<int>(wrappers, "2I");
237 declarePoint3Key<double>(wrappers, "D");
238 declarePoint3Key<int>(wrappers, "I");
239
240 declareBoxKey<lsst::geom::Box2D>(wrappers, "2D");
241 declareBoxKey<lsst::geom::Box2I>(wrappers, "2I");
242
243 declareCoordKey(wrappers);
244 declareQuadrupoleKey(wrappers);
245 declareEllipseKey(wrappers);
246
255}
256
257} // namespace table
258} // namespace afw
259} // namespace lsst
Tag types used to declare specialized field types.
Definition misc.h:31
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
A helper class for subdividing pybind11 module across multiple translation units (i....
Definition python.h:242
PyType wrapType(PyType cls, ClassWrapperCallback function, bool setModuleName=true)
Add a type (class or enum) wrapper, deferring method and other attribute definitions until finish() i...
Definition python.h:391
void wrapAggregates(WrapperCollection &wrappers)