mirror of
https://github.com/slsdetectorgroup/aare.git
synced 2025-06-14 16:27:14 +02:00
Compare commits
15 Commits
main
...
dev/fix/ra
Author | SHA1 | Date | |
---|---|---|---|
35114cde9d | |||
b13f864b2b | |||
05828baa54 | |||
0f56846e3d | |||
be67bbab6b | |||
bd7870e75a | |||
75f63607fc | |||
cfe7c31fe4 | |||
a9a55fb27d | |||
19ecc82fff | |||
923f7d22b8 | |||
6438a4bef1 | |||
ad7525cd02 | |||
87d8682b1e | |||
9c6e629298 |
2
.github/workflows/build_docs.yml
vendored
2
.github/workflows/build_docs.yml
vendored
@ -43,7 +43,7 @@ jobs:
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DAARE_SYSTEM_LIBRARIES=ON -DAARE_PYTHON_BINDINGS=ON -DAARE_DOCS=ON
|
||||
cmake .. -DAARE_SYSTEM_LIBRARIES=ON -DAARE_DOCS=ON
|
||||
make -j 2
|
||||
make docs
|
||||
|
||||
|
@ -335,13 +335,10 @@ if(AARE_ASAN)
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if(AARE_TESTS)
|
||||
enable_testing()
|
||||
add_subdirectory(tests)
|
||||
target_compile_definitions(tests PRIVATE AARE_TESTS)
|
||||
endif()
|
||||
|
||||
###------------------------------------------------------------------------------MAIN LIBRARY
|
||||
@ -364,7 +361,7 @@ set(PUBLICHEADERS
|
||||
include/aare/FilePtr.hpp
|
||||
include/aare/Frame.hpp
|
||||
include/aare/GainMap.hpp
|
||||
include/aare/geo_helpers.hpp
|
||||
include/aare/DetectorGeometry.hpp
|
||||
include/aare/JungfrauDataFile.hpp
|
||||
include/aare/NDArray.hpp
|
||||
include/aare/NDView.hpp
|
||||
@ -389,7 +386,7 @@ set(SourceFiles
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/File.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/FilePtr.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Fit.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/geo_helpers.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/DetectorGeometry.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/JungfrauDataFile.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/NumpyFile.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/NumpyHelpers.cpp
|
||||
@ -424,6 +421,10 @@ target_link_libraries(
|
||||
|
||||
)
|
||||
|
||||
if(AARE_TESTS)
|
||||
target_compile_definitions(aare_core PRIVATE AARE_TESTS)
|
||||
endif()
|
||||
|
||||
set_target_properties(aare_core PROPERTIES
|
||||
ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
PUBLIC_HEADER "${PUBLICHEADERS}"
|
||||
@ -440,7 +441,7 @@ if(AARE_TESTS)
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/decode.test.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Dtype.test.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Frame.test.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/geo_helpers.test.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/DetectorGeometry.test.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/RawMasterFile.test.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/NDArray.test.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/NDView.test.cpp
|
||||
|
@ -4,5 +4,4 @@ ClusterFile
|
||||
.. doxygenclass:: aare::ClusterFile
|
||||
:members:
|
||||
:undoc-members:
|
||||
:private-members:
|
||||
|
||||
:private-members:
|
@ -2,24 +2,9 @@
|
||||
ClusterFile
|
||||
============
|
||||
|
||||
|
||||
The :class:`ClusterFile` class is the main interface to read and write clusters in aare. Unfortunately the
|
||||
old file format does not include metadata like the cluster size and the data type. This means that the
|
||||
user has to know this information from other sources. Specifying the wrong cluster size or data type
|
||||
will lead to garbage data being read.
|
||||
|
||||
.. py:currentmodule:: aare
|
||||
|
||||
.. autoclass:: ClusterFile
|
||||
:members:
|
||||
:undoc-members:
|
||||
:inherited-members:
|
||||
|
||||
|
||||
Below is the API of the ClusterFile_Cluster3x3i but all variants share the same API.
|
||||
|
||||
.. autoclass:: aare._aare.ClusterFile_Cluster3x3i
|
||||
:special-members: __init__
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
@ -2,10 +2,8 @@ ClusterVector
|
||||
================
|
||||
|
||||
The ClusterVector, holds clusters from the ClusterFinder. Since it is templated
|
||||
in C++ we use a suffix indicating the type of cluster it holds. The suffix follows
|
||||
the same pattern as for ClusterFile i.e. ``ClusterVector_Cluster3x3i``
|
||||
for a vector holding 3x3 integer clusters.
|
||||
|
||||
in C++ we use a suffix indicating the data type in python. The suffix is
|
||||
``_i`` for integer, ``_f`` for float, and ``_d`` for double.
|
||||
|
||||
At the moment the functionality from python is limited and it is not supported
|
||||
to push_back clusters to the vector. The intended use case is to pass it to
|
||||
@ -28,8 +26,7 @@ C++ functions that support the ClusterVector or to view it as a numpy array.
|
||||
|
||||
.. py:currentmodule:: aare
|
||||
|
||||
.. autoclass:: aare._aare.ClusterVector_Cluster3x3i
|
||||
:special-members: __init__
|
||||
.. autoclass:: ClusterVector_i
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
@ -5,12 +5,9 @@ dependencies:
|
||||
- anaconda-client
|
||||
- conda-build
|
||||
- doxygen
|
||||
- sphinx
|
||||
- sphinx=7.1.2
|
||||
- breathe
|
||||
- sphinx_rtd_theme
|
||||
- furo
|
||||
- zeromq
|
||||
- pybind11
|
||||
- numpy
|
||||
- matplotlib
|
||||
|
||||
|
81
include/aare/DetectorGeometry.hpp
Normal file
81
include/aare/DetectorGeometry.hpp
Normal file
@ -0,0 +1,81 @@
|
||||
#pragma once
|
||||
#include "aare/RawMasterFile.hpp" //ROI refactor away
|
||||
#include "aare/defs.hpp"
|
||||
namespace aare {
|
||||
|
||||
struct ModuleConfig {
|
||||
int module_gap_row{};
|
||||
int module_gap_col{};
|
||||
|
||||
bool operator==(const ModuleConfig &other) const {
|
||||
if (module_gap_col != other.module_gap_col)
|
||||
return false;
|
||||
if (module_gap_row != other.module_gap_row)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Class to hold the geometry of a module. Where pixel 0 is located and
|
||||
* the size of the module
|
||||
*/
|
||||
struct ModuleGeometry {
|
||||
int origin_x{};
|
||||
int origin_y{};
|
||||
int height{};
|
||||
int width{};
|
||||
int row_index{};
|
||||
int col_index{};
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Class to hold the geometry of a detector. Number of modules, their
|
||||
* size and where pixel 0 for each module is located
|
||||
*/
|
||||
class DetectorGeometry {
|
||||
public:
|
||||
DetectorGeometry(const xy &geometry, const ssize_t module_pixels_x,
|
||||
const ssize_t module_pixels_y,
|
||||
const xy udp_interfaces_per_module = xy{1, 1},
|
||||
const bool quad = false);
|
||||
|
||||
~DetectorGeometry() = default;
|
||||
|
||||
/**
|
||||
* @brief Update the detector geometry given a region of interest
|
||||
*
|
||||
* @param roi
|
||||
* @return DetectorGeometry
|
||||
*/
|
||||
void update_geometry_with_roi(ROI roi);
|
||||
|
||||
size_t n_modules() const;
|
||||
|
||||
size_t n_modules_in_roi() const;
|
||||
|
||||
size_t pixels_x() const;
|
||||
size_t pixels_y() const;
|
||||
|
||||
size_t modules_x() const;
|
||||
size_t modules_y() const;
|
||||
|
||||
const std::vector<ssize_t> &get_modules_in_roi() const;
|
||||
|
||||
ssize_t get_modules_in_roi(const size_t index) const;
|
||||
|
||||
const std::vector<ModuleGeometry> &get_module_geometries() const;
|
||||
|
||||
const ModuleGeometry &get_module_geometries(const size_t index) const;
|
||||
|
||||
private:
|
||||
size_t m_modules_x{};
|
||||
size_t m_modules_y{};
|
||||
size_t m_pixels_x{};
|
||||
size_t m_pixels_y{};
|
||||
static constexpr ModuleConfig cfg{0, 0};
|
||||
std::vector<ModuleGeometry> module_geometries{};
|
||||
std::vector<ssize_t> modules_in_roi{};
|
||||
};
|
||||
|
||||
} // namespace aare
|
@ -1,26 +1,23 @@
|
||||
#pragma once
|
||||
#include "aare/DetectorGeometry.hpp"
|
||||
#include "aare/FileInterface.hpp"
|
||||
#include "aare/Frame.hpp"
|
||||
#include "aare/NDArray.hpp" //for pixel map
|
||||
#include "aare/RawMasterFile.hpp"
|
||||
#include "aare/RawSubFile.hpp"
|
||||
|
||||
#ifdef AARE_TESTS
|
||||
#include "../tests/friend_test.hpp"
|
||||
#endif
|
||||
|
||||
#include <optional>
|
||||
|
||||
namespace aare {
|
||||
|
||||
struct ModuleConfig {
|
||||
int module_gap_row{};
|
||||
int module_gap_col{};
|
||||
|
||||
bool operator==(const ModuleConfig &other) const {
|
||||
if (module_gap_col != other.module_gap_col)
|
||||
return false;
|
||||
if (module_gap_row != other.module_gap_row)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
#ifdef AARE_TESTS
|
||||
TEST_CASE_PRIVATE_FWD(check_find_geometry) // forward declaration
|
||||
TEST_CASE_PRIVATE_FWD(open_multi_module_file_with_roi)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Class to read .raw files. The class will parse the master file
|
||||
@ -29,11 +26,17 @@ struct ModuleConfig {
|
||||
* Consider using that unless you need raw file specific functionality.
|
||||
*/
|
||||
class RawFile : public FileInterface {
|
||||
|
||||
#ifdef AARE_TESTS
|
||||
FRIEND_TEST(check_find_geometry)
|
||||
FRIEND_TEST(open_multi_module_file_with_roi)
|
||||
#endif
|
||||
std::vector<std::unique_ptr<RawSubFile>> m_subfiles;
|
||||
ModuleConfig cfg{0, 0};
|
||||
|
||||
RawMasterFile m_master;
|
||||
size_t m_current_frame{};
|
||||
size_t m_current_subfile{};
|
||||
|
||||
DetectorGeometry m_geometry;
|
||||
|
||||
public:
|
||||
@ -74,6 +77,13 @@ class RawFile : public FileInterface {
|
||||
|
||||
DetectorType detector_type() const override;
|
||||
|
||||
/**
|
||||
* @brief read the header of the file
|
||||
* @param fname path to the data subfile
|
||||
* @return DetectorHeader
|
||||
*/
|
||||
static DetectorHeader read_header(const std::filesystem::path &fname);
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief read the frame at the given frame index into the image buffer
|
||||
@ -91,15 +101,7 @@ class RawFile : public FileInterface {
|
||||
*/
|
||||
Frame get_frame(size_t frame_index);
|
||||
|
||||
/**
|
||||
* @brief read the header of the file
|
||||
* @param fname path to the data subfile
|
||||
* @return DetectorHeader
|
||||
*/
|
||||
static DetectorHeader read_header(const std::filesystem::path &fname);
|
||||
|
||||
void open_subfiles();
|
||||
void find_geometry();
|
||||
};
|
||||
|
||||
} // namespace aare
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include "aare/defs.hpp"
|
||||
#include <algorithm>
|
||||
#include <filesystem>
|
||||
#include <fmt/format.h>
|
||||
#include <fstream>
|
||||
@ -77,8 +78,11 @@ class RawMasterFile {
|
||||
size_t m_pixels_y{};
|
||||
size_t m_pixels_x{};
|
||||
size_t m_bitdepth{};
|
||||
size_t m_num_udp_interfaces_per_module = 1;
|
||||
uint8_t m_quad = 0;
|
||||
|
||||
xy m_geometry{};
|
||||
xy m_udp_interfaces_per_module{1, 1};
|
||||
|
||||
size_t m_max_frames_per_file{};
|
||||
// uint32_t m_adc_mask{}; // TODO! implement reading
|
||||
@ -96,7 +100,6 @@ class RawMasterFile {
|
||||
std::optional<size_t> m_digital_samples;
|
||||
std::optional<size_t> m_transceiver_samples;
|
||||
std::optional<size_t> m_number_of_rows;
|
||||
std::optional<uint8_t> m_quad;
|
||||
|
||||
std::optional<ROI> m_roi;
|
||||
|
||||
@ -115,17 +118,18 @@ class RawMasterFile {
|
||||
size_t max_frames_per_file() const;
|
||||
size_t bitdepth() const;
|
||||
size_t frame_padding() const;
|
||||
xy udp_interfaces_per_module() const;
|
||||
const FrameDiscardPolicy &frame_discard_policy() const;
|
||||
|
||||
size_t total_frames_expected() const;
|
||||
xy geometry() const;
|
||||
size_t n_modules() const;
|
||||
uint8_t quad() const;
|
||||
|
||||
std::optional<size_t> analog_samples() const;
|
||||
std::optional<size_t> digital_samples() const;
|
||||
std::optional<size_t> transceiver_samples() const;
|
||||
std::optional<size_t> number_of_rows() const;
|
||||
std::optional<uint8_t> quad() const;
|
||||
|
||||
std::optional<ROI> roi() const;
|
||||
|
||||
@ -134,6 +138,7 @@ class RawMasterFile {
|
||||
private:
|
||||
void parse_json(const std::filesystem::path &fpath);
|
||||
void parse_raw(const std::filesystem::path &fpath);
|
||||
void retrieve_geometry();
|
||||
};
|
||||
|
||||
} // namespace aare
|
@ -174,35 +174,6 @@ template <typename T> struct t_xy {
|
||||
};
|
||||
using xy = t_xy<uint32_t>;
|
||||
|
||||
/**
|
||||
* @brief Class to hold the geometry of a module. Where pixel 0 is located and
|
||||
* the size of the module
|
||||
*/
|
||||
struct ModuleGeometry {
|
||||
int origin_x{};
|
||||
int origin_y{};
|
||||
int height{};
|
||||
int width{};
|
||||
int row_index{};
|
||||
int col_index{};
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Class to hold the geometry of a detector. Number of modules, their
|
||||
* size and where pixel 0 for each module is located
|
||||
*/
|
||||
struct DetectorGeometry {
|
||||
int modules_x{};
|
||||
int modules_y{};
|
||||
int pixels_x{};
|
||||
int pixels_y{};
|
||||
int module_gap_row{};
|
||||
int module_gap_col{};
|
||||
std::vector<ModuleGeometry> module_pixel_0;
|
||||
|
||||
auto size() const { return module_pixel_0.size(); }
|
||||
};
|
||||
|
||||
struct ROI {
|
||||
ssize_t xmin{};
|
||||
ssize_t xmax{};
|
||||
|
@ -1,15 +0,0 @@
|
||||
#pragma once
|
||||
#include "aare/RawMasterFile.hpp" //ROI refactor away
|
||||
#include "aare/defs.hpp"
|
||||
namespace aare {
|
||||
|
||||
/**
|
||||
* @brief Update the detector geometry given a region of interest
|
||||
*
|
||||
* @param geo
|
||||
* @param roi
|
||||
* @return DetectorGeometry
|
||||
*/
|
||||
DetectorGeometry update_geometry_with_roi(DetectorGeometry geo, ROI roi);
|
||||
|
||||
} // namespace aare
|
@ -1,8 +1,16 @@
|
||||
|
||||
# from ._aare import ClusterFinder_Cluster3x3i, ClusterFinder_Cluster2x2i, ClusterFinderMT_Cluster3x3i, ClusterFinderMT_Cluster2x2i, ClusterCollector_Cluster3x3i, ClusterCollector_Cluster2x2i
|
||||
|
||||
|
||||
# from ._aare import ClusterFileSink_Cluster3x3i, ClusterFileSink_Cluster2x2i
|
||||
|
||||
from . import _aare
|
||||
import numpy as np
|
||||
|
||||
_supported_cluster_sizes = [(2,2), (3,3), (5,5), (7,7), (9,9),]
|
||||
|
||||
# def _get_class()
|
||||
|
||||
def _type_to_char(dtype):
|
||||
if dtype == np.int32:
|
||||
return 'i'
|
||||
@ -66,22 +74,11 @@ def ClusterFileSink(clusterfindermt, cluster_file, dtype=np.int32):
|
||||
return cls(clusterfindermt, cluster_file)
|
||||
|
||||
|
||||
def ClusterFile(fname, cluster_size=(3,3), dtype=np.int32, chunk_size = 1000):
|
||||
def ClusterFile(fname, cluster_size=(3,3), dtype=np.int32):
|
||||
"""
|
||||
Factory function to create a ClusterFile object. Provides a cleaner syntax for
|
||||
the templated ClusterFile in C++.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from aare import ClusterFile
|
||||
|
||||
with ClusterFile("clusters.clust", cluster_size=(3,3), dtype=np.int32) as cf:
|
||||
# cf is now a ClusterFile_Cluster3x3i object but you don't need to know that.
|
||||
for clusters in cf:
|
||||
# Loop over clusters in chunks of 1000
|
||||
# The type of clusters will be a ClusterVector_Cluster3x3i in this case
|
||||
|
||||
"""
|
||||
|
||||
cls = _get_class("ClusterFile", cluster_size, dtype)
|
||||
return cls(fname, chunk_size=chunk_size)
|
||||
return cls(fname)
|
||||
|
@ -38,20 +38,19 @@ void define_ClusterFile(py::module &m, const std::string &typestr) {
|
||||
self.read_clusters(n_clusters));
|
||||
return v;
|
||||
},
|
||||
py::return_value_policy::take_ownership, py::arg("n_clusters"))
|
||||
py::return_value_policy::take_ownership)
|
||||
.def("read_frame",
|
||||
[](ClusterFile<ClusterType> &self) {
|
||||
auto v = new ClusterVector<ClusterType>(self.read_frame());
|
||||
return v;
|
||||
})
|
||||
.def("set_roi", &ClusterFile<ClusterType>::set_roi,
|
||||
py::arg("roi"))
|
||||
.def("set_roi", &ClusterFile<ClusterType>::set_roi)
|
||||
.def(
|
||||
"set_noise_map",
|
||||
[](ClusterFile<ClusterType> &self, py::array_t<int32_t> noise_map) {
|
||||
auto view = make_view_2d(noise_map);
|
||||
self.set_noise_map(view);
|
||||
}, py::arg("noise_map"))
|
||||
})
|
||||
|
||||
.def("set_gain_map",
|
||||
[](ClusterFile<ClusterType> &self, py::array_t<double> gain_map) {
|
||||
|
@ -101,7 +101,7 @@ void define_raw_file_io_bindings(py::module &m) {
|
||||
.def_property_readonly("cols", &RawFile::cols)
|
||||
.def_property_readonly("bitdepth", &RawFile::bitdepth)
|
||||
.def_property_readonly("geometry", &RawFile::geometry)
|
||||
.def_property_readonly("n_modules", &RawFile::n_modules)
|
||||
.def_property_readonly("detector_type", &RawFile::detector_type)
|
||||
.def_property_readonly("master", &RawFile::master);
|
||||
.def_property_readonly("master", &RawFile::master)
|
||||
.def_property_readonly("n_modules", &RawFile::n_modules);
|
||||
}
|
@ -57,6 +57,8 @@ void define_raw_master_file_bindings(py::module &m) {
|
||||
.def_property_readonly("total_frames_expected",
|
||||
&RawMasterFile::total_frames_expected)
|
||||
.def_property_readonly("geometry", &RawMasterFile::geometry)
|
||||
.def_property_readonly("udp_interfaces_per_module",
|
||||
&RawMasterFile::udp_interfaces_per_module)
|
||||
.def_property_readonly("analog_samples", &RawMasterFile::analog_samples,
|
||||
R"(
|
||||
Number of analog samples
|
||||
|
@ -58,8 +58,10 @@ class ClusterFinderMTWrapper
|
||||
};
|
||||
|
||||
TEST_CASE("multithreaded cluster finder", "[.files][.ClusterFinder]") {
|
||||
auto fpath = "/mnt/sls_det_storage/matterhorn_data/aare_test_data/"
|
||||
"Moench03new/cu_half_speed_master_4.json";
|
||||
auto fpath =
|
||||
test_data_path() / "clust/Moench03new/cu_half_speed_master_4.json";
|
||||
|
||||
REQUIRE(std::filesystem::exists(fpath));
|
||||
|
||||
File file(fpath);
|
||||
|
||||
|
152
src/DetectorGeometry.cpp
Normal file
152
src/DetectorGeometry.cpp
Normal file
@ -0,0 +1,152 @@
|
||||
|
||||
#include "aare/DetectorGeometry.hpp"
|
||||
#include "fmt/core.h"
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
namespace aare {
|
||||
|
||||
DetectorGeometry::DetectorGeometry(const xy &geometry,
|
||||
const ssize_t module_pixels_x,
|
||||
const ssize_t module_pixels_y,
|
||||
const xy udp_interfaces_per_module,
|
||||
const bool quad) {
|
||||
|
||||
size_t num_modules = geometry.col * geometry.row;
|
||||
module_geometries.reserve(num_modules);
|
||||
for (size_t col = 0; col < geometry.col;
|
||||
col += udp_interfaces_per_module.col)
|
||||
for (size_t row = 0; row < geometry.row;
|
||||
row += udp_interfaces_per_module.row) {
|
||||
for (size_t port_row = 0; port_row < udp_interfaces_per_module.row;
|
||||
++port_row)
|
||||
for (size_t port_col = 0;
|
||||
port_col < udp_interfaces_per_module.col; ++port_col) {
|
||||
ModuleGeometry g;
|
||||
g.origin_x = (col + port_col) * module_pixels_x;
|
||||
g.origin_y = (row + port_row) *
|
||||
module_pixels_y; // TODO: quad doesnt seem
|
||||
// to have an effect
|
||||
g.row_index =
|
||||
quad ? (row + port_row + 1) % 2 : (row + port_row);
|
||||
g.col_index = col + port_col;
|
||||
g.width = module_pixels_x;
|
||||
g.height = module_pixels_y;
|
||||
module_geometries.push_back(g);
|
||||
}
|
||||
}
|
||||
|
||||
m_pixels_y = (geometry.row * module_pixels_y);
|
||||
m_pixels_x = (geometry.col * module_pixels_x);
|
||||
m_modules_x = geometry.col;
|
||||
m_modules_y = geometry.row;
|
||||
m_pixels_y += static_cast<size_t>((geometry.row - 1) * cfg.module_gap_row);
|
||||
|
||||
modules_in_roi.resize(num_modules);
|
||||
std::iota(modules_in_roi.begin(), modules_in_roi.end(), 0);
|
||||
}
|
||||
|
||||
size_t DetectorGeometry::n_modules() const { return m_modules_x * m_modules_y; }
|
||||
|
||||
size_t DetectorGeometry::n_modules_in_roi() const {
|
||||
return modules_in_roi.size();
|
||||
};
|
||||
|
||||
size_t DetectorGeometry::pixels_x() const { return m_pixels_x; }
|
||||
size_t DetectorGeometry::pixels_y() const { return m_pixels_y; }
|
||||
|
||||
size_t DetectorGeometry::modules_x() const { return m_modules_x; };
|
||||
size_t DetectorGeometry::modules_y() const { return m_modules_y; };
|
||||
|
||||
const std::vector<ssize_t> &DetectorGeometry::get_modules_in_roi() const {
|
||||
return modules_in_roi;
|
||||
}
|
||||
|
||||
ssize_t DetectorGeometry::get_modules_in_roi(const size_t index) const {
|
||||
return modules_in_roi[index];
|
||||
}
|
||||
|
||||
const std::vector<ModuleGeometry> &
|
||||
DetectorGeometry::get_module_geometries() const {
|
||||
return module_geometries;
|
||||
}
|
||||
|
||||
const ModuleGeometry &
|
||||
DetectorGeometry::get_module_geometries(const size_t index) const {
|
||||
return module_geometries[index];
|
||||
}
|
||||
|
||||
void DetectorGeometry::update_geometry_with_roi(ROI roi) {
|
||||
#ifdef AARE_VERBOSE
|
||||
fmt::println("update_geometry_with_roi() called with ROI: {} {} {} {}",
|
||||
roi.xmin, roi.xmax, roi.ymin, roi.ymax);
|
||||
fmt::println("Geometry: {} {} {} {} {} {}", m_modules_x, m_modules_y,
|
||||
m_pixels_x, m_pixels_y, cfg.module_gap_row,
|
||||
cfg.module_gap_col);
|
||||
|
||||
#endif
|
||||
|
||||
modules_in_roi.clear();
|
||||
modules_in_roi.reserve(m_modules_x * m_modules_y);
|
||||
int pos_y = 0;
|
||||
int pos_y_increment = 0;
|
||||
for (size_t row = 0; row < m_modules_y; row++) {
|
||||
int pos_x = 0;
|
||||
for (size_t col = 0; col < m_modules_x; col++) {
|
||||
auto &m = module_geometries[row * m_modules_x + col];
|
||||
|
||||
auto original_height = m.height;
|
||||
auto original_width = m.width;
|
||||
|
||||
// module is to the left of the roi
|
||||
if (m.origin_x + m.width < roi.xmin) {
|
||||
m.width = 0;
|
||||
|
||||
// roi is in module
|
||||
} else {
|
||||
// here we only arrive when the roi is in or to the left of
|
||||
// the module
|
||||
if (roi.xmin > m.origin_x) {
|
||||
m.width -= roi.xmin - m.origin_x;
|
||||
}
|
||||
if (roi.xmax < m.origin_x + original_width) {
|
||||
m.width -= m.origin_x + original_width - roi.xmax;
|
||||
}
|
||||
m.origin_x = pos_x;
|
||||
pos_x += m.width;
|
||||
}
|
||||
|
||||
if (m.origin_y + m.height < roi.ymin) {
|
||||
m.height = 0;
|
||||
} else {
|
||||
if ((roi.ymin > m.origin_y) &&
|
||||
(roi.ymin < m.origin_y + m.height)) {
|
||||
m.height -= roi.ymin - m.origin_y;
|
||||
}
|
||||
if (roi.ymax < m.origin_y + original_height) {
|
||||
m.height -= m.origin_y + original_height - roi.ymax;
|
||||
}
|
||||
m.origin_y = pos_y;
|
||||
pos_y_increment = m.height;
|
||||
}
|
||||
|
||||
if (m.height != 0 && m.width != 0) {
|
||||
modules_in_roi.push_back(row * m_modules_x + col);
|
||||
}
|
||||
|
||||
#ifdef AARE_VERBOSE
|
||||
fmt::println("Module {} {} {} {}", m.origin_x, m.origin_y, m.width,
|
||||
m.height);
|
||||
#endif
|
||||
}
|
||||
// increment pos_y
|
||||
pos_y += pos_y_increment;
|
||||
}
|
||||
|
||||
// m_rows = roi.height();
|
||||
// m_cols = roi.width();
|
||||
m_pixels_x = roi.width();
|
||||
m_pixels_y = roi.height();
|
||||
}
|
||||
|
||||
} // namespace aare
|
194
src/DetectorGeometry.test.cpp
Normal file
194
src/DetectorGeometry.test.cpp
Normal file
@ -0,0 +1,194 @@
|
||||
#include "aare/File.hpp"
|
||||
#include "aare/RawFile.hpp"
|
||||
#include "aare/RawMasterFile.hpp" //needed for ROI
|
||||
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <filesystem>
|
||||
|
||||
#include "aare/DetectorGeometry.hpp"
|
||||
#include "test_config.hpp"
|
||||
|
||||
TEST_CASE("Simple ROIs on one module") {
|
||||
// DetectorGeometry update_geometry_with_roi(DetectorGeometry geo, aare::ROI
|
||||
// roi)
|
||||
aare::DetectorGeometry geo(aare::xy{1, 1}, 1024, 512);
|
||||
|
||||
REQUIRE(geo.get_module_geometries(0).origin_x == 0);
|
||||
REQUIRE(geo.get_module_geometries(0).origin_y == 0);
|
||||
REQUIRE(geo.get_module_geometries(0).width == 1024);
|
||||
REQUIRE(geo.get_module_geometries(0).height == 512);
|
||||
|
||||
SECTION("ROI is the whole module") {
|
||||
aare::ROI roi;
|
||||
roi.xmin = 0;
|
||||
roi.xmax = 1024;
|
||||
roi.ymin = 0;
|
||||
roi.ymax = 512;
|
||||
geo.update_geometry_with_roi(roi);
|
||||
|
||||
REQUIRE(geo.pixels_x() == 1024);
|
||||
REQUIRE(geo.pixels_y() == 512);
|
||||
REQUIRE(geo.modules_x() == 1);
|
||||
REQUIRE(geo.modules_y() == 1);
|
||||
REQUIRE(geo.get_module_geometries(0).height == 512);
|
||||
REQUIRE(geo.get_module_geometries(0).width == 1024);
|
||||
}
|
||||
SECTION("ROI is the top left corner of the module") {
|
||||
aare::ROI roi;
|
||||
roi.xmin = 100;
|
||||
roi.xmax = 200;
|
||||
roi.ymin = 150;
|
||||
roi.ymax = 200;
|
||||
geo.update_geometry_with_roi(roi);
|
||||
|
||||
REQUIRE(geo.pixels_x() == 100);
|
||||
REQUIRE(geo.pixels_y() == 50);
|
||||
REQUIRE(geo.modules_x() == 1);
|
||||
REQUIRE(geo.modules_y() == 1);
|
||||
REQUIRE(geo.get_module_geometries(0).height == 50);
|
||||
REQUIRE(geo.get_module_geometries(0).width == 100);
|
||||
}
|
||||
|
||||
SECTION("ROI is a small square") {
|
||||
aare::ROI roi;
|
||||
roi.xmin = 1000;
|
||||
roi.xmax = 1010;
|
||||
roi.ymin = 500;
|
||||
roi.ymax = 510;
|
||||
geo.update_geometry_with_roi(roi);
|
||||
|
||||
REQUIRE(geo.pixels_x() == 10);
|
||||
REQUIRE(geo.pixels_y() == 10);
|
||||
REQUIRE(geo.modules_x() == 1);
|
||||
REQUIRE(geo.modules_y() == 1);
|
||||
REQUIRE(geo.get_module_geometries(0).height == 10);
|
||||
REQUIRE(geo.get_module_geometries(0).width == 10);
|
||||
}
|
||||
SECTION("ROI is a few columns") {
|
||||
aare::ROI roi;
|
||||
roi.xmin = 750;
|
||||
roi.xmax = 800;
|
||||
roi.ymin = 0;
|
||||
roi.ymax = 512;
|
||||
geo.update_geometry_with_roi(roi);
|
||||
|
||||
REQUIRE(geo.pixels_x() == 50);
|
||||
REQUIRE(geo.pixels_y() == 512);
|
||||
REQUIRE(geo.modules_x() == 1);
|
||||
REQUIRE(geo.modules_y() == 1);
|
||||
REQUIRE(geo.get_module_geometries(0).height == 512);
|
||||
REQUIRE(geo.get_module_geometries(0).width == 50);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Two modules side by side") {
|
||||
// DetectorGeometry update_geometry_with_roi(DetectorGeometry geo, aare::ROI
|
||||
// roi)
|
||||
aare::DetectorGeometry geo(aare::xy{1, 2}, 1024, 512);
|
||||
|
||||
REQUIRE(geo.get_module_geometries(0).origin_x == 0);
|
||||
REQUIRE(geo.get_module_geometries(0).origin_y == 0);
|
||||
REQUIRE(geo.get_module_geometries(0).width == 1024);
|
||||
REQUIRE(geo.get_module_geometries(0).height == 512);
|
||||
REQUIRE(geo.get_module_geometries(1).origin_x == 1024);
|
||||
REQUIRE(geo.get_module_geometries(1).origin_y == 0);
|
||||
|
||||
SECTION("ROI is the whole image") {
|
||||
aare::ROI roi;
|
||||
roi.xmin = 0;
|
||||
roi.xmax = 2048;
|
||||
roi.ymin = 0;
|
||||
roi.ymax = 512;
|
||||
geo.update_geometry_with_roi(roi);
|
||||
|
||||
REQUIRE(geo.pixels_x() == 2048);
|
||||
REQUIRE(geo.pixels_y() == 512);
|
||||
REQUIRE(geo.modules_x() == 2);
|
||||
REQUIRE(geo.modules_y() == 1);
|
||||
}
|
||||
SECTION("rectangle on both modules") {
|
||||
aare::ROI roi;
|
||||
roi.xmin = 800;
|
||||
roi.xmax = 1300;
|
||||
roi.ymin = 200;
|
||||
roi.ymax = 499;
|
||||
geo.update_geometry_with_roi(roi);
|
||||
|
||||
REQUIRE(geo.pixels_x() == 500);
|
||||
REQUIRE(geo.pixels_y() == 299);
|
||||
REQUIRE(geo.modules_x() == 2);
|
||||
REQUIRE(geo.modules_y() == 1);
|
||||
REQUIRE(geo.get_module_geometries(0).height == 299);
|
||||
REQUIRE(geo.get_module_geometries(0).width == 224);
|
||||
REQUIRE(geo.get_module_geometries(1).height == 299);
|
||||
REQUIRE(geo.get_module_geometries(1).width == 276);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Three modules side by side") {
|
||||
// DetectorGeometry update_geometry_with_roi(DetectorGeometry geo, aare::ROI
|
||||
// roi)
|
||||
aare::DetectorGeometry geo(aare::xy{1, 3}, 1024, 512);
|
||||
aare::ROI roi;
|
||||
roi.xmin = 700;
|
||||
roi.xmax = 2500;
|
||||
roi.ymin = 0;
|
||||
roi.ymax = 123;
|
||||
|
||||
REQUIRE(geo.get_module_geometries(0).origin_x == 0);
|
||||
REQUIRE(geo.get_module_geometries(0).origin_y == 0);
|
||||
REQUIRE(geo.get_module_geometries(0).width == 1024);
|
||||
REQUIRE(geo.get_module_geometries(0).height == 512);
|
||||
REQUIRE(geo.get_module_geometries(1).origin_x == 1024);
|
||||
REQUIRE(geo.get_module_geometries(2).origin_x == 2048);
|
||||
|
||||
geo.update_geometry_with_roi(roi);
|
||||
|
||||
REQUIRE(geo.pixels_x() == 1800);
|
||||
REQUIRE(geo.pixels_y() == 123);
|
||||
REQUIRE(geo.modules_x() == 3);
|
||||
REQUIRE(geo.modules_y() == 1);
|
||||
REQUIRE(geo.get_module_geometries(0).height == 123);
|
||||
REQUIRE(geo.get_module_geometries(0).width == 324);
|
||||
REQUIRE(geo.get_module_geometries(1).height == 123);
|
||||
REQUIRE(geo.get_module_geometries(1).width == 1024);
|
||||
REQUIRE(geo.get_module_geometries(2).height == 123);
|
||||
REQUIRE(geo.get_module_geometries(2).width == 452);
|
||||
}
|
||||
|
||||
TEST_CASE("Four modules as a square") {
|
||||
// DetectorGeometry update_geometry_with_roi(DetectorGeometry geo, aare::ROI
|
||||
// roi)
|
||||
aare::DetectorGeometry geo(aare::xy{2, 2}, 1024, 512, aare::xy{1, 2});
|
||||
aare::ROI roi;
|
||||
roi.xmin = 500;
|
||||
roi.xmax = 2000;
|
||||
roi.ymin = 500;
|
||||
roi.ymax = 600;
|
||||
|
||||
REQUIRE(geo.get_module_geometries(0).origin_x == 0);
|
||||
REQUIRE(geo.get_module_geometries(0).origin_y == 0);
|
||||
REQUIRE(geo.get_module_geometries(0).width == 1024);
|
||||
REQUIRE(geo.get_module_geometries(0).height == 512);
|
||||
REQUIRE(geo.get_module_geometries(1).origin_x == 1024);
|
||||
REQUIRE(geo.get_module_geometries(1).origin_y == 0);
|
||||
REQUIRE(geo.get_module_geometries(2).origin_x == 0);
|
||||
REQUIRE(geo.get_module_geometries(2).origin_y == 512);
|
||||
REQUIRE(geo.get_module_geometries(3).origin_x == 1024);
|
||||
REQUIRE(geo.get_module_geometries(3).origin_y == 512);
|
||||
|
||||
geo.update_geometry_with_roi(roi);
|
||||
|
||||
REQUIRE(geo.pixels_x() == 1500);
|
||||
REQUIRE(geo.pixels_y() == 100);
|
||||
REQUIRE(geo.modules_x() == 2);
|
||||
REQUIRE(geo.modules_y() == 2);
|
||||
REQUIRE(geo.get_module_geometries(0).height == 12);
|
||||
REQUIRE(geo.get_module_geometries(0).width == 524);
|
||||
REQUIRE(geo.get_module_geometries(1).height == 12);
|
||||
REQUIRE(geo.get_module_geometries(1).width == 976);
|
||||
REQUIRE(geo.get_module_geometries(2).height == 88);
|
||||
REQUIRE(geo.get_module_geometries(2).width == 524);
|
||||
REQUIRE(geo.get_module_geometries(3).height == 88);
|
||||
REQUIRE(geo.get_module_geometries(3).width == 976);
|
||||
}
|
122
src/RawFile.cpp
122
src/RawFile.cpp
@ -1,8 +1,8 @@
|
||||
#include "aare/RawFile.hpp"
|
||||
#include "aare/DetectorGeometry.hpp"
|
||||
#include "aare/PixelMap.hpp"
|
||||
#include "aare/algorithm.hpp"
|
||||
#include "aare/defs.hpp"
|
||||
#include "aare/geo_helpers.hpp"
|
||||
#include "aare/logger.hpp"
|
||||
|
||||
#include <fmt/format.h>
|
||||
@ -13,13 +13,14 @@ using json = nlohmann::json;
|
||||
namespace aare {
|
||||
|
||||
RawFile::RawFile(const std::filesystem::path &fname, const std::string &mode)
|
||||
: m_master(fname) {
|
||||
: m_master(fname),
|
||||
m_geometry(m_master.geometry(), m_master.pixels_x(), m_master.pixels_y(),
|
||||
m_master.udp_interfaces_per_module(), m_master.quad()) {
|
||||
m_mode = mode;
|
||||
|
||||
if (mode == "r") {
|
||||
find_geometry();
|
||||
if (m_master.roi()) {
|
||||
m_geometry =
|
||||
update_geometry_with_roi(m_geometry, m_master.roi().value());
|
||||
m_geometry.update_geometry_with_roi(m_master.roi().value());
|
||||
}
|
||||
open_subfiles();
|
||||
} else {
|
||||
@ -61,26 +62,25 @@ void RawFile::read_into(std::byte *image_buf, size_t n_frames,
|
||||
this->get_frame_into(m_current_frame++, image_buf, header);
|
||||
image_buf += bytes_per_frame();
|
||||
if (header)
|
||||
header += n_modules();
|
||||
header += m_geometry.n_modules();
|
||||
}
|
||||
}
|
||||
|
||||
size_t RawFile::n_modules() const { return m_master.n_modules(); }
|
||||
|
||||
size_t RawFile::bytes_per_frame() {
|
||||
return m_geometry.pixels_x * m_geometry.pixels_y * m_master.bitdepth() /
|
||||
return m_geometry.pixels_x() * m_geometry.pixels_y() * m_master.bitdepth() /
|
||||
bits_per_byte;
|
||||
}
|
||||
size_t RawFile::pixels_per_frame() {
|
||||
// return m_rows * m_cols;
|
||||
return m_geometry.pixels_x * m_geometry.pixels_y;
|
||||
return m_geometry.pixels_x() * m_geometry.pixels_y();
|
||||
}
|
||||
|
||||
DetectorType RawFile::detector_type() const { return m_master.detector_type(); }
|
||||
|
||||
void RawFile::seek(size_t frame_index) {
|
||||
// check if the frame number is greater than the total frames
|
||||
// if frame_number == total_frames, then the next read will throw an error
|
||||
// if frame_number == total_frames, then the next read will throw an
|
||||
// error
|
||||
if (frame_index > total_frames()) {
|
||||
throw std::runtime_error(
|
||||
fmt::format("frame number {} is greater than total frames {}",
|
||||
@ -92,15 +92,17 @@ void RawFile::seek(size_t frame_index) {
|
||||
size_t RawFile::tell() { return m_current_frame; }
|
||||
|
||||
size_t RawFile::total_frames() const { return m_master.frames_in_file(); }
|
||||
size_t RawFile::rows() const { return m_geometry.pixels_y; }
|
||||
size_t RawFile::cols() const { return m_geometry.pixels_x; }
|
||||
size_t RawFile::rows() const { return m_geometry.pixels_y(); }
|
||||
size_t RawFile::cols() const { return m_geometry.pixels_x(); }
|
||||
size_t RawFile::bitdepth() const { return m_master.bitdepth(); }
|
||||
xy RawFile::geometry() { return m_master.geometry(); }
|
||||
|
||||
size_t RawFile::n_modules() const { return m_geometry.n_modules(); };
|
||||
|
||||
void RawFile::open_subfiles() {
|
||||
if (m_mode == "r")
|
||||
for (size_t i = 0; i != n_modules(); ++i) {
|
||||
auto pos = m_geometry.module_pixel_0[i];
|
||||
for (size_t i : m_geometry.get_modules_in_roi()) {
|
||||
auto pos = m_geometry.get_module_geometries(i);
|
||||
m_subfiles.emplace_back(std::make_unique<RawSubFile>(
|
||||
m_master.data_fname(i, 0), m_master.detector_type(), pos.height,
|
||||
pos.width, m_master.bitdepth(), pos.row_index, pos.col_index));
|
||||
@ -130,45 +132,8 @@ DetectorHeader RawFile::read_header(const std::filesystem::path &fname) {
|
||||
|
||||
RawMasterFile RawFile::master() const { return m_master; }
|
||||
|
||||
/**
|
||||
* @brief Find the geometry of the detector by opening all the subfiles and
|
||||
* reading the headers.
|
||||
*/
|
||||
void RawFile::find_geometry() {
|
||||
|
||||
// Hold the maximal row and column number found
|
||||
// Later used for calculating the total number of rows and columns
|
||||
uint16_t r{};
|
||||
uint16_t c{};
|
||||
|
||||
for (size_t i = 0; i < n_modules(); i++) {
|
||||
auto h = read_header(m_master.data_fname(i, 0));
|
||||
r = std::max(r, h.row);
|
||||
c = std::max(c, h.column);
|
||||
// positions.push_back({h.row, h.column});
|
||||
|
||||
ModuleGeometry g;
|
||||
g.origin_x = h.column * m_master.pixels_x();
|
||||
g.origin_y = h.row * m_master.pixels_y();
|
||||
g.row_index = h.row;
|
||||
g.col_index = h.column;
|
||||
g.width = m_master.pixels_x();
|
||||
g.height = m_master.pixels_y();
|
||||
m_geometry.module_pixel_0.push_back(g);
|
||||
}
|
||||
|
||||
r++;
|
||||
c++;
|
||||
|
||||
m_geometry.pixels_y = (r * m_master.pixels_y());
|
||||
m_geometry.pixels_x = (c * m_master.pixels_x());
|
||||
m_geometry.modules_x = c;
|
||||
m_geometry.modules_y = r;
|
||||
m_geometry.pixels_y += static_cast<size_t>((r - 1) * cfg.module_gap_row);
|
||||
}
|
||||
|
||||
Frame RawFile::get_frame(size_t frame_index) {
|
||||
auto f = Frame(m_geometry.pixels_y, m_geometry.pixels_x,
|
||||
auto f = Frame(m_geometry.pixels_y(), m_geometry.pixels_x(),
|
||||
Dtype::from_bitdepth(m_master.bitdepth()));
|
||||
std::byte *frame_buffer = f.data();
|
||||
get_frame_into(frame_index, frame_buffer);
|
||||
@ -183,13 +148,15 @@ void RawFile::get_frame_into(size_t frame_index, std::byte *frame_buffer,
|
||||
if (frame_index >= total_frames()) {
|
||||
throw std::runtime_error(LOCATION + "Frame number out of range");
|
||||
}
|
||||
std::vector<size_t> frame_numbers(n_modules());
|
||||
std::vector<size_t> frame_indices(n_modules(), frame_index);
|
||||
std::vector<size_t> frame_numbers(m_geometry.n_modules_in_roi());
|
||||
std::vector<size_t> frame_indices(m_geometry.n_modules_in_roi(),
|
||||
frame_index);
|
||||
|
||||
// sync the frame numbers
|
||||
|
||||
if (n_modules() != 1) { // if we have more than one module
|
||||
for (size_t part_idx = 0; part_idx != n_modules(); ++part_idx) {
|
||||
if (m_geometry.n_modules() != 1) { // if we have more than one module
|
||||
for (size_t part_idx = 0; part_idx != m_geometry.n_modules_in_roi();
|
||||
++part_idx) {
|
||||
frame_numbers[part_idx] =
|
||||
m_subfiles[part_idx]->frame_number(frame_index);
|
||||
}
|
||||
@ -219,19 +186,32 @@ void RawFile::get_frame_into(size_t frame_index, std::byte *frame_buffer,
|
||||
|
||||
if (m_master.geometry().col == 1) {
|
||||
// get the part from each subfile and copy it to the frame
|
||||
for (size_t part_idx = 0; part_idx != n_modules(); ++part_idx) {
|
||||
for (size_t part_idx = 0; part_idx != m_geometry.n_modules_in_roi();
|
||||
++part_idx) {
|
||||
auto corrected_idx = frame_indices[part_idx];
|
||||
|
||||
// This is where we start writing
|
||||
auto offset = (m_geometry.module_pixel_0[part_idx].origin_y *
|
||||
m_geometry.pixels_x +
|
||||
m_geometry.module_pixel_0[part_idx].origin_x) *
|
||||
auto offset = (m_geometry
|
||||
.get_module_geometries(
|
||||
m_geometry.get_modules_in_roi(part_idx))
|
||||
.origin_y *
|
||||
m_geometry.pixels_x() +
|
||||
m_geometry
|
||||
.get_module_geometries(
|
||||
m_geometry.get_modules_in_roi(part_idx))
|
||||
.origin_x) *
|
||||
m_master.bitdepth() / 8;
|
||||
|
||||
if (m_geometry.module_pixel_0[part_idx].origin_x != 0)
|
||||
throw std::runtime_error(LOCATION +
|
||||
" Implementation error. x pos not 0.");
|
||||
|
||||
if (m_geometry
|
||||
.get_module_geometries(
|
||||
m_geometry.get_modules_in_roi(part_idx))
|
||||
.origin_x != 0)
|
||||
throw std::runtime_error(
|
||||
LOCATION +
|
||||
" Implementation error. x pos not 0."); // TODO: origin
|
||||
// can still
|
||||
// change if roi
|
||||
// changes
|
||||
// TODO! What if the files don't match?
|
||||
m_subfiles[part_idx]->seek(corrected_idx);
|
||||
m_subfiles[part_idx]->read_into(frame_buffer + offset, header);
|
||||
@ -249,11 +229,13 @@ void RawFile::get_frame_into(size_t frame_index, std::byte *frame_buffer,
|
||||
|
||||
auto *part_buffer = new std::byte[bytes_per_part];
|
||||
|
||||
// TODO! if we have many submodules we should reorder them on the module
|
||||
// level
|
||||
// TODO! if we have many submodules we should reorder them on the
|
||||
// module level
|
||||
|
||||
for (size_t part_idx = 0; part_idx != n_modules(); ++part_idx) {
|
||||
auto pos = m_geometry.module_pixel_0[part_idx];
|
||||
for (size_t part_idx = 0; part_idx != m_geometry.n_modules_in_roi();
|
||||
++part_idx) {
|
||||
auto pos = m_geometry.get_module_geometries(
|
||||
m_geometry.get_modules_in_roi(part_idx));
|
||||
auto corrected_idx = frame_indices[part_idx];
|
||||
|
||||
m_subfiles[part_idx]->seek(corrected_idx);
|
||||
@ -266,7 +248,7 @@ void RawFile::get_frame_into(size_t frame_index, std::byte *frame_buffer,
|
||||
|
||||
auto irow = (pos.origin_y + cur_row);
|
||||
auto icol = pos.origin_x;
|
||||
auto dest = (irow * this->m_geometry.pixels_x + icol);
|
||||
auto dest = (irow * this->m_geometry.pixels_x() + icol);
|
||||
dest = dest * m_master.bitdepth() / 8;
|
||||
memcpy(frame_buffer + dest,
|
||||
part_buffer +
|
||||
|
@ -3,11 +3,15 @@
|
||||
#include "aare/RawMasterFile.hpp" //needed for ROI
|
||||
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <catch2/generators/catch_generators.hpp>
|
||||
#include <filesystem>
|
||||
|
||||
#include "test_config.hpp"
|
||||
#include "test_macros.hpp"
|
||||
|
||||
using aare::File;
|
||||
using aare::RawFile;
|
||||
using namespace aare;
|
||||
|
||||
TEST_CASE("Read number of frames from a jungfrau raw file", "[.integration]") {
|
||||
|
||||
@ -160,6 +164,108 @@ TEST_CASE("Read multipart files", "[.integration]") {
|
||||
}
|
||||
}
|
||||
|
||||
struct TestParameters {
|
||||
const std::string master_filename{};
|
||||
const uint8_t num_ports{};
|
||||
const size_t modules_x{};
|
||||
const size_t modules_y{};
|
||||
const size_t pixels_x{};
|
||||
const size_t pixels_y{};
|
||||
std::vector<ModuleGeometry> module_geometries{};
|
||||
};
|
||||
|
||||
TEST_CASE_PRIVATE(aare, check_find_geometry, "check find_geometry",
|
||||
"[.integration][.files][.rawfile]") {
|
||||
|
||||
auto test_parameters = GENERATE(
|
||||
TestParameters{"raw/jungfrau_2modules_version6.1.2/run_master_0.raw", 2,
|
||||
1, 2, 1024, 1024,
|
||||
std::vector<ModuleGeometry>{
|
||||
ModuleGeometry{0, 0, 512, 1024, 0, 0},
|
||||
ModuleGeometry{0, 512, 512, 1024, 0, 1}}},
|
||||
TestParameters{
|
||||
"raw/eiger_1_module_version7.0.0/eiger_1mod_master_7.json", 4, 2, 2,
|
||||
1024, 512,
|
||||
std::vector<ModuleGeometry>{
|
||||
ModuleGeometry{0, 0, 256, 512, 0, 0},
|
||||
ModuleGeometry{512, 0, 256, 512, 0, 1},
|
||||
ModuleGeometry{0, 256, 256, 512, 1, 0},
|
||||
ModuleGeometry{512, 256, 256, 512, 1, 1}}},
|
||||
|
||||
TestParameters{"raw/jungfrau_2modules_2interfaces/run_master_0.json", 4,
|
||||
1, 4, 1024, 1024,
|
||||
std::vector<ModuleGeometry>{
|
||||
ModuleGeometry{0, 0, 256, 1024, 0, 0},
|
||||
ModuleGeometry{0, 256, 256, 1024, 1, 0},
|
||||
ModuleGeometry{0, 512, 256, 1024, 2, 0},
|
||||
ModuleGeometry{0, 768, 256, 1024, 3, 0}}},
|
||||
TestParameters{
|
||||
"raw/eiger_quad_data/"
|
||||
"W13_vthreshscan_m21C_300V_800eV_vrpre3400_master_0.json",
|
||||
2, 1, 2, 512, 512,
|
||||
std::vector<ModuleGeometry>{
|
||||
ModuleGeometry{0, 0, 256, 512, 0, 0},
|
||||
ModuleGeometry{0, 256, 256, 512, 1, 0}}});
|
||||
|
||||
auto fpath = test_data_path() / test_parameters.master_filename;
|
||||
|
||||
REQUIRE(std::filesystem::exists(fpath));
|
||||
|
||||
RawFile f(fpath, "r");
|
||||
|
||||
auto geometry = f.m_geometry;
|
||||
|
||||
CHECK(geometry.modules_x() == test_parameters.modules_x);
|
||||
CHECK(geometry.modules_y() == test_parameters.modules_y);
|
||||
CHECK(geometry.pixels_x() == test_parameters.pixels_x);
|
||||
CHECK(geometry.pixels_y() == test_parameters.pixels_y);
|
||||
|
||||
REQUIRE(geometry.get_module_geometries().size() ==
|
||||
test_parameters.num_ports);
|
||||
|
||||
// compare to data stored in header
|
||||
for (size_t i = 0; i < test_parameters.num_ports; ++i) {
|
||||
|
||||
auto subfile1_path = f.master().data_fname(i, 0);
|
||||
REQUIRE(std::filesystem::exists(subfile1_path));
|
||||
|
||||
auto header = RawFile::read_header(subfile1_path);
|
||||
|
||||
CHECK(header.column == geometry.get_module_geometries(i).col_index);
|
||||
CHECK(header.row == geometry.get_module_geometries(i).row_index);
|
||||
|
||||
CHECK(geometry.get_module_geometries(i).height ==
|
||||
test_parameters.module_geometries[i].height);
|
||||
CHECK(geometry.get_module_geometries(i).width ==
|
||||
test_parameters.module_geometries[i].width);
|
||||
|
||||
CHECK(geometry.get_module_geometries(i).origin_x ==
|
||||
test_parameters.module_geometries[i].origin_x);
|
||||
CHECK(geometry.get_module_geometries(i).origin_y ==
|
||||
test_parameters.module_geometries[i].origin_y);
|
||||
}
|
||||
}
|
||||
|
||||
} // close the namespace
|
||||
|
||||
TEST_CASE_PRIVATE(aare, open_multi_module_file_with_roi,
|
||||
"Open multi module file with ROI",
|
||||
"[.integration][.files][.rawfile]") {
|
||||
|
||||
auto fpath = test_data_path() / "raw/SingleChipROI/Data_master_0.json";
|
||||
REQUIRE(std::filesystem::exists(fpath));
|
||||
|
||||
RawFile f(fpath, "r");
|
||||
|
||||
REQUIRE(f.master().roi().value().width() == 256);
|
||||
REQUIRE(f.master().roi().value().height() == 256);
|
||||
|
||||
CHECK(f.m_geometry.n_modules() == 2);
|
||||
|
||||
CHECK(f.m_geometry.n_modules_in_roi() == 1);
|
||||
}
|
||||
} // close namespace aare
|
||||
|
||||
TEST_CASE("Read file with unordered frames", "[.integration]") {
|
||||
// TODO! Better explanation and error message
|
||||
auto fpath = test_data_path() / "mythen" / "scan242_master_3.raw";
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "aare/RawMasterFile.hpp"
|
||||
#include "aare/RawFile.hpp"
|
||||
#include <sstream>
|
||||
namespace aare {
|
||||
|
||||
@ -138,7 +139,11 @@ size_t RawMasterFile::n_modules() const {
|
||||
return m_geometry.row * m_geometry.col;
|
||||
}
|
||||
|
||||
std::optional<uint8_t> RawMasterFile::quad() const { return m_quad; }
|
||||
xy RawMasterFile::udp_interfaces_per_module() const {
|
||||
return m_udp_interfaces_per_module;
|
||||
}
|
||||
|
||||
uint8_t RawMasterFile::quad() const { return m_quad; }
|
||||
|
||||
// optional values, these may or may not be present in the master file
|
||||
// and are therefore modeled as std::optional
|
||||
@ -169,7 +174,10 @@ void RawMasterFile::parse_json(const std::filesystem::path &fpath) {
|
||||
m_type = StringTo<DetectorType>(j["Detector Type"].get<std::string>());
|
||||
m_timing_mode = StringTo<TimingMode>(j["Timing Mode"].get<std::string>());
|
||||
|
||||
m_geometry = {j["Geometry"]["y"], j["Geometry"]["x"]};
|
||||
m_geometry = {
|
||||
j["Geometry"]["y"],
|
||||
j["Geometry"]["x"]}; // TODO: isnt it only available for version > 7.1?
|
||||
// - try block default should be 1x1
|
||||
|
||||
m_image_size_in_bytes = j["Image Size in bytes"];
|
||||
m_frames_in_file = j["Frames in File"];
|
||||
@ -258,6 +266,15 @@ void RawMasterFile::parse_json(const std::filesystem::path &fpath) {
|
||||
} catch (const json::out_of_range &e) {
|
||||
// not a scan
|
||||
}
|
||||
try {
|
||||
m_udp_interfaces_per_module = {j.at("Number of UDP Interfaces"), 1};
|
||||
} catch (const json::out_of_range &e) {
|
||||
if (m_type == DetectorType::Eiger && m_quad == 1)
|
||||
m_udp_interfaces_per_module = {2, 1};
|
||||
else if (m_type == DetectorType::Eiger) {
|
||||
m_udp_interfaces_per_module = {1, 2};
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
ROI tmp_roi;
|
||||
@ -272,14 +289,14 @@ void RawMasterFile::parse_json(const std::filesystem::path &fpath) {
|
||||
tmp_roi.ymin != 4294967295 || tmp_roi.ymax != 4294967295) {
|
||||
|
||||
if (v < 7.21) {
|
||||
tmp_roi.xmax++;
|
||||
tmp_roi.xmax++; // why is it updated
|
||||
tmp_roi.ymax++;
|
||||
}
|
||||
|
||||
m_roi = tmp_roi;
|
||||
}
|
||||
|
||||
} catch (const json::out_of_range &e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
// leave the optional empty
|
||||
}
|
||||
|
||||
@ -389,21 +406,54 @@ void RawMasterFile::parse_raw(const std::filesystem::path &fpath) {
|
||||
m_geometry = {
|
||||
static_cast<uint32_t>(std::stoi(value.substr(1, pos))),
|
||||
static_cast<uint32_t>(std::stoi(value.substr(pos + 1)))};
|
||||
} else if (key == "Number of UDP Interfaces") {
|
||||
m_udp_interfaces_per_module = {
|
||||
static_cast<uint32_t>(std::stoi(value)), 1};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_type == DetectorType::Eiger && m_quad == 1) {
|
||||
m_udp_interfaces_per_module = {2, 1};
|
||||
} else if (m_type == DetectorType::Eiger) {
|
||||
m_udp_interfaces_per_module = {1, 2};
|
||||
}
|
||||
|
||||
if (m_pixels_x == 400 && m_pixels_y == 400) {
|
||||
m_type = DetectorType::Moench03_old;
|
||||
}
|
||||
|
||||
// TODO! Look for d0, d1...dn and update geometry
|
||||
if (m_geometry.col == 0 && m_geometry.row == 0) {
|
||||
m_geometry = {1, 1};
|
||||
fmt::print("Warning: No geometry found in master file. Assuming 1x1\n");
|
||||
retrieve_geometry();
|
||||
fmt::print("Warning: No geometry found in master file. Retrieved "
|
||||
"geometry of {}x{}\n",
|
||||
m_geometry.row, m_geometry.col);
|
||||
}
|
||||
|
||||
// TODO! Read files and find actual frames
|
||||
if (m_frames_in_file == 0)
|
||||
m_frames_in_file = m_total_frames_expected;
|
||||
}
|
||||
|
||||
void RawMasterFile::retrieve_geometry() {
|
||||
uint32_t module_index = 0;
|
||||
uint16_t rows = 0;
|
||||
uint16_t cols = 0;
|
||||
// TODO use case for Eiger
|
||||
|
||||
while (std::filesystem::exists(data_fname(module_index, 0))) {
|
||||
|
||||
auto header = RawFile::read_header(data_fname(module_index, 0));
|
||||
|
||||
rows = std::max(rows, header.row);
|
||||
cols = std::max(cols, header.column);
|
||||
|
||||
++module_index;
|
||||
}
|
||||
++rows;
|
||||
++cols;
|
||||
|
||||
m_geometry = {rows, cols};
|
||||
}
|
||||
|
||||
} // namespace aare
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include "test_config.hpp"
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <iostream>
|
||||
|
||||
using namespace aare;
|
||||
|
||||
@ -145,6 +146,19 @@ TEST_CASE("Parse a master file in .json format", "[.integration]") {
|
||||
REQUIRE_FALSE(f.digital_samples());
|
||||
}
|
||||
|
||||
TEST_CASE("Parse a master file in old .raw format",
|
||||
"[.integration][.files][.rawmasterfile]") {
|
||||
auto fpath = test_data_path() /
|
||||
"raw/jungfrau_2modules_version6.1.2/run_master_0.raw";
|
||||
REQUIRE(std::filesystem::exists(fpath));
|
||||
RawMasterFile f(fpath);
|
||||
|
||||
CHECK(f.udp_interfaces_per_module() == xy{1, 1});
|
||||
CHECK(f.n_modules() == 2);
|
||||
CHECK(f.geometry().row == 2);
|
||||
CHECK(f.geometry().col == 1);
|
||||
}
|
||||
|
||||
TEST_CASE("Parse a master file in .raw format", "[.integration]") {
|
||||
|
||||
auto fpath =
|
||||
|
@ -1,72 +0,0 @@
|
||||
|
||||
#include "aare/geo_helpers.hpp"
|
||||
#include "fmt/core.h"
|
||||
|
||||
namespace aare {
|
||||
|
||||
DetectorGeometry update_geometry_with_roi(DetectorGeometry geo, aare::ROI roi) {
|
||||
#ifdef AARE_VERBOSE
|
||||
fmt::println("update_geometry_with_roi() called with ROI: {} {} {} {}",
|
||||
roi.xmin, roi.xmax, roi.ymin, roi.ymax);
|
||||
fmt::println("Geometry: {} {} {} {} {} {}", geo.modules_x, geo.modules_y,
|
||||
geo.pixels_x, geo.pixels_y, geo.module_gap_row,
|
||||
geo.module_gap_col);
|
||||
#endif
|
||||
int pos_y = 0;
|
||||
int pos_y_increment = 0;
|
||||
for (int row = 0; row < geo.modules_y; row++) {
|
||||
int pos_x = 0;
|
||||
for (int col = 0; col < geo.modules_x; col++) {
|
||||
auto &m = geo.module_pixel_0[row * geo.modules_x + col];
|
||||
auto original_height = m.height;
|
||||
auto original_width = m.width;
|
||||
|
||||
// module is to the left of the roi
|
||||
if (m.origin_x + m.width < roi.xmin) {
|
||||
m.width = 0;
|
||||
|
||||
// roi is in module
|
||||
} else {
|
||||
// here we only arrive when the roi is in or to the left of
|
||||
// the module
|
||||
if (roi.xmin > m.origin_x) {
|
||||
m.width -= roi.xmin - m.origin_x;
|
||||
}
|
||||
if (roi.xmax < m.origin_x + original_width) {
|
||||
m.width -= m.origin_x + original_width - roi.xmax;
|
||||
}
|
||||
m.origin_x = pos_x;
|
||||
pos_x += m.width;
|
||||
}
|
||||
|
||||
if (m.origin_y + m.height < roi.ymin) {
|
||||
m.height = 0;
|
||||
} else {
|
||||
if ((roi.ymin > m.origin_y) &&
|
||||
(roi.ymin < m.origin_y + m.height)) {
|
||||
m.height -= roi.ymin - m.origin_y;
|
||||
}
|
||||
if (roi.ymax < m.origin_y + original_height) {
|
||||
m.height -= m.origin_y + original_height - roi.ymax;
|
||||
}
|
||||
m.origin_y = pos_y;
|
||||
pos_y_increment = m.height;
|
||||
}
|
||||
#ifdef AARE_VERBOSE
|
||||
fmt::println("Module {} {} {} {}", m.origin_x, m.origin_y, m.width,
|
||||
m.height);
|
||||
#endif
|
||||
}
|
||||
// increment pos_y
|
||||
pos_y += pos_y_increment;
|
||||
}
|
||||
|
||||
// m_rows = roi.height();
|
||||
// m_cols = roi.width();
|
||||
geo.pixels_x = roi.width();
|
||||
geo.pixels_y = roi.height();
|
||||
|
||||
return geo;
|
||||
}
|
||||
|
||||
} // namespace aare
|
@ -1,228 +0,0 @@
|
||||
#include "aare/File.hpp"
|
||||
#include "aare/RawFile.hpp"
|
||||
#include "aare/RawMasterFile.hpp" //needed for ROI
|
||||
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <filesystem>
|
||||
|
||||
#include "aare/geo_helpers.hpp"
|
||||
#include "test_config.hpp"
|
||||
|
||||
TEST_CASE("Simple ROIs on one module") {
|
||||
// DetectorGeometry update_geometry_with_roi(DetectorGeometry geo, aare::ROI
|
||||
// roi)
|
||||
aare::DetectorGeometry geo;
|
||||
|
||||
aare::ModuleGeometry mod;
|
||||
mod.origin_x = 0;
|
||||
mod.origin_y = 0;
|
||||
mod.width = 1024;
|
||||
mod.height = 512;
|
||||
|
||||
geo.pixels_x = 1024;
|
||||
geo.pixels_y = 512;
|
||||
geo.modules_x = 1;
|
||||
geo.modules_y = 1;
|
||||
geo.module_pixel_0.push_back(mod);
|
||||
|
||||
SECTION("ROI is the whole module") {
|
||||
aare::ROI roi;
|
||||
roi.xmin = 0;
|
||||
roi.xmax = 1024;
|
||||
roi.ymin = 0;
|
||||
roi.ymax = 512;
|
||||
auto updated_geo = aare::update_geometry_with_roi(geo, roi);
|
||||
|
||||
REQUIRE(updated_geo.pixels_x == 1024);
|
||||
REQUIRE(updated_geo.pixels_y == 512);
|
||||
REQUIRE(updated_geo.modules_x == 1);
|
||||
REQUIRE(updated_geo.modules_y == 1);
|
||||
REQUIRE(updated_geo.module_pixel_0[0].height == 512);
|
||||
REQUIRE(updated_geo.module_pixel_0[0].width == 1024);
|
||||
}
|
||||
SECTION("ROI is the top left corner of the module") {
|
||||
aare::ROI roi;
|
||||
roi.xmin = 100;
|
||||
roi.xmax = 200;
|
||||
roi.ymin = 150;
|
||||
roi.ymax = 200;
|
||||
auto updated_geo = aare::update_geometry_with_roi(geo, roi);
|
||||
|
||||
REQUIRE(updated_geo.pixels_x == 100);
|
||||
REQUIRE(updated_geo.pixels_y == 50);
|
||||
REQUIRE(updated_geo.modules_x == 1);
|
||||
REQUIRE(updated_geo.modules_y == 1);
|
||||
REQUIRE(updated_geo.module_pixel_0[0].height == 50);
|
||||
REQUIRE(updated_geo.module_pixel_0[0].width == 100);
|
||||
}
|
||||
|
||||
SECTION("ROI is a small square") {
|
||||
aare::ROI roi;
|
||||
roi.xmin = 1000;
|
||||
roi.xmax = 1010;
|
||||
roi.ymin = 500;
|
||||
roi.ymax = 510;
|
||||
auto updated_geo = aare::update_geometry_with_roi(geo, roi);
|
||||
|
||||
REQUIRE(updated_geo.pixels_x == 10);
|
||||
REQUIRE(updated_geo.pixels_y == 10);
|
||||
REQUIRE(updated_geo.modules_x == 1);
|
||||
REQUIRE(updated_geo.modules_y == 1);
|
||||
REQUIRE(updated_geo.module_pixel_0[0].height == 10);
|
||||
REQUIRE(updated_geo.module_pixel_0[0].width == 10);
|
||||
}
|
||||
SECTION("ROI is a few columns") {
|
||||
aare::ROI roi;
|
||||
roi.xmin = 750;
|
||||
roi.xmax = 800;
|
||||
roi.ymin = 0;
|
||||
roi.ymax = 512;
|
||||
auto updated_geo = aare::update_geometry_with_roi(geo, roi);
|
||||
|
||||
REQUIRE(updated_geo.pixels_x == 50);
|
||||
REQUIRE(updated_geo.pixels_y == 512);
|
||||
REQUIRE(updated_geo.modules_x == 1);
|
||||
REQUIRE(updated_geo.modules_y == 1);
|
||||
REQUIRE(updated_geo.module_pixel_0[0].height == 512);
|
||||
REQUIRE(updated_geo.module_pixel_0[0].width == 50);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Two modules side by side") {
|
||||
// DetectorGeometry update_geometry_with_roi(DetectorGeometry geo, aare::ROI
|
||||
// roi)
|
||||
aare::DetectorGeometry geo;
|
||||
|
||||
aare::ModuleGeometry mod;
|
||||
mod.origin_x = 0;
|
||||
mod.origin_y = 0;
|
||||
mod.width = 1024;
|
||||
mod.height = 512;
|
||||
|
||||
geo.pixels_x = 2048;
|
||||
geo.pixels_y = 512;
|
||||
geo.modules_x = 2;
|
||||
geo.modules_y = 1;
|
||||
|
||||
geo.module_pixel_0.push_back(mod);
|
||||
mod.origin_x = 1024;
|
||||
geo.module_pixel_0.push_back(mod);
|
||||
|
||||
SECTION("ROI is the whole image") {
|
||||
aare::ROI roi;
|
||||
roi.xmin = 0;
|
||||
roi.xmax = 2048;
|
||||
roi.ymin = 0;
|
||||
roi.ymax = 512;
|
||||
auto updated_geo = aare::update_geometry_with_roi(geo, roi);
|
||||
|
||||
REQUIRE(updated_geo.pixels_x == 2048);
|
||||
REQUIRE(updated_geo.pixels_y == 512);
|
||||
REQUIRE(updated_geo.modules_x == 2);
|
||||
REQUIRE(updated_geo.modules_y == 1);
|
||||
}
|
||||
SECTION("rectangle on both modules") {
|
||||
aare::ROI roi;
|
||||
roi.xmin = 800;
|
||||
roi.xmax = 1300;
|
||||
roi.ymin = 200;
|
||||
roi.ymax = 499;
|
||||
auto updated_geo = aare::update_geometry_with_roi(geo, roi);
|
||||
|
||||
REQUIRE(updated_geo.pixels_x == 500);
|
||||
REQUIRE(updated_geo.pixels_y == 299);
|
||||
REQUIRE(updated_geo.modules_x == 2);
|
||||
REQUIRE(updated_geo.modules_y == 1);
|
||||
REQUIRE(updated_geo.module_pixel_0[0].height == 299);
|
||||
REQUIRE(updated_geo.module_pixel_0[0].width == 224);
|
||||
REQUIRE(updated_geo.module_pixel_0[1].height == 299);
|
||||
REQUIRE(updated_geo.module_pixel_0[1].width == 276);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Three modules side by side") {
|
||||
// DetectorGeometry update_geometry_with_roi(DetectorGeometry geo, aare::ROI
|
||||
// roi)
|
||||
aare::DetectorGeometry geo;
|
||||
aare::ROI roi;
|
||||
roi.xmin = 700;
|
||||
roi.xmax = 2500;
|
||||
roi.ymin = 0;
|
||||
roi.ymax = 123;
|
||||
|
||||
aare::ModuleGeometry mod;
|
||||
mod.origin_x = 0;
|
||||
mod.origin_y = 0;
|
||||
mod.width = 1024;
|
||||
mod.height = 512;
|
||||
|
||||
geo.pixels_x = 3072;
|
||||
geo.pixels_y = 512;
|
||||
geo.modules_x = 3;
|
||||
geo.modules_y = 1;
|
||||
|
||||
geo.module_pixel_0.push_back(mod);
|
||||
mod.origin_x = 1024;
|
||||
geo.module_pixel_0.push_back(mod);
|
||||
mod.origin_x = 2048;
|
||||
geo.module_pixel_0.push_back(mod);
|
||||
|
||||
auto updated_geo = aare::update_geometry_with_roi(geo, roi);
|
||||
|
||||
REQUIRE(updated_geo.pixels_x == 1800);
|
||||
REQUIRE(updated_geo.pixels_y == 123);
|
||||
REQUIRE(updated_geo.modules_x == 3);
|
||||
REQUIRE(updated_geo.modules_y == 1);
|
||||
REQUIRE(updated_geo.module_pixel_0[0].height == 123);
|
||||
REQUIRE(updated_geo.module_pixel_0[0].width == 324);
|
||||
REQUIRE(updated_geo.module_pixel_0[1].height == 123);
|
||||
REQUIRE(updated_geo.module_pixel_0[1].width == 1024);
|
||||
REQUIRE(updated_geo.module_pixel_0[2].height == 123);
|
||||
REQUIRE(updated_geo.module_pixel_0[2].width == 452);
|
||||
}
|
||||
|
||||
TEST_CASE("Four modules as a square") {
|
||||
// DetectorGeometry update_geometry_with_roi(DetectorGeometry geo, aare::ROI
|
||||
// roi)
|
||||
aare::DetectorGeometry geo;
|
||||
aare::ROI roi;
|
||||
roi.xmin = 500;
|
||||
roi.xmax = 2000;
|
||||
roi.ymin = 500;
|
||||
roi.ymax = 600;
|
||||
|
||||
aare::ModuleGeometry mod;
|
||||
mod.origin_x = 0;
|
||||
mod.origin_y = 0;
|
||||
mod.width = 1024;
|
||||
mod.height = 512;
|
||||
|
||||
geo.pixels_x = 2048;
|
||||
geo.pixels_y = 1024;
|
||||
geo.modules_x = 2;
|
||||
geo.modules_y = 2;
|
||||
|
||||
geo.module_pixel_0.push_back(mod);
|
||||
mod.origin_x = 1024;
|
||||
geo.module_pixel_0.push_back(mod);
|
||||
mod.origin_x = 0;
|
||||
mod.origin_y = 512;
|
||||
geo.module_pixel_0.push_back(mod);
|
||||
mod.origin_x = 1024;
|
||||
geo.module_pixel_0.push_back(mod);
|
||||
|
||||
auto updated_geo = aare::update_geometry_with_roi(geo, roi);
|
||||
|
||||
REQUIRE(updated_geo.pixels_x == 1500);
|
||||
REQUIRE(updated_geo.pixels_y == 100);
|
||||
REQUIRE(updated_geo.modules_x == 2);
|
||||
REQUIRE(updated_geo.modules_y == 2);
|
||||
REQUIRE(updated_geo.module_pixel_0[0].height == 12);
|
||||
REQUIRE(updated_geo.module_pixel_0[0].width == 524);
|
||||
REQUIRE(updated_geo.module_pixel_0[1].height == 12);
|
||||
REQUIRE(updated_geo.module_pixel_0[1].width == 976);
|
||||
REQUIRE(updated_geo.module_pixel_0[2].height == 88);
|
||||
REQUIRE(updated_geo.module_pixel_0[2].width == 524);
|
||||
REQUIRE(updated_geo.module_pixel_0[3].height == 88);
|
||||
REQUIRE(updated_geo.module_pixel_0[3].width == 976);
|
||||
}
|
@ -40,5 +40,8 @@ target_sources(tests PRIVATE ${TestSources} )
|
||||
#configure a header to pass test file paths
|
||||
get_filename_component(TEST_FILE_PATH ${PROJECT_SOURCE_DIR}/data ABSOLUTE)
|
||||
configure_file(test_config.hpp.in test_config.hpp)
|
||||
target_include_directories(tests PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
|
||||
target_include_directories(tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
|
||||
|
||||
|
||||
|
4
tests/friend_test.hpp
Normal file
4
tests/friend_test.hpp
Normal file
@ -0,0 +1,4 @@
|
||||
#define FRIEND_TEST(test_name) friend void test_name##_impl();
|
||||
|
||||
#define TEST_CASE_PRIVATE_FWD(test_name) \
|
||||
void test_name##_impl(); // foward declaration
|
20
tests/test_macros.hpp
Normal file
20
tests/test_macros.hpp
Normal file
@ -0,0 +1,20 @@
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
#include <catch2/interfaces/catch_interfaces_capture.hpp>
|
||||
#include <catch2/internal/catch_test_registry.hpp>
|
||||
#include <catch2/internal/catch_unique_ptr.hpp>
|
||||
|
||||
#define TEST_CASE_PRIVATE(namespace_name, test_name, test_name_str, \
|
||||
test_tags_str) \
|
||||
namespace namespace_name { \
|
||||
void test_name##_impl(); \
|
||||
namespace { \
|
||||
struct test_name##_Invoker : Catch::ITestInvoker { \
|
||||
void invoke() const override { test_name##_impl(); } \
|
||||
}; \
|
||||
Catch::AutoReg \
|
||||
autoReg_##test_name(Catch::Detail::make_unique<test_name##_Invoker>(), \
|
||||
Catch::SourceLineInfo(__FILE__, __LINE__), "", \
|
||||
Catch::NameAndTags{test_name_str, test_tags_str}); \
|
||||
} \
|
||||
void test_name##_impl()
|
Reference in New Issue
Block a user