added cluster finder

This commit is contained in:
Erik Fröjdh
2024-10-25 16:18:36 +02:00
parent 54dd88f070
commit 5d643dc133
7 changed files with 816 additions and 3 deletions

View File

@ -23,6 +23,8 @@ if(AARE_TESTS)
# ${CMAKE_CURRENT_SOURCE_DIR}/test/ProducerConsumerQueue.test.cpp
${CMAKE_CURRENT_SOURCE_DIR}/NDArray.test.cpp
${CMAKE_CURRENT_SOURCE_DIR}/NDView.test.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ClusterFinder.test.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Pedestal.test.cpp
# ${CMAKE_CURRENT_SOURCE_DIR}/test/CircularFifo.test.cpp
# ${CMAKE_CURRENT_SOURCE_DIR}/test/wrappers.test.cpp
# ${CMAKE_CURRENT_SOURCE_DIR}/test/Transforms.test.cpp

View File

@ -0,0 +1,59 @@
#include "aare/ClusterFinder.hpp"
#include "aare/Pedestal.hpp"
#include <catch2/matchers/catch_matchers_floating_point.hpp>
#include <catch2/catch_test_macros.hpp>
#include <chrono>
#include <random>
using namespace aare;
class ClusterFinderUnitTest : public ClusterFinder {
public:
ClusterFinderUnitTest(int cluster_sizeX, int cluster_sizeY, double nSigma = 5.0, double threshold = 0.0)
: ClusterFinder(cluster_sizeX, cluster_sizeY, nSigma, threshold) {}
double get_c2() { return c2; }
double get_c3() { return c3; }
auto get_threshold() { return m_threshold; }
auto get_nSigma() { return m_nSigma; }
auto get_cluster_sizeX() { return m_cluster_sizeX; }
auto get_cluster_sizeY() { return m_cluster_sizeY; }
};
TEST_CASE("test ClusterFinder constructor") {
ClusterFinderUnitTest cf(55, 100);
REQUIRE(cf.get_cluster_sizeX() == 55);
REQUIRE(cf.get_cluster_sizeY() == 100);
REQUIRE(cf.get_threshold() == 0.0);
REQUIRE(cf.get_nSigma() == 5.0);
double c2 = sqrt((100 + 1) / 2 * (55 + 1) / 2);
double c3 = sqrt(55 * 100);
// REQUIRE(compare_floats<double>(cf.get_c2(), c2));
// REQUIRE(compare_floats<double>(cf.get_c3(), c3));
REQUIRE_THAT(cf.get_c2(), Catch::Matchers::WithinRel(c2, 1e-9));
REQUIRE_THAT(cf.get_c3(), Catch::Matchers::WithinRel(c3, 1e-9));
}
TEST_CASE("test cluster finder") {
aare::Pedestal pedestal(10, 10, 5);
NDArray<double, 2> frame({10, 10});
frame = 0;
ClusterFinder clusterFinder(3, 3, 1, 1); // 3x3 cluster, 1 nSigma, 1 threshold
auto clusters = clusterFinder.find_clusters_without_threshold(frame.span(), pedestal);
REQUIRE(clusters.size() == 0);
frame(5, 5) = 10;
clusters = clusterFinder.find_clusters_without_threshold(frame.span(), pedestal);
REQUIRE(clusters.size() == 1);
REQUIRE(clusters[0].x == 5);
REQUIRE(clusters[0].y == 5);
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (i == 1 && j == 1)
REQUIRE(clusters[0].get<double>(i * 3 + j) == 10);
else
REQUIRE(clusters[0].get<double>(i * 3 + j) == 0);
}
}
}

103
src/Pedestal.test.cpp Normal file
View File

@ -0,0 +1,103 @@
#include "aare/Pedestal.hpp"
#include <catch2/matchers/catch_matchers_floating_point.hpp>
#include <catch2/catch_test_macros.hpp>
#include <chrono>
#include <random>
using namespace aare;
TEST_CASE("test pedestal constructor") {
aare::Pedestal pedestal(10, 10, 5);
REQUIRE(pedestal.rows() == 10);
REQUIRE(pedestal.cols() == 10);
REQUIRE(pedestal.n_samples() == 5);
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
REQUIRE(pedestal.get_sum()(i, j) == 0);
REQUIRE(pedestal.get_sum2()(i, j) == 0);
REQUIRE(pedestal.cur_samples()(i, j) == 0);
}
}
}
TEST_CASE("test pedestal push") {
aare::Pedestal pedestal(10, 10, 5);
aare::Frame frame(10, 10, Dtype::UINT16);
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
frame.set<uint16_t>(i, j, i + j);
}
}
// test single push
pedestal.push<uint16_t>(frame);
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
REQUIRE(pedestal.get_sum()(i, j) == i + j);
REQUIRE(pedestal.get_sum2()(i, j) == (i + j) * (i + j));
REQUIRE(pedestal.cur_samples()(i, j) == 1);
}
}
// test clear
pedestal.clear();
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
REQUIRE(pedestal.get_sum()(i, j) == 0);
REQUIRE(pedestal.get_sum2()(i, j) == 0);
REQUIRE(pedestal.cur_samples()(i, j) == 0);
}
}
// test number of samples after multiple push
for (uint32_t k = 0; k < 50; k++) {
pedestal.push<uint16_t>(frame);
for (uint32_t i = 0; i < 10; i++) {
for (uint32_t j = 0; j < 10; j++) {
if (k < 5) {
REQUIRE(pedestal.cur_samples()(i, j) == k + 1);
REQUIRE(pedestal.get_sum()(i, j) == (k + 1) * (i + j));
REQUIRE(pedestal.get_sum2()(i, j) == (k + 1) * (i + j) * (i + j));
} else {
REQUIRE(pedestal.cur_samples()(i, j) == 5);
REQUIRE(pedestal.get_sum()(i, j) == 5 * (i + j));
REQUIRE(pedestal.get_sum2()(i, j) == 5 * (i + j) * (i + j));
}
REQUIRE(pedestal.mean(i, j) == (i + j));
REQUIRE(pedestal.variance(i, j) == 0);
REQUIRE(pedestal.standard_deviation(i, j) == 0);
}
}
}
}
TEST_CASE("test pedestal with normal distribution") {
const double MEAN = 5.0, STD = 2.0, VAR = STD * STD, TOLERANCE = 0.1;
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
std::default_random_engine generator(seed);
std::normal_distribution<double> distribution(MEAN, STD);
aare::Pedestal pedestal(3, 5, 10000);
for (int i = 0; i < 10000; i++) {
aare::Frame frame(3, 5, Dtype::DOUBLE);
for (int j = 0; j < 3; j++) {
for (int k = 0; k < 5; k++) {
frame.set<double>(j, k, distribution(generator));
}
}
pedestal.push<double>(frame);
}
auto mean = pedestal.mean();
auto variance = pedestal.variance();
auto standard_deviation = pedestal.standard_deviation();
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 5; j++) {
REQUIRE_THAT(mean(i, j), Catch::Matchers::WithinAbs(MEAN, MEAN * TOLERANCE));
REQUIRE_THAT(variance(i, j), Catch::Matchers::WithinAbs(VAR, VAR * TOLERANCE));
REQUIRE_THAT(standard_deviation(i, j), Catch::Matchers::WithinAbs(STD, STD * TOLERANCE));
}
}
}