Binding 5x5, 7x7 and 9x9 clusters in python (#188)
All checks were successful
Build on RHEL8 / build (push) Successful in 2m55s
Build on RHEL9 / build (push) Successful in 2m58s

- New binding code with macros to bind all cluster templates
- Simplified factory function on the python side
- 5x5, 7x7 and 9x9 bindings in python
This commit is contained in:
Erik Fröjdh 2025-06-05 08:57:59 +02:00 committed by GitHub
parent 69964e08d5
commit 1bc2fd770a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 112 additions and 92 deletions

View File

@ -5,6 +5,8 @@
#include "aare/GainMap.hpp"
#include "aare/NDArray.hpp"
#include "aare/defs.hpp"
#include "aare/logger.hpp"
#include <filesystem>
#include <fstream>
#include <optional>
@ -369,11 +371,15 @@ ClusterFile<ClusterType, Enable>::read_frame_without_cut() {
"Could not read number of clusters");
}
LOG(logDEBUG1) << "Reading " << n_clusters
<< " clusters from frame " << frame_number;
ClusterVector<ClusterType> 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<size_t>(n_clusters)) {
throw std::runtime_error(LOCATION + "Could not read clusters");

View File

@ -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<ClusterType> *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<ClusterType, uint16_t, double> *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);

View File

@ -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_TYPE, 2> frame) {
m_pedestal.push(frame);

View File

@ -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<

View File

@ -37,7 +37,7 @@ enum TLogLevel {
logINFOCYAN,
logINFOMAGENTA,
logINFO,
logDEBUG,
logDEBUG, // constructors, destructors etc. should still give too much output
logDEBUG1,
logDEBUG2,
logDEBUG3,

View File

@ -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.")
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)

View File

@ -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

View File

@ -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<T, N, M, U>(m, "Cluster" #N "x" #M #TYPE_CODE); \
define_ClusterVector<T, N, M, U>(m, "Cluster" #N "x" #M #TYPE_CODE); \
define_ClusterFinder<T, N, M, U>(m, "Cluster" #N "x" #M #TYPE_CODE); \
define_ClusterFinderMT<T, N, M, U>(m, "Cluster" #N "x" #M #TYPE_CODE); \
define_ClusterFileSink<T, N, M, U>(m, "Cluster" #N "x" #M #TYPE_CODE); \
define_ClusterCollector<T, N, M, U>(m, "Cluster" #N "x" #M #TYPE_CODE); \
define_Cluster<T, N, M, U>(m, #N "x" #M #TYPE_CODE); \
register_calculate_eta<T, N, M, U>(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<int, 3, 3, uint16_t>(m, "Cluster3x3i");
define_ClusterFile<double, 3, 3, uint16_t>(m, "Cluster3x3d");
define_ClusterFile<float, 3, 3, uint16_t>(m, "Cluster3x3f");
define_ClusterFile<int, 2, 2, uint16_t>(m, "Cluster2x2i");
define_ClusterFile<float, 2, 2, uint16_t>(m, "Cluster2x2f");
define_ClusterFile<double, 2, 2, uint16_t>(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<int, 3, 3, uint16_t>(m, "Cluster3x3i");
define_ClusterVector<double, 3, 3, uint16_t>(m, "Cluster3x3d");
define_ClusterVector<float, 3, 3, uint16_t>(m, "Cluster3x3f");
define_ClusterVector<int, 2, 2, uint16_t>(m, "Cluster2x2i");
define_ClusterVector<double, 2, 2, uint16_t>(m, "Cluster2x2d");
define_ClusterVector<float, 2, 2, uint16_t>(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<int, 3, 3, uint16_t>(m, "Cluster3x3i");
define_ClusterFinder<double, 3, 3, uint16_t>(m, "Cluster3x3d");
define_ClusterFinder<float, 3, 3, uint16_t>(m, "Cluster3x3f");
define_ClusterFinder<int, 2, 2, uint16_t>(m, "Cluster2x2i");
define_ClusterFinder<double, 2, 2, uint16_t>(m, "Cluster2x2d");
define_ClusterFinder<float, 2, 2, uint16_t>(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<int, 3, 3, uint16_t>(m, "Cluster3x3i");
define_ClusterFinderMT<double, 3, 3, uint16_t>(m, "Cluster3x3d");
define_ClusterFinderMT<float, 3, 3, uint16_t>(m, "Cluster3x3f");
define_ClusterFinderMT<int, 2, 2, uint16_t>(m, "Cluster2x2i");
define_ClusterFinderMT<double, 2, 2, uint16_t>(m, "Cluster2x2d");
define_ClusterFinderMT<float, 2, 2, uint16_t>(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<int, 3, 3, uint16_t>(m, "Cluster3x3i");
define_ClusterFileSink<double, 3, 3, uint16_t>(m, "Cluster3x3d");
define_ClusterFileSink<float, 3, 3, uint16_t>(m, "Cluster3x3f");
define_ClusterFileSink<int, 2, 2, uint16_t>(m, "Cluster2x2i");
define_ClusterFileSink<double, 2, 2, uint16_t>(m, "Cluster2x2d");
define_ClusterFileSink<float, 2, 2, uint16_t>(m, "Cluster2x2f");
define_ClusterCollector<int, 3, 3, uint16_t>(m, "Cluster3x3i");
define_ClusterCollector<double, 3, 3, uint16_t>(m, "Cluster3x3d");
define_ClusterCollector<float, 3, 3, uint16_t>(m, "Cluster3x3f");
define_ClusterCollector<int, 2, 2, uint16_t>(m, "Cluster2x2i");
define_ClusterCollector<double, 2, 2, uint16_t>(m, "Cluster2x2d");
define_ClusterCollector<float, 2, 2, uint16_t>(m, "Cluster2x2f");
define_Cluster<int, 3, 3, uint16_t>(m, "3x3i");
define_Cluster<float, 3, 3, uint16_t>(m, "3x3f");
define_Cluster<double, 3, 3, uint16_t>(m, "3x3d");
define_Cluster<int, 2, 2, uint16_t>(m, "2x2i");
define_Cluster<float, 2, 2, uint16_t>(m, "2x2f");
define_Cluster<double, 2, 2, uint16_t>(m, "2x2d");
register_calculate_eta<int, 3, 3, uint16_t>(m);
register_calculate_eta<float, 3, 3, uint16_t>(m);
register_calculate_eta<double, 3, 3, uint16_t>(m);
register_calculate_eta<int, 2, 2, uint16_t>(m);
register_calculate_eta<float, 2, 2, uint16_t>(m);
register_calculate_eta<double, 2, 2, uint16_t>(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);
}