mirror of
https://github.com/slsdetectorgroup/aare.git
synced 2025-04-28 17:30:02 +02:00
Merge branch 'api_cluster_vector' into testing_clusters
This commit is contained in:
commit
5c8a5099fd
@ -384,7 +384,6 @@ set(SourceFiles
|
|||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/utils/task.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/src/utils/task.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
add_library(aare_core STATIC ${SourceFiles})
|
add_library(aare_core STATIC ${SourceFiles})
|
||||||
target_include_directories(aare_core PUBLIC
|
target_include_directories(aare_core PUBLIC
|
||||||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
|
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
|
||||||
|
@ -33,7 +33,7 @@ template <typename T> 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 <typename ClusterType,
|
template <typename ClusterType,
|
||||||
typename = std::enable_if_t<is_cluster_v<ClusterType>>>
|
typename = std::enable_if_t<is_cluster_v<ClusterType>>>
|
||||||
|
@ -39,9 +39,10 @@ template <typename ClusterType,
|
|||||||
typename Enable = std::enable_if_t<is_cluster_v<ClusterType>>>
|
typename Enable = std::enable_if_t<is_cluster_v<ClusterType>>>
|
||||||
class ClusterFile {
|
class ClusterFile {
|
||||||
FILE *fp{};
|
FILE *fp{};
|
||||||
|
const std::string m_filename{};
|
||||||
uint32_t m_num_left{}; /*Number of photons left in frame*/
|
uint32_t m_num_left{}; /*Number of photons left in frame*/
|
||||||
size_t m_chunk_size{}; /*Number of clusters to read at a time*/
|
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<ROI> m_roi; /*Region of interest, will be applied if set*/
|
std::optional<ROI> m_roi; /*Region of interest, will be applied if set*/
|
||||||
std::optional<NDArray<int32_t, 2>>
|
std::optional<NDArray<int32_t, 2>>
|
||||||
m_noise_map; /*Noise map to cut photons, will be applied if set*/
|
m_noise_map; /*Noise map to cut photons, will be applied if set*/
|
||||||
@ -115,6 +116,11 @@ class ClusterFile {
|
|||||||
*/
|
*/
|
||||||
void close();
|
void close();
|
||||||
|
|
||||||
|
/** @brief Open the file in specific mode
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void open(const std::string &mode);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ClusterVector<ClusterType> read_clusters_with_cut(size_t n_clusters);
|
ClusterVector<ClusterType> read_clusters_with_cut(size_t n_clusters);
|
||||||
ClusterVector<ClusterType> read_clusters_without_cut(size_t n_clusters);
|
ClusterVector<ClusterType> read_clusters_without_cut(size_t n_clusters);
|
||||||
@ -128,25 +134,25 @@ template <typename ClusterType, typename Enable>
|
|||||||
ClusterFile<ClusterType, Enable>::ClusterFile(
|
ClusterFile<ClusterType, Enable>::ClusterFile(
|
||||||
const std::filesystem::path &fname, size_t chunk_size,
|
const std::filesystem::path &fname, size_t chunk_size,
|
||||||
const std::string &mode)
|
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") {
|
if (mode == "r") {
|
||||||
fp = fopen(fname.c_str(), "rb");
|
fp = fopen(m_filename.c_str(), "rb");
|
||||||
if (!fp) {
|
if (!fp) {
|
||||||
throw std::runtime_error("Could not open file for reading: " +
|
throw std::runtime_error("Could not open file for reading: " +
|
||||||
fname.string());
|
m_filename);
|
||||||
}
|
}
|
||||||
} else if (mode == "w") {
|
} else if (mode == "w") {
|
||||||
fp = fopen(fname.c_str(), "wb");
|
fp = fopen(m_filename.c_str(), "wb");
|
||||||
if (!fp) {
|
if (!fp) {
|
||||||
throw std::runtime_error("Could not open file for writing: " +
|
throw std::runtime_error("Could not open file for writing: " +
|
||||||
fname.string());
|
m_filename);
|
||||||
}
|
}
|
||||||
} else if (mode == "a") {
|
} else if (mode == "a") {
|
||||||
fp = fopen(fname.c_str(), "ab");
|
fp = fopen(m_filename.c_str(), "ab");
|
||||||
if (!fp) {
|
if (!fp) {
|
||||||
throw std::runtime_error("Could not open file for appending: " +
|
throw std::runtime_error("Could not open file for appending: " +
|
||||||
fname.string());
|
m_filename);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw std::runtime_error("Unsupported mode: " + mode);
|
throw std::runtime_error("Unsupported mode: " + mode);
|
||||||
@ -165,6 +171,39 @@ void ClusterFile<ClusterType, Enable>::close() {
|
|||||||
fp = nullptr;
|
fp = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename ClusterType, typename Enable>
|
||||||
|
void ClusterFile<ClusterType, Enable>::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 <typename ClusterType, typename Enable>
|
template <typename ClusterType, typename Enable>
|
||||||
void ClusterFile<ClusterType, Enable>::set_roi(ROI roi) {
|
void ClusterFile<ClusterType, Enable>::set_roi(ROI roi) {
|
||||||
m_roi = roi;
|
m_roi = roi;
|
||||||
@ -197,10 +236,7 @@ void ClusterFile<ClusterType, Enable>::write_frame(
|
|||||||
if (m_mode != "w" && m_mode != "a") {
|
if (m_mode != "w" && m_mode != "a") {
|
||||||
throw std::runtime_error("File not opened for writing");
|
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();
|
int32_t frame_number = clusters.frame_number();
|
||||||
fwrite(&frame_number, sizeof(frame_number), 1, fp);
|
fwrite(&frame_number, sizeof(frame_number), 1, fp);
|
||||||
uint32_t n_clusters = clusters.size();
|
uint32_t n_clusters = clusters.size();
|
||||||
@ -270,7 +306,7 @@ ClusterFile<ClusterType, Enable>::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.
|
// No new allocation, only change bounds.
|
||||||
clusters.resize(nph_read);
|
clusters.resize(nph_read);
|
||||||
if (m_gain_map)
|
if (m_gain_map)
|
||||||
@ -375,11 +411,13 @@ ClusterFile<ClusterType, Enable>::read_frame_without_cut() {
|
|||||||
ClusterVector<ClusterType> clusters(n_clusters);
|
ClusterVector<ClusterType> clusters(n_clusters);
|
||||||
clusters.set_frame_number(frame_number);
|
clusters.set_frame_number(frame_number);
|
||||||
|
|
||||||
|
clusters.resize(n_clusters);
|
||||||
|
|
||||||
if (fread(clusters.data(), clusters.item_size(), n_clusters, fp) !=
|
if (fread(clusters.data(), clusters.item_size(), n_clusters, fp) !=
|
||||||
static_cast<size_t>(n_clusters)) {
|
static_cast<size_t>(n_clusters)) {
|
||||||
throw std::runtime_error(LOCATION + "Could not read clusters");
|
throw std::runtime_error(LOCATION + "Could not read clusters");
|
||||||
}
|
}
|
||||||
clusters.resize(n_clusters);
|
|
||||||
if (m_gain_map)
|
if (m_gain_map)
|
||||||
m_gain_map->apply_gain_map(clusters);
|
m_gain_map->apply_gain_map(clusters);
|
||||||
return clusters;
|
return clusters;
|
||||||
|
@ -1,154 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "aare/core/defs.hpp"
|
|
||||||
#include <filesystem>
|
|
||||||
#include <fmt/format.h>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
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<int32_t, 9> 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<ClusterV2> read() {
|
|
||||||
check_open();
|
|
||||||
|
|
||||||
ClusterHeader header;
|
|
||||||
fread(&header, sizeof(ClusterHeader), 1, fp);
|
|
||||||
std::vector<ClusterV2_> clusters_(header.n_clusters);
|
|
||||||
fread(clusters_.data(), sizeof(ClusterV2_), header.n_clusters, fp);
|
|
||||||
std::vector<ClusterV2> 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<std::vector<ClusterV2>> read(int n_frames) {
|
|
||||||
std::vector<std::vector<ClusterV2>> clusters;
|
|
||||||
for (int i = 0; i < n_frames; i++) {
|
|
||||||
clusters.push_back(read());
|
|
||||||
}
|
|
||||||
return clusters;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t write(std::vector<ClusterV2> 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<std::vector<ClusterV2>> 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
|
|
@ -18,256 +18,6 @@ template <typename ClusterType,
|
|||||||
typename = std::enable_if_t<is_cluster_v<ClusterType>>>
|
typename = std::enable_if_t<is_cluster_v<ClusterType>>>
|
||||||
class ClusterVector; // Forward declaration
|
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 <typename T, uint8_t ClusterSizeX, uint8_t ClusterSizeY,
|
|
||||||
typename CoordType>
|
|
||||||
class ClusterVector<Cluster<T, ClusterSizeX, ClusterSizeY, CoordType>> {
|
|
||||||
|
|
||||||
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<T, ClusterSizeX, ClusterSizeY, CoordType>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @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<CoordType *>(ptr) = cluster.x;
|
|
||||||
ptr += sizeof(CoordType);
|
|
||||||
*reinterpret_cast<CoordType *>(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<T> vector of sums for each cluster
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
std::vector<T> sum() {
|
|
||||||
std::vector<T> 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<T *>(ptr),
|
|
||||||
reinterpret_cast<T *>(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<T> vector of sums for each cluster
|
|
||||||
*/ //TODO if underlying container is a vector use std::for_each
|
|
||||||
/*
|
|
||||||
std::vector<T> sum_2x2() {
|
|
||||||
std::vector<T> 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<ClusterType *>(element_ptr(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
const ClusterType &at(size_t i) const {
|
|
||||||
return *reinterpret_cast<const ClusterType *>(element_ptr(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename V> const V &at(size_t i) const {
|
|
||||||
return *reinterpret_cast<const V *>(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
|
* @brief ClusterVector is a container for clusters of various sizes. It
|
||||||
* uses a contiguous memory buffer to store the clusters. It is templated on
|
* uses a contiguous memory buffer to store the clusters. It is templated on
|
||||||
@ -285,7 +35,7 @@ template <typename T, uint8_t ClusterSizeX, uint8_t ClusterSizeY,
|
|||||||
class ClusterVector<Cluster<T, ClusterSizeX, ClusterSizeY, CoordType>> {
|
class ClusterVector<Cluster<T, ClusterSizeX, ClusterSizeY, CoordType>> {
|
||||||
|
|
||||||
std::vector<Cluster<T, ClusterSizeX, ClusterSizeY, CoordType>> m_data{};
|
std::vector<Cluster<T, ClusterSizeX, ClusterSizeY, CoordType>> 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:
|
public:
|
||||||
using value_type = T;
|
using value_type = T;
|
||||||
@ -319,6 +69,33 @@ class ClusterVector<Cluster<T, ClusterSizeX, ClusterSizeY, CoordType>> {
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sum the pixels in each cluster
|
||||||
|
* @return std::vector<T> vector of sums for each cluster
|
||||||
|
*/
|
||||||
|
std::vector<T> sum() {
|
||||||
|
std::vector<T> 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<T> vector of sums for each cluster
|
||||||
|
*/ //TODO if underlying container is a vector use std::for_each
|
||||||
|
std::vector<T> sum_2x2() {
|
||||||
|
std::vector<T> 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
|
* @brief Reserve space for at least capacity clusters
|
||||||
* @param capacity number of clusters to reserve space for
|
* @param capacity number of clusters to reserve space for
|
||||||
@ -361,7 +138,8 @@ class ClusterVector<Cluster<T, ClusterSizeX, ClusterSizeY, CoordType>> {
|
|||||||
* @brief Return the size in bytes of a single cluster
|
* @brief Return the size in bytes of a single cluster
|
||||||
*/
|
*/
|
||||||
size_t item_size() const {
|
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(); }
|
ClusterType *data() { return m_data.data(); }
|
||||||
@ -379,9 +157,9 @@ class ClusterVector<Cluster<T, ClusterSizeX, ClusterSizeY, CoordType>> {
|
|||||||
* @brief Return the frame number of the clusters. 0 is used to indicate
|
* @brief Return the frame number of the clusters. 0 is used to indicate
|
||||||
* that the clusters come from many frames
|
* 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;
|
m_frame_number = frame_number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,6 +66,7 @@ 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,
|
||||||
|
@ -26,3 +26,9 @@ TEST_CASE("Correct Instantiation of Cluster and ClusterVector",
|
|||||||
CHECK(not is_cluster_v<int>);
|
CHECK(not is_cluster_v<int>);
|
||||||
CHECK(is_cluster_v<Cluster<int, 3, 3>>);
|
CHECK(is_cluster_v<Cluster<int, 3, 3>>);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Test sum of Cluster", "[.cluster]") {
|
||||||
|
Cluster<int, 2, 2> cluster{0, 0, {1, 2, 3, 4}};
|
||||||
|
|
||||||
|
CHECK(cluster.sum() == 10);
|
||||||
|
}
|
@ -2,21 +2,29 @@
|
|||||||
#include "test_config.hpp"
|
#include "test_config.hpp"
|
||||||
|
|
||||||
#include "aare/defs.hpp"
|
#include "aare/defs.hpp"
|
||||||
|
#include <algorithm>
|
||||||
#include <catch2/catch_test_macros.hpp>
|
#include <catch2/catch_test_macros.hpp>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
|
||||||
using aare::Cluster;
|
using aare::Cluster;
|
||||||
using aare::ClusterFile;
|
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
|
// We know that the frame has 97 clusters
|
||||||
auto fpath = test_data_path() / "clust" / "single_frame_97_clustrers.clust";
|
auto fpath = test_data_path() / "clust" / "single_frame_97_clustrers.clust";
|
||||||
REQUIRE(std::filesystem::exists(fpath));
|
REQUIRE(std::filesystem::exists(fpath));
|
||||||
|
|
||||||
ClusterFile<Cluster<int32_t, 3, 3>> f(fpath);
|
ClusterFile<Cluster<int32_t, 3, 3>> f(fpath);
|
||||||
auto clusters = f.read_frame();
|
auto clusters = f.read_frame();
|
||||||
REQUIRE(clusters.size() == 97);
|
CHECK(clusters.size() == 97);
|
||||||
REQUIRE(clusters.frame_number() == 135);
|
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]") {
|
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.ymin);
|
||||||
REQUIRE(c.y <= roi.ymax);
|
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]") {
|
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);
|
auto clusters = f.read_clusters(50);
|
||||||
REQUIRE(clusters.size() == 50);
|
REQUIRE(clusters.size() == 50);
|
||||||
REQUIRE(clusters.frame_number() == 135);
|
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") {
|
SECTION("Read more clusters than available") {
|
||||||
ClusterFile<Cluster<int32_t, 3, 3>> f(fpath);
|
ClusterFile<Cluster<int32_t, 3, 3>> f(fpath);
|
||||||
@ -161,24 +182,169 @@ TEST_CASE("Read clusters from single frame file", "[.files]") {
|
|||||||
auto clusters = f.read_clusters(100);
|
auto clusters = f.read_clusters(100);
|
||||||
REQUIRE(clusters.size() == 97);
|
REQUIRE(clusters.size() == 97);
|
||||||
REQUIRE(clusters.frame_number() == 135);
|
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") {
|
SECTION("Read all clusters") {
|
||||||
ClusterFile<Cluster<int32_t, 3, 3>> f(fpath);
|
ClusterFile<Cluster<int32_t, 3, 3>> f(fpath);
|
||||||
auto clusters = f.read_clusters(97);
|
auto clusters = f.read_clusters(97);
|
||||||
REQUIRE(clusters.size() == 97);
|
REQUIRE(clusters.size() == 97);
|
||||||
REQUIRE(clusters.frame_number() == 135);
|
REQUIRE(clusters.frame_number() == 135);
|
||||||
|
|
||||||
REQUIRE(clusters.at(0).x == 1);
|
REQUIRE(clusters.at(0).x == 1);
|
||||||
REQUIRE(clusters.at(0).y == 200);
|
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]") {
|
TEST_CASE("Read clusters from single frame file with ROI", "[.files]") {
|
||||||
// beam_En700eV_-40deg_300V_10us_d0_f0_100.clust
|
auto fpath = test_data_path() / "clust" / "single_frame_97_clustrers.clust";
|
||||||
auto fpath = test_data_path() / "clust" /
|
|
||||||
"beam_En700eV_-40deg_300V_10us_d0_f0_100.clust";
|
|
||||||
REQUIRE(std::filesystem::exists(fpath));
|
REQUIRE(std::filesystem::exists(fpath));
|
||||||
|
|
||||||
ClusterFile<Cluster<int32_t, 3, 3>> f(fpath);
|
ClusterFile<Cluster<int32_t, 3, 3>> 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<double, 2, 2>;
|
||||||
|
|
||||||
|
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<ClusterType> 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<ClusterType> f(fpath);
|
||||||
|
auto clusters = f.read_clusters(8);
|
||||||
|
REQUIRE(clusters.size() == 8);
|
||||||
|
REQUIRE(clusters.frame_number() == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Read clusters from one frame") {
|
||||||
|
ClusterFile<ClusterType> 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<double, 3, 3>;
|
||||||
|
|
||||||
|
REQUIRE(std::filesystem::exists(test_data_path() / "clust"));
|
||||||
|
|
||||||
|
auto fpath = test_data_path() / "clust" / "single_frame_2_clusters.clust";
|
||||||
|
|
||||||
|
ClusterFile<ClusterType> file(fpath, 1000, "w");
|
||||||
|
|
||||||
|
ClusterVector<ClusterType> 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<double>::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<double>::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<Cluster<int32_t, 3, 3>> 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<int32_t, 3, 3>{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)));
|
||||||
}
|
}
|
||||||
|
@ -8,14 +8,13 @@
|
|||||||
using aare::Cluster;
|
using aare::Cluster;
|
||||||
using aare::ClusterVector;
|
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<int32_t, 2, 2>;
|
using C1 = Cluster<int32_t, 2, 2>;
|
||||||
ClusterVector<C1> cv(4);
|
ClusterVector<C1> cv(4);
|
||||||
CHECK(cv.item_size() == sizeof(C1));
|
CHECK(cv.item_size() == sizeof(C1));
|
||||||
|
|
||||||
//Sanity check
|
// Sanity check
|
||||||
//2*2*4 = 16 bytes of data for the cluster
|
// 2*2*4 = 16 bytes of data for the cluster
|
||||||
// 2*2 = 4 bytes for the x and y coordinates
|
// 2*2 = 4 bytes for the x and y coordinates
|
||||||
REQUIRE(cv.item_size() == 20);
|
REQUIRE(cv.item_size() == 20);
|
||||||
|
|
||||||
@ -30,6 +29,18 @@ TEST_CASE("item_size return the size of the cluster stored"){
|
|||||||
using C4 = Cluster<char, 10, 5>;
|
using C4 = Cluster<char, 10, 5>;
|
||||||
ClusterVector<C4> cv4(4);
|
ClusterVector<C4> cv4(4);
|
||||||
CHECK(cv4.item_size() == sizeof(C4));
|
CHECK(cv4.item_size() == sizeof(C4));
|
||||||
|
|
||||||
|
using C5 = Cluster<int32_t, 2, 3>;
|
||||||
|
ClusterVector<C5> cv5(4);
|
||||||
|
CHECK(cv5.item_size() == sizeof(C5));
|
||||||
|
|
||||||
|
using C6 = Cluster<double, 5, 5>;
|
||||||
|
ClusterVector<C6> cv6(4);
|
||||||
|
CHECK(cv6.item_size() == sizeof(C6));
|
||||||
|
|
||||||
|
using C7 = Cluster<double, 3, 3>;
|
||||||
|
ClusterVector<C7> cv7(4);
|
||||||
|
CHECK(cv7.item_size() == sizeof(C7));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("ClusterVector 2x2 int32_t capacity 4, push back then read",
|
TEST_CASE("ClusterVector 2x2 int32_t capacity 4, push back then read",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user