// SPDX-License-Identifier: MPL-2.0 #include "aare/Pedestal.hpp" #include "np_helper.hpp" #include #include #include #include #include namespace py = pybind11; template void define_pedestal_bindings(py::module &m, const std::string &name) { py::class_>(m, name.c_str(), py::buffer_protocol()) .def(py::init()) .def(py::init()) .def("mean", [](Pedestal &self) { auto mea = new NDArray{}; *mea = self.mean(); return return_image_data(mea); }) .def("view", [](py::object self_py) { auto &self = self_py.cast &>(); auto v = self.view(); std::array shape{ static_cast(v.shape(0)), static_cast(v.shape(1))}; std::array byte_strides{ static_cast(v.strides()[0]) * static_cast(sizeof(SUM_TYPE)), static_cast(v.strides()[1]) * static_cast(sizeof(SUM_TYPE))}; auto arr = py::array_t(shape, byte_strides, v.data(), self_py); arr.attr("setflags")(py::arg("write") = false); return arr; }) .def("variance", [](Pedestal &self) { auto var = new NDArray{}; *var = self.variance(); return return_image_data(var); }) .def("std", [](Pedestal &self) { auto std = new NDArray{}; *std = self.std(); return return_image_data(std); }) .def("cached_std", [](Pedestal &self) { auto standard_deviation = new NDArray{}; *standard_deviation = self.cached_std(); return return_image_data(standard_deviation); }) .def( "__array_ufunc__", [](py::object self, py::object ufunc, const std::string &method, py::args inputs, py::kwargs kwargs) -> py::object { if (method != "__call__" || inputs.size() != 2 || inputs[1].ptr() != self.ptr() || py::cast(ufunc.attr("__name__")) != "subtract") { return py::reinterpret_borrow( Py_NotImplemented); } auto mean = py::module_::import("builtins").attr("memoryview")(self); return ufunc(inputs[0], mean, **kwargs); }, "Support subtracting a Pedestal from a NumPy array.") .def("clear", py::overload_cast<>(&Pedestal::clear)) .def_property_readonly("rows", &Pedestal::rows) .def_property_readonly("cols", &Pedestal::cols) .def_property_readonly("n_samples", &Pedestal::n_samples) .def_property_readonly("sum", &Pedestal::get_sum) .def_property_readonly("sum2", &Pedestal::get_sum2) .def("clone", [&](Pedestal &pedestal) { return Pedestal(pedestal); }) // TODO! add push for other data types .def("push", [](Pedestal &pedestal, py::array_t &f) { auto v = make_view_2d(f); pedestal.push(v); }) .def( "push_with_threshold", [](Pedestal &pedestal, py::array_t &f, py::array_t &threshold) { auto frame_view = make_view_2d(f); auto threshold_view = make_view_2d(threshold); pedestal.push_with_threshold(frame_view, threshold_view); }, py::arg("frame").noconvert(), py::arg("threshold").noconvert()) .def( "push_no_update", [](Pedestal &pedestal, py::array_t &f) { auto v = make_view_2d(f); pedestal.push_no_update(v); }, py::arg().noconvert()) .def("update_mean", &Pedestal::update_mean) .def("update_std", &Pedestal::update_std) .def_buffer([](Pedestal &self) { auto mean = self.view(); return py::buffer_info( const_cast(mean.data()), sizeof(SUM_TYPE), py::format_descriptor::format(), 2, {static_cast(mean.shape(0)), static_cast(mean.shape(1))}, {static_cast(mean.strides()[0] * sizeof(SUM_TYPE)), static_cast(mean.strides()[1] * sizeof(SUM_TYPE))}, true); }); }