LSST Applications g0b6bd0c080+a72a5dd7e6,g1182afd7b4+2a019aa3bb,g17e5ecfddb+2b8207f7de,g1d67935e3f+06cf436103,g38293774b4+ac198e9f13,g396055baef+6a2097e274,g3b44f30a73+6611e0205b,g480783c3b1+98f8679e14,g48ccf36440+89c08d0516,g4b93dc025c+98f8679e14,g5c4744a4d9+a302e8c7f0,g613e996a0d+e1c447f2e0,g6c8d09e9e7+25247a063c,g7271f0639c+98f8679e14,g7a9cd813b8+124095ede6,g9d27549199+a302e8c7f0,ga1cf026fa3+ac198e9f13,ga32aa97882+7403ac30ac,ga786bb30fb+7a139211af,gaa63f70f4e+9994eb9896,gabf319e997+ade567573c,gba47b54d5d+94dc90c3ea,gbec6a3398f+06cf436103,gc6308e37c7+07dd123edb,gc655b1545f+ade567573c,gcc9029db3c+ab229f5caf,gd01420fc67+06cf436103,gd877ba84e5+06cf436103,gdb4cecd868+6f279b5b48,ge2d134c3d5+cc4dbb2e3f,ge448b5faa6+86d1ceac1d,gecc7e12556+98f8679e14,gf3ee170dca+25247a063c,gf4ac96e456+ade567573c,gf9f5ea5b4d+ac198e9f13,gff490e6085+8c2580be5c,w.2022.27
LSST Data Management Base Package
_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 Box>
60using PyBoxKey = py::class_<BoxKey<Box>, std::shared_ptr<BoxKey<Box>>>;
61
62using PyCoordKey = py::class_<CoordKey, std::shared_ptr<CoordKey>>;
63
64using PyQuadrupoleKey = py::class_<QuadrupoleKey, std::shared_ptr<QuadrupoleKey>>;
65
66using PyEllipseKey = py::class_<EllipseKey, std::shared_ptr<EllipseKey>>;
67
68template <typename T, int N>
69using PyCovarianceMatrixKey =
70 py::class_<CovarianceMatrixKey<T, N>, std::shared_ptr<CovarianceMatrixKey<T, N>>>;
71
72template <typename T>
73static void declarePointKey(WrapperCollection &wrappers, std::string const &suffix) {
74 wrappers.wrapType(
75 PyPointKey<T>(wrappers.module, ("Point" + suffix + "Key").c_str()), [](auto &mod, auto &cls) {
76 cls.def(py::init<>());
77 cls.def(py::init<Key<T> const &, Key<T> const &>(), "x"_a, "y"_a);
78 cls.def(py::init<SubSchema const &>());
79 cls.def("__eq__", &PointKey<T>::operator==, py::is_operator());
80 cls.def("__ne__", &PointKey<T>::operator!=, py::is_operator());
81 cls.def("getX", &PointKey<T>::getX);
82 cls.def("getY", &PointKey<T>::getY);
83 cls.def("isValid", &PointKey<T>::isValid);
84 cls.def_static("addFields", &PointKey<T>::addFields, "schema"_a, "name"_a, "doc"_a, "unit"_a);
85 cls.def("set", [](PointKey<T> &self, BaseRecord &record,
86 lsst::geom::Point<T, 2> const &value) { return self.set(record, value); });
87 cls.def("get", &PointKey<T>::get);
88 });
89};
90
91template <typename Box>
92static void declareBoxKey(WrapperCollection &wrappers, std::string const &suffix) {
93 wrappers.wrapType(
94 PyBoxKey<Box>(wrappers.module, ("Box" + suffix + "Key").c_str()), [](auto &mod, auto &cls) {
95 using Element = typename Box::Element;
96 cls.def(py::init<>());
97 cls.def(py::init<PointKey<Element> const &, PointKey<Element> const &>(), "min"_a, "max"_a);
98 cls.def(py::init<SubSchema const &>());
99 cls.def("__eq__", &BoxKey<Box>::operator==, py::is_operator());
100 cls.def("__ne__", &BoxKey<Box>::operator!=, py::is_operator());
101 cls.def("getMin", &BoxKey<Box>::getMin);
102 cls.def("getMax", &BoxKey<Box>::getMax);
103 cls.def("isValid", &BoxKey<Box>::isValid);
104 cls.def_static("addFields", &BoxKey<Box>::addFields, "schema"_a, "name"_a, "doc"_a, "unit"_a);
105 cls.def("set", &BoxKey<Box>::set);
106 cls.def("get", &BoxKey<Box>::get);
107
108 });
109};
110
111static void declareCoordKey(WrapperCollection &wrappers) {
112 wrappers.wrapType(PyCoordKey(wrappers.module, "CoordKey"), [](auto &mod, auto &cls) {
113 cls.def(py::init<>());
114 cls.def(py::init<Key<lsst::geom::Angle>, Key<lsst::geom::Angle>>(), "ra"_a, "dec"_a);
115 cls.def(py::init<SubSchema const &>());
116 cls.def("__eq__", &CoordKey::operator==, py::is_operator());
117 cls.def("__ne__", &CoordKey::operator!=, py::is_operator());
118 cls.def_static("addFields", &CoordKey::addFields, "schema"_a, "name"_a, "doc"_a);
119 cls.def("getRa", &CoordKey::getRa);
120 cls.def("getDec", &CoordKey::getDec);
121 cls.def("isValid", &CoordKey::isValid);
122 cls.def("get", [](CoordKey &self, BaseRecord const &record) { return self.get(record); });
123 cls.def("set", &CoordKey::set);
124 });
125}
126
127static void declareQuadrupoleKey(WrapperCollection &wrappers) {
128 wrappers.wrapType(PyQuadrupoleKey(wrappers.module, "QuadrupoleKey"), [](auto &mod, auto &cls) {
129 cls.def(py::init<>());
130 cls.def(py::init<Key<double> const &, Key<double> const &, Key<double> const &>(), "ixx"_a, "iyy"_a,
131 "ixy"_a);
132 cls.def(py::init<SubSchema const &>());
133 cls.def("__eq__", &QuadrupoleKey::operator==, py::is_operator());
134 cls.def("__nq__", &QuadrupoleKey::operator!=, py::is_operator());
135 cls.def_static("addFields", &QuadrupoleKey::addFields, "schema"_a, "name"_a, "doc"_a,
136 "coordType"_a = CoordinateType::PIXEL);
137 cls.def("getIxx", &QuadrupoleKey::getIxx);
138 cls.def("getIyy", &QuadrupoleKey::getIyy);
139 cls.def("getIxy", &QuadrupoleKey::getIxy);
140 cls.def("isValid", &QuadrupoleKey::isValid);
141 cls.def("set", &QuadrupoleKey::set);
142 cls.def("get", &QuadrupoleKey::get);
143 });
144}
145
146static void declareEllipseKey(WrapperCollection &wrappers) {
147 wrappers.wrapType(PyEllipseKey(wrappers.module, "EllipseKey"), [](auto &mod, auto &cls) {
148 cls.def(py::init<>());
149 cls.def(py::init<QuadrupoleKey const &, PointKey<double> const &>(), "qKey"_a, "pKey"_a);
150 cls.def(py::init<SubSchema const &>());
151 cls.def("__eq__", &EllipseKey::operator==, py::is_operator());
152 cls.def("__nq__", &EllipseKey::operator!=, py::is_operator());
153 cls.def_static("addFields", &EllipseKey::addFields, "schema"_a, "name"_a, "doc"_a, "unit"_a);
154 cls.def("get", &EllipseKey::get);
155 cls.def("set", &EllipseKey::set);
156 cls.def("isValid", &EllipseKey::isValid);
157 cls.def("getCore", &EllipseKey::getCore);
158 cls.def("getCenter", &EllipseKey::getCenter);
159 });
160}
161
162template <typename T, int N>
163static void declareCovarianceMatrixKey(WrapperCollection &wrappers, const ::std::string &suffix) {
164 wrappers.wrapType(
165 PyCovarianceMatrixKey<T, N>(wrappers.module, ("CovarianceMatrix" + suffix + "Key").c_str()),
166 [](auto &mod, auto &cls) {
167 using ErrKeyArray = std::vector<Key<T>>;
168 using CovarianceKeyArray = std::vector<Key<T>>;
169 using NameArray = std::vector<std::string>;
170
171 cls.def(py::init<>());
172 // Ordering of the next two ctor declaration matters, as a workaround for DM-8580.
173 cls.def(py::init<SubSchema const &, NameArray const &>());
174 cls.def(py::init<ErrKeyArray const &, CovarianceKeyArray const &>(), "err"_a,
175 "cov"_a = CovarianceKeyArray());
176 cls.def("__eq__", &CovarianceMatrixKey<T, N>::operator==, py::is_operator());
177 cls.def("__ne__", &CovarianceMatrixKey<T, N>::operator!=, py::is_operator());
178 cls.def_static("addFields",
179 (CovarianceMatrixKey<T, N>(*)(Schema &, std::string const &, NameArray const &,
180 std::string const &, bool)) &
181 CovarianceMatrixKey<T, N>::addFields,
182 "schema"_a, "prefix"_a, "names"_a, "unit"_a, "diagonalOnly"_a = false);
183 cls.def_static("addFields",
184 (CovarianceMatrixKey<T, N>(*)(Schema &, std::string const &, NameArray const &,
185 NameArray const &, bool)) &
186 CovarianceMatrixKey<T, N>::addFields,
187 "schema"_a, "prefix"_a, "names"_a, "units"_a, "diagonalOnly"_a = false);
188 cls.def("set", [](CovarianceMatrixKey<T, N> &cov, BaseRecord &record,
189 Eigen::Matrix<T, N, N> const &value) { return cov.set(record, value); });
190 cls.def("get", [](CovarianceMatrixKey<T, N> &cov, BaseRecord const &record) {
191 return cov.get(record);
192 });
193 cls.def("isValid", &CovarianceMatrixKey<T, N>::isValid);
194 cls.def("setElement", &CovarianceMatrixKey<T, N>::setElement);
195 cls.def("getElement", &CovarianceMatrixKey<T, N>::getElement);
196 });
197}
198
199} // namespace
200
201void wrapAggregates(WrapperCollection &wrappers) {
202 // TODO: uncomment once afw.geom uses WrapperCollection
203 // wrappers.addSignatureDependency("lsst.afw.geom.ellipses");
204
205 wrappers.wrapType(py::enum_<CoordinateType>(wrappers.module, "CoordinateType"), [](auto &mod, auto &enm) {
206 enm.value("PIXEL", CoordinateType::PIXEL);
207 enm.value("CELESTIAL", CoordinateType::CELESTIAL);
208 enm.export_values();
209 });
210
211 declarePointKey<double>(wrappers, "2D");
212 declarePointKey<int>(wrappers, "2I");
213
214 declareBoxKey<lsst::geom::Box2D>(wrappers, "2D");
215 declareBoxKey<lsst::geom::Box2I>(wrappers, "2I");
216
217 declareCoordKey(wrappers);
218 declareQuadrupoleKey(wrappers);
219 declareEllipseKey(wrappers);
220
221 declareCovarianceMatrixKey<float, 2>(wrappers, "2f");
222 declareCovarianceMatrixKey<float, 3>(wrappers, "3f");
223 declareCovarianceMatrixKey<float, 4>(wrappers, "4f");
224 declareCovarianceMatrixKey<float, Eigen::Dynamic>(wrappers, "Xf");
225 declareCovarianceMatrixKey<double, 2>(wrappers, "2d");
226 declareCovarianceMatrixKey<double, 3>(wrappers, "3d");
227 declareCovarianceMatrixKey<double, 4>(wrappers, "4d");
228 declareCovarianceMatrixKey<double, Eigen::Dynamic>(wrappers, "Xd");
229}
230
231} // namespace table
232} // namespace afw
233} // namespace lsst
void set(BaseRecord &record, lsst::geom::SpherePoint const &value) const override
Set an lsst::geom::SpherePoint in the given record.
Definition: aggregates.cc:93
lsst::geom::Point< T, 2 > get(BaseRecord const &record) const override
Get a Point from the given record.
Definition: aggregates.cc:44
bool isValid
Definition: fits.cc:399
void wrapAggregates(WrapperCollection &wrappers)
Definition: _aggregates.cc:201
A base class for image defects.