removed cluster_2x2 and cluster3x3 specializations
All checks were successful
Build on RHEL9 / buildh (push) Successful in 1m58s

This commit is contained in:
Mazzoleni Alice Francesca 2025-04-16 16:40:42 +02:00
parent 14211047ff
commit c49a2fdf8e
7 changed files with 93 additions and 151 deletions

View File

@ -16,33 +16,43 @@
namespace aare { namespace aare {
template <typename T, uint8_t ClusterSizeX, uint8_t ClusterSizeY,
typename CoordType = int16_t>
constexpr bool is_valid_cluster =
std::is_arithmetic_v<T> && std::is_integral_v<CoordType> &&
(ClusterSizeX > 0) && (ClusterSizeY > 0);
// requires clause c++20 maybe update // requires clause c++20 maybe update
template <typename T, uint8_t ClusterSizeX, uint8_t ClusterSizeY, template <typename T, uint8_t ClusterSizeX, uint8_t ClusterSizeY,
typename CoordType = int16_t, typename CoordType = int16_t>
typename Enable = std::enable_if_t<
is_valid_cluster<T, ClusterSizeX, ClusterSizeY, CoordType>>>
struct Cluster { struct Cluster {
static_assert(std::is_arithmetic_v<T>, "T needs to be an arithmetic type");
static_assert(std::is_integral_v<CoordType>,
"CoordType needs to be an integral type");
static_assert(ClusterSizeX > 0 && ClusterSizeY > 0,
"Cluster sizes must be bigger than zero");
CoordType x; CoordType x;
CoordType y; CoordType y;
T data[ClusterSizeX * ClusterSizeY]; std::array<T, ClusterSizeX * ClusterSizeY> data;
static constexpr uint8_t cluster_size_x = ClusterSizeX; static constexpr uint8_t cluster_size_x = ClusterSizeX;
static constexpr uint8_t cluster_size_y = ClusterSizeY; static constexpr uint8_t cluster_size_y = ClusterSizeY;
using value_type = T; using value_type = T;
using coord_type = CoordType; using coord_type = CoordType;
T sum() const { T sum() const { return std::accumulate(data.begin(), data.end(), T{}); }
return std::accumulate(data, data + ClusterSizeX * ClusterSizeY, 0);
}
std::pair<T, int> max_sum_2x2() const { std::pair<T, int> max_sum_2x2() const {
if constexpr (cluster_size_x == 3 && cluster_size_y == 3) {
std::array<T, 4> sum_2x2_subclusters;
sum_2x2_subclusters[0] = data[0] + data[1] + data[3] + data[4];
sum_2x2_subclusters[1] = data[1] + data[2] + data[4] + data[5];
sum_2x2_subclusters[2] = data[3] + data[4] + data[6] + data[7];
sum_2x2_subclusters[3] = data[4] + data[5] + data[7] + data[8];
int index = std::max_element(sum_2x2_subclusters.begin(),
sum_2x2_subclusters.end()) -
sum_2x2_subclusters.begin();
return std::make_pair(sum_2x2_subclusters[index], index);
} else if constexpr (cluster_size_x == 2 && cluster_size_y == 2) {
return std::make_pair(data[0] + data[1] + data[2] + data[3], 0);
} else {
constexpr size_t num_2x2_subclusters = constexpr size_t num_2x2_subclusters =
(ClusterSizeX - 1) * (ClusterSizeY - 1); (ClusterSizeX - 1) * (ClusterSizeY - 1);
@ -61,49 +71,6 @@ struct Cluster {
sum_2x2_subcluster.begin(); sum_2x2_subcluster.begin();
return std::make_pair(sum_2x2_subcluster[index], index); return std::make_pair(sum_2x2_subcluster[index], index);
} }
};
// Specialization for 2x2 clusters (only one sum exists)
template <typename T> struct Cluster<T, 2, 2, int16_t> {
int16_t x;
int16_t y;
T data[4];
static constexpr uint8_t cluster_size_x = 2;
static constexpr uint8_t cluster_size_y = 2;
using value_type = T;
using coord_type = int16_t;
T sum() const { return std::accumulate(data, data + 4, 0); }
std::pair<T, int> max_sum_2x2() const {
return std::make_pair(data[0] + data[1] + data[2] + data[3],
0); // Only one possible 2x2 sum
}
};
// Specialization for 3x3 clusters
template <typename T> struct Cluster<T, 3, 3, int16_t> {
int16_t x;
int16_t y;
T data[9];
static constexpr uint8_t cluster_size_x = 3;
static constexpr uint8_t cluster_size_y = 3;
using value_type = T;
using coord_type = int16_t;
T sum() const { return std::accumulate(data, data + 9, 0); }
std::pair<T, int> max_sum_2x2() const {
std::array<T, 4> sum_2x2_subclusters;
sum_2x2_subclusters[0] = data[0] + data[1] + data[3] + data[4];
sum_2x2_subclusters[1] = data[1] + data[2] + data[4] + data[5];
sum_2x2_subclusters[2] = data[3] + data[4] + data[6] + data[7];
sum_2x2_subclusters[3] = data[4] + data[5] + data[7] + data[8];
int index = std::max_element(sum_2x2_subclusters.begin(),
sum_2x2_subclusters.end()) -
sum_2x2_subclusters.begin();
return std::make_pair(sum_2x2_subclusters[index], index);
} }
}; };

View File

@ -77,7 +77,6 @@ class ClusterFinder {
int has_center_pixel_y = ClusterSizeY % 2; int has_center_pixel_y = ClusterSizeY % 2;
m_clusters.set_frame_number(frame_number); m_clusters.set_frame_number(frame_number);
std::vector<CT> cluster_data(ClusterSizeX * ClusterSizeY);
for (int iy = 0; iy < frame.shape(0); iy++) { for (int iy = 0; iy < frame.shape(0); iy++) {
for (int ix = 0; ix < frame.shape(1); ix++) { for (int ix = 0; ix < frame.shape(1); ix++) {
@ -124,8 +123,9 @@ class ClusterFinder {
// Store cluster // Store cluster
if (value == max) { if (value == max) {
// Zero out the cluster data ClusterType cluster{};
std::fill(cluster_data.begin(), cluster_data.end(), 0); cluster.x = ix;
cluster.y = iy;
// Fill the cluster data since we have a photon to store // Fill the cluster data since we have a photon to store
// It's worth redoing the look since most of the time we // It's worth redoing the look since most of the time we
@ -139,20 +139,15 @@ class ClusterFinder {
static_cast<CT>(frame(iy + ir, ix + ic)) - static_cast<CT>(frame(iy + ir, ix + ic)) -
static_cast<CT>( static_cast<CT>(
m_pedestal.mean(iy + ir, ix + ic)); m_pedestal.mean(iy + ir, ix + ic));
cluster_data[i] = cluster.data[i] =
tmp; // Watch for out of bounds access tmp; // Watch for out of bounds access
i++; i++;
} }
} }
} }
ClusterType new_cluster{};
new_cluster.x = ix;
new_cluster.y = iy;
std::copy(cluster_data.begin(), cluster_data.end(),
new_cluster.data);
// Add the cluster to the output ClusterVector // Add the cluster to the output ClusterVector
m_clusters.push_back(new_cluster); m_clusters.push_back(cluster);
} }
} }
} }

