24#ifndef LSST_GAUSS2D_PYTHON_IMAGE_H
25#define LSST_GAUSS2D_PYTHON_IMAGE_H
30#include <pybind11/pybind11.h>
31#include <pybind11/numpy.h>
32#include <pybind11/operators.h>
33#include <pybind11/stl.h>
35#include "lsst/gauss2d/evaluate.h"
36#include "lsst/gauss2d/image.h"
37#include "lsst/gauss2d/string_utils.h"
38#include "lsst/gauss2d/type_name.h"
40namespace py = pybind11;
41using namespace pybind11::literals;
43namespace lsst::gauss2d::python {
50std::string replace_type(std::string target, std::string replacement) {
51 std::string token =
"<" + gauss2d::type_name_str<T>() +
">";
52 return replace_all(target, token, replacement);
65#pragma GCC visibility push(hidden)
74 explicit Image(
size_t n_rows,
size_t n_cols,
76 const std::shared_ptr<const lsst::gauss2d::CoordinateSystem> coordsys =
nullptr)
78 _ptr_own(std::make_unique<py::array_t<T>>(py::array::ShapeContainer({n_rows, n_cols}))),
80 _data_ref(_validate().
template mutable_unchecked<2>()) {
81 if (value_init !=
nullptr) {
82 this->fill(*value_init);
94 explicit Image(py::array_t<T> data,
95 const std::shared_ptr<const lsst::gauss2d::CoordinateSystem> coordsys =
nullptr)
96 : gauss2d::Image<T, Image<T>>(coordsys),
99 _data_ref(_validate().template mutable_unchecked<2>()) {}
103 inline T &_get_value_unchecked_impl(
size_t row,
size_t col) {
return this->_data_ref(row, col); };
105 py::array_t<T> &get_data() {
return this->_data; }
107 size_t get_n_cols_impl()
const {
return _data.shape(1); };
108 size_t get_n_rows_impl()
const {
return _data.shape(0); };
110 inline T get_value_unchecked_impl(
size_t row,
size_t col)
const {
return this->_data_ref(row, col); };
111 void set_value_unchecked_impl(
size_t row,
size_t col, T value) { this->_data_ref(row, col) = value; }
115 std::unique_ptr<py::array_t<T>> _ptr_own =
nullptr;
118 py::array_t<T> _data_in;
120 py::array_t<T> &_data;
122 py::detail::unchecked_mutable_reference<T, 2> _data_ref;
124 py::array_t<T> &_validate()
const {
125 if (_data.ndim() != 2) {
126 throw std::runtime_error(
"Input data must have 2 dimensions");
131#pragma GCC visibility pop
143template <
typename Value,
typename Index>
144std::string replace_images_types(std::string target, std::string str_type, std::string_view separator) {
145 std::string token1 = std::string(
"<") + type_name_str<Value>() +
", ";
146 target = replace_all_none(target, token1);
147 std::string token2 = type_name_str<Image<Value>>(
false, separator) + std::string(
", ");
148 target = replace_all_none(target, token2);
149 std::string token3 = type_name_str<Image<Index>>(
false, separator) + std::string(
" >");
150 target = replace_all(target, token3, str_type);
152 target = replace_type<Value>(target, str_type);
157void declare_image(py::module &m, std::string str_type) {
159 std::string pyclass_name = std::string(
"Image") + str_type;
160 py::classh<Class>(m, pyclass_name.c_str())
161 .def(py::init<
size_t,
size_t,
const T *,
162 const std::shared_ptr<const lsst::gauss2d::CoordinateSystem>>(),
163 "n_rows"_a,
"n_cols"_a,
"value_init"_a = Class::_value_default_ptr(),
164 "coordsys"_a = gauss2d::COORDS_DEFAULT)
165 .def(py::init<py::array_t<T>,
const std::shared_ptr<const lsst::gauss2d::CoordinateSystem>>(),
166 "data"_a,
"coordsys"_a = gauss2d::COORDS_DEFAULT)
167 .def_property_readonly(
"coordsys", &Class::get_coordsys_ptr_const)
168 .def_property_readonly(
"data", &Class::get_data)
169 .def_property_readonly(
"n_rows", &Class::get_n_rows)
170 .def_property_readonly(
"n_cols", &Class::get_n_cols)
171 .def(
"fill", &Class::fill)
172 .def(
"get_value", &Class::get_value,
"row"_a,
"col"_a)
173 .def(
"set_value", &Class::set_value,
"row"_a,
"col"_a,
"value"_a)
174 .def(
"get_value_unchecked", &Class::get_value_unchecked,
"row"_a,
"col"_a)
175 .def(
"set_value_unchecked", &Class::set_value_unchecked,
"row"_a,
"col"_a,
"value"_a)
176 .def_property_readonly(
"size", &Class::size)
177 .def_property_readonly(
"shape", &Class::shape)
178 .def(py::self == py::self)
179 .def(py::self != py::self)
180 .def(py::self += T())
181 .def(py::self *= T())
183 [str_type](
const Class &self) {
184 std::string repr = self.repr(
true, self.PY_NAMESPACE_SEPARATOR);
185 return replace_type<T>(repr, str_type);
187 .def(
"__str__", [str_type](
const Class &self) {
188 std::string str = self.str();
189 return replace_type<T>(str, str_type);
203std::string replace_image_types(std::string target, std::string str_type, std::string_view separator) {
204 std::string token1 = std::string(
"<") + type_name_str<T>() +
", ";
205 target = replace_all_none(target, token1);
206 std::string token2 = type_name_str<Image<T>>(
false, separator) + std::string(
" >");
207 target = replace_all(target, token2, str_type);
209 target = replace_type<T>(target, str_type);
214void declare_image_array(py::module &m, std::string str_type) {
215 using Class = lsst::gauss2d::ImageArray<T, Image<T>>;
216 std::string pyclass_name = std::string(
"ImageArray") + str_type;
217 py::classh<Class>(m, pyclass_name.c_str())
218 .def(py::init<const typename Class::Data *>(),
"data"_a)
219 .def(
"at", &Class::at, py::return_value_policy::reference)
220 .def_property_readonly(
"size", &Class::size)
221 .def(
"__getitem__", &Class::at, py::return_value_policy::reference)
222 .def(
"__len__", &Class::size)
224 [str_type](
const Class &self) {
225 std::string repr = self.repr(
true, self.PY_NAMESPACE_SEPARATOR);
226 repr = replace_image_types<T>(repr, str_type, self.PY_NAMESPACE_SEPARATOR);
229 .def(
"__str__", [str_type](
const Class &self) {
230 std::string str = self.str();
231 str = replace_image_types<T>(str, str_type, self.CC_NAMESPACE_SEPARATOR);
237void declare_evaluator(py::module &m, std::string str_type) {
239 std::string pyclass_name = std::string(
"GaussianEvaluator") + str_type;
240 py::classh<Class>(m, pyclass_name.c_str())
241 .def(py::init<
const std::shared_ptr<const gauss2d::ConvolvedGaussians>,
242 const std::shared_ptr<
const Image<T>>,
const std::shared_ptr<
const Image<T>>,
244 const std::shared_ptr<gauss2d::ImageArray<T,
Image<T>>>,
246 const std::shared_ptr<
const Image<T>>,
248 const std::shared_ptr<
const Image<T>>,
const std::shared_ptr<
const Image<T>>>(),
249 "gaussians"_a,
"data"_a =
nullptr,
"sigma_inv"_a =
nullptr,
"output"_a =
nullptr,
250 "residual"_a =
nullptr,
"grads"_a =
nullptr,
"grad_param_map"_a =
nullptr,
251 "grad_param_factor"_a =
nullptr,
"extra_param_map"_a =
nullptr,
252 "extra_param_factor"_a =
nullptr,
"background"_a =
nullptr)
253 .def(
"loglike_pixel", &Class::loglike_pixel,
"to_add"_a =
false)
254 .def_property_readonly(
"n_cols", &Class::get_n_cols)
255 .def_property_readonly(
"n_rows", &Class::get_n_rows)
256 .def_property_readonly(
"size", &Class::get_size)
257 .def(
"__len__", &Class::get_size)
259 [str_type](
const Class &self) {
260 std::string repr = self.repr(
true, self.PY_NAMESPACE_SEPARATOR);
261 repr = replace_images_types<T, lsst::gauss2d::idx_type>(repr, str_type,
262 self.PY_NAMESPACE_SEPARATOR);
265 .def(
"__str__", [str_type](
const Class &self) {
266 std::string str = self.str();
267 str = replace_images_types<T, lsst::gauss2d::idx_type>(str, str_type,
268 self.CC_NAMESPACE_SEPARATOR);
273template <
typename T,
class Data,
class Indices>
274void declare_maker(py::module &m, std::string str_type) {
275 m.def((
"make_gaussians_pixel_" + str_type).c_str(), lsst::gauss2d::make_gaussians_pixel<T, Data, Indices>,
276 "Evaluate a 2D Gaussian at the centers of pixels on a rectangular grid using the standard bivariate"
278 "gaussians"_a,
"output"_a =
nullptr,
"n_rows"_a = 0,
"n_cols"_a = 0,
"coordsys"_a =
nullptr,
A Python image using numpy arrrays for storage.
Definition image.h:72
Image(py::array_t< T > data, const std::shared_ptr< const lsst::gauss2d::CoordinateSystem > coordsys=nullptr)
Definition image.h:94