Dev/multiple rois in aare (#263)
Some checks failed
Build on RHEL8 / build (push) Successful in 2m23s
Build on RHEL9 / build (push) Successful in 2m32s
Run tests using data on local RHEL8 / build (push) Failing after 3m14s

Reading multiple ROI's for aare 

- read_frame, read_n etc throws for multiple ROIs
- new functions read_ROIs, read_n_ROIs 
-  read_roi_into (used for python bindings - to not copy) 

all these functions use get_frame or get_frame_into where one passes the
roi_index
## Refactoring:
- each roi keeps track of its subfiles that one has to open e.g.
subfiles can be opened several times
- refactored class DetectorGeometry - keep track of the updated module
geometries in new class ROIGeometry.
- ModuleGeometry updates based on ROI

## ROIGeometry: 
- stores number of modules overlapping with ROI and its indices
- size of ROI 

Note: only tested size of the resulting frames not the actual values

---------

Co-authored-by: Erik Fröjdh <erik.frojdh@psi.ch>
Co-authored-by: Erik Fröjdh <erik.frojdh@gmail.com>
This commit is contained in:
2026-02-18 10:57:56 +01:00
committed by GitHub
parent 7f64b9a616
commit 218f31ce60
17 changed files with 1242 additions and 421 deletions

View File

@@ -41,31 +41,16 @@ DetectorGeometry::DetectorGeometry(const xy &geometry,
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;
@@ -76,77 +61,8 @@ 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();
ModuleGeometry &DetectorGeometry::get_module_geometries(const size_t index) {
return module_geometries[index];
}
} // namespace aare

View File

@@ -7,17 +7,20 @@
#include <filesystem>
#include "aare/DetectorGeometry.hpp"
#include "aare/ROIGeometry.hpp"
#include "test_config.hpp"
TEST_CASE("Simple ROIs on one module") {
// DetectorGeometry update_geometry_with_roi(DetectorGeometry geo, aare::ROI
// roi)
TEST_CASE("Simple ROIs on one module", "[DetectorGeometry]") {
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);
REQUIRE(geo.modules_x() == 1);
REQUIRE(geo.modules_y() == 1);
REQUIRE(geo.pixels_x() == 1024);
REQUIRE(geo.pixels_y() == 512);
SECTION("ROI is the whole module") {
aare::ROI roi;
@@ -25,14 +28,18 @@ TEST_CASE("Simple ROIs on one module") {
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);
aare::ROIGeometry roi_geometry(roi, geo);
REQUIRE(roi_geometry.pixels_x() == 1024);
REQUIRE(roi_geometry.pixels_y() == 512);
REQUIRE(roi_geometry.num_modules_in_roi() == 1);
auto module_geometry =
geo.get_module_geometries(roi_geometry.module_indices_in_roi(0));
REQUIRE(module_geometry.height == 512);
REQUIRE(module_geometry.width == 1024);
REQUIRE(module_geometry.origin_x == 0);
REQUIRE(module_geometry.origin_y == 0);
}
SECTION("ROI is the top left corner of the module") {
aare::ROI roi;
@@ -40,51 +47,22 @@ TEST_CASE("Simple ROIs on one module") {
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);
}
aare::ROIGeometry roi_geometry(roi, geo);
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);
REQUIRE(roi_geometry.pixels_x() == 100);
REQUIRE(roi_geometry.pixels_y() == 50);
REQUIRE(roi_geometry.num_modules_in_roi() == 1);
auto module_geometry =
geo.get_module_geometries(roi_geometry.module_indices_in_roi(0));
REQUIRE(module_geometry.height == 50);
REQUIRE(module_geometry.width == 100);
REQUIRE(module_geometry.origin_x == 0);
REQUIRE(module_geometry.origin_y == 0);
}
}
TEST_CASE("Two modules side by side") {
// DetectorGeometry update_geometry_with_roi(DetectorGeometry geo, aare::ROI
// roi)
TEST_CASE("Two modules side by side", "[DetectorGeometry]") {
aare::DetectorGeometry geo(aare::xy{1, 2}, 1024, 512);
REQUIRE(geo.get_module_geometries(0).origin_x == 0);
@@ -93,6 +71,10 @@ TEST_CASE("Two modules side by side") {
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.modules_x() == 2);
REQUIRE(geo.modules_y() == 1);
REQUIRE(geo.pixels_x() == 2048);
REQUIRE(geo.pixels_y() == 512);
SECTION("ROI is the whole image") {
aare::ROI roi;
@@ -100,12 +82,24 @@ TEST_CASE("Two modules side by side") {
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);
aare::ROIGeometry roi_geometry(roi, geo);
REQUIRE(roi_geometry.pixels_x() == 2048);
REQUIRE(roi_geometry.pixels_y() == 512);
REQUIRE(roi_geometry.num_modules_in_roi() == 2);
auto module_geometry_0 = geo.get_module_geometries(0);
auto module_geometry_1 = geo.get_module_geometries(1);
REQUIRE(module_geometry_0.height == 512);
REQUIRE(module_geometry_0.width == 1024);
REQUIRE(module_geometry_1.height == 512);
REQUIRE(module_geometry_1.width == 1024);
REQUIRE(module_geometry_0.origin_x == 0);
REQUIRE(module_geometry_1.origin_x == 1024);
REQUIRE(module_geometry_0.origin_y == 0);
REQUIRE(module_geometry_1.origin_y == 0);
}
SECTION("rectangle on both modules") {
aare::ROI roi;
@@ -113,28 +107,30 @@ TEST_CASE("Two modules side by side") {
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);
aare::ROIGeometry roi_geometry(roi, geo);
REQUIRE(roi_geometry.pixels_x() == 500);
REQUIRE(roi_geometry.pixels_y() == 299);
REQUIRE(roi_geometry.num_modules_in_roi() == 2);
auto module_geometry_0 = geo.get_module_geometries(0);
auto module_geometry_1 = geo.get_module_geometries(1);
REQUIRE(module_geometry_0.height == 299);
REQUIRE(module_geometry_0.width == 224);
REQUIRE(module_geometry_1.height == 299);
REQUIRE(module_geometry_1.width == 276);
REQUIRE(module_geometry_0.origin_x == 0);
REQUIRE(module_geometry_1.origin_x == 224);
REQUIRE(module_geometry_0.origin_y == 0);
REQUIRE(module_geometry_1.origin_y == 0);
}
}
TEST_CASE("Three modules side by side") {
// DetectorGeometry update_geometry_with_roi(DetectorGeometry geo, aare::ROI
// roi)
TEST_CASE("Three modules side by side", "[DetectorGeometry]") {
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);
@@ -142,24 +138,78 @@ TEST_CASE("Three modules side by side") {
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);
REQUIRE(geo.pixels_x() == 3072);
REQUIRE(geo.pixels_y() == 512);
SECTION("ROI overlapping all three modules") {
aare::ROI roi;
roi.xmin = 500;
roi.xmax = 2500;
roi.ymin = 0;
roi.ymax = 123;
aare::ROIGeometry roi_geometry(roi, geo);
REQUIRE(roi_geometry.pixels_x() == 2000);
REQUIRE(roi_geometry.pixels_y() == 123);
REQUIRE(roi_geometry.num_modules_in_roi() == 3);
auto module_geometry_0 = geo.get_module_geometries(0);
auto module_geometry_1 = geo.get_module_geometries(1);
auto module_geometry_2 = geo.get_module_geometries(2);
REQUIRE(module_geometry_0.height == 123);
REQUIRE(module_geometry_0.width == 524);
REQUIRE(module_geometry_0.origin_x == 0);
REQUIRE(module_geometry_0.origin_y == 0);
REQUIRE(module_geometry_1.height == 123);
REQUIRE(module_geometry_1.width == 1024);
REQUIRE(module_geometry_1.origin_x == 524);
REQUIRE(module_geometry_1.origin_y == 0);
REQUIRE(module_geometry_2.height == 123);
REQUIRE(module_geometry_2.width == 452);
REQUIRE(module_geometry_2.origin_x == 1548);
REQUIRE(module_geometry_2.origin_y == 0);
}
SECTION("ROI overlapping last two modules") {
aare::ROI roi;
roi.xmin = 1050;
roi.xmax = 2500;
roi.ymin = 0;
roi.ymax = 123;
aare::ROIGeometry roi_geometry(roi, geo);
REQUIRE(roi_geometry.pixels_x() == 1450);
REQUIRE(roi_geometry.pixels_y() == 123);
REQUIRE(roi_geometry.num_modules_in_roi() == 2);
auto module_geometry_0 = geo.get_module_geometries(0);
auto module_geometry_1 = geo.get_module_geometries(1);
auto module_geometry_2 = geo.get_module_geometries(2);
REQUIRE(module_geometry_0.height == 512);
REQUIRE(module_geometry_0.width == 1024);
REQUIRE(module_geometry_0.origin_x == 0);
REQUIRE(module_geometry_0.origin_y == 0);
REQUIRE(module_geometry_1.height == 123);
REQUIRE(module_geometry_1.width == 998);
REQUIRE(module_geometry_1.origin_x == 0);
REQUIRE(module_geometry_1.origin_y == 0);
REQUIRE(module_geometry_2.height == 123);
REQUIRE(module_geometry_2.width == 452);
REQUIRE(module_geometry_2.origin_x == 998);
REQUIRE(module_geometry_2.origin_y == 0);
}
}
TEST_CASE("Four modules as a square") {
// DetectorGeometry update_geometry_with_roi(DetectorGeometry geo, aare::ROI
// roi)
TEST_CASE("Four modules as a square", "[DetectorGeometry]") {
aare::DetectorGeometry geo(aare::xy{2, 2}, 1024, 512, aare::xy{1, 2});
aare::ROI roi;
roi.xmin = 500;
@@ -177,19 +227,99 @@ TEST_CASE("Four modules as a square") {
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.pixels_x() == 2048);
REQUIRE(geo.pixels_y() == 1024);
aare::ROIGeometry roi_geometry(roi, geo);
REQUIRE(roi_geometry.pixels_x() == 1500);
REQUIRE(roi_geometry.pixels_y() == 100);
REQUIRE(roi_geometry.num_modules_in_roi() == 4);
REQUIRE(geo.get_module_geometries(0).height == 12);
REQUIRE(geo.get_module_geometries(0).width == 524);
REQUIRE(geo.get_module_geometries(0).origin_x == 0);
REQUIRE(geo.get_module_geometries(0).origin_y == 0);
REQUIRE(geo.get_module_geometries(1).height == 12);
REQUIRE(geo.get_module_geometries(1).width == 976);
REQUIRE(geo.get_module_geometries(1).origin_x == 524);
REQUIRE(geo.get_module_geometries(1).origin_y == 0);
REQUIRE(geo.get_module_geometries(2).height == 88);
REQUIRE(geo.get_module_geometries(2).width == 524);
REQUIRE(geo.get_module_geometries(2).origin_x == 0);
REQUIRE(geo.get_module_geometries(2).origin_y == 12);
REQUIRE(geo.get_module_geometries(3).height == 88);
REQUIRE(geo.get_module_geometries(3).width == 976);
REQUIRE(geo.get_module_geometries(3).origin_x == 524);
REQUIRE(geo.get_module_geometries(3).origin_y == 12);
}
TEST_CASE("check if module in ROI", "[DetectorGeometry]") {
aare::DetectorGeometry geo(aare::xy{2, 2}, 1024, 512, aare::xy{1, 2});
SECTION("all modules in ROI") {
aare::ROI roi;
roi.xmin = 500;
roi.xmax = 2000;
roi.ymin = 500;
roi.ymax = 600;
REQUIRE(geo.get_module_geometries(0).module_in_roi(roi) == true);
REQUIRE(geo.get_module_geometries(1).module_in_roi(roi) == true);
REQUIRE(geo.get_module_geometries(2).module_in_roi(roi) == true);
REQUIRE(geo.get_module_geometries(3).module_in_roi(roi) == true);
}
SECTION("some modules on border of ROI") {
aare::ROI roi;
roi.xmin = 1024;
roi.xmax = 2000;
roi.ymin = 500;
roi.ymax = 600;
REQUIRE(geo.get_module_geometries(0).module_in_roi(roi) == false);
REQUIRE(geo.get_module_geometries(1).module_in_roi(roi) == true);
REQUIRE(geo.get_module_geometries(2).module_in_roi(roi) == false);
REQUIRE(geo.get_module_geometries(3).module_in_roi(roi) == true);
}
SECTION("one module on border of ROI") {
aare::ROI roi;
roi.xmin = 1025;
roi.xmax = 2000;
roi.ymin = 513;
roi.ymax = 600;
REQUIRE(geo.get_module_geometries(0).module_in_roi(roi) == false);
REQUIRE(geo.get_module_geometries(1).module_in_roi(roi) == false);
REQUIRE(geo.get_module_geometries(2).module_in_roi(roi) == false);
REQUIRE(geo.get_module_geometries(3).module_in_roi(roi) == true);
}
SECTION("some modules to the left of ROI") {
aare::ROI roi;
roi.xmin = 500;
roi.xmax = 1024;
roi.ymin = 500;
roi.ymax = 600;
REQUIRE(geo.get_module_geometries(0).module_in_roi(roi) == true);
REQUIRE(geo.get_module_geometries(1).module_in_roi(roi) == false);
REQUIRE(geo.get_module_geometries(2).module_in_roi(roi) == true);
REQUIRE(geo.get_module_geometries(3).module_in_roi(roi) == false);
}
SECTION("all modules in ROI") {
aare::ROI roi;
roi.xmin = 500;
roi.xmax = 2000;
roi.ymin = 10;
roi.ymax = 513;
REQUIRE(geo.get_module_geometries(0).module_in_roi(roi) == true);
REQUIRE(geo.get_module_geometries(1).module_in_roi(roi) == true);
REQUIRE(geo.get_module_geometries(2).module_in_roi(roi) == true);
REQUIRE(geo.get_module_geometries(3).module_in_roi(roi) == true);
}
}

42
src/ROIGeometry.cpp Normal file
View File

@@ -0,0 +1,42 @@
#include "aare/ROIGeometry.hpp"
#include <vector>
namespace aare {
ROIGeometry::ROIGeometry(const ROI &roi, DetectorGeometry &geometry)
: m_pixels_x(roi.width()), m_pixels_y(roi.height()), m_geometry(geometry) {
m_module_indices_in_roi.reserve(m_geometry.n_modules());
// determine which modules are in the roi
for (size_t i = 0; i < m_geometry.n_modules(); ++i) {
auto &module_geometry = m_geometry.get_module_geometries(i);
if (module_geometry.module_in_roi(roi)) {
module_geometry.update_geometry_with_roi(roi);
m_module_indices_in_roi.push_back(i);
}
}
};
ROIGeometry::ROIGeometry(DetectorGeometry &geometry)
: m_pixels_x(geometry.pixels_x()), m_pixels_y(geometry.pixels_y()),
m_geometry(geometry) {
m_module_indices_in_roi.resize(m_geometry.n_modules());
std::iota(m_module_indices_in_roi.begin(), m_module_indices_in_roi.end(),
0);
};
size_t ROIGeometry::num_modules_in_roi() const {
return m_module_indices_in_roi.size();
}
const std::vector<size_t> &ROIGeometry::module_indices_in_roi() const {
return m_module_indices_in_roi;
}
size_t ROIGeometry::module_indices_in_roi(const size_t module_index) const {
return m_module_indices_in_roi.at(module_index);
}
size_t ROIGeometry::pixels_x() const { return m_pixels_x; }
size_t ROIGeometry::pixels_y() const { return m_pixels_y; }
} // namespace aare

View File

@@ -2,6 +2,7 @@
#include "aare/RawFile.hpp"
#include "aare/DetectorGeometry.hpp"
#include "aare/PixelMap.hpp"
#include "aare/ROIGeometry.hpp"
#include "aare/algorithm.hpp"
#include "aare/defs.hpp"
#include "aare/logger.hpp"
@@ -17,28 +18,98 @@ RawFile::RawFile(const std::filesystem::path &fname, const std::string &mode)
: 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_subfiles.resize(m_master.rois().has_value() ? m_master.rois()->size()
: 1);
if (mode == "r") {
if (m_master.roi()) {
m_geometry.update_geometry_with_roi(m_master.roi().value());
if (m_master.rois().has_value()) {
m_ROI_geometries.reserve(m_master.rois()->size());
// iterate over all ROIS
size_t roi_index = 0;
const auto rois = m_master.rois().value();
for (const auto &roi : rois) {
m_ROI_geometries.push_back(ROIGeometry(roi, m_geometry));
// open subfiles
open_subfiles(roi_index);
++roi_index;
}
} else {
// no ROI use full detector
m_ROI_geometries.reserve(1);
m_ROI_geometries.push_back(ROIGeometry(m_geometry));
open_subfiles(0);
}
open_subfiles();
} else {
throw std::runtime_error(LOCATION +
" Unsupported mode. Can only read RawFiles.");
}
}
Frame RawFile::read_frame() { return get_frame(m_current_frame++); }
Frame RawFile::read_roi(const size_t roi_index) {
if (!m_master.rois()) {
throw std::runtime_error(LOCATION +
"No ROIs defined in the master file.");
}
if (roi_index >= m_ROI_geometries.size()) {
throw std::runtime_error(LOCATION + "ROI index out of range.");
}
return get_frame(m_current_frame++, roi_index);
}
std::vector<Frame> RawFile::read_rois() {
if (!m_master.rois()) {
throw std::runtime_error(LOCATION +
"No ROIs defined in the master file.");
}
const size_t num_rois = m_ROI_geometries.size();
std::vector<Frame> frames;
frames.reserve(num_rois);
for (size_t roi_idx = 0; roi_idx < num_rois; ++roi_idx) {
frames.push_back(get_frame(m_current_frame, roi_idx));
}
++m_current_frame;
return frames;
}
Frame RawFile::read_frame() {
if (m_master.rois().has_value() && m_master.rois()->size() > 1) {
throw std::runtime_error(LOCATION +
"Multiple ROIs defined in the master file. "
"Use read_ROIs() instead.");
}
return get_frame(m_current_frame++);
}
Frame RawFile::read_frame(size_t frame_number) {
if (m_master.rois().has_value() && m_master.rois()->size() > 1) {
throw std::runtime_error(
LOCATION + "Multiple ROIs defined in the master file. "
"Use read_ROIs(const size_t frame_number) instead.");
}
seek(frame_number);
return read_frame();
}
void RawFile::read_into(std::byte *image_buf, size_t n_frames) {
// TODO: implement this in a more efficient way
if (m_master.rois().has_value() && m_master.rois()->size() > 1) {
throw std::runtime_error(LOCATION +
"Cannot use read_into for multiple ROIs.");
}
for (size_t i = 0; i < n_frames; i++) {
this->get_frame_into(m_current_frame++, image_buf);
@@ -47,33 +118,83 @@ void RawFile::read_into(std::byte *image_buf, size_t n_frames) {
}
void RawFile::read_into(std::byte *image_buf) {
if (m_master.rois().has_value() && m_master.rois()->size() > 1) {
throw std::runtime_error(LOCATION +
"Cannot use read_into for multiple ROIs. Use "
"read_roi_into() for a single ROI instead.");
}
return get_frame_into(m_current_frame++, image_buf);
}
void RawFile::read_into(std::byte *image_buf, DetectorHeader *header) {
void RawFile::read_roi_into(std::byte *image_buf, const size_t roi_index,
const size_t frame_number, DetectorHeader *header) {
if (!m_master.rois().has_value()) {
throw std::runtime_error(LOCATION +
"No ROIs defined in the master file.");
}
if (roi_index >= num_rois()) {
throw std::runtime_error(LOCATION + "ROI index out of range.");
}
return get_frame_into(frame_number, image_buf, roi_index, header);
}
return get_frame_into(m_current_frame++, image_buf, header);
void RawFile::read_into(std::byte *image_buf, DetectorHeader *header) {
if (m_master.rois().has_value() && m_master.rois()->size() > 1) {
throw std::runtime_error(LOCATION +
"Cannot use read_into for multiple ROIs. Use "
"read_roi_into() for a single ROI instead.");
}
return get_frame_into(m_current_frame++, image_buf, 0, header);
}
void RawFile::read_into(std::byte *image_buf, size_t n_frames,
DetectorHeader *header) {
// return get_frame_into(m_current_frame++, image_buf, header);
if (m_master.rois().has_value() && m_master.rois()->size() > 1) {
throw std::runtime_error(
LOCATION +
"Cannot use read_into for multiple ROIs."); // TODO: maybe pass
// roi_index so one can
// use read_into for a
// specific ROI
}
for (size_t i = 0; i < n_frames; i++) {
this->get_frame_into(m_current_frame++, image_buf, header);
this->get_frame_into(m_current_frame++, image_buf, 0, header);
image_buf += bytes_per_frame();
if (header)
header += m_geometry.n_modules_in_roi();
header += m_ROI_geometries[0].num_modules_in_roi();
}
}
size_t RawFile::bytes_per_frame() {
return m_geometry.pixels_x() * m_geometry.pixels_y() * m_master.bitdepth() /
if (m_master.rois().has_value() && m_master.rois()->size() > 1) {
throw std::runtime_error(
LOCATION + "Pass the desired roi_index to bytes_per_frame to get "
"bytes_per_frame for the specific ROI. ");
}
return bytes_per_frame(0);
}
size_t RawFile::bytes_per_frame(const size_t roi_index) {
return m_ROI_geometries.at(roi_index).pixels_x() *
m_ROI_geometries.at(roi_index).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();
if (m_master.rois().has_value() && m_master.rois()->size() > 1) {
throw std::runtime_error(
LOCATION + "Pass the desired roi_index to pixels_per_frame to get "
"pixels_per_frame for the specific ROI. ");
}
return pixels_per_frame(0);
}
size_t RawFile::pixels_per_frame(const size_t roi_index) {
return m_ROI_geometries.at(roi_index).pixels_x() *
m_ROI_geometries.at(roi_index).pixels_y();
}
DetectorType RawFile::detector_type() const { return m_master.detector_type(); }
@@ -93,8 +214,29 @@ 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 {
if (m_master.rois().has_value() && m_master.rois()->size() > 1) {
throw std::runtime_error(LOCATION +
"Pass the desired roi_index to rows to get "
"rows for the specific ROI. ");
}
return rows(0);
}
size_t RawFile::rows(const size_t roi_index) const {
return m_ROI_geometries.at(roi_index).pixels_y();
}
size_t RawFile::cols() const {
if (m_master.rois().has_value() && m_master.rois()->size() > 1) {
throw std::runtime_error(LOCATION +
"Pass the desired roi_index to cols to get "
"cols for the specific ROI. ");
}
return cols(0);
}
size_t RawFile::cols(const size_t roi_index) const {
return m_ROI_geometries.at(roi_index).pixels_x();
}
size_t RawFile::bitdepth() const { return m_master.bitdepth(); }
xy RawFile::geometry() const {
return xy{static_cast<uint32_t>(m_geometry.modules_y()),
@@ -102,19 +244,46 @@ xy RawFile::geometry() const {
}
size_t RawFile::n_modules() const { return m_geometry.n_modules(); };
size_t RawFile::n_modules_in_roi() const {
return m_geometry.n_modules_in_roi();
size_t RawFile::num_rois() const {
if (m_master.rois().has_value()) {
return m_master.rois()->size();
} else {
return 0;
}
};
void RawFile::open_subfiles() {
if (m_mode == "r")
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>(
const ROIGeometry &RawFile::roi_geometries(size_t roi_index) const {
return m_ROI_geometries[roi_index];
}
std::vector<size_t> RawFile::n_modules_in_roi() const {
std::vector<size_t> results(m_ROI_geometries.size());
std::transform(
m_ROI_geometries.begin(), m_ROI_geometries.end(), results.begin(),
[](const ROIGeometry &roi) { return roi.num_modules_in_roi(); });
return results;
};
void RawFile::open_subfiles(const size_t roi_index) {
if (m_mode == "r") {
m_subfiles[roi_index].reserve(
m_ROI_geometries[roi_index].num_modules_in_roi());
auto module_indices =
m_ROI_geometries[roi_index].module_indices_in_roi();
for (const size_t i :
m_ROI_geometries[roi_index].module_indices_in_roi()) {
const auto pos = m_geometry.get_module_geometries(i);
m_subfiles[roi_index].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));
}
else {
} else {
throw std::runtime_error(LOCATION +
"Unsupported mode. Can only read RawFiles.");
}
@@ -139,33 +308,37 @@ DetectorHeader RawFile::read_header(const std::filesystem::path &fname) {
RawMasterFile RawFile::master() const { return m_master; }
Frame RawFile::get_frame(size_t frame_index) {
auto f = Frame(m_geometry.pixels_y(), m_geometry.pixels_x(),
Frame RawFile::get_frame(size_t frame_index, const size_t roi_index) {
auto f = Frame(m_ROI_geometries[roi_index].pixels_y(),
m_ROI_geometries[roi_index].pixels_x(),
Dtype::from_bitdepth(m_master.bitdepth()));
std::byte *frame_buffer = f.data();
get_frame_into(frame_index, frame_buffer);
get_frame_into(frame_index, frame_buffer, roi_index);
return f;
}
size_t RawFile::bytes_per_pixel() const { return m_master.bitdepth() / 8; }
void RawFile::get_frame_into(size_t frame_index, std::byte *frame_buffer,
DetectorHeader *header) {
const size_t roi_index, DetectorHeader *header) {
LOG(logDEBUG) << "RawFile::get_frame_into(" << frame_index << ")";
if (frame_index >= total_frames()) {
throw std::runtime_error(LOCATION + "Frame number out of range");
}
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);
std::vector<size_t> frame_numbers(
m_ROI_geometries[roi_index].num_modules_in_roi());
std::vector<size_t> frame_indices(
m_ROI_geometries[roi_index].num_modules_in_roi(), frame_index);
// sync the frame numbers
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();
if (m_ROI_geometries[roi_index].num_modules_in_roi() !=
1) { // if we have more than one module
for (size_t part_idx = 0;
part_idx != m_ROI_geometries[roi_index].num_modules_in_roi();
++part_idx) {
frame_numbers[part_idx] =
m_subfiles[part_idx]->frame_number(frame_index);
m_subfiles[roi_index][part_idx]->frame_number(frame_index);
}
// 1. if frame number vector is the same break
@@ -176,7 +349,8 @@ void RawFile::get_frame_into(size_t frame_index, std::byte *frame_buffer,
frame_numbers.begin(),
std::min_element(frame_numbers.begin(), frame_numbers.end()));
// 3. increase its index and update its respective frame number
// 3. increase its index and update its respective frame
// number
frame_indices[min_frame_idx]++;
// 4. if we can't increase its index => throw error
@@ -186,42 +360,50 @@ void RawFile::get_frame_into(size_t frame_index, std::byte *frame_buffer,
}
frame_numbers[min_frame_idx] =
m_subfiles[min_frame_idx]->frame_number(
m_subfiles[roi_index][min_frame_idx]->frame_number(
frame_indices[min_frame_idx]);
}
}
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 != m_geometry.n_modules_in_roi();
for (size_t part_idx = 0;
part_idx != m_ROI_geometries[roi_index].num_modules_in_roi();
++part_idx) {
auto corrected_idx = frame_indices[part_idx];
// This is where we start writing
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;
auto offset =
(m_geometry
.get_module_geometries(
m_ROI_geometries[roi_index].module_indices_in_roi(
part_idx))
.origin_y *
m_ROI_geometries[roi_index].pixels_x() +
m_geometry
.get_module_geometries(
m_ROI_geometries[roi_index].module_indices_in_roi(
part_idx))
.origin_x) *
m_master.bitdepth() / 8;
if (m_geometry
.get_module_geometries(
m_geometry.get_modules_in_roi(part_idx))
m_ROI_geometries[roi_index].module_indices_in_roi(
part_idx))
.origin_x != 0)
throw std::runtime_error(
LOCATION +
" Implementation error. x pos not 0."); // TODO: origin
" Implementation error. x pos not 0."); // TODO:
// origin
// can still
// change if roi
// 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);
m_subfiles[roi_index][part_idx]->seek(corrected_idx);
m_subfiles[roi_index][part_idx]->read_into(frame_buffer + offset,
header);
if (header)
++header;
}
@@ -230,23 +412,25 @@ void RawFile::get_frame_into(size_t frame_index, std::byte *frame_buffer,
// TODO! should we read row by row?
// create a buffer large enough to hold a full module
auto bytes_per_part = m_master.pixels_y() * m_master.pixels_x() *
m_master.bitdepth() /
8; // TODO! replace with image_size_in_bytes
auto bytes_per_part =
m_master.pixels_y() * m_master.pixels_x() * m_master.bitdepth() /
8; // TODO! replace with image_size_in_bytes // TODO
// shouldnt it only be the module size? - check
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 != m_geometry.n_modules_in_roi();
for (size_t part_idx = 0;
part_idx != m_ROI_geometries[roi_index].num_modules_in_roi();
++part_idx) {
auto pos = m_geometry.get_module_geometries(
m_geometry.get_modules_in_roi(part_idx));
m_ROI_geometries[roi_index].module_indices_in_roi(part_idx));
auto corrected_idx = frame_indices[part_idx];
m_subfiles[part_idx]->seek(corrected_idx);
m_subfiles[part_idx]->read_into(part_buffer, header);
m_subfiles[roi_index][part_idx]->seek(corrected_idx);
m_subfiles[roi_index][part_idx]->read_into(part_buffer, header);
if (header)
++header;
@@ -255,7 +439,8 @@ 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 * m_ROI_geometries[roi_index].pixels_x() + icol);
dest = dest * m_master.bitdepth() / 8;
memcpy(frame_buffer + dest,
part_buffer +
@@ -269,7 +454,17 @@ void RawFile::get_frame_into(size_t frame_index, std::byte *frame_buffer,
std::vector<Frame> RawFile::read_n(size_t n_frames) {
// TODO: implement this in a more efficient way
if (num_rois() > 1) {
throw std::runtime_error(LOCATION +
"Multiple ROIs defined in the master "
"file. Use "
"read_num_rois for a specific ROI or use "
"read_ROIs to read one frame after "
"the other.");
}
std::vector<Frame> frames;
frames.reserve(n_frames);
for (size_t i = 0; i < n_frames; i++) {
frames.push_back(this->get_frame(m_current_frame));
m_current_frame++;
@@ -277,11 +472,26 @@ std::vector<Frame> RawFile::read_n(size_t n_frames) {
return frames;
}
std::vector<Frame> RawFile::read_n_with_roi(const size_t n_frames,
const size_t roi_index) {
if (roi_index >= num_rois()) {
throw std::runtime_error(LOCATION + "ROI index out of range.");
}
std::vector<Frame> frames;
frames.reserve(n_frames);
for (size_t i = 0; i < n_frames; i++) {
frames.push_back(this->get_frame(m_current_frame, roi_index));
m_current_frame++;
}
return frames;
}
size_t RawFile::frame_number(size_t frame_index) {
if (frame_index >= m_master.frames_in_file()) {
throw std::runtime_error(LOCATION + " Frame number out of range");
}
return m_subfiles[0]->frame_number(frame_index);
return m_subfiles[0][0]->frame_number(frame_index);
}
} // namespace aare

View File

@@ -14,7 +14,8 @@ using aare::File;
using aare::RawFile;
using namespace aare;
TEST_CASE("Read number of frames from a jungfrau raw file", "[.with-data]") {
TEST_CASE("Read number of frames from a jungfrau raw file",
"[.with-data][RawFile]") {
auto fpath =
test_data_path() / "raw/jungfrau/jungfrau_single_master_0.json";
@@ -24,7 +25,8 @@ TEST_CASE("Read number of frames from a jungfrau raw file", "[.with-data]") {
REQUIRE(f.total_frames() == 10);
}
TEST_CASE("Read frame numbers from a jungfrau raw file", "[.with-data]") {
TEST_CASE("Read frame numbers from a jungfrau raw file",
"[.with-data][RawFile]") {
auto fpath =
test_data_path() / "raw/jungfrau/jungfrau_single_master_0.json";
REQUIRE(std::filesystem::exists(fpath));
@@ -41,7 +43,7 @@ TEST_CASE("Read frame numbers from a jungfrau raw file", "[.with-data]") {
}
}
TEST_CASE("Read a frame number too high throws", "[.with-data]") {
TEST_CASE("Read a frame number too high throws", "[.with-data][RawFile]") {
auto fpath =
test_data_path() / "raw/jungfrau/jungfrau_single_master_0.json";
REQUIRE(std::filesystem::exists(fpath));
@@ -57,7 +59,7 @@ TEST_CASE("Read a frame number too high throws", "[.with-data]") {
}
TEST_CASE("Read a frame numbers where the subfile is missing throws",
"[.with-data]") {
"[.with-data][RawFile]") {
auto fpath = test_data_path() / "raw/jungfrau" /
"jungfrau_missing_subfile_master_0.json";
@@ -80,7 +82,7 @@ TEST_CASE("Read a frame numbers where the subfile is missing throws",
}
TEST_CASE("Read data from a jungfrau 500k single port raw file",
"[.with-data]") {
"[.with-data][RawFile]") {
auto fpath =
test_data_path() / "raw/jungfrau/jungfrau_single_master_0.json";
REQUIRE(std::filesystem::exists(fpath));
@@ -99,7 +101,7 @@ TEST_CASE("Read data from a jungfrau 500k single port raw file",
}
}
TEST_CASE("Read frame numbers from a raw file", "[.with-data]") {
TEST_CASE("Read frame numbers from a raw file", "[.with-data][RawFile]") {
auto fpath =
test_data_path() / "raw/eiger" / "eiger_500k_16bit_master_0.json";
REQUIRE(std::filesystem::exists(fpath));
@@ -113,7 +115,8 @@ TEST_CASE("Read frame numbers from a raw file", "[.with-data]") {
}
}
TEST_CASE("Compare reading from a numpy file with a raw file", "[.with-data]") {
TEST_CASE("Compare reading from a numpy file with a raw file",
"[.with-data][RawFile]") {
SECTION("jungfrau data") {
auto fpath_raw =
@@ -155,6 +158,11 @@ TEST_CASE("Compare reading from a numpy file with a raw file", "[.with-data]") {
auto raw_frame = raw.read_frame();
auto npy_frame = npy.read_frame();
CHECK(raw_frame.rows() == 512);
CHECK(raw_frame.cols() == 512);
CHECK(npy_frame.rows() == 512);
CHECK(npy_frame.cols() == 512);
CHECK((raw_frame.view<uint32_t>() == npy_frame.view<uint32_t>()));
}
SECTION("eiger data") {
@@ -176,7 +184,7 @@ TEST_CASE("Compare reading from a numpy file with a raw file", "[.with-data]") {
}
}
TEST_CASE("Read multipart files", "[.with-data]") {
TEST_CASE("Read multipart files", "[.with-data][RawFile]") {
auto fpath =
test_data_path() / "raw/jungfrau" / "jungfrau_double_master_0.json";
REQUIRE(std::filesystem::exists(fpath));
@@ -217,7 +225,7 @@ struct TestParameters {
std::vector<ModuleGeometry> module_geometries{};
};
TEST_CASE("check find_geometry", "[.with-data]") {
TEST_CASE("check find_geometry", "[.with-data][RawFile]") {
auto test_parameters = GENERATE(
TestParameters{"raw/jungfrau_2modules_version6.1.2/run_master_0.raw", 2,
@@ -290,7 +298,8 @@ TEST_CASE("check find_geometry", "[.with-data]") {
}
}
TEST_CASE("Open multi module file with ROI", "[.with-data]") {
TEST_CASE("Open multi module file with ROI",
"[.with-data][read_rois][RawFile]") {
auto fpath =
test_data_path() / "raw/ROITestData/SingleChipROI/Data_master_0.json";
@@ -304,7 +313,8 @@ TEST_CASE("Open multi module file with ROI", "[.with-data]") {
CHECK(f.n_modules() == 2);
CHECK(f.n_modules_in_roi() == 1);
REQUIRE(f.n_modules_in_roi().size() == 1);
CHECK(f.n_modules_in_roi()[0] == 1);
auto frames = f.read_n(2);
@@ -315,7 +325,70 @@ TEST_CASE("Open multi module file with ROI", "[.with-data]") {
}
}
TEST_CASE("Read file with unordered frames", "[.with-data]") {
TEST_CASE("Open multi module file with ROI spanning over multiple modules",
"[.width-data][read_rois][RawFile]") {
auto fpath =
test_data_path() / "raw/ROITestData/MultipleChipROI/run_master_2.json";
REQUIRE(std::filesystem::exists(fpath));
RawFile f(fpath, "r");
CHECK(f.n_modules() == 2);
CHECK(f.n_modules_in_roi().size() == 1);
CHECK(f.n_modules_in_roi()[0] == 2);
auto frame = f.read_frame();
CHECK(frame.rows() == 301);
CHECK(frame.cols() == 101);
CHECK(f.rows() == 301);
CHECK(f.cols() == 101);
}
TEST_CASE("Open multi module file with two ROIs",
"[.width-data][read_rois][RawFile]") {
auto fpath =
test_data_path() / "raw/ROITestData/MultipleROIs/run_master_0.json";
REQUIRE(std::filesystem::exists(fpath));
RawFile f(fpath, "r");
CHECK(f.n_modules() == 2);
REQUIRE(f.n_modules_in_roi().size() == 2);
CHECK(f.n_modules_in_roi()[0] == 1);
CHECK(f.n_modules_in_roi()[1] == 1);
CHECK_THROWS(f.read_frame());
CHECK(f.tell() == 0);
auto frame = f.read_rois();
CHECK(f.tell() == 1);
REQUIRE(frame.size() == 2);
CHECK(frame[0].rows() == 301);
CHECK(frame[0].cols() == 101);
CHECK(frame[1].rows() == 101);
CHECK(frame[1].cols() == 101);
CHECK_THROWS(f.rows());
CHECK(f.rows(0) == 301);
auto frames = f.read_n_with_roi(2, 1);
REQUIRE(frames.size() == 2);
CHECK(f.tell() == 3);
for (const auto &frm : frames) {
CHECK(frm.rows() == 101);
CHECK(frm.cols() == 101);
}
}
TEST_CASE("Read file with unordered frames", "[.with-data][RawFile]") {
// TODO! Better explanation and error message
auto fpath = test_data_path() / "raw/mythen/scan242_master_3.raw";
REQUIRE(std::filesystem::exists(fpath));
@@ -323,7 +396,7 @@ TEST_CASE("Read file with unordered frames", "[.with-data]") {
REQUIRE_THROWS((f.read_frame()));
}
TEST_CASE("Read Mythenframe", "[.with-data]") {
TEST_CASE("Read Mythenframe", "[.with-data][RawFile]") {
auto fpath = test_data_path() / "raw/newmythen03/run_2_master_1.json";
REQUIRE(std::filesystem::exists(fpath));
RawFile f(fpath);

View File

@@ -71,7 +71,7 @@ ScanParameters::ScanParameters(const bool enabled, const DACIndex dac,
const int start, const int stop, const int step,
const int64_t settleTime)
: m_enabled(enabled), m_dac(dac), m_start(start), m_stop(stop),
m_step(step), m_settleTime(settleTime) {};
m_step(step), m_settleTime(settleTime){};
// "[enabled\ndac dac 4\nstart 500\nstop 2200\nstep 5\nsettleTime 100us\n]"
ScanParameters::ScanParameters(const std::string &par) {
@@ -193,7 +193,18 @@ ScanParameters RawMasterFile::scan_parameters() const {
return m_scan_parameters;
}
std::optional<ROI> RawMasterFile::roi() const { return m_roi; }
std::optional<ROI> RawMasterFile::roi() const {
if (m_rois.value().size() > 1) {
throw std::runtime_error(LOCATION +
"Multiple ROIs present, use rois() method.");
} else {
return m_rois.has_value()
? std::optional<ROI>(m_rois.value().at(0))
: std::nullopt; // TODO: maybe throw if no roi exists
}
}
std::optional<std::vector<ROI>> RawMasterFile::rois() const { return m_rois; }
void RawMasterFile::parse_json(std::istream &is) {
json j;
@@ -255,9 +266,9 @@ void RawMasterFile::parse_json(std::istream &is) {
m_frame_discard_policy = string_to<FrameDiscardPolicy>(
j["Frame Discard Policy"].get<std::string>());
if(j.contains("Number of rows") && j["Number of rows"].is_number()){
if (j.contains("Number of rows") && j["Number of rows"].is_number()) {
m_number_of_rows = j["Number of rows"];
}
}
// ----------------------------------------------------------------
// Special treatment of analog flag because of Moench03
@@ -338,34 +349,35 @@ void RawMasterFile::parse_json(std::istream &is) {
}
}
try {
ROI tmp_roi;
if (v < 8.0) {
auto obj = j.at("Receiver Roi");
tmp_roi.xmin = obj.at("xmin");
tmp_roi.xmax = obj.at("xmax");
tmp_roi.ymin = obj.at("ymin");
tmp_roi.ymax = obj.at("ymax");
} else {
// TODO: for now only handle single ROI
auto obj = j.at("Receiver Rois");
tmp_roi.xmin = obj[0].at("xmin");
tmp_roi.xmax = obj[0].at("xmax");
tmp_roi.ymin = obj[0].at("ymin");
tmp_roi.ymax = obj[0].at("ymax");
}
// if any of the values are set update the roi
// TODO: doesnt it write garbage if one of them is not set
if (tmp_roi.xmin != 4294967295 || tmp_roi.xmax != 4294967295 ||
tmp_roi.ymin != 4294967295 || tmp_roi.ymax != 4294967295) {
tmp_roi.xmax++;
// Handle Mythen
if (tmp_roi.ymin == -1 && tmp_roi.ymax == -1) {
tmp_roi.ymin = 0;
tmp_roi.ymax = 0;
if (obj.at("xmin") != 4294967295 || obj.at("xmax") != 4294967295 ||
obj.at("ymin") != 4294967295 || obj.at("ymax") != 4294967295) {
// Handle Mythen
if (obj.at("ymin") == -1 && obj.at("ymax") == -1) {
obj.at("ymin") = 0;
obj.at("ymax") = 0;
}
m_rois.emplace();
m_rois.value().push_back(ROI{
obj.at("xmin"), static_cast<ssize_t>(obj.at("xmax")) + 1,
obj.at("ymin"), static_cast<ssize_t>(obj.at("ymax")) + 1});
}
} else {
auto obj = j.at("Receiver Rois");
m_rois.emplace();
for (auto &elem : obj) {
// handle Mythen
if (elem.at("ymin") == -1 && elem.at("ymax") == -1) {
elem.at("ymin") = 0;
elem.at("ymax") = 0;
}
m_rois.value().push_back(ROI{
elem.at("xmin"), static_cast<ssize_t>(elem.at("xmax")) + 1,
elem.at("ymin"),
static_cast<ssize_t>(elem.at("ymax")) + 1});
}
tmp_roi.ymax++;
m_roi = tmp_roi;
}
} catch (const json::out_of_range &e) {
@@ -379,7 +391,6 @@ void RawMasterFile::parse_json(std::istream &is) {
m_counter_mask =
std::stoi(j["Counter Mask"].get<std::string>(), nullptr, 16);
}
// Update detector type for Moench
// TODO! How does this work with old .raw master files?