mirror of
https://github.com/slsdetectorgroup/aare.git
synced 2026-02-21 02:38:42 +01:00
Dev/multiple rois in aare (#263)
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:
@@ -1,7 +1,10 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
#pragma once
|
||||
#include "aare/ROIGeometry.hpp"
|
||||
#include "aare/RawMasterFile.hpp" //ROI refactor away
|
||||
#include "aare/defs.hpp"
|
||||
#include <iostream>
|
||||
|
||||
namespace aare {
|
||||
|
||||
struct ModuleConfig {
|
||||
@@ -18,16 +21,69 @@ struct ModuleConfig {
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Class to hold the geometry of a module. Where pixel 0 is located and
|
||||
* the size of the module
|
||||
* @brief Class to hold the geometry of a module. Where pixel 0 is located
|
||||
* relative to full Detector/ROI and the size of the module e.g. size of ROI
|
||||
* occupied by the module
|
||||
*/
|
||||
struct ModuleGeometry {
|
||||
/// @brief start x coordinate of the module in the full detector/ROI
|
||||
int origin_x{};
|
||||
/// @brief start y coordinate of the module in the full detector/ROI
|
||||
int origin_y{};
|
||||
/// @brief height of the module in pixels
|
||||
int height{};
|
||||
/// @brief width of the module in pixels
|
||||
int width{};
|
||||
/// @brief module index of the module in the detector
|
||||
int row_index{};
|
||||
/// @brief module index of the module in the detector
|
||||
int col_index{};
|
||||
|
||||
/**
|
||||
* @brief checks if module is in the region of interest
|
||||
*/
|
||||
bool module_in_roi(const ROI &roi) {
|
||||
// module is to the left of the roi
|
||||
bool to_the_left = origin_x + width - 1 < roi.xmin;
|
||||
bool to_the_right = origin_x >= roi.xmax;
|
||||
bool above = origin_y + height - 1 < roi.ymin;
|
||||
bool below = origin_y >= roi.ymax;
|
||||
|
||||
return !(to_the_left || to_the_right || below || above);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update the module geometry given a region of interest
|
||||
*/
|
||||
void update_geometry_with_roi(const ROI &roi) {
|
||||
|
||||
if (!(module_in_roi(roi))) {
|
||||
return; // do nothing
|
||||
}
|
||||
|
||||
int new_width = std::min(origin_x + width, static_cast<int>(roi.xmax)) -
|
||||
std::max(origin_x, static_cast<int>(roi.xmin));
|
||||
|
||||
// ROI starts inside module
|
||||
if (roi.xmin >= origin_x && roi.xmin < origin_x + width) {
|
||||
origin_x = 0;
|
||||
} else {
|
||||
origin_x -= roi.xmin;
|
||||
}
|
||||
|
||||
int new_height =
|
||||
std::min(origin_y + height, static_cast<int>(roi.ymax)) -
|
||||
std::max(origin_y, static_cast<int>(roi.ymin));
|
||||
|
||||
if (roi.ymin >= origin_y && roi.ymin < origin_y + height) {
|
||||
origin_y = 0;
|
||||
} else {
|
||||
origin_y -= roi.ymin;
|
||||
}
|
||||
|
||||
height = new_height;
|
||||
width = new_width;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -49,34 +105,33 @@ class DetectorGeometry {
|
||||
* @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;
|
||||
|
||||
ModuleGeometry &get_module_geometries(const size_t index);
|
||||
|
||||
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{};
|
||||
|
||||
// TODO: maybe remove - should be a member in ROIGeometry - in particular
|
||||
// only works as no overlap between ROIs allowed? maybe just have another
|
||||
// additional vector of ModuleGeometry for each ROIGeometry - some
|
||||
// duplication but nicer design?
|
||||
std::vector<ModuleGeometry> module_geometries;
|
||||
};
|
||||
|
||||
} // namespace aare
|
||||
48
include/aare/ROIGeometry.hpp
Normal file
48
include/aare/ROIGeometry.hpp
Normal file
@@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
#include "aare/DetectorGeometry.hpp"
|
||||
#include "aare/defs.hpp"
|
||||
|
||||
namespace aare {
|
||||
|
||||
class DetectorGeometry; // forward declaration to avoid circular dependency
|
||||
|
||||
/**
|
||||
* @brief Class to hold the geometry of a region of interest (ROI)
|
||||
*/
|
||||
class ROIGeometry {
|
||||
public:
|
||||
/** @brief Constructor
|
||||
* @param roi
|
||||
* @param geometry general detector geometry
|
||||
*/
|
||||
ROIGeometry(const ROI &roi, DetectorGeometry &geometry);
|
||||
|
||||
/** @brief Constructor for ROI geometry expanding over full detector
|
||||
* @param geometry general detector geometry
|
||||
*/
|
||||
ROIGeometry(DetectorGeometry &geometry);
|
||||
|
||||
/// @brief Get number of modules in the ROI
|
||||
size_t num_modules_in_roi() const;
|
||||
|
||||
/// @brief Get the indices of modules in the ROI
|
||||
const std::vector<size_t> &module_indices_in_roi() const;
|
||||
|
||||
size_t module_indices_in_roi(const size_t module_index) const;
|
||||
|
||||
size_t pixels_x() const;
|
||||
size_t pixels_y() const;
|
||||
|
||||
private:
|
||||
/// @brief Size of the ROI in pixels in x direction
|
||||
size_t m_pixels_x{};
|
||||
/// @brief Size of the ROI in pixels in y direction
|
||||
size_t m_pixels_y{};
|
||||
|
||||
DetectorGeometry &m_geometry;
|
||||
|
||||
/// @brief Indices of modules included in the ROI
|
||||
std::vector<size_t> m_module_indices_in_roi;
|
||||
};
|
||||
|
||||
} // namespace aare
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "aare/FileInterface.hpp"
|
||||
#include "aare/Frame.hpp"
|
||||
#include "aare/NDArray.hpp" //for pixel map
|
||||
#include "aare/ROIGeometry.hpp"
|
||||
#include "aare/RawMasterFile.hpp"
|
||||
#include "aare/RawSubFile.hpp"
|
||||
|
||||
@@ -23,13 +24,17 @@ namespace aare {
|
||||
*/
|
||||
class RawFile : public FileInterface {
|
||||
|
||||
std::vector<std::unique_ptr<RawSubFile>> m_subfiles;
|
||||
std::vector<std::vector<std::unique_ptr<RawSubFile>>>
|
||||
m_subfiles; // [ROI][modules_per_ROI]
|
||||
|
||||
RawMasterFile m_master;
|
||||
size_t m_current_frame{};
|
||||
|
||||
DetectorGeometry m_geometry;
|
||||
|
||||
/// @brief Geometries e.g. number of modules, size etc. for each ROI
|
||||
std::vector<ROIGeometry> m_ROI_geometries;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief RawFile constructor
|
||||
@@ -43,26 +48,94 @@ class RawFile : public FileInterface {
|
||||
Frame read_frame() override;
|
||||
Frame read_frame(size_t frame_number) override;
|
||||
std::vector<Frame> read_n(size_t n_frames) override;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Read one ROI defined in the master file
|
||||
* @param roi_index index of the ROI to read
|
||||
* @return Frame
|
||||
* @note the frame index is incremented after calling this function so
|
||||
* reading rois one after the other wont work.
|
||||
*/
|
||||
Frame read_roi(const size_t roi_index);
|
||||
|
||||
/**
|
||||
* @brief Read all ROIs defined in the master file
|
||||
* @return vector of Frames (one Frame per ROI)
|
||||
*/
|
||||
std::vector<Frame>read_rois();
|
||||
|
||||
/**
|
||||
* @brief Read n frames for the given ROI index
|
||||
* @param n_frames number of frames to read
|
||||
* @param roi_index index of the ROI to read
|
||||
* @return vector of Frames
|
||||
*/
|
||||
std::vector<Frame> read_n_with_roi(const size_t n_frames,
|
||||
const size_t roi_index);
|
||||
|
||||
void read_into(std::byte *image_buf) override;
|
||||
void read_into(std::byte *image_buf, size_t n_frames) override;
|
||||
|
||||
// TODO! do we need to adapt the API?
|
||||
void read_into(std::byte *image_buf, DetectorHeader *header);
|
||||
void read_into(std::byte *image_buf, DetectorHeader *header = nullptr);
|
||||
void read_into(std::byte *image_buf, size_t n_frames,
|
||||
DetectorHeader *header);
|
||||
|
||||
void read_roi_into(std::byte *image_buf, const size_t roi_index,
|
||||
const size_t frame_number,
|
||||
DetectorHeader *header =
|
||||
nullptr); // maybe just make get_frame_into public
|
||||
|
||||
size_t frame_number(size_t frame_index) override;
|
||||
size_t bytes_per_frame() override;
|
||||
// TODO: mmh maybe also pass roi_index in Base class File. Leave it unused
|
||||
// for NumpyFile and JungfrauDataFile
|
||||
/**
|
||||
* @brief bytes per frame for the given ROI
|
||||
* @param roi_index index of the ROI
|
||||
*/
|
||||
size_t bytes_per_frame(const size_t roi_index);
|
||||
size_t pixels_per_frame() override;
|
||||
/**
|
||||
* @brief pixels per frame for the given ROI
|
||||
* @param roi_index index of the ROI
|
||||
*/
|
||||
size_t pixels_per_frame(const size_t roi_index);
|
||||
size_t bytes_per_pixel() const;
|
||||
void seek(size_t frame_index) override;
|
||||
size_t tell() override;
|
||||
size_t total_frames() const override;
|
||||
size_t rows() const override;
|
||||
/**
|
||||
* @brief rows for the given ROI
|
||||
* @param roi_index index of the ROI
|
||||
*/
|
||||
size_t rows(const size_t roi_index) const;
|
||||
size_t cols() const override;
|
||||
/**
|
||||
* @brief cols for the given ROI
|
||||
* @param roi_index index of the ROI
|
||||
*/
|
||||
size_t cols(const size_t roi_index) const;
|
||||
size_t bitdepth() const override;
|
||||
size_t n_modules() const;
|
||||
size_t n_modules_in_roi() const;
|
||||
|
||||
/**
|
||||
* @brief number of ROIs defined
|
||||
*/
|
||||
size_t num_rois() const;
|
||||
|
||||
/**
|
||||
* @brief get the ROI geometry for the given ROI index
|
||||
* @param roi_index index of the ROI
|
||||
*/
|
||||
const ROIGeometry &roi_geometries(size_t roi_index) const;
|
||||
|
||||
/**
|
||||
* @brief number of modules in each ROI
|
||||
*/
|
||||
std::vector<size_t> n_modules_in_roi() const;
|
||||
xy geometry() const;
|
||||
|
||||
RawMasterFile master() const;
|
||||
@@ -79,21 +152,23 @@ class RawFile : public FileInterface {
|
||||
private:
|
||||
/**
|
||||
* @brief read the frame at the given frame index into the image buffer
|
||||
* @param frame_number frame number to read
|
||||
* @param image_buf buffer to store the frame
|
||||
* @param frame_index frame number to read
|
||||
* @param frame_buffer buffer to store the frame
|
||||
* @param roi_index index of the ROI to read (default is 0 e.g. full frame)
|
||||
*/
|
||||
|
||||
void get_frame_into(size_t frame_index, std::byte *frame_buffer,
|
||||
DetectorHeader *header = nullptr);
|
||||
void get_frame_into(
|
||||
size_t frame_index, std::byte *frame_buffer, const size_t roi_index = 0,
|
||||
DetectorHeader *header = nullptr); // TODO read_into updates it!!!!
|
||||
|
||||
/**
|
||||
* @brief get the frame at the given frame index
|
||||
* @param frame_number frame number to read
|
||||
* @param roi_index index of the ROI to read (default is 0 e.g. full frame)
|
||||
* @return Frame
|
||||
*/
|
||||
Frame get_frame(size_t frame_index);
|
||||
Frame get_frame(size_t frame_index, const size_t roi_index = 0);
|
||||
|
||||
void open_subfiles();
|
||||
void open_subfiles(const size_t roi_index);
|
||||
};
|
||||
|
||||
} // namespace aare
|
||||
@@ -2,11 +2,11 @@
|
||||
#pragma once
|
||||
#include "aare/defs.hpp"
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <filesystem>
|
||||
#include <fmt/format.h>
|
||||
#include <fstream>
|
||||
#include <optional>
|
||||
#include <chrono>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
using json = nlohmann::json;
|
||||
@@ -109,7 +109,7 @@ class RawMasterFile {
|
||||
std::optional<size_t> m_number_of_rows;
|
||||
std::optional<uint8_t> m_counter_mask;
|
||||
|
||||
std::optional<ROI> m_roi;
|
||||
std::optional<std::vector<ROI>> m_rois;
|
||||
|
||||
public:
|
||||
RawMasterFile(const std::filesystem::path &fpath);
|
||||
@@ -141,11 +141,15 @@ class RawMasterFile {
|
||||
std::optional<size_t> number_of_rows() const;
|
||||
std::optional<uint8_t> counter_mask() const;
|
||||
|
||||
std::optional<std::vector<ROI>> rois() const;
|
||||
|
||||
std::optional<ROI> roi() const;
|
||||
|
||||
ScanParameters scan_parameters() const;
|
||||
|
||||
std::optional<std::chrono::nanoseconds> exptime() const { return m_exptime; }
|
||||
std::optional<std::chrono::nanoseconds> exptime() const {
|
||||
return m_exptime;
|
||||
}
|
||||
std::chrono::nanoseconds period() const { return m_period; }
|
||||
|
||||
private:
|
||||
|
||||
Reference in New Issue
Block a user