Cluster reading, expression templates (#99)

Co-authored-by: froejdh_e <erik.frojdh@psi.ch>
This commit is contained in:
Erik Fröjdh 2024-11-15 16:32:36 +01:00 committed by GitHub
parent fbaf9dce89
commit 95ff77c8fc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
28 changed files with 861 additions and 218 deletions

View File

@ -29,6 +29,7 @@ set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
# General options # General options
option(AARE_PYTHON_BINDINGS "Build python bindings" ON) option(AARE_PYTHON_BINDINGS "Build python bindings" ON)
option(AARE_TESTS "Build tests" OFF) option(AARE_TESTS "Build tests" OFF)
option(AARE_BENCHMARKS "Build benchmarks" OFF)
option(AARE_EXAMPLES "Build examples" OFF) option(AARE_EXAMPLES "Build examples" OFF)
option(AARE_IN_GITHUB_ACTIONS "Running in Github Actions" OFF) option(AARE_IN_GITHUB_ACTIONS "Running in Github Actions" OFF)
option(AARE_DOCS "Build documentation" OFF) option(AARE_DOCS "Build documentation" OFF)
@ -63,6 +64,10 @@ if(AARE_CUSTOM_ASSERT)
add_compile_definitions(AARE_CUSTOM_ASSERT) add_compile_definitions(AARE_CUSTOM_ASSERT)
endif() endif()
if(AARE_BENCHMARKS)
add_subdirectory(benchmarks)
endif()
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
@ -242,7 +247,9 @@ endif()
###------------------------------------------------------------------------------------------ ###------------------------------------------------------------------------------------------
set(PUBLICHEADERS set(PUBLICHEADERS
include/aare/ArrayExpr.hpp
include/aare/ClusterFinder.hpp include/aare/ClusterFinder.hpp
include/aare/ClusterFile.hpp
include/aare/CtbRawFile.hpp include/aare/CtbRawFile.hpp
include/aare/defs.hpp include/aare/defs.hpp
include/aare/Dtype.hpp include/aare/Dtype.hpp
@ -265,6 +272,7 @@ set(PUBLICHEADERS
set(SourceFiles set(SourceFiles
${CMAKE_CURRENT_SOURCE_DIR}/src/CtbRawFile.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/CtbRawFile.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/ClusterFile.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/defs.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/defs.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/Dtype.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Dtype.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/Frame.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Frame.cpp

11
benchmarks/CMakeLists.txt Normal file
View File

@ -0,0 +1,11 @@
find_package(benchmark REQUIRED)
add_executable(ndarray_benchmark ndarray_benchmark.cpp)
target_link_libraries(ndarray_benchmark benchmark::benchmark aare_core aare_compiler_flags)
# target_link_libraries(tests PRIVATE aare_core aare_compiler_flags)
set_target_properties(ndarray_benchmark PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}
# OUTPUT_NAME run_tests
)

View File

@ -0,0 +1,136 @@
#include <benchmark/benchmark.h>
#include "aare/NDArray.hpp"
using aare::NDArray;
constexpr ssize_t size = 1024;
class TwoArrays : public benchmark::Fixture {
public:
NDArray<int,2> a{{size,size},0};
NDArray<int,2> b{{size,size},0};
void SetUp(::benchmark::State& state) {
for(uint32_t i = 0; i < size; i++){
for(uint32_t j = 0; j < size; j++){
a(i, j)= i*j+1;
b(i, j)= i*j+1;
}
}
}
// void TearDown(::benchmark::State& state) {
// }
};
BENCHMARK_F(TwoArrays, AddWithOperator)(benchmark::State& st) {
for (auto _ : st) {
// This code gets timed
NDArray<int,2> res = a+b;
benchmark::DoNotOptimize(res);
}
}
BENCHMARK_F(TwoArrays, AddWithIndex)(benchmark::State& st) {
for (auto _ : st) {
// This code gets timed
NDArray<int,2> res(a.shape());
for (uint32_t i = 0; i < a.size(); i++) {
res(i) = a(i) + b(i);
}
benchmark::DoNotOptimize(res);
}
}
BENCHMARK_F(TwoArrays, SubtractWithOperator)(benchmark::State& st) {
for (auto _ : st) {
// This code gets timed
NDArray<int,2> res = a-b;
benchmark::DoNotOptimize(res);
}
}
BENCHMARK_F(TwoArrays, SubtractWithIndex)(benchmark::State& st) {
for (auto _ : st) {
// This code gets timed
NDArray<int,2> res(a.shape());
for (uint32_t i = 0; i < a.size(); i++) {
res(i) = a(i) - b(i);
}
benchmark::DoNotOptimize(res);
}
}
BENCHMARK_F(TwoArrays, MultiplyWithOperator)(benchmark::State& st) {
for (auto _ : st) {
// This code gets timed
NDArray<int,2> res = a*b;
benchmark::DoNotOptimize(res);
}
}
BENCHMARK_F(TwoArrays, MultiplyWithIndex)(benchmark::State& st) {
for (auto _ : st) {
// This code gets timed
NDArray<int,2> res(a.shape());
for (uint32_t i = 0; i < a.size(); i++) {
res(i) = a(i) * b(i);
}
benchmark::DoNotOptimize(res);
}
}
BENCHMARK_F(TwoArrays, DivideWithOperator)(benchmark::State& st) {
for (auto _ : st) {
// This code gets timed
NDArray<int,2> res = a/b;
benchmark::DoNotOptimize(res);
}
}
BENCHMARK_F(TwoArrays, DivideWithIndex)(benchmark::State& st) {
for (auto _ : st) {
// This code gets timed
NDArray<int,2> res(a.shape());
for (uint32_t i = 0; i < a.size(); i++) {
res(i) = a(i) / b(i);
}
benchmark::DoNotOptimize(res);
}
}
BENCHMARK_F(TwoArrays, FourAddWithOperator)(benchmark::State& st) {
for (auto _ : st) {
// This code gets timed
NDArray<int,2> res = a+b+a+b;
benchmark::DoNotOptimize(res);
}
}
BENCHMARK_F(TwoArrays, FourAddWithIndex)(benchmark::State& st) {
for (auto _ : st) {
// This code gets timed
NDArray<int,2> res(a.shape());
for (uint32_t i = 0; i < a.size(); i++) {
res(i) = a(i) + b(i) + a(i) + b(i);
}
benchmark::DoNotOptimize(res);
}
}
BENCHMARK_F(TwoArrays, MultiplyAddDivideWithOperator)(benchmark::State& st) {
for (auto _ : st) {
// This code gets timed
NDArray<int,2> res = a*a+b/a;
benchmark::DoNotOptimize(res);
}
}
BENCHMARK_F(TwoArrays, MultiplyAddDivideWithIndex)(benchmark::State& st) {
for (auto _ : st) {
// This code gets timed
NDArray<int,2> res(a.shape());
for (uint32_t i = 0; i < a.size(); i++) {
res(i) = a(i) * a(i) + b(i) / a(i);
}
benchmark::DoNotOptimize(res);
}
}
BENCHMARK_MAIN();

View File

@ -1,6 +1,6 @@
package: package:
name: aare name: aare
version: 2024.11.11.dev0 #TODO! how to not duplicate this? version: 2024.11.15.dev0 #TODO! how to not duplicate this?
source: source:

View File

@ -10,31 +10,36 @@ configure_file(${DOXYGEN_IN} ${DOXYGEN_OUT} @ONLY)
set(SPHINX_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/src) set(SPHINX_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/src)
set(SPHINX_BUILD ${CMAKE_CURRENT_BINARY_DIR}) set(SPHINX_BUILD ${CMAKE_CURRENT_BINARY_DIR})
set(SPHINX_SOURCE_FILES
src/index.rst file(GLOB SPHINX_SOURCE_FILES CONFIGURE_DEPENDS "src/*.rst")
src/Installation.rst # set(SPHINX_SOURCE_FILES
src/Requirements.rst # src/index.rst
src/NDArray.rst # src/Installation.rst
src/NDView.rst # src/Requirements.rst
src/File.rst # src/NDArray.rst
src/Frame.rst # src/NDView.rst
src/Dtype.rst # src/File.rst
src/ClusterFinder.rst # src/Frame.rst
src/Pedestal.rst # src/Dtype.rst
src/RawFile.rst # src/ClusterFinder.rst
src/RawSubFile.rst # src/ClusterFile.rst
src/RawMasterFile.rst # src/Pedestal.rst
src/VarClusterFinder.rst # src/RawFile.rst
src/pyVarClusterFinder.rst # src/RawSubFile.rst
src/pyFile.rst # src/RawMasterFile.rst
src/pyCtbRawFile.rst # src/VarClusterFinder.rst
src/pyRawFile.rst # src/pyVarClusterFinder.rst
src/pyRawMasterFile.rst # src/pyFile.rst
) # src/pyCtbRawFile.rst
# src/pyRawFile.rst
# src/pyRawMasterFile.rst
# )
foreach(filename ${SPHINX_SOURCE_FILES}) foreach(filename ${SPHINX_SOURCE_FILES})
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${filename} get_filename_component(fname ${filename} NAME)
"${SPHINX_BUILD}/${filename}") message(STATUS "Copying ${filename} to ${SPHINX_BUILD}/src/${fname}")
configure_file(${filename} "${SPHINX_BUILD}/src/${fname}")
endforeach(filename ${SPHINX_SOURCE_FILES}) endforeach(filename ${SPHINX_SOURCE_FILES})
configure_file( configure_file(

7
docs/src/ClusterFile.rst Normal file
View File

@ -0,0 +1,7 @@
ClusterFile
=============
.. doxygenclass:: aare::ClusterFile
:members:
:undoc-members:
:private-members:

View File

@ -14,27 +14,19 @@ AARE
Requirements Requirements
.. toctree:: .. toctree::
:caption: Python API :caption: Python API
:maxdepth: 1 :maxdepth: 1
pyFile pyFile
pyCtbRawFile pyCtbRawFile
pyClusterFile
pyRawFile pyRawFile
pyRawMasterFile pyRawMasterFile
pyVarClusterFinder pyVarClusterFinder
.. toctree::
:caption: Python API
:maxdepth: 1
pyFile
pyCtbRawFile
pyRawMasterFile
pyVarClusterFinder
.. toctree:: .. toctree::
:caption: C++ API :caption: C++ API
:maxdepth: 1 :maxdepth: 1
@ -45,6 +37,7 @@ AARE
File File
Dtype Dtype
ClusterFinder ClusterFinder
ClusterFile
Pedestal Pedestal
RawFile RawFile
RawSubFile RawSubFile

View File

@ -0,0 +1,11 @@
ClusterFile
============
.. py:currentmodule:: aare
.. autoclass:: ClusterFile
:members:
:undoc-members:
:show-inheritance:
:inherited-members:

View File

@ -0,0 +1,99 @@
#pragma once
#include <cstdint> //int64_t
#include <cstddef> //size_t
#include <array>
#include <cassert>
namespace aare {
template <typename E, int64_t Ndim> class ArrayExpr {
public:
static constexpr bool is_leaf = false;
auto operator[](size_t i) const { return static_cast<E const &>(*this)[i]; }
auto operator()(size_t i) const { return static_cast<E const &>(*this)[i]; }
auto size() const { return static_cast<E const &>(*this).size(); }
std::array<int64_t, Ndim> shape() const { return static_cast<E const &>(*this).shape(); }
};
template <typename A, typename B, int64_t Ndim>
class ArrayAdd : public ArrayExpr<ArrayAdd<A, B, Ndim>, Ndim> {
const A &arr1_;
const B &arr2_;
public:
ArrayAdd(const A &arr1, const B &arr2) : arr1_(arr1), arr2_(arr2) {
assert(arr1.size() == arr2.size());
}
auto operator[](int i) const { return arr1_[i] + arr2_[i]; }
size_t size() const { return arr1_.size(); }
std::array<int64_t, Ndim> shape() const { return arr1_.shape(); }
};
template <typename A, typename B, int64_t Ndim>
class ArraySub : public ArrayExpr<ArraySub<A, B, Ndim>, Ndim> {
const A &arr1_;
const B &arr2_;
public:
ArraySub(const A &arr1, const B &arr2) : arr1_(arr1), arr2_(arr2) {
assert(arr1.size() == arr2.size());
}
auto operator[](int i) const { return arr1_[i] - arr2_[i]; }
size_t size() const { return arr1_.size(); }
std::array<int64_t, Ndim> shape() const { return arr1_.shape(); }
};
template <typename A, typename B, int64_t Ndim>
class ArrayMul : public ArrayExpr<ArrayMul<A, B, Ndim>,Ndim> {
const A &arr1_;
const B &arr2_;
public:
ArrayMul(const A &arr1, const B &arr2) : arr1_(arr1), arr2_(arr2) {
assert(arr1.size() == arr2.size());
}
auto operator[](int i) const { return arr1_[i] * arr2_[i]; }
size_t size() const { return arr1_.size(); }
std::array<int64_t, Ndim> shape() const { return arr1_.shape(); }
};
template <typename A, typename B, int64_t Ndim>
class ArrayDiv : public ArrayExpr<ArrayDiv<A, B, Ndim>, Ndim> {
const A &arr1_;
const B &arr2_;
public:
ArrayDiv(const A &arr1, const B &arr2) : arr1_(arr1), arr2_(arr2) {
assert(arr1.size() == arr2.size());
}
auto operator[](int i) const { return arr1_[i] / arr2_[i]; }
size_t size() const { return arr1_.size(); }
std::array<int64_t, Ndim> shape() const { return arr1_.shape(); }
};
template <typename A, typename B, int64_t Ndim>
auto operator+(const ArrayExpr<A, Ndim> &arr1, const ArrayExpr<B, Ndim> &arr2) {
return ArrayAdd<ArrayExpr<A, Ndim>, ArrayExpr<B, Ndim>, Ndim>(arr1, arr2);
}
template <typename A, typename B, int64_t Ndim>
auto operator-(const ArrayExpr<A,Ndim> &arr1, const ArrayExpr<B, Ndim> &arr2) {
return ArraySub<ArrayExpr<A, Ndim>, ArrayExpr<B, Ndim>, Ndim>(arr1, arr2);
}
template <typename A, typename B, int64_t Ndim>
auto operator*(const ArrayExpr<A, Ndim> &arr1, const ArrayExpr<B, Ndim> &arr2) {
return ArrayMul<ArrayExpr<A, Ndim>, ArrayExpr<B, Ndim>, Ndim>(arr1, arr2);
}
template <typename A, typename B, int64_t Ndim>
auto operator/(const ArrayExpr<A, Ndim> &arr1, const ArrayExpr<B, Ndim> &arr2) {
return ArrayDiv<ArrayExpr<A, Ndim>, ArrayExpr<B, Ndim>, Ndim>(arr1, arr2);
}
} // namespace aare

View File

@ -0,0 +1,65 @@
#include "aare/defs.hpp"
#include <filesystem>
#include <fstream>
namespace aare {
struct Cluster {
int16_t x;
int16_t y;
int32_t data[9];
};
typedef enum {
cBottomLeft = 0,
cBottomRight = 1,
cTopLeft = 2,
cTopRight = 3
} corner;
typedef enum {
pBottomLeft = 0,
pBottom = 1,
pBottomRight = 2,
pLeft = 3,
pCenter = 4,
pRight = 5,
pTopLeft = 6,
pTop = 7,
pTopRight = 8
} pixel;
struct ClusterAnalysis {
uint32_t c;
int32_t tot;
double etax;
double etay;
};
class ClusterFile {
FILE *fp{};
uint32_t m_num_left{};
size_t m_chunk_size{};
public:
ClusterFile(const std::filesystem::path &fname, size_t chunk_size = 1000);
std::vector<Cluster> read_clusters(size_t n_clusters);
std::vector<Cluster> read_frame(int32_t &out_fnum);
std::vector<Cluster>
read_cluster_with_cut(size_t n_clusters, double *noise_map, int nx, int ny);
int analyze_data(int32_t *data, int32_t *t2, int32_t *t3, char *quad,
double *eta2x, double *eta2y, double *eta3x, double *eta3y);
int analyze_cluster(Cluster cl, int32_t *t2, int32_t *t3, char *quad,
double *eta2x, double *eta2y, double *eta3x,
double *eta3y);
size_t chunk_size() const { return m_chunk_size; }
};
} // namespace aare

View File

@ -53,7 +53,7 @@ class ClusterFinder {
return m_pedestal.mean(); return m_pedestal.mean();
} }
std::vector<Cluster> std::vector<DynamicCluster>
find_clusters_without_threshold(NDView<FRAME_TYPE, 2> frame, find_clusters_without_threshold(NDView<FRAME_TYPE, 2> frame,
// Pedestal<PEDESTAL_TYPE> &pedestal, // Pedestal<PEDESTAL_TYPE> &pedestal,
bool late_update = false) { bool late_update = false) {
@ -64,7 +64,7 @@ class ClusterFinder {
}; };
std::vector<pedestal_update> pedestal_updates; std::vector<pedestal_update> pedestal_updates;
std::vector<Cluster> clusters; std::vector<DynamicCluster> clusters;
std::vector<std::vector<eventType>> eventMask; std::vector<std::vector<eventType>> eventMask;
for (int i = 0; i < frame.shape(0); i++) { for (int i = 0; i < frame.shape(0); i++) {
eventMask.push_back(std::vector<eventType>(frame.shape(1))); eventMask.push_back(std::vector<eventType>(frame.shape(1)));
@ -115,7 +115,7 @@ class ClusterFinder {
if (eventMask[iy][ix] == PHOTON && if (eventMask[iy][ix] == PHOTON &&
(frame(iy, ix) - m_pedestal.mean(iy, ix)) >= max) { (frame(iy, ix) - m_pedestal.mean(iy, ix)) >= max) {
eventMask[iy][ix] = PHOTON_MAX; eventMask[iy][ix] = PHOTON_MAX;
Cluster cluster(m_cluster_sizeX, m_cluster_sizeY, DynamicCluster cluster(m_cluster_sizeX, m_cluster_sizeY,
Dtype(typeid(PEDESTAL_TYPE))); Dtype(typeid(PEDESTAL_TYPE)));
cluster.x = ix; cluster.x = ix;
cluster.y = iy; cluster.y = iy;
@ -149,11 +149,11 @@ class ClusterFinder {
} }
// template <typename FRAME_TYPE, typename PEDESTAL_TYPE> // template <typename FRAME_TYPE, typename PEDESTAL_TYPE>
std::vector<Cluster> std::vector<DynamicCluster>
find_clusters_with_threshold(NDView<FRAME_TYPE, 2> frame, find_clusters_with_threshold(NDView<FRAME_TYPE, 2> frame,
Pedestal<PEDESTAL_TYPE> &pedestal) { Pedestal<PEDESTAL_TYPE> &pedestal) {
assert(m_threshold > 0); assert(m_threshold > 0);
std::vector<Cluster> clusters; std::vector<DynamicCluster> clusters;
std::vector<std::vector<eventType>> eventMask; std::vector<std::vector<eventType>> eventMask;
for (int i = 0; i < frame.shape(0); i++) { for (int i = 0; i < frame.shape(0); i++) {
eventMask.push_back(std::vector<eventType>(frame.shape(1))); eventMask.push_back(std::vector<eventType>(frame.shape(1)));
@ -230,7 +230,7 @@ class ClusterFinder {
if (eventMask[iy][ix] == PHOTON && if (eventMask[iy][ix] == PHOTON &&
frame(iy, ix) - pedestal.mean(iy, ix) >= max) { frame(iy, ix) - pedestal.mean(iy, ix) >= max) {
eventMask[iy][ix] = PHOTON_MAX; eventMask[iy][ix] = PHOTON_MAX;
Cluster cluster(m_cluster_sizeX, m_cluster_sizeY, DynamicCluster cluster(m_cluster_sizeX, m_cluster_sizeY,
Dtype(typeid(FRAME_TYPE))); Dtype(typeid(FRAME_TYPE)));
cluster.x = ix; cluster.x = ix;
cluster.y = iy; cluster.y = iy;

View File

@ -7,6 +7,7 @@ memory.
TODO! Add expression templates for operators TODO! Add expression templates for operators
*/ */
#include "aare/ArrayExpr.hpp"
#include "aare/NDView.hpp" #include "aare/NDView.hpp"
#include <algorithm> #include <algorithm>
@ -20,7 +21,9 @@ TODO! Add expression templates for operators
namespace aare { namespace aare {
template <typename T, int64_t Ndim = 2> class NDArray {
template <typename T, int64_t Ndim = 2>
class NDArray : public ArrayExpr<NDArray<T, Ndim>, Ndim> {
std::array<int64_t, Ndim> shape_; std::array<int64_t, Ndim> shape_;
std::array<int64_t, Ndim> strides_; std::array<int64_t, Ndim> strides_;
size_t size_{}; size_t size_{};
@ -43,7 +46,8 @@ template <typename T, int64_t Ndim = 2> class NDArray {
: shape_(shape), strides_(c_strides<Ndim>(shape_)), : shape_(shape), strides_(c_strides<Ndim>(shape_)),
size_(std::accumulate(shape_.begin(), shape_.end(), 1, size_(std::accumulate(shape_.begin(), shape_.end(), 1,
std::multiplies<>())), std::multiplies<>())),
data_(new T[size_]) {}; data_(new T[size_]) {}
/** /**
* @brief Construct a new NDArray object with a shape and value. * @brief Construct a new NDArray object with a shape and value.
@ -69,8 +73,8 @@ template <typename T, int64_t Ndim = 2> class NDArray {
NDArray(NDArray &&other) noexcept NDArray(NDArray &&other) noexcept
: shape_(other.shape_), strides_(c_strides<Ndim>(shape_)), : shape_(other.shape_), strides_(c_strides<Ndim>(shape_)),
size_(other.size_), data_(other.data_) { size_(other.size_), data_(other.data_) {
other.reset(); // TODO! is this necessary?
other.reset();
} }
// Copy constructor // Copy constructor
@ -78,7 +82,14 @@ template <typename T, int64_t Ndim = 2> class NDArray {
: shape_(other.shape_), strides_(c_strides<Ndim>(shape_)), : shape_(other.shape_), strides_(c_strides<Ndim>(shape_)),
size_(other.size_), data_(new T[size_]) { size_(other.size_), data_(new T[size_]) {
std::copy(other.data_, other.data_ + size_, data_); std::copy(other.data_, other.data_ + size_, data_);
// fmt::print("NDArray(const NDArray &other)\n"); }
// Conversion operator from array expression to array
template <typename E>
NDArray(ArrayExpr<E, Ndim> &&expr) : NDArray(expr.shape()) {
for (int i = 0; i < size_; ++i) {
data_[i] = expr[i];
}
} }
~NDArray() { delete[] data_; } ~NDArray() { delete[] data_; }
@ -90,14 +101,10 @@ template <typename T, int64_t Ndim = 2> class NDArray {
NDArray &operator=(NDArray &&other) noexcept; // Move assign NDArray &operator=(NDArray &&other) noexcept; // Move assign
NDArray &operator=(const NDArray &other); // Copy assign NDArray &operator=(const NDArray &other); // Copy assign
NDArray operator+(const NDArray &other);
NDArray &operator+=(const NDArray &other); NDArray &operator+=(const NDArray &other);
NDArray operator-(const NDArray &other);
NDArray &operator-=(const NDArray &other); NDArray &operator-=(const NDArray &other);
NDArray operator*(const NDArray &other);
NDArray &operator*=(const NDArray &other); NDArray &operator*=(const NDArray &other);
NDArray operator/(const NDArray &other);
// NDArray& operator/=(const NDArray& other); // NDArray& operator/=(const NDArray& other);
template <typename V> NDArray &operator/=(const NDArray<V, Ndim> &other) { template <typename V> NDArray &operator/=(const NDArray<V, Ndim> &other) {
@ -151,12 +158,16 @@ template <typename T, int64_t Ndim = 2> class NDArray {
return data_[element_offset(strides_, index...)]; return data_[element_offset(strides_, index...)];
} }
// TODO! is int the right type for index?
T &operator()(int i) { return data_[i]; } T &operator()(int i) { return data_[i]; }
const T &operator()(int i) const { return data_[i]; } const T &operator()(int i) const { return data_[i]; }
T &operator[](int i) { return data_[i]; }
const T &operator[](int i) const { return data_[i]; }
T *data() { return data_; } T *data() { return data_; }
std::byte *buffer() { return reinterpret_cast<std::byte *>(data_); } std::byte *buffer() { return reinterpret_cast<std::byte *>(data_); }
uint64_t size() const { return size_; } size_t size() const { return size_; }
size_t total_bytes() const { return size_ * sizeof(T); } size_t total_bytes() const { return size_ * sizeof(T); }
std::array<int64_t, Ndim> shape() const noexcept { return shape_; } std::array<int64_t, Ndim> shape() const noexcept { return shape_; }
int64_t shape(int64_t i) const noexcept { return shape_[i]; } int64_t shape(int64_t i) const noexcept { return shape_[i]; }
@ -204,17 +215,11 @@ NDArray<T, Ndim>::operator=(NDArray<T, Ndim> &&other) noexcept {
return *this; return *this;
} }
template <typename T, int64_t Ndim>
NDArray<T, Ndim> NDArray<T, Ndim>::operator+(const NDArray &other) {
NDArray result(*this);
result += other;
return result;
}
template <typename T, int64_t Ndim> template <typename T, int64_t Ndim>
NDArray<T, Ndim> &NDArray<T, Ndim>::operator+=(const NDArray<T, Ndim> &other) { NDArray<T, Ndim> &NDArray<T, Ndim>::operator+=(const NDArray<T, Ndim> &other) {
// check shape // check shape
if (shape_ == other.shape_) { if (shape_ == other.shape_) {
for (uint32_t i = 0; i < size_; ++i) { for (size_t i = 0; i < size_; ++i) {
data_[i] += other.data_[i]; data_[i] += other.data_[i];
} }
return *this; return *this;
@ -222,13 +227,6 @@ NDArray<T, Ndim> &NDArray<T, Ndim>::operator+=(const NDArray<T, Ndim> &other) {
throw(std::runtime_error("Shape of ImageDatas must match")); throw(std::runtime_error("Shape of ImageDatas must match"));
} }
template <typename T, int64_t Ndim>
NDArray<T, Ndim> NDArray<T, Ndim>::operator-(const NDArray &other) {
NDArray result{*this};
result -= other;
return result;
}
template <typename T, int64_t Ndim> template <typename T, int64_t Ndim>
NDArray<T, Ndim> &NDArray<T, Ndim>::operator-=(const NDArray<T, Ndim> &other) { NDArray<T, Ndim> &NDArray<T, Ndim>::operator-=(const NDArray<T, Ndim> &other) {
// check shape // check shape
@ -240,12 +238,6 @@ NDArray<T, Ndim> &NDArray<T, Ndim>::operator-=(const NDArray<T, Ndim> &other) {
} }
throw(std::runtime_error("Shape of ImageDatas must match")); throw(std::runtime_error("Shape of ImageDatas must match"));
} }
template <typename T, int64_t Ndim>
NDArray<T, Ndim> NDArray<T, Ndim>::operator*(const NDArray &other) {
NDArray result = *this;
result *= other;
return result;
}
template <typename T, int64_t Ndim> template <typename T, int64_t Ndim>
NDArray<T, Ndim> &NDArray<T, Ndim>::operator*=(const NDArray<T, Ndim> &other) { NDArray<T, Ndim> &NDArray<T, Ndim>::operator*=(const NDArray<T, Ndim> &other) {
@ -259,13 +251,6 @@ NDArray<T, Ndim> &NDArray<T, Ndim>::operator*=(const NDArray<T, Ndim> &other) {
throw(std::runtime_error("Shape of ImageDatas must match")); throw(std::runtime_error("Shape of ImageDatas must match"));
} }
template <typename T, int64_t Ndim>
NDArray<T, Ndim> NDArray<T, Ndim>::operator/(const NDArray &other) {
NDArray result = *this;
result /= other;
return result;
}
template <typename T, int64_t Ndim> template <typename T, int64_t Ndim>
NDArray<T, Ndim> &NDArray<T, Ndim>::operator&=(const T &mask) { NDArray<T, Ndim> &NDArray<T, Ndim>::operator&=(const T &mask) {
for (auto it = begin(); it != end(); ++it) for (auto it = begin(); it != end(); ++it)
@ -276,7 +261,7 @@ NDArray<T, Ndim> &NDArray<T, Ndim>::operator&=(const T &mask) {
template <typename T, int64_t Ndim> template <typename T, int64_t Ndim>
NDArray<bool, Ndim> NDArray<T, Ndim>::operator>(const NDArray &other) { NDArray<bool, Ndim> NDArray<T, Ndim>::operator>(const NDArray &other) {
if (shape_ == other.shape_) { if (shape_ == other.shape_) {
NDArray<bool> result{shape_}; NDArray<bool, Ndim> result{shape_};
for (int i = 0; i < size_; ++i) { for (int i = 0; i < size_; ++i) {
result(i) = (data_[i] > other.data_[i]); result(i) = (data_[i] > other.data_[i]);
} }

View File

@ -1,4 +1,7 @@
#pragma once #pragma once
#include "aare/ArrayExpr.hpp"
#include <algorithm> #include <algorithm>
#include <array> #include <array>
#include <cassert> #include <cassert>
@ -45,7 +48,7 @@ template <int64_t Ndim> std::array<int64_t, Ndim> make_array(const std::vector<i
return arr; return arr;
} }
template <typename T, int64_t Ndim = 2> class NDView { template <typename T, int64_t Ndim = 2> class NDView : public ArrayExpr<NDView<T, Ndim>, Ndim> {
public: public:
NDView() = default; NDView() = default;
~NDView() = default; ~NDView() = default;
@ -68,7 +71,7 @@ template <typename T, int64_t Ndim = 2> class NDView {
return buffer_[element_offset(strides_, index...)]; return buffer_[element_offset(strides_, index...)];
} }
uint64_t size() const { return size_; } size_t size() const { return size_; }
size_t total_bytes() const { return size_ * sizeof(T); } size_t total_bytes() const { return size_ * sizeof(T); }
std::array<int64_t, Ndim> strides() const noexcept { return strides_; } std::array<int64_t, Ndim> strides() const noexcept { return strides_; }

View File

@ -41,7 +41,7 @@ namespace aare {
void assert_failed(const std::string &msg); void assert_failed(const std::string &msg);
class Cluster { class DynamicCluster {
public: public:
int cluster_sizeX; int cluster_sizeX;
int cluster_sizeY; int cluster_sizeY;
@ -53,36 +53,36 @@ class Cluster {
std::byte *m_data; std::byte *m_data;
public: public:
Cluster(int cluster_sizeX_, int cluster_sizeY_, DynamicCluster(int cluster_sizeX_, int cluster_sizeY_,
Dtype dt_ = Dtype(typeid(int32_t))) Dtype dt_ = Dtype(typeid(int32_t)))
: cluster_sizeX(cluster_sizeX_), cluster_sizeY(cluster_sizeY_), : cluster_sizeX(cluster_sizeX_), cluster_sizeY(cluster_sizeY_),
dt(dt_) { dt(dt_) {
m_data = new std::byte[cluster_sizeX * cluster_sizeY * dt.bytes()]{}; m_data = new std::byte[cluster_sizeX * cluster_sizeY * dt.bytes()]{};
} }
Cluster() : Cluster(3, 3) {} DynamicCluster() : DynamicCluster(3, 3) {}
Cluster(const Cluster &other) DynamicCluster(const DynamicCluster &other)
: Cluster(other.cluster_sizeX, other.cluster_sizeY, other.dt) { : DynamicCluster(other.cluster_sizeX, other.cluster_sizeY, other.dt) {
if (this == &other) if (this == &other)
return; return;
x = other.x; x = other.x;
y = other.y; y = other.y;
memcpy(m_data, other.m_data, other.bytes()); memcpy(m_data, other.m_data, other.bytes());
} }
Cluster &operator=(const Cluster &other) { DynamicCluster &operator=(const DynamicCluster &other) {
if (this == &other) if (this == &other)
return *this; return *this;
this->~Cluster(); this->~DynamicCluster();
new (this) Cluster(other); new (this) DynamicCluster(other);
return *this; return *this;
} }
Cluster(Cluster &&other) noexcept DynamicCluster(DynamicCluster &&other) noexcept
: cluster_sizeX(other.cluster_sizeX), : cluster_sizeX(other.cluster_sizeX),
cluster_sizeY(other.cluster_sizeY), x(other.x), y(other.y), cluster_sizeY(other.cluster_sizeY), x(other.x), y(other.y),
dt(other.dt), m_data(other.m_data) { dt(other.dt), m_data(other.m_data) {
other.m_data = nullptr; other.m_data = nullptr;
other.dt = Dtype(Dtype::TypeIndex::ERROR); other.dt = Dtype(Dtype::TypeIndex::ERROR);
} }
~Cluster() { delete[] m_data; } ~DynamicCluster() { delete[] m_data; }
template <typename T> T get(int idx) { template <typename T> T get(int idx) {
(sizeof(T) == dt.bytes()) (sizeof(T) == dt.bytes())
? 0 ? 0
@ -95,10 +95,6 @@ class Cluster {
: throw std::invalid_argument("[ERROR] Type size mismatch"); : throw std::invalid_argument("[ERROR] Type size mismatch");
return memcpy(m_data + idx * dt.bytes(), &val, (size_t)dt.bytes()); return memcpy(m_data + idx * dt.bytes(), &val, (size_t)dt.bytes());
} }
// auto x() const { return x; }
// auto y() const { return y; }
// auto x(int16_t x_) { return x = x_; }
// auto y(int16_t y_) { return y = y_; }
template <typename T> std::string to_string() const { template <typename T> std::string to_string() const {
(sizeof(T) == dt.bytes()) (sizeof(T) == dt.bytes())

View File

@ -4,7 +4,7 @@ build-backend = "scikit_build_core.build"
[project] [project]
name = "aare" name = "aare"
version = "2024.11.11.dev0" version = "2024.11.15.dev0"
[tool.scikit-build] [tool.scikit-build]

View File

@ -5,6 +5,7 @@ from . import _aare
from ._aare import File, RawFile, RawMasterFile, RawSubFile from ._aare import File, RawFile, RawMasterFile, RawSubFile
from ._aare import Pedestal, ClusterFinder, VarClusterFinder from ._aare import Pedestal, ClusterFinder, VarClusterFinder
from ._aare import DetectorType from ._aare import DetectorType
from ._aare import ClusterFile
from .CtbRawFile import CtbRawFile from .CtbRawFile import CtbRawFile
from .ScanParameters import ScanParameters from .ScanParameters import ScanParameters

View File

@ -1,95 +1,15 @@
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
import numpy as np import numpy as np
plt.ion() plt.ion()
import aare
from aare import CtbRawFile
print('aare imported')
from aare import transform
print('transform imported')
from pathlib import Path from pathlib import Path
from aare import ClusterFile
import json base = Path('~/data/aare_test_data/clusters').expanduser()
def decode(frames, rawdata): f = ClusterFile(base / 'beam_En700eV_-40deg_300V_10us_d0_f0_100.clust')
# rawdata = np.fromfile(f, dtype = np.uint16) # f = ClusterFile(base / 'single_frame_97_clustrers.clust')
counters = int((np.shape(rawdata)[0]/frames-56)/(48*48))
print('Counters:', counters)
rawdata = rawdata.reshape(frames,-1)[:,56:]
rawdata = rawdata.reshape(frames,576*counters,4) #Data come in "blocks" of 4 pixels/receiver
tr1 = rawdata[:,0:576*counters:2] #Transceiver1
tr1=tr1.reshape((frames,48*counters,24))
tr2 = rawdata[:,1:576*counters:2] #Transceiver2
tr2=tr2.reshape((frames,48*counters,24))
data = np.append(tr1,tr2,axis=2)
return data
def get_Mh02_frames(fname):
# this function gives you the data from a file that is not a scan
# it returns a (frames,48*counters,48)
jsonf = open(fname)
jsonpar = json.load(jsonf)
jsonf.close()
frames=jsonpar["Frames in File"]
print('Frames:', frames)
rawf = fname.replace('master','d0_f0')
rawf = rawf.replace('.json','.raw')
with open(rawf, 'rb') as f:
rawdata = np.fromfile(f, dtype = np.uint16)
data = decode(frames, rawdata)
print('Data:', np.shape(data))
return data
#target format for i in range(10):
# [frame, counter, row, col] fn, cl = f.read_frame()
# plt.imshow(data[0,0]) print(fn, cl.size)
base = Path('/mnt/sls_det_storage/matterhorn_data/aare_test_data/ci/aare_test_data')
# p = Path(base / 'jungfrau/jungfrau_single_master_0.json')
# f = aare.File(p)
# for i in range(10):
# frame = f.read_frame()
# # f2 = aare.CtbRawFile(fpath, transform=transform.matterhorn02)
# # header, data = f2.read()
# # plt.plot(data[:,0,20,20])
# from aare import RawMasterFile, File, RawSubFile, DetectorType, RawFile
# base = Path('/mnt/sls_det_storage/matterhorn_data/aare_test_data/Jungfrau10/Jungfrau_DoubleModule_1UDP_ROI/SideBySide/')
# fpath = Path('241019_JF_12keV_Si_FF_GaAs_FF_7p88mmFilter_PedestalStart_ZPos_5.5_master_0.json')
# raw = Path('241019_JF_12keV_Si_FF_GaAs_FF_7p88mmFilter_PedestalStart_ZPos_5.5_d0_f0_0.raw')
# m = RawMasterFile(base / fpath)
# # roi = m.roi
# # rows = roi.ymax-roi.ymin+1
# # cols = 1024-roi.xmin
# # sf = RawSubFile(base / raw, DetectorType.Jungfrau, rows, cols, 16)
from aare import RawFile
from aare import RawFile, File
base = Path('/mnt/sls_det_storage/matterhorn_data/aare_test_data/Jungfrau10/Jungfrau_DoubleModule_1UDP_ROI/')
fname = base / Path('SideBySide/241019_JF_12keV_Si_FF_GaAs_FF_7p88mmFilter_PedestalStart_ZPos_5.5_master_0.json')
# fname = Path(base / 'jungfrau/jungfrau_single_master_0.json')
# fname = base / 'Stacked/241024_JF10_m450_m367_KnifeEdge_TestBesom_9keV_750umFilter_PedestalStart_ZPos_-6_master_0.json'
f = RawFile(fname)
h,img = f.read_frame()
print(f'{h["frameNumber"]}')

View File

@ -33,20 +33,20 @@ void define_cluster_finder_bindings(py::module &m) {
return clusters; return clusters;
}); });
py::class_<Cluster>(m, "Cluster", py::buffer_protocol()) py::class_<DynamicCluster>(m, "DynamicCluster", py::buffer_protocol())
.def(py::init<int, int, Dtype>()) .def(py::init<int, int, Dtype>())
.def("size", &Cluster::size) .def("size", &DynamicCluster::size)
.def("begin", &Cluster::begin) .def("begin", &DynamicCluster::begin)
.def("end", &Cluster::end) .def("end", &DynamicCluster::end)
.def_readwrite("x", &Cluster::x) .def_readwrite("x", &DynamicCluster::x)
.def_readwrite("y", &Cluster::y) .def_readwrite("y", &DynamicCluster::y)
.def_buffer([](Cluster &c) -> py::buffer_info { .def_buffer([](DynamicCluster &c) -> py::buffer_info {
return py::buffer_info(c.data(), c.dt.bytes(), c.dt.format_descr(), return py::buffer_info(c.data(), c.dt.bytes(), c.dt.format_descr(),
1, {c.size()}, {c.dt.bytes()}); 1, {c.size()}, {c.dt.bytes()});
}) })
.def("__repr__", [](const Cluster &a) { .def("__repr__", [](const DynamicCluster &a) {
return "<Cluster: x: " + std::to_string(a.x) + return "<DynamicCluster: x: " + std::to_string(a.x) +
", y: " + std::to_string(a.y) + ">"; ", y: " + std::to_string(a.y) + ">";
}); });
} }

View File

@ -0,0 +1,50 @@
#include "aare/ClusterFile.hpp"
#include "aare/defs.hpp"
#include <cstdint>
#include <filesystem>
#include <pybind11/iostream.h>
#include <pybind11/numpy.h>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/stl/filesystem.h>
#include <string>
namespace py = pybind11;
using namespace ::aare;
void define_cluster_file_io_bindings(py::module &m) {
PYBIND11_NUMPY_DTYPE(Cluster, x, y, data);
py::class_<ClusterFile>(m, "ClusterFile")
.def(py::init<const std::filesystem::path &, size_t>(), py::arg(), py::arg("chunk_size") = 1000)
.def("read_clusters",
[](ClusterFile &self, size_t n_clusters) {
auto* vec = new std::vector<Cluster>(self.read_clusters(n_clusters));
return return_vector(vec);
})
.def("read_frame",
[](ClusterFile &self) {
int32_t frame_number;
auto* vec = new std::vector<Cluster>(self.read_frame(frame_number));
return py::make_tuple(frame_number, return_vector(vec));
})
.def("read_cluster_with_cut",
[](ClusterFile &self, size_t n_clusters, py::array_t<double> noise_map, int nx, int ny) {
auto view = make_view_2d(noise_map);
auto* vec = new std::vector<Cluster>(self.read_cluster_with_cut(n_clusters, view.data(), nx, ny));
return return_vector(vec);
})
.def("__enter__", [](ClusterFile &self) { return &self; })
.def("__exit__", [](ClusterFile &self, py::args args) { return; })
.def("__iter__", [](ClusterFile &self) { return &self; })
.def("__next__", [](ClusterFile &self) {
auto vec = new std::vector<Cluster>(self.read_clusters(self.chunk_size()));
if(vec->size() == 0) {
throw py::stop_iteration();
}
return return_vector(vec);
});
}

View File

@ -264,7 +264,7 @@ void define_file_io_bindings(py::module &m) {
// .def("close", &ClusterFileV2::close); // .def("close", &ClusterFileV2::close);
// m.def("to_clustV2", [](std::vector<Cluster> &clusters, const int // m.def("to_clustV2", [](std::vector<DynamicCluster> &clusters, const int
// frame_number) { // frame_number) {
// std::vector<ClusterV2> clusters_; // std::vector<ClusterV2> clusters_;
// for (auto &c : clusters) { // for (auto &c : clusters) {

View File

@ -6,6 +6,7 @@
#include "pixel_map.hpp" #include "pixel_map.hpp"
#include "pedestal.hpp" #include "pedestal.hpp"
#include "cluster.hpp" #include "cluster.hpp"
#include "cluster_file.hpp"
//Pybind stuff //Pybind stuff
#include <pybind11/pybind11.h> #include <pybind11/pybind11.h>
@ -22,4 +23,5 @@ PYBIND11_MODULE(_aare, m) {
define_pedestal_bindings<double>(m, "Pedestal"); define_pedestal_bindings<double>(m, "Pedestal");
define_pedestal_bindings<float>(m, "Pedestal_float32"); define_pedestal_bindings<float>(m, "Pedestal_float32");
define_cluster_finder_bindings(m); define_cluster_finder_bindings(m);
define_cluster_file_io_bindings(m);
} }

312
src/ClusterFile.cpp Normal file
View File

@ -0,0 +1,312 @@
#include "aare/ClusterFile.hpp"
namespace aare {
ClusterFile::ClusterFile(const std::filesystem::path &fname, size_t chunk_size): m_chunk_size(chunk_size) {
fp = fopen(fname.c_str(), "rb");
if (!fp) {
throw std::runtime_error("Could not open file: " + fname.string());
}
}
std::vector<Cluster> ClusterFile::read_clusters(size_t n_clusters) {
std::vector<Cluster> clusters(n_clusters);
int32_t iframe = 0; // frame number needs to be 4 bytes!
size_t nph_read = 0;
uint32_t nn = m_num_left;
uint32_t nph = m_num_left; // number of clusters in frame needs to be 4
auto buf = reinterpret_cast<Cluster *>(clusters.data());
// if there are photons left from previous frame read them first
if (nph) {
if (nph > n_clusters) {
// if we have more photons left in the frame then photons to read we
// read directly the requested number
nn = n_clusters;
} else {
nn = nph;
}
nph_read += fread((void *)(buf + nph_read), sizeof(Cluster), nn, fp);
m_num_left = nph - nn; // write back the number of photons left
}
if (nph_read < n_clusters) {
// keep on reading frames and photons until reaching n_clusters
while (fread(&iframe, sizeof(iframe), 1, fp)) {
// read number of clusters in frame
if (fread(&nph, sizeof(nph), 1, fp)) {
if (nph > (n_clusters - nph_read))
nn = n_clusters - nph_read;
else
nn = nph;
nph_read +=
fread((void *)(buf + nph_read), sizeof(Cluster), nn, fp);
m_num_left = nph - nn;
}
if (nph_read >= n_clusters)
break;
}
}
// Resize the vector to the number of clusters.
// No new allocation, only change bounds.
clusters.resize(nph_read);
return clusters;
}
std::vector<Cluster> ClusterFile::read_frame(int32_t &out_fnum) {
if (m_num_left) {
throw std::runtime_error("There are still photons left in the last frame");
}
if (fread(&out_fnum, sizeof(out_fnum), 1, fp) != 1) {
throw std::runtime_error("Could not read frame number");
}
int n_clusters;
if (fread(&n_clusters, sizeof(n_clusters), 1, fp) != 1) {
throw std::runtime_error("Could not read number of clusters");
}
std::vector<Cluster> clusters(n_clusters);
if (fread(clusters.data(), sizeof(Cluster), n_clusters, fp) != n_clusters) {
throw std::runtime_error("Could not read clusters");
}
return clusters;
}
std::vector<Cluster> ClusterFile::read_cluster_with_cut(size_t n_clusters,
double *noise_map,
int nx, int ny) {
std::vector<Cluster> clusters(n_clusters);
// size_t read_clusters_with_cut(FILE *fp, size_t n_clusters, Cluster *buf,
// uint32_t *n_left, double *noise_map, int
// nx, int ny) {
int iframe = 0;
// uint32_t nph = *n_left;
uint32_t nph = m_num_left;
// uint32_t nn = *n_left;
uint32_t nn = m_num_left;
size_t nph_read = 0;
int32_t t2max, tot1;
int32_t tot3;
// Cluster *ptr = buf;
Cluster *ptr = clusters.data();
int good = 1;
double noise;
// read photons left from previous frame
if (noise_map)
printf("Using noise map\n");
if (nph) {
if (nph > n_clusters) {
// if we have more photons left in the frame then photons to
// read we read directly the requested number
nn = n_clusters;
} else {
nn = nph;
}
for (size_t iph = 0; iph < nn; iph++) {
// read photons 1 by 1
size_t n_read = fread((void *)(ptr), sizeof(Cluster), 1, fp);
if (n_read != 1) {
clusters.resize(nph_read);
return clusters;
}
// TODO! error handling on read
good = 1;
if (noise_map) {
if (ptr->x >= 0 && ptr->x < nx && ptr->y >= 0 && ptr->y < ny) {
tot1 = ptr->data[4];
analyze_cluster(*ptr, &t2max, &tot3, NULL, NULL, NULL, NULL,
NULL);
noise = noise_map[ptr->y * nx + ptr->x];
if (tot1 > noise || t2max > 2 * noise || tot3 > 3 * noise) {
;
} else {
good = 0;
printf("%d %d %f %d %d %d\n", ptr->x, ptr->y, noise,
tot1, t2max, tot3);
}
} else {
printf("Bad pixel number %d %d\n", ptr->x, ptr->y);
good = 0;
}
}
if (good) {
ptr++;
nph_read++;
}
(m_num_left)--;
if (nph_read >= n_clusters)
break;
}
}
if (nph_read < n_clusters) {
// // keep on reading frames and photons until reaching n_clusters
while (fread(&iframe, sizeof(iframe), 1, fp)) {
// // printf("%d\n",nph_read);
if (fread(&nph, sizeof(nph), 1, fp)) {
// // printf("** %d\n",nph);
m_num_left = nph;
for (size_t iph = 0; iph < nph; iph++) {
// // read photons 1 by 1
size_t n_read =
fread((void *)(ptr), sizeof(Cluster), 1, fp);
if (n_read != 1) {
clusters.resize(nph_read);
return clusters;
// return nph_read;
}
good = 1;
if (noise_map) {
if (ptr->x >= 0 && ptr->x < nx && ptr->y >= 0 &&
ptr->y < ny) {
tot1 = ptr->data[4];
analyze_cluster(*ptr, &t2max, &tot3, NULL,
NULL,
NULL, NULL, NULL);
// noise = noise_map[ptr->y * nx + ptr->x];
noise = noise_map[ptr->y + ny * ptr->x];
if (tot1 > noise || t2max > 2 * noise ||
tot3 > 3 * noise) {
;
} else
good = 0;
} else {
printf("Bad pixel number %d %d\n", ptr->x,
ptr->y); good = 0;
}
}
if (good) {
ptr++;
nph_read++;
}
(m_num_left)--;
if (nph_read >= n_clusters)
break;
}
}
if (nph_read >= n_clusters)
break;
}
}
// printf("%d\n",nph_read);
clusters.resize(nph_read);
return clusters;
}
int ClusterFile::analyze_cluster(Cluster cl, int32_t *t2, int32_t *t3, char *quad,
double *eta2x, double *eta2y, double *eta3x,
double *eta3y) {
return analyze_data(cl.data, t2, t3, quad, eta2x, eta2y, eta3x, eta3y);
}
int ClusterFile::analyze_data(int32_t *data, int32_t *t2, int32_t *t3, char *quad,
double *eta2x, double *eta2y, double *eta3x, double *eta3y) {
int ok = 1;
int32_t tot2[4];
int32_t t2max = 0;
char c = 0;
int32_t val, tot3;
tot3 = 0;
for (int i = 0; i < 4; i++)
tot2[i] = 0;
for (int ix = 0; ix < 3; ix++) {
for (int iy = 0; iy < 3; iy++) {
val = data[iy * 3 + ix];
// printf ("%d ",data[iy * 3 + ix]);
tot3 += val;
if (ix <= 1 && iy <= 1)
tot2[cBottomLeft] += val;
if (ix >= 1 && iy <= 1)
tot2[cBottomRight] += val;
if (ix <= 1 && iy >= 1)
tot2[cTopLeft] += val;
if (ix >= 1 && iy >= 1)
tot2[cTopRight] += val;
}
// printf ("\n");
}
// printf ("\n");
if (t2 || quad) {
t2max = tot2[0];
c = cBottomLeft;
for (int i = 1; i < 4; i++) {
if (tot2[i] > t2max) {
t2max = tot2[i];
c = i;
}
}
//printf("*** %d %d %d %d -- %d\n",tot2[0],tot2[1],tot2[2],tot2[3],t2max);
if (quad)
*quad = c;
if (t2)
*t2 = t2max;
}
if (t3)
*t3 = tot3;
if (eta2x || eta2y) {
if (eta2x)
*eta2x = 0;
if (eta2y)
*eta2y = 0;
switch (c) {
case cBottomLeft:
if (eta2x && (data[3] + data[4]) != 0)
*eta2x = (double)(data[4]) / (data[3] + data[4]);
if (eta2y && (data[1] + data[4]) != 0)
*eta2y = (double)(data[4]) / (data[1] + data[4]);
break;
case cBottomRight:
if (eta2x && (data[2] + data[5]) != 0)
*eta2x = (double)(data[5]) / (data[4] + data[5]);
if (eta2y && (data[1] + data[4]) != 0)
*eta2y = (double)(data[4]) / (data[1] + data[4]);
break;
case cTopLeft:
if (eta2x && (data[7] + data[4]) != 0)
*eta2x = (double)(data[4]) / (data[3] + data[4]);
if (eta2y && (data[7] + data[4]) != 0)
*eta2y = (double)(data[7]) / (data[7] + data[4]);
break;
case cTopRight:
if (eta2x && t2max != 0)
*eta2x = (double)(data[5]) / (data[5] + data[4]);
if (eta2y && t2max != 0)
*eta2y = (double)(data[7]) / (data[7] + data[4]);
break;
default:;
}
}
if (eta3x || eta3y) {
if (eta3x && (data[3] + data[4] + data[5]) != 0)
*eta3x = (double)(-data[3] + data[3 + 2]) /
(data[3] + data[4] + data[5]);
if (eta3y && (data[1] + data[4] + data[7]) != 0)
*eta3y = (double)(-data[1] + data[2 * 3 + 1]) /
(data[1] + data[4] + data[7]);
}
return ok;
}
} // namespace aare

View File

@ -1,5 +1,6 @@
#include "aare/NDArray.hpp" #include "aare/NDArray.hpp"
#include <array> #include <array>
#include <catch2/benchmark/catch_benchmark.hpp>
#include <catch2/catch_test_macros.hpp> #include <catch2/catch_test_macros.hpp>
using aare::NDArray; using aare::NDArray;
@ -101,7 +102,8 @@ TEST_CASE("Elementwise multiplication of 3D image") {
a(i) = i; a(i) = i;
b(i) = i; b(i) = i;
} }
auto c = a * b; // auto c = a * b; // This works but the result is a lazy ArrayMul object
NDArray<double, 3> c = a * b;
REQUIRE(c(0, 0, 0) == 0 * 0); REQUIRE(c(0, 0, 0) == 0 * 0);
REQUIRE(c(0, 0, 1) == 1 * 1); REQUIRE(c(0, 0, 1) == 1 * 1);
REQUIRE(c(0, 1, 1) == 3 * 3); REQUIRE(c(0, 1, 1) == 3 * 3);
@ -109,6 +111,39 @@ TEST_CASE("Elementwise multiplication of 3D image") {
REQUIRE(c(2, 3, 1) == 23 * 23); REQUIRE(c(2, 3, 1) == 23 * 23);
} }
NDArray<int> MultiplyNDArrayUsingOperator(NDArray<int> &a, NDArray<int> &b) {
// return a * a * b * b;
NDArray<int>c = a*b;
return c;
}
NDArray<int> MultiplyNDArrayUsingIndex(NDArray<int> &a, NDArray<int> &b) {
NDArray<int> res(a.shape());
for (uint32_t i = 0; i < a.size(); i++) {
// res(i) = a(i) * a(i) * b(i) * b(i);
res(i) = a(i) * b(i);
}
return res;
}
NDArray<int> AddNDArrayUsingOperator(NDArray<int> &a, NDArray<int> &b) {
// return a * a * b * b;
// NDArray<int>c = a+b;
NDArray<int> c(a.shape());
c = a + b;
return c;
}
NDArray<int> AddNDArrayUsingIndex(NDArray<int> &a, NDArray<int> &b) {
NDArray<int> res(a.shape());
for (uint32_t i = 0; i < a.size(); i++) {
// res(i) = a(i) * a(i) * b(i) * b(i);
res(i) = a(i) + b(i);
}
return res;
}
TEST_CASE("Compare two images") { TEST_CASE("Compare two images") {
NDArray<int> a; NDArray<int> a;
NDArray<int> b; NDArray<int> b;
@ -178,7 +213,8 @@ TEST_CASE("Elementwise operations on images") {
NDArray<double> A(shape, a_val); NDArray<double> A(shape, a_val);
NDArray<double> B(shape, b_val); NDArray<double> B(shape, b_val);
auto C = A + B; NDArray<double> C = A + B;
// auto C = A+B; // This works but the result is a lazy ArraySum object
// Value of C matches // Value of C matches
for (uint32_t i = 0; i < C.size(); ++i) { for (uint32_t i = 0; i < C.size(); ++i) {
@ -202,7 +238,8 @@ TEST_CASE("Elementwise operations on images") {
SECTION("Subtract two images") { SECTION("Subtract two images") {
NDArray<double> A(shape, a_val); NDArray<double> A(shape, a_val);
NDArray<double> B(shape, b_val); NDArray<double> B(shape, b_val);
auto C = A - B; NDArray<double> C = A - B;
// auto C = A - B; // This works but the result is a lazy ArraySub object
// Value of C matches // Value of C matches
for (uint32_t i = 0; i < C.size(); ++i) { for (uint32_t i = 0; i < C.size(); ++i) {
@ -226,7 +263,8 @@ TEST_CASE("Elementwise operations on images") {
SECTION("Multiply two images") { SECTION("Multiply two images") {
NDArray<double> A(shape, a_val); NDArray<double> A(shape, a_val);
NDArray<double> B(shape, b_val); NDArray<double> B(shape, b_val);
auto C = A * B; // auto C = A * B; // This works but the result is a lazy ArrayMul object
NDArray<double> C = A * B;
// Value of C matches // Value of C matches
for (uint32_t i = 0; i < C.size(); ++i) { for (uint32_t i = 0; i < C.size(); ++i) {
@ -250,7 +288,8 @@ TEST_CASE("Elementwise operations on images") {
SECTION("Divide two images") { SECTION("Divide two images") {
NDArray<double> A(shape, a_val); NDArray<double> A(shape, a_val);
NDArray<double> B(shape, b_val); NDArray<double> B(shape, b_val);
auto C = A / B; // auto C = A / B; // This works but the result is a lazy ArrayDiv object
NDArray<double> C = A / B;
// Value of C matches // Value of C matches
for (uint32_t i = 0; i < C.size(); ++i) { for (uint32_t i = 0; i < C.size(); ++i) {

View File

@ -6,7 +6,7 @@
using aare::Dtype; using aare::Dtype;
using aare::NumpyFile; using aare::NumpyFile;
TEST_CASE("Read a 1D numpy file with int32 data type") { TEST_CASE("Read a 1D numpy file with int32 data type", "[.integration]") {
auto fpath = test_data_path() / "numpy" / "test_1d_int32.npy"; auto fpath = test_data_path() / "numpy" / "test_1d_int32.npy";
REQUIRE(std::filesystem::exists(fpath)); REQUIRE(std::filesystem::exists(fpath));
@ -24,7 +24,7 @@ TEST_CASE("Read a 1D numpy file with int32 data type") {
} }
} }
TEST_CASE("Read a 3D numpy file with np.double data type") { TEST_CASE("Read a 3D numpy file with np.double data type", "[.integration]") {
auto fpath = test_data_path() / "numpy" / "test_3d_double.npy"; auto fpath = test_data_path() / "numpy" / "test_3d_double.npy";
REQUIRE(std::filesystem::exists(fpath)); REQUIRE(std::filesystem::exists(fpath));

View File

@ -7,7 +7,7 @@
using aare::File; using aare::File;
TEST_CASE("Read number of frames from a jungfrau raw file") { TEST_CASE("Read number of frames from a jungfrau raw file", "[.integration]") {
auto fpath = test_data_path() / "jungfrau" / "jungfrau_single_master_0.json"; auto fpath = test_data_path() / "jungfrau" / "jungfrau_single_master_0.json";
REQUIRE(std::filesystem::exists(fpath)); REQUIRE(std::filesystem::exists(fpath));
@ -16,7 +16,7 @@ TEST_CASE("Read number of frames from a jungfrau raw file") {
REQUIRE(f.total_frames() == 10); REQUIRE(f.total_frames() == 10);
} }
TEST_CASE("Read frame numbers from a jungfrau raw file") { TEST_CASE("Read frame numbers from a jungfrau raw file", "[.integration]") {
auto fpath = test_data_path() / "jungfrau" / "jungfrau_single_master_0.json"; auto fpath = test_data_path() / "jungfrau" / "jungfrau_single_master_0.json";
REQUIRE(std::filesystem::exists(fpath)); REQUIRE(std::filesystem::exists(fpath));
@ -32,7 +32,7 @@ TEST_CASE("Read frame numbers from a jungfrau raw file") {
} }
} }
TEST_CASE("Read a frame number too high throws") { TEST_CASE("Read a frame number too high throws", "[.integration]") {
auto fpath = test_data_path() / "jungfrau" / "jungfrau_single_master_0.json"; auto fpath = test_data_path() / "jungfrau" / "jungfrau_single_master_0.json";
REQUIRE(std::filesystem::exists(fpath)); REQUIRE(std::filesystem::exists(fpath));
@ -46,7 +46,7 @@ TEST_CASE("Read a frame number too high throws") {
REQUIRE_THROWS(f.frame_number(10)); REQUIRE_THROWS(f.frame_number(10));
} }
TEST_CASE("Read a frame numbers where the subfile is missing throws") { TEST_CASE("Read a frame numbers where the subfile is missing throws", "[.integration]") {
auto fpath = test_data_path() / "jungfrau" / "jungfrau_missing_subfile_master_0.json"; auto fpath = test_data_path() / "jungfrau" / "jungfrau_missing_subfile_master_0.json";
REQUIRE(std::filesystem::exists(fpath)); REQUIRE(std::filesystem::exists(fpath));
@ -67,7 +67,7 @@ TEST_CASE("Read a frame numbers where the subfile is missing throws") {
} }
TEST_CASE("Read data from a jungfrau 500k single port raw file") { TEST_CASE("Read data from a jungfrau 500k single port raw file", "[.integration]") {
auto fpath = test_data_path() / "jungfrau" / "jungfrau_single_master_0.json"; auto fpath = test_data_path() / "jungfrau" / "jungfrau_single_master_0.json";
REQUIRE(std::filesystem::exists(fpath)); REQUIRE(std::filesystem::exists(fpath));
@ -83,7 +83,7 @@ TEST_CASE("Read data from a jungfrau 500k single port raw file") {
} }
} }
TEST_CASE("Read frame numbers from a raw file") { TEST_CASE("Read frame numbers from a raw file", "[.integration]") {
auto fpath = test_data_path() / "eiger" / "eiger_500k_16bit_master_0.json"; auto fpath = test_data_path() / "eiger" / "eiger_500k_16bit_master_0.json";
REQUIRE(std::filesystem::exists(fpath)); REQUIRE(std::filesystem::exists(fpath));
@ -96,7 +96,7 @@ TEST_CASE("Read frame numbers from a raw file") {
} }
} }
TEST_CASE("Compare reading from a numpy file with a raw file") { TEST_CASE("Compare reading from a numpy file with a raw file", "[.integration]") {
auto fpath_raw = test_data_path() / "jungfrau" / "jungfrau_single_master_0.json"; auto fpath_raw = test_data_path() / "jungfrau" / "jungfrau_single_master_0.json";
REQUIRE(std::filesystem::exists(fpath_raw)); REQUIRE(std::filesystem::exists(fpath_raw));
@ -116,7 +116,7 @@ TEST_CASE("Compare reading from a numpy file with a raw file") {
} }
} }
TEST_CASE("Read multipart files") { TEST_CASE("Read multipart files", "[.integration]") {
auto fpath = test_data_path() / "jungfrau" / "jungfrau_double_master_0.json"; auto fpath = test_data_path() / "jungfrau" / "jungfrau_double_master_0.json";
REQUIRE(std::filesystem::exists(fpath)); REQUIRE(std::filesystem::exists(fpath));
@ -141,7 +141,7 @@ TEST_CASE("Read multipart files") {
} }
} }
TEST_CASE("Read file with unordered frames") { TEST_CASE("Read file with unordered frames", "[.integration]") {
//TODO! Better explanation and error message //TODO! Better explanation and error message
auto fpath = test_data_path() / "mythen" / "scan242_master_3.raw"; auto fpath = test_data_path() / "mythen" / "scan242_master_3.raw";
REQUIRE(std::filesystem::exists(fpath)); REQUIRE(std::filesystem::exists(fpath));

View File

@ -58,7 +58,7 @@ TEST_CASE("A disabled scan"){
} }
TEST_CASE("Parse a master file in .json format"){ TEST_CASE("Parse a master file in .json format", "[.integration]"){
auto fpath = test_data_path() / "jungfrau" / "jungfrau_single_master_0.json"; auto fpath = test_data_path() / "jungfrau" / "jungfrau_single_master_0.json";
REQUIRE(std::filesystem::exists(fpath)); REQUIRE(std::filesystem::exists(fpath));
RawMasterFile f(fpath); RawMasterFile f(fpath);
@ -139,7 +139,7 @@ TEST_CASE("Parse a master file in .json format"){
} }
TEST_CASE("Parse a master file in .raw format"){ TEST_CASE("Parse a master file in .raw format", "[.integration]"){
auto fpath = test_data_path() / "moench/moench04_noise_200V_sto_both_100us_no_light_thresh_900_master_0.raw"; auto fpath = test_data_path() / "moench/moench04_noise_200V_sto_both_100us_no_light_thresh_900_master_0.raw";
REQUIRE(std::filesystem::exists(fpath)); REQUIRE(std::filesystem::exists(fpath));
@ -204,7 +204,7 @@ TEST_CASE("Parse a master file in .raw format"){
} }
TEST_CASE("Read eiger master file"){ TEST_CASE("Read eiger master file", "[.integration]"){
auto fpath = test_data_path() / "eiger" / "eiger_500k_32bit_master_0.json"; auto fpath = test_data_path() / "eiger" / "eiger_500k_32bit_master_0.json";
REQUIRE(std::filesystem::exists(fpath)); REQUIRE(std::filesystem::exists(fpath));
RawMasterFile f(fpath); RawMasterFile f(fpath);

View File

@ -9,14 +9,14 @@ TEST_CASE("Enum to string conversion") {
REQUIRE(ToString(aare::DetectorType::Jungfrau) == "Jungfrau"); REQUIRE(ToString(aare::DetectorType::Jungfrau) == "Jungfrau");
} }
TEST_CASE("Cluster creation") { TEST_CASE("DynamicCluster creation") {
aare::Cluster c(13, 15); aare::DynamicCluster c(13, 15);
REQUIRE(c.cluster_sizeX == 13); REQUIRE(c.cluster_sizeX == 13);
REQUIRE(c.cluster_sizeY == 15); REQUIRE(c.cluster_sizeY == 15);
REQUIRE(c.dt == aare::Dtype(typeid(int32_t))); REQUIRE(c.dt == aare::Dtype(typeid(int32_t)));
REQUIRE(c.data() != nullptr); REQUIRE(c.data() != nullptr);
aare::Cluster c2(c); aare::DynamicCluster c2(c);
REQUIRE(c2.cluster_sizeX == 13); REQUIRE(c2.cluster_sizeX == 13);
REQUIRE(c2.cluster_sizeY == 15); REQUIRE(c2.cluster_sizeY == 15);
REQUIRE(c2.dt == aare::Dtype(typeid(int32_t))); REQUIRE(c2.dt == aare::Dtype(typeid(int32_t)));
@ -25,7 +25,7 @@ TEST_CASE("Cluster creation") {
// TEST_CASE("cluster set and get data") { // TEST_CASE("cluster set and get data") {
// aare::Cluster c2(33, 44, aare::Dtype(typeid(double))); // aare::DynamicCluster c2(33, 44, aare::Dtype(typeid(double)));
// REQUIRE(c2.cluster_sizeX == 33); // REQUIRE(c2.cluster_sizeX == 33);
// REQUIRE(c2.cluster_sizeY == 44); // REQUIRE(c2.cluster_sizeY == 44);
// REQUIRE(c2.dt == aare::Dtype::DOUBLE); // REQUIRE(c2.dt == aare::Dtype::DOUBLE);

View File

@ -4,12 +4,12 @@
#include <filesystem> #include <filesystem>
#include <fstream> #include <fstream>
TEST_CASE("Test suite can find data assets") { TEST_CASE("Test suite can find data assets", "[.integration]") {
auto fpath = test_data_path() / "numpy" / "test_numpy_file.npy"; auto fpath = test_data_path() / "numpy" / "test_numpy_file.npy";
REQUIRE(std::filesystem::exists(fpath)); REQUIRE(std::filesystem::exists(fpath));
} }
TEST_CASE("Test suite can open data assets") { TEST_CASE("Test suite can open data assets", "[.integration]") {
auto fpath = test_data_path() / "numpy" / "test_numpy_file.npy"; auto fpath = test_data_path() / "numpy" / "test_numpy_file.npy";
auto f = std::ifstream(fpath, std::ios::binary); auto f = std::ifstream(fpath, std::ios::binary);
REQUIRE(f.is_open()); REQUIRE(f.is_open());