View File

@ -44,9 +44,8 @@ class GainMap {
cl.data[j] = cl.data[j] * static_cast<T>(m_gain_map(y, x)); cl.data[j] = cl.data[j] * static_cast<T>(m_gain_map(y, x));
} }
} else { } else {
memset(cl.data, 0, // clear edge clusters
ClusterSizeX * ClusterSizeY * cl.data.fill(0);
sizeof(T)); // clear edge clusters
} }
} }
} }

View File

@ -21,16 +21,14 @@ using namespace aare;
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter" #pragma GCC diagnostic ignored "-Wunused-parameter"
template <typename Type, uint8_t ClusterSizeX, uint8_t ClusterSizeY, template <typename Type, uint8_t ClusterSizeX, uint8_t ClusterSizeY,
typename CoordType = uint16_t> typename CoordType = uint16_t>
void define_ClusterVector(py::module &m, const std::string &typestr) { void define_ClusterVector(py::module &m, const std::string &typestr) {
using ClusterType = using ClusterType = Cluster<Type, ClusterSizeX, ClusterSizeY, CoordType>;
Cluster<Type, ClusterSizeX, ClusterSizeY, CoordType, void>;
auto class_name = fmt::format("ClusterVector_{}", typestr); auto class_name = fmt::format("ClusterVector_{}", typestr);
py::class_<ClusterVector< py::class_<ClusterVector<
Cluster<Type, ClusterSizeX, ClusterSizeY, CoordType, void>, void>>( Cluster<Type, ClusterSizeX, ClusterSizeY, CoordType>, void>>(
m, class_name.c_str(), m, class_name.c_str(),
py::buffer_protocol()) py::buffer_protocol())
@ -41,7 +39,8 @@ void define_ClusterVector(py::module &m, const std::string &typestr) {
self.push_back(cluster); self.push_back(cluster);
}) })
.def("sum", [](ClusterVector<ClusterType> &self) { .def("sum",
[](ClusterVector<ClusterType> &self) {
auto *vec = new std::vector<Type>(self.sum()); auto *vec = new std::vector<Type>(self.sum());
return return_vector(vec); return return_vector(vec);
}) })
@ -75,7 +74,6 @@ void define_ClusterVector(py::module &m, const std::string &typestr) {
// Free functions using ClusterVector // Free functions using ClusterVector
m.def("hitmap", m.def("hitmap",
[](std::array<size_t, 2> image_size, ClusterVector<ClusterType> &cv) { [](std::array<size_t, 2> image_size, ClusterVector<ClusterType> &cv) {
// Create a numpy array to hold the hitmap // Create a numpy array to hold the hitmap
// The shape of the array is (image_size[0], image_size[1]) // The shape of the array is (image_size[0], image_size[1])
// note that the python array is passed as [row, col] which // note that the python array is passed as [row, col] which
@ -88,7 +86,6 @@ void define_ClusterVector(py::module &m, const std::string &typestr) {
for (py::ssize_t j = 0; j < r.shape(1); j++) for (py::ssize_t j = 0; j < r.shape(1); j++)
r(i, j) = 0; r(i, j) = 0;
// Loop over the clusters and increment the hitmap // Loop over the clusters and increment the hitmap
// Skip out of bound clusters // Skip out of bound clusters
for (const auto &cluster : cv) { for (const auto &cluster : cv) {

View File

@ -26,17 +26,18 @@ template <typename Type, uint8_t ClusterSizeX, uint8_t ClusterSizeY,
void define_cluster(py::module &m, const std::string &typestr) { void define_cluster(py::module &m, const std::string &typestr) {
auto class_name = fmt::format("Cluster{}", typestr); auto class_name = fmt::format("Cluster{}", typestr);
py::class_<Cluster<Type, ClusterSizeX, ClusterSizeY, CoordType, void>>( py::class_<Cluster<Type, ClusterSizeX, ClusterSizeY, CoordType>>(
m, class_name.c_str(), py::buffer_protocol()) m, class_name.c_str(), py::buffer_protocol())
.def(py::init([](uint8_t x, uint8_t y, py::array_t<Type> data) { .def(py::init([](uint8_t x, uint8_t y, py::array_t<Type> data) {
py::buffer_info buf_info = data.request(); py::buffer_info buf_info = data.request();
Type *ptr = static_cast<Type *>(buf_info.ptr); Cluster<Type, ClusterSizeX, ClusterSizeY, CoordType> cluster;
Cluster<Type, ClusterSizeX, ClusterSizeY, CoordType, void> cluster;
cluster.x = x; cluster.x = x;
cluster.y = y; cluster.y = y;
std::copy(ptr, ptr + ClusterSizeX * ClusterSizeY, auto r = data.template unchecked<1>(); // no bounds checks
cluster.data); // Copy array contents for (py::ssize_t i = 0; i < data.size(); ++i) {
cluster.data[i] = r(i);
}
return cluster; return cluster;
})); }));
@ -64,9 +65,6 @@ void define_cluster(py::module &m, const std::string &typestr) {
*/ */
} }
template <typename T, uint8_t ClusterSizeX, uint8_t ClusterSizeY, template <typename T, uint8_t ClusterSizeX, uint8_t ClusterSizeY,
typename CoordType = uint16_t> typename CoordType = uint16_t>
void define_cluster_finder_mt_bindings(py::module &m, void define_cluster_finder_mt_bindings(py::module &m,
@ -206,6 +204,5 @@ void define_cluster_finder_bindings(py::module &m, const std::string &typestr) {
return; return;
}, },
py::arg(), py::arg("frame_number") = 0); py::arg(), py::arg("frame_number") = 0);
} }
#pragma GCC diagnostic pop #pragma GCC diagnostic pop

View File

@ -14,19 +14,6 @@
using namespace aare; using namespace aare;
TEST_CASE("Correct Instantiation of Cluster and ClusterVector",
"[.cluster][.instantiation]") {
CHECK(is_valid_cluster<double, 3, 3>);
CHECK(is_valid_cluster<double, 3, 2>);
CHECK(not is_valid_cluster<int, 0, 0>);
CHECK(not is_valid_cluster<std::string, 2, 2>);
CHECK(not is_valid_cluster<int, 2, 2, double>);
CHECK(not is_cluster_v<int>);
CHECK(is_cluster_v<Cluster<int, 3, 3>>);
}
TEST_CASE("Test sum of Cluster", "[.cluster]") { TEST_CASE("Test sum of Cluster", "[.cluster]") {
Cluster<int, 2, 2> cluster{0, 0, {1, 2, 3, 4}}; Cluster<int, 2, 2> cluster{0, 0, {1, 2, 3, 4}};

View File

@ -311,18 +311,18 @@ TEST_CASE("Write cluster with potential padding", "[.files][.ClusterFile]") {
CHECK(read_cluster_vector.at(0).x == clustervec.at(0).x); CHECK(read_cluster_vector.at(0).x == clustervec.at(0).x);
CHECK(read_cluster_vector.at(0).y == clustervec.at(0).y); CHECK(read_cluster_vector.at(0).y == clustervec.at(0).y);
CHECK(std::equal(clustervec.at(0).data, clustervec.at(0).data + 9, CHECK(std::equal(
read_cluster_vector.at(0).data, [](double a, double b) { clustervec.at(0).data.begin(), clustervec.at(0).data.end(),
return std::abs(a - b) < read_cluster_vector.at(0).data.begin(), [](double a, double b) {
std::numeric_limits<double>::epsilon(); return std::abs(a - b) < std::numeric_limits<double>::epsilon();
})); }));
CHECK(read_cluster_vector.at(1).x == clustervec.at(1).x); CHECK(read_cluster_vector.at(1).x == clustervec.at(1).x);
CHECK(read_cluster_vector.at(1).y == clustervec.at(1).y); CHECK(read_cluster_vector.at(1).y == clustervec.at(1).y);
CHECK(std::equal(clustervec.at(1).data, std::end(clustervec.at(1).data), CHECK(std::equal(
read_cluster_vector.at(1).data, [](double a, double b) { clustervec.at(1).data.begin(), clustervec.at(1).data.end(),
return std::abs(a - b) < read_cluster_vector.at(1).data.begin(), [](double a, double b) {
std::numeric_limits<double>::epsilon(); return std::abs(a - b) < std::numeric_limits<double>::epsilon();
})); }));
} }