mirror of
https://github.com/slsdetectorgroup/aare.git
synced 2025-04-26 00:20: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
|
||||
)
|
||||
|
||||
|
||||
add_library(aare_core STATIC ${SourceFiles})
|
||||
target_include_directories(aare_core PUBLIC
|
||||
"$<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,
|
||||
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>>>
|
||||
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<ROI> m_roi; /*Region of interest, will be applied if set*/
|
||||
std::optional<NDArray<int32_t, 2>>
|
||||
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<ClusterType> read_clusters_with_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(
|
||||
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<ClusterType, Enable>::close() {
|
||||
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>
|
||||
void ClusterFile<ClusterType, Enable>::set_roi(ROI roi) {
|
||||
m_roi = roi;
|
||||
@ -197,10 +236,7 @@ void ClusterFile<ClusterType, Enable>::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<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.
|
||||
clusters.resize(nph_read);
|
||||
if (m_gain_map)
|
||||
@ -375,11 +411,13 @@ ClusterFile<ClusterType, Enable>::read_frame_without_cut() {
|
||||
ClusterVector<ClusterType> 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<size_t>(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;
|
||||
|
@ -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>>>
|
||||
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
|
||||
* 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>> {
|
||||
|
||||
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:
|
||||
using value_type = T;
|
||||
@ -319,6 +69,33 @@ class ClusterVector<Cluster<T, ClusterSizeX, ClusterSizeY, CoordType>> {
|
||||
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
|
||||
* @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
|
||||
*/
|
||||
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<Cluster<T, ClusterSizeX, ClusterSizeY, CoordType>> {
|
||||
* @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;
|
||||
}
|
||||
|
||||
|
@ -66,6 +66,7 @@ void define_cluster(py::module &m, const std::string &typestr) {
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename T, uint8_t ClusterSizeX, uint8_t ClusterSizeY,
|
||||
typename CoordType = uint16_t>
|
||||
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(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 "aare/defs.hpp"
|
||||
#include <algorithm>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <filesystem>
|
||||
|
||||
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<Cluster<int32_t, 3, 3>> 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<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);
|
||||
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<Cluster<int32_t, 3, 3>> 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<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,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<int32_t, 2, 2>;
|
||||
ClusterVector<C1> 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<int32_t, 3, 3>;
|
||||
@ -30,6 +29,18 @@ TEST_CASE("item_size return the size of the cluster stored"){
|
||||
using C4 = Cluster<char, 10, 5>;
|
||||
ClusterVector<C4> cv4(4);
|
||||
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",
|
||||
|
Loading…
x
Reference in New Issue
Block a user