From 1bc2fd770af08bd8d5aeedadec9145ff74c4b968 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Fr=C3=B6jdh?= Date: Thu, 5 Jun 2025 08:57:59 +0200 Subject: [PATCH] Binding 5x5, 7x7 and 9x9 clusters in python (#188) - New binding code with macros to bind all cluster templates - Simplified factory function on the python side - 5x5, 7x7 and 9x9 bindings in python --- include/aare/ClusterFile.hpp | 8 ++- include/aare/ClusterFileSink.hpp | 7 ++- include/aare/ClusterFinder.hpp | 7 ++- include/aare/ClusterFinderMT.hpp | 7 +++ include/aare/logger.hpp | 2 +- python/aare/ClusterFinder.py | 85 +++++++++++++++++++------------- python/aare/__init__.py | 3 +- python/src/module.cpp | 85 +++++++++++++------------------- 8 files changed, 112 insertions(+), 92 deletions(-) diff --git a/include/aare/ClusterFile.hpp b/include/aare/ClusterFile.hpp index ef78874..e26e765 100644 --- a/include/aare/ClusterFile.hpp +++ b/include/aare/ClusterFile.hpp @@ -5,6 +5,8 @@ #include "aare/GainMap.hpp" #include "aare/NDArray.hpp" #include "aare/defs.hpp" +#include "aare/logger.hpp" + #include #include #include @@ -369,11 +371,15 @@ ClusterFile::read_frame_without_cut() { "Could not read number of clusters"); } + LOG(logDEBUG1) << "Reading " << n_clusters + << " clusters from frame " << frame_number; + ClusterVector clusters(n_clusters); clusters.set_frame_number(frame_number); - clusters.resize(n_clusters); + LOG(logDEBUG1) << "clusters.item_size(): " << clusters.item_size(); + if (fread(clusters.data(), clusters.item_size(), n_clusters, fp) != static_cast(n_clusters)) { throw std::runtime_error(LOCATION + "Could not read clusters"); diff --git a/include/aare/ClusterFileSink.hpp b/include/aare/ClusterFileSink.hpp index 810e63c..09190fe 100644 --- a/include/aare/ClusterFileSink.hpp +++ b/include/aare/ClusterFileSink.hpp @@ -21,7 +21,7 @@ class ClusterFileSink { void process() { m_stopped = false; - fmt::print("ClusterFileSink started\n"); + LOG(logDEBUG) << "ClusterFileSink started"; while (!m_stop_requested || !m_source->isEmpty()) { if (ClusterVector *clusters = m_source->frontPtr(); clusters != nullptr) { @@ -41,13 +41,16 @@ class ClusterFileSink { std::this_thread::sleep_for(m_default_wait); } } - fmt::print("ClusterFileSink stopped\n"); + LOG(logDEBUG) << "ClusterFileSink stopped"; m_stopped = true; } public: ClusterFileSink(ClusterFinderMT *source, const std::filesystem::path &fname) { + LOG(logDEBUG) << "ClusterFileSink: " + << "source: " << source->sink() + << ", file: " << fname.string(); m_source = source->sink(); m_thread = std::thread(&ClusterFileSink::process, this); m_file.open(fname, std::ios::binary); diff --git a/include/aare/ClusterFinder.hpp b/include/aare/ClusterFinder.hpp index ea11162..7a34722 100644 --- a/include/aare/ClusterFinder.hpp +++ b/include/aare/ClusterFinder.hpp @@ -38,7 +38,12 @@ class ClusterFinder { : m_image_size(image_size), m_nSigma(nSigma), c2(sqrt((ClusterSizeY + 1) / 2 * (ClusterSizeX + 1) / 2)), c3(sqrt(ClusterSizeX * ClusterSizeY)), - m_pedestal(image_size[0], image_size[1]), m_clusters(capacity) {}; + m_pedestal(image_size[0], image_size[1]), m_clusters(capacity) { + LOG(logDEBUG ) << "ClusterFinder: " + << "image_size: " << image_size[0] << "x" << image_size[1] + << ", nSigma: " << nSigma + << ", capacity: " << capacity; + } void push_pedestal_frame(NDView frame) { m_pedestal.push(frame); diff --git a/include/aare/ClusterFinderMT.hpp b/include/aare/ClusterFinderMT.hpp index 2dfb279..efc22d4 100644 --- a/include/aare/ClusterFinderMT.hpp +++ b/include/aare/ClusterFinderMT.hpp @@ -7,6 +7,7 @@ #include "aare/ClusterFinder.hpp" #include "aare/NDArray.hpp" +#include "aare/logger.hpp" #include "aare/ProducerConsumerQueue.hpp" namespace aare { @@ -123,6 +124,12 @@ class ClusterFinderMT { size_t capacity = 2000, size_t n_threads = 3) : m_n_threads(n_threads) { + LOG(logDEBUG1) << "ClusterFinderMT: " + << "image_size: " << image_size[0] << "x" << image_size[1] + << ", nSigma: " << nSigma + << ", capacity: " << capacity + << ", n_threads: " << n_threads; + for (size_t i = 0; i < n_threads; i++) { m_cluster_finders.push_back( std::make_unique< diff --git a/include/aare/logger.hpp b/include/aare/logger.hpp index 06e6feb..b93c091 100644 --- a/include/aare/logger.hpp +++ b/include/aare/logger.hpp @@ -37,7 +37,7 @@ enum TLogLevel { logINFOCYAN, logINFOMAGENTA, logINFO, - logDEBUG, + logDEBUG, // constructors, destructors etc. should still give too much output logDEBUG1, logDEBUG2, logDEBUG3, diff --git a/python/aare/ClusterFinder.py b/python/aare/ClusterFinder.py index 6e7c352..99bcc5f 100644 --- a/python/aare/ClusterFinder.py +++ b/python/aare/ClusterFinder.py @@ -1,22 +1,47 @@ -from ._aare import ClusterFinder_Cluster3x3i, ClusterFinder_Cluster2x2i, ClusterFinderMT_Cluster3x3i, ClusterFinderMT_Cluster2x2i, ClusterCollector_Cluster3x3i, ClusterCollector_Cluster2x2i +# from ._aare import ClusterFinder_Cluster3x3i, ClusterFinder_Cluster2x2i, ClusterFinderMT_Cluster3x3i, ClusterFinderMT_Cluster2x2i, ClusterCollector_Cluster3x3i, ClusterCollector_Cluster2x2i -from ._aare import ClusterFileSink_Cluster3x3i, ClusterFileSink_Cluster2x2i +# from ._aare import ClusterFileSink_Cluster3x3i, ClusterFileSink_Cluster2x2i + +from . import _aare import numpy as np +_supported_cluster_sizes = [(2,2), (3,3), (5,5), (7,7), (9,9),] + +# def _get_class() + +def _type_to_char(dtype): + if dtype == np.int32: + return 'i' + elif dtype == np.float32: + return 'f' + elif dtype == np.float64: + return 'd' + else: + raise ValueError(f"Unsupported dtype: {dtype}. Only np.int32, np.float32, and np.float64 are supported.") + +def _get_class(name, cluster_size, dtype): + """ + Helper function to get the class based on the name, cluster size, and dtype. + """ + try: + class_name = f"{name}_Cluster{cluster_size[0]}x{cluster_size[1]}{_type_to_char(dtype)}" + cls = getattr(_aare, class_name) + except AttributeError: + raise ValueError(f"Unsupported combination of type and cluster size: {dtype}/{cluster_size} when requesting {class_name}") + return cls + + + def ClusterFinder(image_size, cluster_size, n_sigma=5, dtype = np.int32, capacity = 1024): """ Factory function to create a ClusterFinder object. Provides a cleaner syntax for the templated ClusterFinder in C++. """ - if dtype == np.int32 and cluster_size == (3,3): - return ClusterFinder_Cluster3x3i(image_size, n_sigma = n_sigma, capacity=capacity) - elif dtype == np.int32 and cluster_size == (2,2): - return ClusterFinder_Cluster2x2i(image_size, n_sigma = n_sigma, capacity=capacity) - else: - #TODO! add the other formats - raise ValueError(f"Unsupported dtype: {dtype}. Only np.int32 is supported.") + cls = _get_class("ClusterFinder", cluster_size, dtype) + return cls(image_size, n_sigma=n_sigma, capacity=capacity) + def ClusterFinderMT(image_size, cluster_size = (3,3), dtype=np.int32, n_sigma=5, capacity = 1024, n_threads = 3): @@ -25,15 +50,9 @@ def ClusterFinderMT(image_size, cluster_size = (3,3), dtype=np.int32, n_sigma=5, the templated ClusterFinderMT in C++. """ - if dtype == np.int32 and cluster_size == (3,3): - return ClusterFinderMT_Cluster3x3i(image_size, n_sigma = n_sigma, - capacity = capacity, n_threads = n_threads) - elif dtype == np.int32 and cluster_size == (2,2): - return ClusterFinderMT_Cluster2x2i(image_size, n_sigma = n_sigma, - capacity = capacity, n_threads = n_threads) - else: - #TODO! add the other formats - raise ValueError(f"Unsupported dtype: {dtype}. Only np.int32 is supported.") + cls = _get_class("ClusterFinderMT", cluster_size, dtype) + return cls(image_size, n_sigma=n_sigma, capacity=capacity, n_threads=n_threads) + def ClusterCollector(clusterfindermt, cluster_size = (3,3), dtype=np.int32): @@ -42,14 +61,8 @@ def ClusterCollector(clusterfindermt, cluster_size = (3,3), dtype=np.int32): the templated ClusterCollector in C++. """ - if dtype == np.int32 and cluster_size == (3,3): - return ClusterCollector_Cluster3x3i(clusterfindermt) - elif dtype == np.int32 and cluster_size == (2,2): - return ClusterCollector_Cluster2x2i(clusterfindermt) - - else: - #TODO! add the other formats - raise ValueError(f"Unsupported dtype: {dtype}. Only np.int32 is supported.") + cls = _get_class("ClusterCollector", cluster_size, dtype) + return cls(clusterfindermt) def ClusterFileSink(clusterfindermt, cluster_file, dtype=np.int32): """ @@ -57,11 +70,15 @@ def ClusterFileSink(clusterfindermt, cluster_file, dtype=np.int32): the templated ClusterCollector in C++. """ - if dtype == np.int32 and clusterfindermt.cluster_size == (3,3): - return ClusterFileSink_Cluster3x3i(clusterfindermt, cluster_file) - elif dtype == np.int32 and clusterfindermt.cluster_size == (2,2): - return ClusterFileSink_Cluster2x2i(clusterfindermt, cluster_file) - - else: - #TODO! add the other formats - raise ValueError(f"Unsupported dtype: {dtype}. Only np.int32 is supported.") \ No newline at end of file + cls = _get_class("ClusterFileSink", clusterfindermt.cluster_size, dtype) + return cls(clusterfindermt, cluster_file) + + +def ClusterFile(fname, cluster_size=(3,3), dtype=np.int32): + """ + Factory function to create a ClusterFile object. Provides a cleaner syntax for + the templated ClusterFile in C++. + """ + + cls = _get_class("ClusterFile", cluster_size, dtype) + return cls(fname) diff --git a/python/aare/__init__.py b/python/aare/__init__.py index d2bbe0a..0b95702 100644 --- a/python/aare/__init__.py +++ b/python/aare/__init__.py @@ -5,13 +5,12 @@ from . import _aare from ._aare import File, RawMasterFile, RawSubFile, JungfrauDataFile from ._aare import Pedestal_d, Pedestal_f, ClusterFinder_Cluster3x3i, VarClusterFinder from ._aare import DetectorType -from ._aare import ClusterFile_Cluster3x3i as ClusterFile from ._aare import hitmap from ._aare import ROI # from ._aare import ClusterFinderMT, ClusterCollector, ClusterFileSink, ClusterVector_i -from .ClusterFinder import ClusterFinder, ClusterCollector, ClusterFinderMT, ClusterFileSink +from .ClusterFinder import ClusterFinder, ClusterCollector, ClusterFinderMT, ClusterFileSink, ClusterFile from .ClusterVector import ClusterVector diff --git a/python/src/module.cpp b/python/src/module.cpp index 5945afb..681dd4b 100644 --- a/python/src/module.cpp +++ b/python/src/module.cpp @@ -28,6 +28,25 @@ namespace py = pybind11; +/* MACRO that defines Cluster bindings for a specific size and type + +T - Storage type of the cluster data (int, float, double) +N - Number of rows in the cluster +M - Number of columns in the cluster +U - Type of the pixel data (e.g., uint16_t) +TYPE_CODE - A character representing the type code (e.g., 'i' for int, 'd' for double, 'f' for float) + +*/ +#define DEFINE_CLUSTER_BINDINGS(T, N, M, U, TYPE_CODE) \ + define_ClusterFile(m, "Cluster" #N "x" #M #TYPE_CODE); \ + define_ClusterVector(m, "Cluster" #N "x" #M #TYPE_CODE); \ + define_ClusterFinder(m, "Cluster" #N "x" #M #TYPE_CODE); \ + define_ClusterFinderMT(m, "Cluster" #N "x" #M #TYPE_CODE); \ + define_ClusterFileSink(m, "Cluster" #N "x" #M #TYPE_CODE); \ + define_ClusterCollector(m, "Cluster" #N "x" #M #TYPE_CODE); \ + define_Cluster(m, #N "x" #M #TYPE_CODE); \ + register_calculate_eta(m); + PYBIND11_MODULE(_aare, m) { define_file_io_bindings(m); define_raw_file_io_bindings(m); @@ -42,59 +61,23 @@ PYBIND11_MODULE(_aare, m) { define_interpolation_bindings(m); define_jungfrau_data_file_io_bindings(m); - define_ClusterFile(m, "Cluster3x3i"); - define_ClusterFile(m, "Cluster3x3d"); - define_ClusterFile(m, "Cluster3x3f"); - define_ClusterFile(m, "Cluster2x2i"); - define_ClusterFile(m, "Cluster2x2f"); - define_ClusterFile(m, "Cluster2x2d"); + DEFINE_CLUSTER_BINDINGS(int, 3, 3, uint16_t, i); + DEFINE_CLUSTER_BINDINGS(double, 3, 3, uint16_t, d); + DEFINE_CLUSTER_BINDINGS(float, 3, 3, uint16_t, f); - define_ClusterVector(m, "Cluster3x3i"); - define_ClusterVector(m, "Cluster3x3d"); - define_ClusterVector(m, "Cluster3x3f"); - define_ClusterVector(m, "Cluster2x2i"); - define_ClusterVector(m, "Cluster2x2d"); - define_ClusterVector(m, "Cluster2x2f"); + DEFINE_CLUSTER_BINDINGS(int, 2, 2, uint16_t, i); + DEFINE_CLUSTER_BINDINGS(double, 2, 2, uint16_t, d); + DEFINE_CLUSTER_BINDINGS(float, 2, 2, uint16_t, f); - define_ClusterFinder(m, "Cluster3x3i"); - define_ClusterFinder(m, "Cluster3x3d"); - define_ClusterFinder(m, "Cluster3x3f"); - define_ClusterFinder(m, "Cluster2x2i"); - define_ClusterFinder(m, "Cluster2x2d"); - define_ClusterFinder(m, "Cluster2x2f"); + DEFINE_CLUSTER_BINDINGS(int, 5, 5, uint16_t, i); + DEFINE_CLUSTER_BINDINGS(double, 5, 5, uint16_t, d); + DEFINE_CLUSTER_BINDINGS(float, 5, 5, uint16_t, f); - define_ClusterFinderMT(m, "Cluster3x3i"); - define_ClusterFinderMT(m, "Cluster3x3d"); - define_ClusterFinderMT(m, "Cluster3x3f"); - define_ClusterFinderMT(m, "Cluster2x2i"); - define_ClusterFinderMT(m, "Cluster2x2d"); - define_ClusterFinderMT(m, "Cluster2x2f"); + DEFINE_CLUSTER_BINDINGS(int, 7, 7, uint16_t, i); + DEFINE_CLUSTER_BINDINGS(double, 7, 7, uint16_t, d); + DEFINE_CLUSTER_BINDINGS(float, 7, 7, uint16_t, f); - define_ClusterFileSink(m, "Cluster3x3i"); - define_ClusterFileSink(m, "Cluster3x3d"); - define_ClusterFileSink(m, "Cluster3x3f"); - define_ClusterFileSink(m, "Cluster2x2i"); - define_ClusterFileSink(m, "Cluster2x2d"); - define_ClusterFileSink(m, "Cluster2x2f"); - - define_ClusterCollector(m, "Cluster3x3i"); - define_ClusterCollector(m, "Cluster3x3d"); - define_ClusterCollector(m, "Cluster3x3f"); - define_ClusterCollector(m, "Cluster2x2i"); - define_ClusterCollector(m, "Cluster2x2d"); - define_ClusterCollector(m, "Cluster2x2f"); - - define_Cluster(m, "3x3i"); - define_Cluster(m, "3x3f"); - define_Cluster(m, "3x3d"); - define_Cluster(m, "2x2i"); - define_Cluster(m, "2x2f"); - define_Cluster(m, "2x2d"); - - register_calculate_eta(m); - register_calculate_eta(m); - register_calculate_eta(m); - register_calculate_eta(m); - register_calculate_eta(m); - register_calculate_eta(m); + DEFINE_CLUSTER_BINDINGS(int, 9, 9, uint16_t, i); + DEFINE_CLUSTER_BINDINGS(double, 9, 9, uint16_t, d); + DEFINE_CLUSTER_BINDINGS(float, 9, 9, uint16_t, f); }