LSSTApplications  19.0.0-10-g920eed2,19.0.0-11-g48a0200+2,19.0.0-18-gfc4e62b+17,19.0.0-2-g3b2f90d+2,19.0.0-2-gd671419+5,19.0.0-20-g5a5a17ab+15,19.0.0-21-g2644856+18,19.0.0-23-g84eeccb+6,19.0.0-24-g878c510+5,19.0.0-25-g6c8df7140,19.0.0-25-gb330496+5,19.0.0-3-g2b32d65+5,19.0.0-3-g8227491+16,19.0.0-3-g9c54d0d+16,19.0.0-3-gca68e65+12,19.0.0-3-gcfc5f51+5,19.0.0-3-ge110943+15,19.0.0-3-ge74d124,19.0.0-3-gfe04aa6+16,19.0.0-30-g9c3fd16+6,19.0.0-4-g06f5963+5,19.0.0-4-g3d16501+18,19.0.0-4-g4a9c019+5,19.0.0-4-g5a8b323,19.0.0-4-g66397f0+1,19.0.0-4-g8278b9b+1,19.0.0-4-g8557e14,19.0.0-4-g8964aba+17,19.0.0-4-ge404a01+16,19.0.0-5-g40f3a5a,19.0.0-5-g4db63b3,19.0.0-5-gfb03ce7+17,19.0.0-6-gbaebbfb+16,19.0.0-61-gec4c6e08+6,19.0.0-7-g039c0b5+16,19.0.0-7-gbea9075+4,19.0.0-7-gc567de5+17,19.0.0-70-g334bf3e+1,19.0.0-9-g463f923+16,b.20.0.x-g5487ab2134,v20.0.0.rc1
LSSTDataManagementBasePackage
transform.cc
Go to the documentation of this file.
1 /*
2  * LSST Data Management System
3  * See COPYRIGHT file at the top of the source tree.
4  *
5  * This product includes software developed by the
6  * LSST Project (http://www.lsst.org/).
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the LSST License Statement and
19  * the GNU General Public License along with this program. If not,
20  * see <http://www.lsstcorp.org/LegalNotices/>.
21  */
22 #include "pybind11/pybind11.h"
23 #include "pybind11/eigen.h"
24 
25 #include <memory>
26 
27 #include "astshim.h"
28 #include "pybind11/stl.h"
29 #include "ndarray/pybind11.h"
30 
32 #include "lsst/afw/geom/Endpoint.h"
34 
35 namespace py = pybind11;
36 using namespace py::literals;
37 
38 namespace lsst {
39 namespace afw {
40 namespace geom {
41 namespace {
42 
43 // Return a string consisting of "_pythonClassName_[_fromNAxes_->_toNAxes_]",
44 // for example "TransformGenericToPoint2[4->2]"
45 template <class Class>
46 std::string formatStr(Class const &self, std::string const &pyClassName) {
48  os << pyClassName;
49  os << "[" << self.getFromEndpoint().getNAxes() << "->" << self.getToEndpoint().getNAxes() << "]";
50  return os.str();
51 }
52 
53 template <class FromEndpoint, class ToEndpoint, class NextToEndpoint, class PyClass>
54 void declareMethodTemplates(PyClass &cls) {
55  using ThisTransform = Transform<FromEndpoint, ToEndpoint>;
56  using NextTransform = Transform<ToEndpoint, NextToEndpoint>;
57  using SeriesTransform = Transform<FromEndpoint, NextToEndpoint>;
58  // Need Python-specific logic to give sensible errors for mismatched Transform types
59  cls.def("_then",
60  (std::shared_ptr<SeriesTransform>(ThisTransform::*)(NextTransform const &, bool) const) &
61  ThisTransform::template then<NextToEndpoint>,
62  "next"_a, "simplify"_a = true);
63 }
64 
65 // Declare Transform<FromEndpoint, ToEndpoint> using python class name Transform<X>To<Y>
66 // where <X> and <Y> are the prefix of the from endpoint and to endpoint class, respectively,
67 // for example TransformGenericToPoint2
68 template <class FromEndpoint, class ToEndpoint>
69 void declareTransform(py::module &mod) {
70  using Class = Transform<FromEndpoint, ToEndpoint>;
71  using ToPoint = typename ToEndpoint::Point;
72  using ToArray = typename ToEndpoint::Array;
73  using FromPoint = typename FromEndpoint::Point;
74  using FromArray = typename FromEndpoint::Array;
75 
76  std::string const pyClassName = Class::getShortClassName();
77 
78  py::class_<Class, std::shared_ptr<Class>> cls(mod, pyClassName.c_str());
79 
80  cls.def(py::init<ast::FrameSet const &, bool>(), "frameSet"_a, "simplify"_a = true);
81  cls.def(py::init<ast::Mapping const &, bool>(), "mapping"_a, "simplify"_a = true);
82 
83  cls.def_property_readonly("hasForward", &Class::hasForward);
84  cls.def_property_readonly("hasInverse", &Class::hasInverse);
85  cls.def_property_readonly("fromEndpoint", &Class::getFromEndpoint);
86  cls.def_property_readonly("toEndpoint", &Class::getToEndpoint);
87 
88  // Return a copy of the contained Mapping in order to assure changing the returned Mapping
89  // will not affect the contained Mapping (since Python ignores constness)
90  cls.def("getMapping", [](Class const &self) { return self.getMapping()->copy(); });
91 
92  cls.def("applyForward", py::overload_cast<FromArray const &>(&Class::applyForward, py::const_),
93  "array"_a);
94  cls.def("applyForward", py::overload_cast<FromPoint const &>(&Class::applyForward, py::const_),
95  "point"_a);
96  cls.def("applyInverse", py::overload_cast<ToArray const &>(&Class::applyInverse, py::const_), "array"_a);
97  cls.def("applyInverse", py::overload_cast<ToPoint const &>(&Class::applyInverse, py::const_), "point"_a);
98  cls.def("inverted", &Class::inverted);
99  /* Need some extra handling of ndarray return type in Python to prevent dimensions
100  * of length 1 from being deleted */
101  cls.def("_getJacobian", &Class::getJacobian);
102  // Do not wrap getShortClassName because it returns the name of the class;
103  // use `<class>.__name__` or `type(<instance>).__name__` instead.
104  // Do not wrap readStream or writeStream because C++ streams are not easy to wrap.
105  cls.def_static("readString", &Class::readString);
106  cls.def("writeString", &Class::writeString);
107 
108  declareMethodTemplates<FromEndpoint, ToEndpoint, GenericEndpoint>(cls);
109  declareMethodTemplates<FromEndpoint, ToEndpoint, Point2Endpoint>(cls);
110  declareMethodTemplates<FromEndpoint, ToEndpoint, SpherePointEndpoint>(cls);
111 
112  // str(self) = "<Python class name>[<nIn>-><nOut>]"
113  cls.def("__str__", [pyClassName](Class const &self) { return formatStr(self, pyClassName); });
114  // repr(self) = "lsst.afw.geom.<Python class name>[<nIn>-><nOut>]"
115  cls.def("__repr__",
116  [pyClassName](Class const &self) { return "lsst.afw.geom." + formatStr(self, pyClassName); });
117 
118  table::io::python::addPersistableMethods<Class>(cls);
119 }
120 
122  py::module::import("astshim");
123  py::module::import("lsst.afw.geom.endpoint");
124 
125  declareTransform<GenericEndpoint, GenericEndpoint>(mod);
126  declareTransform<GenericEndpoint, Point2Endpoint>(mod);
127  declareTransform<GenericEndpoint, SpherePointEndpoint>(mod);
128  declareTransform<Point2Endpoint, GenericEndpoint>(mod);
129  declareTransform<Point2Endpoint, Point2Endpoint>(mod);
130  declareTransform<Point2Endpoint, SpherePointEndpoint>(mod);
131  declareTransform<SpherePointEndpoint, GenericEndpoint>(mod);
132  declareTransform<SpherePointEndpoint, Point2Endpoint>(mod);
133  declareTransform<SpherePointEndpoint, SpherePointEndpoint>(mod);
134 }
135 
136 } // namespace
137 } // namespace geom
138 } // namespace afw
139 } // namespace lsst
std::string
STL class.
std::shared_ptr
STL class.
lsst::afw::geom.python.transform.getJacobian
getJacobian
Definition: transform.py:112
lsst::afw
Definition: imageAlgorithm.dox:1
Endpoint.h
astshim.h
lsst::afw::geom.transform.transformContinued.cls
cls
Definition: transformContinued.py:33
std::string::c_str
T c_str(T... args)
python.h
PyClass
py::class_< ProductBoundedField, std::shared_ptr< ProductBoundedField >, BoundedField > PyClass
Definition: productBoundedField.cc:32
std::copy
T copy(T... args)
lsst::meas::base::PYBIND11_MODULE
PYBIND11_MODULE(transform, mod)
Definition: transform.cc:36
lsst
A base class for image defects.
Definition: imageAlgorithm.dox:1
std::ostringstream
STL class.
lsst::geom
Definition: geomOperators.dox:4
os
std::ostream * os
Definition: Schema.cc:746
transform
table::Key< int > transform
Definition: TransformMap.cc:299
Transform.h
pybind11
Definition: _GenericMap.cc:40
lsst::meas::modelfit.psf.psfContinued.module
module
Definition: psfContinued.py:42