#include "aare/ClusterCollector.hpp" #include "aare/ClusterFileSink.hpp" #include "aare/ClusterFinder.hpp" #include "aare/ClusterFinderMT.hpp" #include "aare/ClusterVector.hpp" #include "aare/NDView.hpp" #include "aare/Pedestal.hpp" #include "np_helper.hpp" #include #include #include #include #include namespace py = pybind11; using pd_type = double; using namespace aare; #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" template void define_cluster(py::module &m, const std::string &typestr) { auto class_name = fmt::format("Cluster{}", typestr); py::class_>( m, class_name.c_str(), py::buffer_protocol()) .def(py::init([](uint8_t x, uint8_t y, py::array_t data) { py::buffer_info buf_info = data.request(); Type *ptr = static_cast(buf_info.ptr); Cluster cluster; cluster.x = x; cluster.y = y; std::copy(ptr, ptr + ClusterSizeX * ClusterSizeY, cluster.data); // Copy array contents return cluster; })); /* .def_property( "data", [](ClusterType &c) -> py::array { return py::array(py::buffer_info( c.data, sizeof(Type), py::format_descriptor::format(), // Type // format 1, // Number of dimensions {static_cast(ClusterSizeX * ClusterSizeY)}, // Shape (flattened) {sizeof(Type)} // Stride (step size between elements) )); }, [](ClusterType &c, py::array_t arr) { py::buffer_info buf_info = arr.request(); Type *ptr = static_cast(buf_info.ptr); std::copy(ptr, ptr + ClusterSizeX * ClusterSizeY, c.data); // TODO dont iterate over centers!!! }); */ } template void define_cluster_vector(py::module &m, const std::string &typestr) { using ClusterType = Cluster; auto class_name = fmt::format("ClusterVector_{}", typestr); py::class_, void>>( m, class_name.c_str(), py::buffer_protocol()) .def(py::init()) // TODO change!!! .def("push_back", [](ClusterVector &self, const ClusterType &cluster) { self.push_back(cluster); }) // implement push_back .def_property_readonly("size", &ClusterVector::size) .def("item_size", &ClusterVector::item_size) .def_property_readonly("fmt", [typestr](ClusterVector &self) { return fmt_format; }) .def_property_readonly("cluster_size_x", &ClusterVector::cluster_size_x) .def_property_readonly("cluster_size_y", &ClusterVector::cluster_size_y) .def_property_readonly("capacity", &ClusterVector::capacity) .def_property("frame_number", &ClusterVector::frame_number, &ClusterVector::set_frame_number) .def_buffer( [typestr](ClusterVector &self) -> py::buffer_info { return py::buffer_info( self.data(), /* Pointer to buffer */ self.item_size(), /* Size of one scalar */ fmt_format, /* Format descriptor */ 1, /* Number of dimensions */ {self.size()}, /* Buffer dimensions */ {self.item_size()} /* Strides (in bytes) for each index */ ); }); } template void define_cluster_finder_mt_bindings(py::module &m, const std::string &typestr) { auto class_name = fmt::format("ClusterFinderMT_{}", typestr); using ClusterType = Cluster; py::class_>( m, class_name.c_str()) .def(py::init, pd_type, size_t, size_t>(), py::arg("image_size"), py::arg("n_sigma") = 5.0, py::arg("capacity") = 2048, py::arg("n_threads") = 3) .def("push_pedestal_frame", [](ClusterFinderMT &self, py::array_t frame) { auto view = make_view_2d(frame); self.push_pedestal_frame(view); }) .def( "find_clusters", [](ClusterFinderMT &self, py::array_t frame, uint64_t frame_number) { auto view = make_view_2d(frame); self.find_clusters(view, frame_number); return; }, py::arg(), py::arg("frame_number") = 0) .def("clear_pedestal", &ClusterFinderMT::clear_pedestal) .def("sync", &ClusterFinderMT::sync) .def("stop", &ClusterFinderMT::stop) .def("start", &ClusterFinderMT::start) .def( "pedestal", [](ClusterFinderMT &self, size_t thread_index) { auto pd = new NDArray{}; *pd = self.pedestal(thread_index); return return_image_data(pd); }, py::arg("thread_index") = 0) .def( "noise", [](ClusterFinderMT &self, size_t thread_index) { auto arr = new NDArray{}; *arr = self.noise(thread_index); return return_image_data(arr); }, py::arg("thread_index") = 0); } template void define_cluster_collector_bindings(py::module &m, const std::string &typestr) { auto class_name = fmt::format("ClusterCollector_{}", typestr); using ClusterType = Cluster; py::class_>(m, class_name.c_str()) .def(py::init *>()) .def("stop", &ClusterCollector::stop) .def( "steal_clusters", [](ClusterCollector &self) { auto v = new std::vector>( self.steal_clusters()); return v; // TODO change!!! }, py::return_value_policy::take_ownership); } template void define_cluster_file_sink_bindings(py::module &m, const std::string &typestr) { auto class_name = fmt::format("ClusterFileSink_{}", typestr); using ClusterType = Cluster; py::class_>(m, class_name.c_str()) .def(py::init *, const std::filesystem::path &>()) .def("stop", &ClusterFileSink::stop); } template void define_cluster_finder_bindings(py::module &m, const std::string &typestr) { auto class_name = fmt::format("ClusterFinder_{}", typestr); using ClusterType = Cluster; py::class_>( m, class_name.c_str()) .def(py::init, pd_type, size_t>(), py::arg("image_size"), py::arg("n_sigma") = 5.0, py::arg("capacity") = 1'000'000) .def("push_pedestal_frame", [](ClusterFinder &self, py::array_t frame) { auto view = make_view_2d(frame); self.push_pedestal_frame(view); }) .def("clear_pedestal", &ClusterFinder::clear_pedestal) .def_property_readonly( "pedestal", [](ClusterFinder &self) { auto pd = new NDArray{}; *pd = self.pedestal(); return return_image_data(pd); }) .def_property_readonly( "noise", [](ClusterFinder &self) { auto arr = new NDArray{}; *arr = self.noise(); return return_image_data(arr); }) .def( "steal_clusters", [](ClusterFinder &self, bool realloc_same_capacity) { ClusterVector clusters = self.steal_clusters(realloc_same_capacity); return clusters; }, py::arg("realloc_same_capacity") = false) .def( "find_clusters", [](ClusterFinder &self, py::array_t frame, uint64_t frame_number) { auto view = make_view_2d(frame); self.find_clusters(view, frame_number); return; }, py::arg(), py::arg("frame_number") = 0); m.def("hitmap", [](std::array image_size, ClusterVector &cv) { py::array_t hitmap(image_size); auto r = hitmap.mutable_unchecked<2>(); // Initialize hitmap to 0 for (py::ssize_t i = 0; i < r.shape(0); i++) for (py::ssize_t j = 0; j < r.shape(1); j++) r(i, j) = 0; size_t stride = cv.item_size(); auto ptr = cv.data(); for (size_t i = 0; i < cv.size(); i++) { auto x = *reinterpret_cast(ptr); auto y = *reinterpret_cast(ptr + sizeof(int16_t)); r(y, x) += 1; ptr += stride; } return hitmap; }); } #pragma GCC diagnostic pop