diff --git a/CMakeLists.txt b/CMakeLists.txt index 8bb7667..b57f05f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -384,7 +384,6 @@ set(SourceFiles ${CMAKE_CURRENT_SOURCE_DIR}/src/utils/task.cpp ) - add_library(aare_core STATIC ${SourceFiles}) target_include_directories(aare_core PUBLIC "$" diff --git a/include/aare/CalculateEta.hpp b/include/aare/CalculateEta.hpp index 0aab540..2797233 100644 --- a/include/aare/CalculateEta.hpp +++ b/include/aare/CalculateEta.hpp @@ -33,7 +33,7 @@ template struct Eta2 { }; /** - * @brief Calculate the eta2 values for all clusters in a Clsutervector + * @brief Calculate the eta2 values for all clusters in a Clustervector */ template >> diff --git a/include/aare/ClusterFile.hpp b/include/aare/ClusterFile.hpp index 6ec2f2d..06de985 100644 --- a/include/aare/ClusterFile.hpp +++ b/include/aare/ClusterFile.hpp @@ -39,9 +39,10 @@ template >> class ClusterFile { FILE *fp{}; + const std::string m_filename{}; uint32_t m_num_left{}; /*Number of photons left in frame*/ size_t m_chunk_size{}; /*Number of clusters to read at a time*/ - const std::string m_mode; /*Mode to open the file in*/ + std::string m_mode; /*Mode to open the file in*/ std::optional m_roi; /*Region of interest, will be applied if set*/ std::optional> m_noise_map; /*Noise map to cut photons, will be applied if set*/ @@ -115,6 +116,11 @@ class ClusterFile { */ void close(); + /** @brief Open the file in specific mode + * + */ + void open(const std::string &mode); + private: ClusterVector read_clusters_with_cut(size_t n_clusters); ClusterVector read_clusters_without_cut(size_t n_clusters); @@ -128,25 +134,25 @@ template ClusterFile::ClusterFile( const std::filesystem::path &fname, size_t chunk_size, const std::string &mode) - : m_chunk_size(chunk_size), m_mode(mode) { + : m_filename(fname.string()), m_chunk_size(chunk_size), m_mode(mode) { if (mode == "r") { - fp = fopen(fname.c_str(), "rb"); + fp = fopen(m_filename.c_str(), "rb"); if (!fp) { throw std::runtime_error("Could not open file for reading: " + - fname.string()); + m_filename); } } else if (mode == "w") { - fp = fopen(fname.c_str(), "wb"); + fp = fopen(m_filename.c_str(), "wb"); if (!fp) { throw std::runtime_error("Could not open file for writing: " + - fname.string()); + m_filename); } } else if (mode == "a") { - fp = fopen(fname.c_str(), "ab"); + fp = fopen(m_filename.c_str(), "ab"); if (!fp) { throw std::runtime_error("Could not open file for appending: " + - fname.string()); + m_filename); } } else { throw std::runtime_error("Unsupported mode: " + mode); @@ -165,6 +171,39 @@ void ClusterFile::close() { fp = nullptr; } } + +template +void ClusterFile::open(const std::string &mode) { + if (fp) { + close(); + } + + if (mode == "r") { + fp = fopen(m_filename.c_str(), "rb"); + if (!fp) { + throw std::runtime_error("Could not open file for reading: " + + m_filename); + } + m_mode = "r"; + } else if (mode == "w") { + fp = fopen(m_filename.c_str(), "wb"); + if (!fp) { + throw std::runtime_error("Could not open file for writing: " + + m_filename); + } + m_mode = "w"; + } else if (mode == "a") { + fp = fopen(m_filename.c_str(), "ab"); + if (!fp) { + throw std::runtime_error("Could not open file for appending: " + + m_filename); + } + m_mode = "a"; + } else { + throw std::runtime_error("Unsupported mode: " + mode); + } +} + template void ClusterFile::set_roi(ROI roi) { m_roi = roi; @@ -197,10 +236,7 @@ void ClusterFile::write_frame( if (m_mode != "w" && m_mode != "a") { throw std::runtime_error("File not opened for writing"); } - if (!(clusters.cluster_size_x() == 3) && - !(clusters.cluster_size_y() == 3)) { - throw std::runtime_error("Only 3x3 clusters are supported"); - } + int32_t frame_number = clusters.frame_number(); fwrite(&frame_number, sizeof(frame_number), 1, fp); uint32_t n_clusters = clusters.size(); @@ -270,7 +306,7 @@ ClusterFile::read_clusters_without_cut(size_t n_clusters) { } } - // Resize the vector to the number of clusters. + // Resize the vector to the number o f clusters. // No new allocation, only change bounds. clusters.resize(nph_read); if (m_gain_map) @@ -375,11 +411,13 @@ ClusterFile::read_frame_without_cut() { ClusterVector clusters(n_clusters); clusters.set_frame_number(frame_number); + clusters.resize(n_clusters); + if (fread(clusters.data(), clusters.item_size(), n_clusters, fp) != static_cast(n_clusters)) { throw std::runtime_error(LOCATION + "Could not read clusters"); } - clusters.resize(n_clusters); + if (m_gain_map) m_gain_map->apply_gain_map(clusters); return clusters; diff --git a/include/aare/ClusterFileV2.hpp b/include/aare/ClusterFileV2.hpp deleted file mode 100644 index 55b8a2b..0000000 --- a/include/aare/ClusterFileV2.hpp +++ /dev/null @@ -1,154 +0,0 @@ -#pragma once -#include "aare/core/defs.hpp" -#include -#include -#include - -namespace aare { -struct ClusterHeader { - int32_t frame_number; - int32_t n_clusters; - std::string to_string() const { - return "frame_number: " + std::to_string(frame_number) + - ", n_clusters: " + std::to_string(n_clusters); - } -}; - -struct ClusterV2_ { - int16_t x; - int16_t y; - std::array data; - std::string to_string(bool detailed = false) const { - if (detailed) { - std::string data_str = "["; - for (auto &d : data) { - data_str += std::to_string(d) + ", "; - } - data_str += "]"; - return "x: " + std::to_string(x) + ", y: " + std::to_string(y) + - ", data: " + data_str; - } - return "x: " + std::to_string(x) + ", y: " + std::to_string(y); - } -}; - -struct ClusterV2 { - ClusterV2_ cluster; - int32_t frame_number; - std::string to_string() const { - return "frame_number: " + std::to_string(frame_number) + ", " + - cluster.to_string(); - } -}; - -/** - * @brief - * important not: fp always points to the clusters header and does not point to - * individual clusters - * - */ -class ClusterFileV2 { - std::filesystem::path m_fpath; - std::string m_mode; - FILE *fp{nullptr}; - - void check_open() { - if (!fp) - throw std::runtime_error( - fmt::format("File: {} not open", m_fpath.string())); - } - - public: - ClusterFileV2(std::filesystem::path const &fpath, std::string const &mode) - : m_fpath(fpath), m_mode(mode) { - if (m_mode != "r" && m_mode != "w") - throw std::invalid_argument("mode must be 'r' or 'w'"); - if (m_mode == "r" && !std::filesystem::exists(m_fpath)) - throw std::invalid_argument("File does not exist"); - if (mode == "r") { - fp = fopen(fpath.string().c_str(), "rb"); - } else if (mode == "w") { - if (std::filesystem::exists(fpath)) { - fp = fopen(fpath.string().c_str(), "r+b"); - } else { - fp = fopen(fpath.string().c_str(), "wb"); - } - } - if (fp == nullptr) { - throw std::runtime_error("Failed to open file"); - } - } - ~ClusterFileV2() { close(); } - std::vector read() { - check_open(); - - ClusterHeader header; - fread(&header, sizeof(ClusterHeader), 1, fp); - std::vector clusters_(header.n_clusters); - fread(clusters_.data(), sizeof(ClusterV2_), header.n_clusters, fp); - std::vector clusters; - for (auto &c : clusters_) { - ClusterV2 cluster; - cluster.cluster = std::move(c); - cluster.frame_number = header.frame_number; - clusters.push_back(cluster); - } - - return clusters; - } - std::vector> read(int n_frames) { - std::vector> clusters; - for (int i = 0; i < n_frames; i++) { - clusters.push_back(read()); - } - return clusters; - } - - size_t write(std::vector const &clusters) { - check_open(); - if (m_mode != "w") - throw std::runtime_error("File not opened in write mode"); - if (clusters.empty()) - return 0; - - ClusterHeader header; - header.frame_number = clusters[0].frame_number; - header.n_clusters = clusters.size(); - fwrite(&header, sizeof(ClusterHeader), 1, fp); - for (auto &c : clusters) { - fwrite(&c.cluster, sizeof(ClusterV2_), 1, fp); - } - return clusters.size(); - } - - size_t write(std::vector> const &clusters) { - check_open(); - if (m_mode != "w") - throw std::runtime_error("File not opened in write mode"); - - size_t n_clusters = 0; - for (auto &c : clusters) { - n_clusters += write(c); - } - return n_clusters; - } - - int seek_to_begin() { return fseek(fp, 0, SEEK_SET); } - int seek_to_end() { return fseek(fp, 0, SEEK_END); } - - int32_t frame_number() { - auto pos = ftell(fp); - ClusterHeader header; - fread(&header, sizeof(ClusterHeader), 1, fp); - fseek(fp, pos, SEEK_SET); - return header.frame_number; - } - - void close() { - if (fp) { - fclose(fp); - fp = nullptr; - } - } -}; -} // namespace aare \ No newline at end of file diff --git a/include/aare/ClusterVector.hpp b/include/aare/ClusterVector.hpp index e85a6f0..3084c96 100644 --- a/include/aare/ClusterVector.hpp +++ b/include/aare/ClusterVector.hpp @@ -18,256 +18,6 @@ template >> class ClusterVector; // Forward declaration -/** - * @brief ClusterVector is a container for clusters of various sizes. It uses a - * contiguous memory buffer to store the clusters. It is templated on the data - * type and the coordinate type of the clusters. - * @note push_back can invalidate pointers to elements in the container - * @warning ClusterVector is currently move only to catch unintended copies, but - * this might change since there are probably use cases where copying is needed. - * @tparam T data type of the pixels in the cluster - * @tparam CoordType data type of the x and y coordinates of the cluster - * (normally int16_t) - */ -#if 0 -template -class ClusterVector> { - - std::byte *m_data{}; - size_t m_size{0}; - size_t m_capacity; - uint64_t m_frame_number{0}; // TODO! Check frame number size and type - /** - Format string used in the python bindings to create a numpy - array from the buffer - = - native byte order - h - short - d - double - i - int - */ - constexpr static char m_fmt_base[] = "=h:x:\nh:y:\n({},{}){}:data:"; - - public: - using value_type = T; - using ClusterType = Cluster; - - /** - * @brief Construct a new ClusterVector object - * @param capacity initial capacity of the buffer in number of clusters - * @param frame_number frame number of the clusters. Default is 0, which is - * also used to indicate that the clusters come from many frames - */ - ClusterVector(size_t capacity = 1024, uint64_t frame_number = 0) - : m_capacity(capacity), m_frame_number(frame_number) { - allocate_buffer(m_capacity); - } - - ~ClusterVector() { delete[] m_data; } - - // Move constructor - ClusterVector(ClusterVector &&other) noexcept - : m_data(other.m_data), m_size(other.m_size), - m_capacity(other.m_capacity), m_frame_number(other.m_frame_number) { - other.m_data = nullptr; - other.m_size = 0; - other.m_capacity = 0; - } - - // Move assignment operator - ClusterVector &operator=(ClusterVector &&other) noexcept { - if (this != &other) { - delete[] m_data; - m_data = other.m_data; - m_size = other.m_size; - m_capacity = other.m_capacity; - m_frame_number = other.m_frame_number; - other.m_data = nullptr; - other.m_size = 0; - other.m_capacity = 0; - other.m_frame_number = 0; - } - return *this; - } - - /** - * @brief Reserve space for at least capacity clusters - * @param capacity number of clusters to reserve space for - * @note If capacity is less than the current capacity, the function does - * nothing. - */ - void reserve(size_t capacity) { - if (capacity > m_capacity) { - allocate_buffer(capacity); - } - } - - /** - * @brief Add a cluster to the vector - */ - void push_back(const ClusterType &cluster) { - if (m_size == m_capacity) { - allocate_buffer(m_capacity * 2); - } - std::byte *ptr = element_ptr(m_size); - *reinterpret_cast(ptr) = cluster.x; - ptr += sizeof(CoordType); - *reinterpret_cast(ptr) = cluster.y; - ptr += sizeof(CoordType); - - std::memcpy(ptr, cluster.data, ClusterSizeX * ClusterSizeY * sizeof(T)); - - m_size++; - } - - ClusterVector &operator+=(const ClusterVector &other) { - if (m_size + other.m_size > m_capacity) { - allocate_buffer(m_capacity + other.m_size); - } - std::copy(other.m_data, other.m_data + other.m_size * item_size(), - m_data + m_size * item_size()); - m_size += other.m_size; - return *this; - } - - /** - * @brief Sum the pixels in each cluster - * @return std::vector vector of sums for each cluster - */ - /* - std::vector sum() { - std::vector sums(m_size); - const size_t stride = item_size(); - const size_t n_pixels = ClusterSizeX * ClusterSizeY; - std::byte *ptr = m_data + 2 * sizeof(CoordType); // skip x and y - - for (size_t i = 0; i < m_size; i++) { - sums[i] = - std::accumulate(reinterpret_cast(ptr), - reinterpret_cast(ptr) + n_pixels, T{}); - ptr += stride; - } - return sums; - } - */ - - /** - * @brief Sum the pixels in the 2x2 subcluster with the biggest pixel sum in - * each cluster - * @return std::vector vector of sums for each cluster - */ //TODO if underlying container is a vector use std::for_each - /* - std::vector sum_2x2() { - std::vector sums_2x2(m_size); - - for (size_t i = 0; i < m_size; i++) { - sums_2x2[i] = at(i).max_sum_2x2; - } - return sums_2x2; - } - */ - - /** - * @brief Return the number of clusters in the vector - */ - size_t size() const { return m_size; } - - uint8_t cluster_size_x() const { return ClusterSizeX; } - - uint8_t cluster_size_y() const { return ClusterSizeY; } - - /** - * @brief Return the capacity of the buffer in number of clusters. This is - * the number of clusters that can be stored in the current buffer without - * reallocation. - */ - size_t capacity() const { return m_capacity; } - - /** - * @brief Return the size in bytes of a single cluster - */ - size_t item_size() const { - return 2 * sizeof(CoordType) + ClusterSizeX * ClusterSizeY * sizeof(T); - } - - /** - * @brief Return the offset in bytes for the i-th cluster - */ - size_t element_offset(size_t i) const { return item_size() * i; } - - /** - * @brief Return a pointer to the i-th cluster - */ - std::byte *element_ptr(size_t i) { return m_data + element_offset(i); } - - /** - * @brief Return a pointer to the i-th cluster - */ - const std::byte *element_ptr(size_t i) const { - return m_data + element_offset(i); - } - - std::byte *data() { return m_data; } - std::byte const *data() const { return m_data; } - - /** - * @brief Return a reference to the i-th cluster casted to type V - * @tparam V type of the cluster - */ - ClusterType &at(size_t i) { - return *reinterpret_cast(element_ptr(i)); - } - - const ClusterType &at(size_t i) const { - return *reinterpret_cast(element_ptr(i)); - } - - template const V &at(size_t i) const { - return *reinterpret_cast(element_ptr(i)); - } - - const std::string_view fmt_base() const { - // TODO! how do we match on coord_t? - return m_fmt_base; - } - - /** - * @brief Return the frame number of the clusters. 0 is used to indicate - * that the clusters come from many frames - */ - uint64_t frame_number() const { return m_frame_number; } - - void set_frame_number(uint64_t frame_number) { - m_frame_number = frame_number; - } - - /** - * @brief Resize the vector to contain new_size clusters. If new_size is - * greater than the current capacity, a new buffer is allocated. If the size - * is smaller no memory is freed, size is just updated. - * @param new_size new size of the vector - * @warning The additional clusters are not initialized - */ - void resize(size_t new_size) { - // TODO! Should we initialize the new clusters? - if (new_size > m_capacity) { - allocate_buffer(new_size); - } - m_size = new_size; - } - - private: - void allocate_buffer(size_t new_capacity) { - size_t num_bytes = item_size() * new_capacity; - std::byte *new_data = new std::byte[num_bytes]{}; - std::copy(m_data, m_data + item_size() * m_size, new_data); - delete[] m_data; - m_data = new_data; - m_capacity = new_capacity; - } -}; -#endif - /** * @brief ClusterVector is a container for clusters of various sizes. It * uses a contiguous memory buffer to store the clusters. It is templated on @@ -285,7 +35,7 @@ template > { std::vector> m_data{}; - uint64_t m_frame_number{0}; // TODO! Check frame number size and type + int32_t m_frame_number{0}; // TODO! Check frame number size and type public: using value_type = T; @@ -319,6 +69,33 @@ class ClusterVector> { return *this; } + /** + * @brief Sum the pixels in each cluster + * @return std::vector vector of sums for each cluster + */ + std::vector sum() { + std::vector sums(m_data.size()); + + for (size_t i = 0; i < m_data.size(); i++) { + sums[i] = at(i).sum(); + } + return sums; + } + + /** + * @brief Sum the pixels in the 2x2 subcluster with the biggest pixel sum in + * each cluster + * @return std::vector vector of sums for each cluster + */ //TODO if underlying container is a vector use std::for_each + std::vector sum_2x2() { + std::vector sums_2x2(m_data.size()); + + for (size_t i = 0; i < m_data.size(); i++) { + sums_2x2[i] = at(i).max_sum_2x2().first; + } + return sums_2x2; + } + /** * @brief Reserve space for at least capacity clusters * @param capacity number of clusters to reserve space for @@ -361,7 +138,8 @@ class ClusterVector> { * @brief Return the size in bytes of a single cluster */ size_t item_size() const { - return 2 * sizeof(CoordType) + ClusterSizeX * ClusterSizeY * sizeof(T); + return sizeof(ClusterType); // 2 * sizeof(CoordType) + ClusterSizeX * + // ClusterSizeY * sizeof(T); } ClusterType *data() { return m_data.data(); } @@ -379,9 +157,9 @@ class ClusterVector> { * @brief Return the frame number of the clusters. 0 is used to indicate * that the clusters come from many frames */ - uint64_t frame_number() const { return m_frame_number; } + int32_t frame_number() const { return m_frame_number; } - void set_frame_number(uint64_t frame_number) { + void set_frame_number(int32_t frame_number) { m_frame_number = frame_number; } diff --git a/python/src/cluster.hpp b/python/src/cluster.hpp index 16cda5c..d025050 100644 --- a/python/src/cluster.hpp +++ b/python/src/cluster.hpp @@ -66,6 +66,7 @@ void define_cluster(py::module &m, const std::string &typestr) { + template void define_cluster_finder_mt_bindings(py::module &m, diff --git a/src/Cluster.test.cpp b/src/Cluster.test.cpp index e502012..879a5e7 100644 --- a/src/Cluster.test.cpp +++ b/src/Cluster.test.cpp @@ -26,3 +26,9 @@ TEST_CASE("Correct Instantiation of Cluster and ClusterVector", CHECK(not is_cluster_v); CHECK(is_cluster_v>); } + +TEST_CASE("Test sum of Cluster", "[.cluster]") { + Cluster cluster{0, 0, {1, 2, 3, 4}}; + + CHECK(cluster.sum() == 10); +} \ No newline at end of file diff --git a/src/ClusterFile.test.cpp b/src/ClusterFile.test.cpp index 1ee54e7..024bed4 100644 --- a/src/ClusterFile.test.cpp +++ b/src/ClusterFile.test.cpp @@ -2,21 +2,29 @@ #include "test_config.hpp" #include "aare/defs.hpp" +#include #include #include using aare::Cluster; using aare::ClusterFile; +using aare::ClusterVector; -TEST_CASE("Read one frame from a a cluster file", "[.files]") { +TEST_CASE("Read one frame from a cluster file", "[.files]") { // We know that the frame has 97 clusters auto fpath = test_data_path() / "clust" / "single_frame_97_clustrers.clust"; REQUIRE(std::filesystem::exists(fpath)); ClusterFile> f(fpath); auto clusters = f.read_frame(); - REQUIRE(clusters.size() == 97); - REQUIRE(clusters.frame_number() == 135); + CHECK(clusters.size() == 97); + CHECK(clusters.frame_number() == 135); + CHECK(clusters.at(0).x == 1); + CHECK(clusters.at(0).y == 200); + int32_t expected_cluster_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; + CHECK(std::equal(std::begin(clusters.at(0).data), + std::end(clusters.at(0).data), + std::begin(expected_cluster_data))); } TEST_CASE("Read one frame using ROI", "[.files]") { @@ -43,6 +51,13 @@ TEST_CASE("Read one frame using ROI", "[.files]") { REQUIRE(c.y >= roi.ymin); REQUIRE(c.y <= roi.ymax); } + + CHECK(clusters.at(0).x == 1); + CHECK(clusters.at(0).y == 200); + int32_t expected_cluster_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; + CHECK(std::equal(std::begin(clusters.at(0).data), + std::end(clusters.at(0).data), + std::begin(expected_cluster_data))); } TEST_CASE("Read clusters from single frame file", "[.files]") { @@ -154,6 +169,12 @@ TEST_CASE("Read clusters from single frame file", "[.files]") { auto clusters = f.read_clusters(50); REQUIRE(clusters.size() == 50); REQUIRE(clusters.frame_number() == 135); + int32_t expected_cluster_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; + REQUIRE(clusters.at(0).x == 1); + REQUIRE(clusters.at(0).y == 200); + CHECK(std::equal(std::begin(clusters.at(0).data), + std::end(clusters.at(0).data), + std::begin(expected_cluster_data))); } SECTION("Read more clusters than available") { ClusterFile> f(fpath); @@ -161,24 +182,169 @@ TEST_CASE("Read clusters from single frame file", "[.files]") { auto clusters = f.read_clusters(100); REQUIRE(clusters.size() == 97); REQUIRE(clusters.frame_number() == 135); + int32_t expected_cluster_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; + REQUIRE(clusters.at(0).x == 1); + REQUIRE(clusters.at(0).y == 200); + CHECK(std::equal(std::begin(clusters.at(0).data), + std::end(clusters.at(0).data), + std::begin(expected_cluster_data))); } SECTION("Read all clusters") { ClusterFile> f(fpath); auto clusters = f.read_clusters(97); REQUIRE(clusters.size() == 97); REQUIRE(clusters.frame_number() == 135); - REQUIRE(clusters.at(0).x == 1); REQUIRE(clusters.at(0).y == 200); + int32_t expected_cluster_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; + CHECK(std::equal(std::begin(clusters.at(0).data), + std::end(clusters.at(0).data), + std::begin(expected_cluster_data))); } } -TEST_CASE("Read clusters", "[.files]") { - // beam_En700eV_-40deg_300V_10us_d0_f0_100.clust - auto fpath = test_data_path() / "clust" / - "beam_En700eV_-40deg_300V_10us_d0_f0_100.clust"; +TEST_CASE("Read clusters from single frame file with ROI", "[.files]") { + auto fpath = test_data_path() / "clust" / "single_frame_97_clustrers.clust"; REQUIRE(std::filesystem::exists(fpath)); ClusterFile> f(fpath); - auto clusters = f.read_clusters(500); + + aare::ROI roi; + roi.xmin = 0; + roi.xmax = 50; + roi.ymin = 200; + roi.ymax = 249; + f.set_roi(roi); + + auto clusters = f.read_clusters(10); + + CHECK(clusters.size() == 10); + CHECK(clusters.frame_number() == 135); + CHECK(clusters.at(0).x == 1); + CHECK(clusters.at(0).y == 200); + int32_t expected_cluster_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; + CHECK(std::equal(std::begin(clusters.at(0).data), + std::end(clusters.at(0).data), + std::begin(expected_cluster_data))); +} + +TEST_CASE("Read cluster from multiple frame file", "[.files]") { + + using ClusterType = Cluster; + + auto fpath = + test_data_path() / "clust" / "Two_frames_2x2double_test_clusters.clust"; + + REQUIRE(std::filesystem::exists(fpath)); + + // Two_frames_2x2double_test_clusters.clust + // frame number, num_clusters 0, 4 + //[10, 20], {0. ,0., 0., 0.} + //[11, 30], {1., 1., 1., 1.} + //[12, 40], {2., 2., 2., 2.} + //[13, 50], {3., 3., 3., 3.} + // 1,4 + //[10, 20], {4., 4., 4., 4.} + //[11, 30], {5., 5., 5., 5.} + //[12, 40], {6., 6., 6., 6.} + //[13, 50], {7., 7., 7., 7.} + + SECTION("Read clusters from both frames") { + ClusterFile f(fpath); + auto clusters = f.read_clusters(2); + REQUIRE(clusters.size() == 2); + REQUIRE(clusters.frame_number() == 0); + + auto clusters1 = f.read_clusters(3); + + REQUIRE(clusters1.size() == 3); + REQUIRE(clusters1.frame_number() == 1); + } + + SECTION("Read all clusters") { + ClusterFile f(fpath); + auto clusters = f.read_clusters(8); + REQUIRE(clusters.size() == 8); + REQUIRE(clusters.frame_number() == 1); + } + + SECTION("Read clusters from one frame") { + ClusterFile f(fpath); + auto clusters = f.read_clusters(2); + REQUIRE(clusters.size() == 2); + REQUIRE(clusters.frame_number() == 0); + + auto clusters1 = f.read_clusters(1); + + REQUIRE(clusters1.size() == 1); + REQUIRE(clusters1.frame_number() == 0); + } +} + +TEST_CASE("Write cluster with potential padding", "[.files][.ClusterFile]") { + + using ClusterType = Cluster; + + REQUIRE(std::filesystem::exists(test_data_path() / "clust")); + + auto fpath = test_data_path() / "clust" / "single_frame_2_clusters.clust"; + + ClusterFile file(fpath, 1000, "w"); + + ClusterVector clustervec(2); + int16_t coordinate = 5; + clustervec.push_back(ClusterType{ + coordinate, coordinate, {0., 0., 0., 0., 0., 0., 0., 0., 0.}}); + clustervec.push_back(ClusterType{ + coordinate, coordinate, {0., 0., 0., 0., 0., 0., 0., 0., 0.}}); + + file.write_frame(clustervec); + + file.close(); + + file.open("r"); + + auto read_cluster_vector = file.read_frame(); + + CHECK(read_cluster_vector.size() == 2); + CHECK(read_cluster_vector.frame_number() == 0); + + CHECK(read_cluster_vector.at(0).x == clustervec.at(0).x); + CHECK(read_cluster_vector.at(0).y == clustervec.at(0).y); + CHECK(std::equal(clustervec.at(0).data, clustervec.at(0).data + 9, + read_cluster_vector.at(0).data, [](double a, double b) { + return std::abs(a - b) < + std::numeric_limits::epsilon(); + })); + + CHECK(read_cluster_vector.at(1).x == clustervec.at(1).x); + CHECK(read_cluster_vector.at(1).y == clustervec.at(1).y); + CHECK(std::equal(clustervec.at(1).data, std::end(clustervec.at(1).data), + read_cluster_vector.at(1).data, [](double a, double b) { + return std::abs(a - b) < + std::numeric_limits::epsilon(); + })); +} + +TEST_CASE("Read frame and modify cluster data", "[.files][.ClusterFile]") { + auto fpath = test_data_path() / "clust" / "single_frame_97_clustrers.clust"; + REQUIRE(std::filesystem::exists(fpath)); + + ClusterFile> f(fpath); + + auto clusters = f.read_frame(); + CHECK(clusters.size() == 97); + CHECK(clusters.frame_number() == 135); + + int32_t expected_cluster_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; + clusters.push_back( + Cluster{0, 0, {0, 1, 2, 3, 4, 5, 6, 7, 8}}); + + CHECK(clusters.size() == 98); + CHECK(clusters.at(0).x == 1); + CHECK(clusters.at(0).y == 200); + + CHECK(std::equal(std::begin(clusters.at(0).data), + std::end(clusters.at(0).data), + std::begin(expected_cluster_data))); } diff --git a/src/ClusterVector.test.cpp b/src/ClusterVector.test.cpp index 5a5abe0..468a707 100644 --- a/src/ClusterVector.test.cpp +++ b/src/ClusterVector.test.cpp @@ -8,15 +8,14 @@ using aare::Cluster; using aare::ClusterVector; - -TEST_CASE("item_size return the size of the cluster stored"){ +TEST_CASE("item_size return the size of the cluster stored") { using C1 = Cluster; ClusterVector cv(4); CHECK(cv.item_size() == sizeof(C1)); - //Sanity check - //2*2*4 = 16 bytes of data for the cluster - // 2*2 = 4 bytes for the x and y coordinates + // Sanity check + // 2*2*4 = 16 bytes of data for the cluster + // 2*2 = 4 bytes for the x and y coordinates REQUIRE(cv.item_size() == 20); using C2 = Cluster; @@ -30,6 +29,18 @@ TEST_CASE("item_size return the size of the cluster stored"){ using C4 = Cluster; ClusterVector cv4(4); CHECK(cv4.item_size() == sizeof(C4)); + + using C5 = Cluster; + ClusterVector cv5(4); + CHECK(cv5.item_size() == sizeof(C5)); + + using C6 = Cluster; + ClusterVector cv6(4); + CHECK(cv6.item_size() == sizeof(C6)); + + using C7 = Cluster; + ClusterVector cv7(4); + CHECK(cv7.item_size() == sizeof(C7)); } TEST_CASE("ClusterVector 2x2 int32_t capacity 4, push back then read",