extended DetectorGeometry class with find_geometry, update_geometry (refactoring)

This commit is contained in:
2025-06-13 16:16:23 +02:00
parent bd7870e75a
commit be67bbab6b
11 changed files with 526 additions and 496 deletions

View File

@ -361,7 +361,7 @@ set(PUBLICHEADERS
include/aare/FilePtr.hpp include/aare/FilePtr.hpp
include/aare/Frame.hpp include/aare/Frame.hpp
include/aare/GainMap.hpp include/aare/GainMap.hpp
include/aare/geo_helpers.hpp include/aare/DetectorGeometry.hpp
include/aare/JungfrauDataFile.hpp include/aare/JungfrauDataFile.hpp
include/aare/NDArray.hpp include/aare/NDArray.hpp
include/aare/NDView.hpp include/aare/NDView.hpp
@ -386,7 +386,7 @@ set(SourceFiles
${CMAKE_CURRENT_SOURCE_DIR}/src/File.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/File.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/FilePtr.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/FilePtr.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/Fit.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/JungfrauDataFile.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/NumpyFile.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/NumpyFile.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/NumpyHelpers.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/NumpyHelpers.cpp
@ -441,7 +441,7 @@ if(AARE_TESTS)
${CMAKE_CURRENT_SOURCE_DIR}/src/decode.test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/decode.test.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/Dtype.test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Dtype.test.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/Frame.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/RawMasterFile.test.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/NDArray.test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/NDArray.test.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/NDView.test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/NDView.test.cpp

View 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

View File

@ -1,4 +1,5 @@
#pragma once #pragma once
#include "aare/DetectorGeometry.hpp"
#include "aare/FileInterface.hpp" #include "aare/FileInterface.hpp"
#include "aare/Frame.hpp" #include "aare/Frame.hpp"
#include "aare/NDArray.hpp" //for pixel map #include "aare/NDArray.hpp" //for pixel map
@ -13,18 +14,6 @@
namespace aare { 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 #ifdef AARE_TESTS
TEST_CASE_PRIVATE_FWD(check_find_geometry) // forward declaration TEST_CASE_PRIVATE_FWD(check_find_geometry) // forward declaration
TEST_CASE_PRIVATE_FWD(open_multi_module_file_with_roi) TEST_CASE_PRIVATE_FWD(open_multi_module_file_with_roi)
@ -43,13 +32,11 @@ class RawFile : public FileInterface {
FRIEND_TEST(open_multi_module_file_with_roi) FRIEND_TEST(open_multi_module_file_with_roi)
#endif #endif
std::vector<std::unique_ptr<RawSubFile>> m_subfiles; std::vector<std::unique_ptr<RawSubFile>> m_subfiles;
ModuleConfig cfg{0, 0};
RawMasterFile m_master; RawMasterFile m_master;
size_t m_current_frame{}; size_t m_current_frame{};
size_t m_current_subfile{}; size_t m_current_subfile{};
std::vector<ssize_t> m_modules_in_roi{};
DetectorGeometry m_geometry; DetectorGeometry m_geometry;
public: public:
@ -84,7 +71,6 @@ class RawFile : public FileInterface {
size_t cols() const override; size_t cols() const override;
size_t bitdepth() const override; size_t bitdepth() const override;
xy geometry(); xy geometry();
size_t n_modules() const;
RawMasterFile master() const; RawMasterFile master() const;
@ -115,10 +101,6 @@ class RawFile : public FileInterface {
Frame get_frame(size_t frame_index); Frame get_frame(size_t frame_index);
void open_subfiles(); void open_subfiles();
size_t n_modules_in_roi() const;
void find_geometry();
}; };
} // namespace aare } // namespace aare

View File

@ -174,35 +174,6 @@ template <typename T> struct t_xy {
}; };
using xy = t_xy<uint32_t>; 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 { struct ROI {
ssize_t xmin{}; ssize_t xmin{};
ssize_t xmax{}; ssize_t xmax{};

View File

@ -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

152
src/DetectorGeometry.cpp Normal file
View 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

View 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);
}

View File

@ -1,8 +1,8 @@
#include "aare/RawFile.hpp" #include "aare/RawFile.hpp"
#include "aare/DetectorGeometry.hpp"
#include "aare/PixelMap.hpp" #include "aare/PixelMap.hpp"
#include "aare/algorithm.hpp" #include "aare/algorithm.hpp"
#include "aare/defs.hpp" #include "aare/defs.hpp"
#include "aare/geo_helpers.hpp"
#include "aare/logger.hpp" #include "aare/logger.hpp"
#include <fmt/format.h> #include <fmt/format.h>
@ -13,26 +13,16 @@ using json = nlohmann::json;
namespace aare { namespace aare {
RawFile::RawFile(const std::filesystem::path &fname, const std::string &mode) 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; m_mode = mode;
if (mode == "r") { if (mode == "r") {
find_geometry();
if (m_master.roi()) { if (m_master.roi()) {
m_geometry = m_geometry.update_geometry_with_roi(m_master.roi().value());
update_geometry_with_roi(m_geometry, m_master.roi().value());
m_modules_in_roi.reserve(n_modules());
for (size_t module_index = 0; module_index < n_modules();
++module_index) {
if (m_geometry.module_pixel_0[module_index].width != 0 &&
m_geometry.module_pixel_0[module_index].height != 0)
m_modules_in_roi.push_back(module_index);
}
} else {
m_modules_in_roi.resize(n_modules());
std::iota(m_modules_in_roi.begin(), m_modules_in_roi.end(), 0);
}
open_subfiles(); open_subfiles();
}
} else { } else {
throw std::runtime_error(LOCATION + throw std::runtime_error(LOCATION +
" Unsupported mode. Can only read RawFiles."); " Unsupported mode. Can only read RawFiles.");
@ -72,28 +62,30 @@ void RawFile::read_into(std::byte *image_buf, size_t n_frames,
this->get_frame_into(m_current_frame++, image_buf, header); this->get_frame_into(m_current_frame++, image_buf, header);
image_buf += bytes_per_frame(); image_buf += bytes_per_frame();
if (header) if (header)
header += n_modules(); header += m_geometry.n_modules();
} }
} }
size_t RawFile::n_modules() const { return m_master.n_modules(); } // size_t RawFile::n_modules() const { return m_master.n_modules(); }
size_t RawFile::n_modules_in_roi() const { return m_modules_in_roi.size(); } // size_t RawFile::n_modules_in_roi() const { return
// m_modules_in_roi.size(); }
size_t RawFile::bytes_per_frame() { 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; bits_per_byte;
} }
size_t RawFile::pixels_per_frame() { size_t RawFile::pixels_per_frame() {
// return m_rows * m_cols; // 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(); } DetectorType RawFile::detector_type() const { return m_master.detector_type(); }
void RawFile::seek(size_t frame_index) { void RawFile::seek(size_t frame_index) {
// check if the frame number is greater than the total frames // 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()) { if (frame_index > total_frames()) {
throw std::runtime_error( throw std::runtime_error(
fmt::format("frame number {} is greater than total frames {}", fmt::format("frame number {} is greater than total frames {}",
@ -105,15 +97,15 @@ void RawFile::seek(size_t frame_index) {
size_t RawFile::tell() { return m_current_frame; } size_t RawFile::tell() { return m_current_frame; }
size_t RawFile::total_frames() const { return m_master.frames_in_file(); } 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::rows() const { return m_geometry.pixels_y(); }
size_t RawFile::cols() const { return m_geometry.pixels_x; } size_t RawFile::cols() const { return m_geometry.pixels_x(); }
size_t RawFile::bitdepth() const { return m_master.bitdepth(); } size_t RawFile::bitdepth() const { return m_master.bitdepth(); }
xy RawFile::geometry() { return m_master.geometry(); } xy RawFile::geometry() { return m_master.geometry(); }
void RawFile::open_subfiles() { void RawFile::open_subfiles() {
if (m_mode == "r") if (m_mode == "r")
for (size_t i : m_modules_in_roi) { for (size_t i : m_geometry.get_modules_in_roi()) {
auto pos = m_geometry.module_pixel_0[i]; auto pos = m_geometry.get_module_geometries(i);
m_subfiles.emplace_back(std::make_unique<RawSubFile>( m_subfiles.emplace_back(std::make_unique<RawSubFile>(
m_master.data_fname(i, 0), m_master.detector_type(), pos.height, m_master.data_fname(i, 0), m_master.detector_type(), pos.height,
pos.width, m_master.bitdepth(), pos.row_index, pos.col_index)); pos.width, m_master.bitdepth(), pos.row_index, pos.col_index));
@ -143,46 +135,8 @@ DetectorHeader RawFile::read_header(const std::filesystem::path &fname) {
RawMasterFile RawFile::master() const { return m_master; } RawMasterFile RawFile::master() const { return m_master; }
/**
* @brief Find the geometry of the detector
*/
void RawFile::find_geometry() {
m_geometry.module_pixel_0.reserve(n_modules());
for (size_t col = 0; col < m_master.geometry().col;
col += m_master.udp_interfaces_per_module().col)
for (size_t row = 0; row < m_master.geometry().row;
row += m_master.udp_interfaces_per_module().row) {
for (size_t port_row = 0;
port_row < m_master.udp_interfaces_per_module().row;
++port_row)
for (size_t port_col = 0;
port_col < m_master.udp_interfaces_per_module().col;
++port_col) {
ModuleGeometry g;
g.origin_x = (col + port_col) * m_master.pixels_x();
g.origin_y = (row + port_row) *
m_master.pixels_y(); // TODO: quad doesnt seem
// to have an effect
g.row_index = m_master.quad() ? (row + port_row + 1) % 2
: (row + port_row);
g.col_index = col + port_col;
g.width = m_master.pixels_x();
g.height = m_master.pixels_y();
m_geometry.module_pixel_0.push_back(g);
}
}
m_geometry.pixels_y = (m_master.geometry().row * m_master.pixels_y());
m_geometry.pixels_x = (m_master.geometry().col * m_master.pixels_x());
m_geometry.modules_x = m_master.geometry().col;
m_geometry.modules_y = m_master.geometry().row;
m_geometry.pixels_y +=
static_cast<size_t>((m_master.geometry().row - 1) * cfg.module_gap_row);
}
Frame RawFile::get_frame(size_t frame_index) { 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())); Dtype::from_bitdepth(m_master.bitdepth()));
std::byte *frame_buffer = f.data(); std::byte *frame_buffer = f.data();
get_frame_into(frame_index, frame_buffer); get_frame_into(frame_index, frame_buffer);
@ -197,13 +151,15 @@ void RawFile::get_frame_into(size_t frame_index, std::byte *frame_buffer,
if (frame_index >= total_frames()) { if (frame_index >= total_frames()) {
throw std::runtime_error(LOCATION + "Frame number out of range"); throw std::runtime_error(LOCATION + "Frame number out of range");
} }
std::vector<size_t> frame_numbers(n_modules_in_roi()); std::vector<size_t> frame_numbers(m_geometry.n_modules_in_roi());
std::vector<size_t> frame_indices(n_modules_in_roi(), frame_index); std::vector<size_t> frame_indices(m_geometry.n_modules_in_roi(),
frame_index);
// sync the frame numbers // sync the frame numbers
if (n_modules() != 1) { // if we have more than one module if (m_geometry.n_modules() != 1) { // if we have more than one module
for (size_t part_idx = 0; part_idx != n_modules_in_roi(); ++part_idx) { for (size_t part_idx = 0; part_idx != m_geometry.n_modules_in_roi();
++part_idx) {
frame_numbers[part_idx] = frame_numbers[part_idx] =
m_subfiles[part_idx]->frame_number(frame_index); m_subfiles[part_idx]->frame_number(frame_index);
} }
@ -233,24 +189,32 @@ void RawFile::get_frame_into(size_t frame_index, std::byte *frame_buffer,
if (m_master.geometry().col == 1) { if (m_master.geometry().col == 1) {
// get the part from each subfile and copy it to the frame // get the part from each subfile and copy it to the frame
for (size_t part_idx = 0; part_idx != n_modules_in_roi(); ++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]; auto corrected_idx = frame_indices[part_idx];
// This is where we start writing // This is where we start writing
auto offset = (m_geometry.module_pixel_0[m_modules_in_roi[part_idx]] auto offset = (m_geometry
.get_module_geometries(
m_geometry.get_modules_in_roi(part_idx))
.origin_y * .origin_y *
m_geometry.pixels_x + m_geometry.pixels_x() +
m_geometry.module_pixel_0[m_modules_in_roi[part_idx]] m_geometry
.get_module_geometries(
m_geometry.get_modules_in_roi(part_idx))
.origin_x) * .origin_x) *
m_master.bitdepth() / 8; m_master.bitdepth() / 8;
if (m_geometry.module_pixel_0[m_modules_in_roi[part_idx]] if (m_geometry
.get_module_geometries(
m_geometry.get_modules_in_roi(part_idx))
.origin_x != 0) .origin_x != 0)
throw std::runtime_error( throw std::runtime_error(
LOCATION + LOCATION +
" Implementation error. x pos not 0."); // TODO: origin can " Implementation error. x pos not 0."); // TODO: origin
// still change if // can still
// roi changes // change if roi
// changes
// TODO! What if the files don't match? // TODO! What if the files don't match?
m_subfiles[part_idx]->seek(corrected_idx); m_subfiles[part_idx]->seek(corrected_idx);
m_subfiles[part_idx]->read_into(frame_buffer + offset, header); m_subfiles[part_idx]->read_into(frame_buffer + offset, header);
@ -268,11 +232,13 @@ void RawFile::get_frame_into(size_t frame_index, std::byte *frame_buffer,
auto *part_buffer = new std::byte[bytes_per_part]; auto *part_buffer = new std::byte[bytes_per_part];
// TODO! if we have many submodules we should reorder them on the module // TODO! if we have many submodules we should reorder them on the
// level // module level
for (size_t part_idx = 0; part_idx != n_modules_in_roi(); ++part_idx) { for (size_t part_idx = 0; part_idx != m_geometry.n_modules_in_roi();
auto pos = m_geometry.module_pixel_0[m_modules_in_roi[part_idx]]; ++part_idx) {
auto pos = m_geometry.get_module_geometries(
m_geometry.get_modules_in_roi(part_idx));
auto corrected_idx = frame_indices[part_idx]; auto corrected_idx = frame_indices[part_idx];
m_subfiles[part_idx]->seek(corrected_idx); m_subfiles[part_idx]->seek(corrected_idx);
@ -285,7 +251,7 @@ void RawFile::get_frame_into(size_t frame_index, std::byte *frame_buffer,
auto irow = (pos.origin_y + cur_row); auto irow = (pos.origin_y + cur_row);
auto icol = pos.origin_x; 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; dest = dest * m_master.bitdepth() / 8;
memcpy(frame_buffer + dest, memcpy(frame_buffer + dest,
part_buffer + part_buffer +

View File

@ -167,44 +167,45 @@ TEST_CASE("Read multipart files", "[.integration]") {
struct TestParameters { struct TestParameters {
const std::string master_filename{}; const std::string master_filename{};
const uint8_t num_ports{}; const uint8_t num_ports{};
const DetectorGeometry geometry{}; 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", TEST_CASE_PRIVATE(aare, check_find_geometry, "check find_geometry",
"[.integration][.files][.rawfile]") { "[.integration][.files][.rawfile]") {
auto test_parameters = GENERATE( auto test_parameters = GENERATE(
TestParameters{ TestParameters{"raw/jungfrau_2modules_version6.1.2/run_master_0.raw", 2,
"raw/jungfrau_2modules_version6.1.2/run_master_0.raw", 2, 1, 2, 1024, 1024,
DetectorGeometry{1, 2, 1024, 1024, 0, 0,
std::vector<ModuleGeometry>{ std::vector<ModuleGeometry>{
ModuleGeometry{0, 0, 512, 1024, 0, 0}, ModuleGeometry{0, 0, 512, 1024, 0, 0},
ModuleGeometry{0, 512, 512, 1024, 0, 1}}}}, ModuleGeometry{0, 512, 512, 1024, 0, 1}}},
TestParameters{ TestParameters{
"raw/eiger_1_module_version7.0.0/eiger_1mod_master_7.json", 4, "raw/eiger_1_module_version7.0.0/eiger_1mod_master_7.json", 4, 2, 2,
DetectorGeometry{2, 2, 1024, 512, 0, 0, 1024, 512,
std::vector<ModuleGeometry>{ std::vector<ModuleGeometry>{
ModuleGeometry{0, 0, 256, 512, 0, 0}, ModuleGeometry{0, 0, 256, 512, 0, 0},
ModuleGeometry{512, 0, 256, 512, 0, 1}, ModuleGeometry{512, 0, 256, 512, 0, 1},
ModuleGeometry{0, 256, 256, 512, 1, 0}, ModuleGeometry{0, 256, 256, 512, 1, 0},
ModuleGeometry{512, 256, 256, 512, 1, 1}}}}, ModuleGeometry{512, 256, 256, 512, 1, 1}}},
TestParameters{ TestParameters{"raw/jungfrau_2modules_2interfaces/run_master_0.json", 4,
"raw/jungfrau_2modules_2interfaces/run_master_0.json", 4, 1, 4, 1024, 1024,
DetectorGeometry{1, 4, 1024, 1024, 0, 0,
std::vector<ModuleGeometry>{ std::vector<ModuleGeometry>{
ModuleGeometry{0, 0, 256, 1024, 0, 0}, ModuleGeometry{0, 0, 256, 1024, 0, 0},
ModuleGeometry{0, 256, 256, 1024, 1, 0}, ModuleGeometry{0, 256, 256, 1024, 1, 0},
ModuleGeometry{0, 512, 256, 1024, 2, 0}, ModuleGeometry{0, 512, 256, 1024, 2, 0},
ModuleGeometry{0, 768, 256, 1024, 3, 0}}}}, ModuleGeometry{0, 768, 256, 1024, 3, 0}}},
TestParameters{ TestParameters{
"raw/eiger_quad_data/" "raw/eiger_quad_data/"
"W13_vthreshscan_m21C_300V_800eV_vrpre3400_master_0.json", "W13_vthreshscan_m21C_300V_800eV_vrpre3400_master_0.json",
2, 2, 1, 2, 512, 512,
DetectorGeometry{1, 2, 512, 512, 0, 0,
std::vector<ModuleGeometry>{ std::vector<ModuleGeometry>{
ModuleGeometry{0, 0, 256, 512, 0, 0}, ModuleGeometry{0, 0, 256, 512, 0, 0},
ModuleGeometry{0, 256, 256, 512, 1, 0}}}}); ModuleGeometry{0, 256, 256, 512, 1, 0}}});
auto fpath = test_data_path() / test_parameters.master_filename; auto fpath = test_data_path() / test_parameters.master_filename;
@ -212,17 +213,15 @@ TEST_CASE_PRIVATE(aare, check_find_geometry, "check find_geometry",
RawFile f(fpath, "r"); RawFile f(fpath, "r");
f.m_geometry.module_pixel_0.clear();
f.find_geometry();
auto geometry = f.m_geometry; auto geometry = f.m_geometry;
CHECK(geometry.modules_x == test_parameters.geometry.modules_x); CHECK(geometry.modules_x() == test_parameters.modules_x);
CHECK(geometry.modules_y == test_parameters.geometry.modules_y); CHECK(geometry.modules_y() == test_parameters.modules_y);
CHECK(geometry.pixels_x == test_parameters.geometry.pixels_x); CHECK(geometry.pixels_x() == test_parameters.pixels_x);
CHECK(geometry.pixels_y == test_parameters.geometry.pixels_y); CHECK(geometry.pixels_y() == test_parameters.pixels_y);
REQUIRE(geometry.module_pixel_0.size() == test_parameters.num_ports); REQUIRE(geometry.get_module_geometries().size() ==
test_parameters.num_ports);
// compare to data stored in header // compare to data stored in header
for (size_t i = 0; i < test_parameters.num_ports; ++i) { for (size_t i = 0; i < test_parameters.num_ports; ++i) {
@ -232,18 +231,18 @@ TEST_CASE_PRIVATE(aare, check_find_geometry, "check find_geometry",
auto header = RawFile::read_header(subfile1_path); auto header = RawFile::read_header(subfile1_path);
CHECK(header.column == geometry.module_pixel_0[i].col_index); CHECK(header.column == geometry.get_module_geometries(i).col_index);
CHECK(header.row == geometry.module_pixel_0[i].row_index); CHECK(header.row == geometry.get_module_geometries(i).row_index);
CHECK(geometry.module_pixel_0[i].height == CHECK(geometry.get_module_geometries(i).height ==
test_parameters.geometry.module_pixel_0[i].height); test_parameters.module_geometries[i].height);
CHECK(geometry.module_pixel_0[i].width == CHECK(geometry.get_module_geometries(i).width ==
test_parameters.geometry.module_pixel_0[i].width); test_parameters.module_geometries[i].width);
CHECK(geometry.module_pixel_0[i].origin_x == CHECK(geometry.get_module_geometries(i).origin_x ==
test_parameters.geometry.module_pixel_0[i].origin_x); test_parameters.module_geometries[i].origin_x);
CHECK(geometry.module_pixel_0[i].origin_y == CHECK(geometry.get_module_geometries(i).origin_y ==
test_parameters.geometry.module_pixel_0[i].origin_y); test_parameters.module_geometries[i].origin_y);
} }
} }
@ -261,9 +260,9 @@ TEST_CASE_PRIVATE(aare, open_multi_module_file_with_roi,
REQUIRE(f.master().roi().value().width() == 256); REQUIRE(f.master().roi().value().width() == 256);
REQUIRE(f.master().roi().value().height() == 256); REQUIRE(f.master().roi().value().height() == 256);
CHECK(f.n_modules() == 2); CHECK(f.m_geometry.n_modules() == 2);
CHECK(f.n_modules_in_roi() == 1); CHECK(f.m_geometry.n_modules_in_roi() == 1);
} }
} // close namespace aare } // close namespace aare

View File

@ -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

View File

@ -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);
}