From b172c7aa0a478c3de87d1aeff68feb2a86bad782 Mon Sep 17 00:00:00 2001 From: froejdh_e Date: Thu, 7 Nov 2024 16:24:48 +0100 Subject: [PATCH] starting work on ROI --- include/aare/RawFile.hpp | 9 +++-- include/aare/RawMasterFile.hpp | 11 ++++++ include/aare/SubFile.hpp | 32 ++++++++------- python/examples/play.py | 15 ++++--- python/src/file.hpp | 72 +++++++++++++++++++++------------- src/RawFile.cpp | 39 +++++++++++++----- src/RawMasterFile.cpp | 29 ++++++++++++++ src/SubFile.cpp | 9 ----- 8 files changed, 145 insertions(+), 71 deletions(-) diff --git a/include/aare/RawFile.hpp b/include/aare/RawFile.hpp index 78e68ef..12acea3 100644 --- a/include/aare/RawFile.hpp +++ b/include/aare/RawFile.hpp @@ -29,9 +29,10 @@ struct ModuleConfig { * Consider using that unless you need raw file specific functionality. */ class RawFile : public FileInterface { - size_t n_subfiles{}; - size_t n_subfile_parts{}; - std::vector> subfiles; + size_t n_subfiles{}; //f0,f1...fn + size_t n_subfile_parts{}; // d0,d1...dn + //TODO! move to vector of SubFile instead of pointers + std::vector> subfiles; //subfiles[f0,f1...fn][d0,d1...dn] std::vector positions; ModuleConfig cfg{0, 0}; @@ -102,7 +103,7 @@ class RawFile : public FileInterface { static DetectorHeader read_header(const std::filesystem::path &fname); - void find_number_of_subfiles(); + int find_number_of_subfiles(); void open_subfiles(); void find_geometry(); }; diff --git a/include/aare/RawMasterFile.hpp b/include/aare/RawMasterFile.hpp index f86054a..76292b7 100644 --- a/include/aare/RawMasterFile.hpp +++ b/include/aare/RawMasterFile.hpp @@ -58,6 +58,13 @@ class ScanParameters { bool enabled() const; }; +struct ROI{ + size_t xmin{}; + size_t xmax{}; + size_t ymin{}; + size_t ymax{}; +}; + /** * @brief Class for parsing a master file either in our .json format or the old * .raw format @@ -95,6 +102,8 @@ class RawMasterFile { std::optional m_number_of_rows; std::optional m_quad; + std::optional m_roi; + public: RawMasterFile(const std::filesystem::path &fpath); @@ -121,6 +130,8 @@ class RawMasterFile { std::optional number_of_rows() const; std::optional quad() const; + std::optional roi() const; + ScanParameters scan_parameters() const; private: diff --git a/include/aare/SubFile.hpp b/include/aare/SubFile.hpp index 47cc07c..d9f7d0a 100644 --- a/include/aare/SubFile.hpp +++ b/include/aare/SubFile.hpp @@ -14,8 +14,20 @@ namespace aare { * @brief Class to read a subfile from a RawFile */ class SubFile { + protected: + FILE *fp = nullptr; + size_t m_bitdepth; + std::filesystem::path m_fname; + size_t m_rows{}; + size_t m_cols{}; + std::string m_mode; + size_t n_frames{}; + int m_sub_file_index_{}; + DetectorType m_detector_type; + std::optional> pixel_map; + + public: - size_t write_part(std::byte *buffer, DetectorHeader header, size_t frame_index); /** * @brief SubFile constructor * @param fname path to the subfile @@ -58,23 +70,13 @@ class SubFile { size_t get_part(std::byte *buffer, size_t frame_index); size_t frame_number(size_t frame_index); - // TODO: define the inlines as variables and assign them in constructor - inline size_t bytes_per_part() const { return (m_bitdepth / 8) * m_rows * m_cols; } - inline size_t pixels_per_part() const { return m_rows * m_cols; } + + size_t bytes_per_part() const { return (m_bitdepth / 8) * m_rows * m_cols; } + size_t pixels_per_part() const { return m_rows * m_cols; } ~SubFile(); - protected: - FILE *fp = nullptr; - size_t m_bitdepth; - std::filesystem::path m_fname; - size_t m_rows{}; - size_t m_cols{}; - std::string m_mode; - size_t n_frames{}; - int m_sub_file_index_{}; - DetectorType m_detector_type; - std::optional> pixel_map; + }; } // namespace aare \ No newline at end of file diff --git a/python/examples/play.py b/python/examples/play.py index 3a12d28..42f3c33 100644 --- a/python/examples/play.py +++ b/python/examples/play.py @@ -89,11 +89,11 @@ def get_Mh02_frames(fname): -base = Path('/Users/erik/data/matterhorn/raw') -fpath = Path(base / 'scan_15keV_vrf700_vrsh700_th0_master_0.json') -f = aare.CtbRawFile(fpath, transform=transform.matterhorn02) -f.seek(100) -header1, image1 = f.read_frame() +# base = Path('/Users/erik/data/matterhorn/raw') +# fpath = Path(base / 'scan_15keV_vrf700_vrsh700_th0_master_0.json') +# f = aare.CtbRawFile(fpath, transform=transform.matterhorn02) +# f.seek(100) +# header1, image1 = f.read_frame() # fpath = Path(base / 'scan_all15keV_vrf500_vrsh700_th0_master_0.json') @@ -133,4 +133,7 @@ header1, image1 = f.read_frame() # f2 = aare.CtbRawFile(fpath, transform=transform.matterhorn02) # header, data = f2.read() # plt.plot(data[:,0,20,20]) - +from aare import RawMasterFile, File +fpath = Path('/mnt/sls_det_storage/matterhorn_data/aare_test_data/Jungfrau10/Jungfrau_DoubleModule_1UDP_ROI/SideBySide/241019_JF_12keV_Si_FF_GaAs_FF_7p88mmFilter_PedestalStart_ZPos_5.5_master_0.json') +m = RawMasterFile(fpath) +f = File(fpath) \ No newline at end of file diff --git a/python/src/file.hpp b/python/src/file.hpp index 6471b44..2c3a36f 100644 --- a/python/src/file.hpp +++ b/python/src/file.hpp @@ -17,7 +17,8 @@ namespace py = pybind11; using namespace ::aare; -void define_file_io_bindings(py::module &m) { +void define_file_io_bindings(py::module &m) +{ PYBIND11_NUMPY_DTYPE(DetectorHeader, frameNumber, expLength, packetNumber, bunchId, timestamp, modId, row, column, reserved, @@ -26,7 +27,8 @@ void define_file_io_bindings(py::module &m) { py::class_(m, "CtbRawFile") .def(py::init()) .def("read_frame", - [](CtbRawFile &self) { + [](CtbRawFile &self) + { size_t image_size = self.image_size_in_bytes(); py::array image; std::vector shape; @@ -36,7 +38,6 @@ void define_file_io_bindings(py::module &m) { py::array_t header(1); - // always read bytes image = py::array_t(shape); @@ -53,11 +54,11 @@ void define_file_io_bindings(py::module &m) { .def_property_readonly("frames_in_file", &CtbRawFile::frames_in_file); py::class_(m, "File") - .def(py::init([](const std::filesystem::path &fname) { - return File(fname, "r", {}); - })) + .def(py::init([](const std::filesystem::path &fname) + { return File(fname, "r", {}); })) .def(py::init( - [](const std::filesystem::path &fname, const std::string &mode) { + [](const std::filesystem::path &fname, const std::string &mode) + { return File(fname, mode, {}); })) .def(py::init shape; shape.reserve(2); shape.push_back(self.rows()); shape.push_back(self.cols()); - if (item_size == 1) { + if (item_size == 1) + { image = py::array_t(shape); - } else if (item_size == 2) { + } + else if (item_size == 2) + { image = py::array_t(shape); - } else if (item_size == 4) { + } + else if (item_size == 4) + { image = py::array_t(shape); } self.read_into( @@ -96,7 +104,8 @@ void define_file_io_bindings(py::module &m) { return image; }) .def("read_frame", - [](File &self, size_t frame_number) { + [](File &self, size_t frame_number) + { self.seek(frame_number); const uint8_t item_size = self.bytes_per_pixel(); py::array image; @@ -104,18 +113,24 @@ void define_file_io_bindings(py::module &m) { shape.reserve(2); shape.push_back(self.rows()); shape.push_back(self.cols()); - if (item_size == 1) { + if (item_size == 1) + { image = py::array_t(shape); - } else if (item_size == 2) { + } + else if (item_size == 2) + { image = py::array_t(shape); - } else if (item_size == 4) { + } + else if (item_size == 4) + { image = py::array_t(shape); } self.read_into( reinterpret_cast(image.mutable_data())); return image; }) - .def("read_n", [](File &self, size_t n_frames) { + .def("read_n", [](File &self, size_t n_frames) + { const uint8_t item_size = self.bytes_per_pixel(); py::array image; std::vector shape; @@ -132,8 +147,7 @@ void define_file_io_bindings(py::module &m) { } self.read_into(reinterpret_cast(image.mutable_data()), n_frames); - return image; - }); + return image; }); py::class_(m, "FileConfig") .def(py::init<>()) @@ -147,10 +161,8 @@ void define_file_io_bindings(py::module &m) { .def_readwrite("dtype", &FileConfig::dtype) .def("__eq__", &FileConfig::operator==) .def("__ne__", &FileConfig::operator!=) - .def("__repr__", [](const FileConfig &a) { - return ""; - }); - + .def("__repr__", [](const FileConfig &a) + { return ""; }); py::class_(m, "RawMasterFile") .def(py::init()) @@ -177,18 +189,24 @@ void define_file_io_bindings(py::module &m) { .def_property_readonly("transceiver_samples", &RawMasterFile::transceiver_samples) .def_property_readonly("number_of_rows", &RawMasterFile::number_of_rows) .def_property_readonly("quad", &RawMasterFile::quad) - .def_property_readonly("scan_parameters", &RawMasterFile::scan_parameters); - - + .def_property_readonly("scan_parameters", &RawMasterFile::scan_parameters) + .def_property_readonly("roi", &RawMasterFile::roi); py::class_(m, "ScanParameters") .def(py::init()) - .def(py::init()) + .def(py::init()) .def_property_readonly("enabled", &ScanParameters::enabled) .def_property_readonly("dac", &ScanParameters::dac) .def_property_readonly("start", &ScanParameters::start) .def_property_readonly("stop", &ScanParameters::stop) .def_property_readonly("step", &ScanParameters::step); + + py::class_(m, "ROI") + .def(py::init<>()) + .def_readwrite("xmin", &ROI::xmin) + .def_readwrite("xmax", &ROI::xmax) + .def_readwrite("ymin", &ROI::ymin) + .def_readwrite("ymax", &ROI::ymax); // py::class_(m, "ClusterHeader") // .def(py::init<>()) // .def_readwrite("frame_number", &ClusterHeader::frame_number) diff --git a/src/RawFile.cpp b/src/RawFile.cpp index 31b57c5..85f9736 100644 --- a/src/RawFile.cpp +++ b/src/RawFile.cpp @@ -13,9 +13,10 @@ RawFile::RawFile(const std::filesystem::path &fname, const std::string &mode) : m_master(fname) { m_mode = mode; if (mode == "r") { - find_number_of_subfiles(); - n_subfile_parts = m_master.geometry().col * m_master.geometry().row; + n_subfiles = find_number_of_subfiles(); //f0,f1...fn + n_subfile_parts = m_master.geometry().col * m_master.geometry().row; // d0,d1...dn find_geometry(); + //update_geometry_from_roi(); open_subfiles(); } else { throw std::runtime_error(LOCATION + @@ -107,27 +108,41 @@ bool RawFile::is_master_file(const std::filesystem::path &fpath) { return stem.find("_master_") != std::string::npos; } -void RawFile::find_number_of_subfiles() { - int n_mod = 0; - while (std::filesystem::exists(m_master.data_fname(0, ++n_mod))) +int RawFile::find_number_of_subfiles() { + int n_files = 0; + // f0,f1...fn How many files is the data split into? + while (std::filesystem::exists(m_master.data_fname(0, ++n_files))) ; - n_subfiles = n_mod; + #ifdef AARE_VERBOSE fmt::print("Found: {} subfiles\n", n_subfiles); #endif + return n_files; } void RawFile::find_geometry() { uint16_t r{}; uint16_t c{}; + // for (size_t i = 0; i < n_subfile_parts; i++) { + // for (size_t j = 0; j != n_subfiles; ++j) { + // auto h = this->read_header(m_master.data_fname(i, j)); + // r = std::max(r, h.row); + // c = std::max(c, h.column); + + // positions.push_back({h.row, h.column}); + // } + // } + + + std::vector module_position; + for (size_t i = 0; i < n_subfile_parts; i++) { - for (size_t j = 0; j != n_subfiles; ++j) { - auto h = this->read_header(m_master.data_fname(i, j)); + auto h = this->read_header(m_master.data_fname(i, 0)); r = std::max(r, h.row); c = std::max(c, h.column); - positions.push_back({h.row, h.column}); - } + xy pos = {h.row * m_master.pixels_y(), h.column* m_master.pixels_x()}; + module_position.emplace_back(pos); } r++; @@ -137,6 +152,10 @@ void RawFile::find_geometry() { m_cols = (c * m_master.pixels_x()); m_rows += static_cast((r - 1) * cfg.module_gap_row); + + for (size_t i=0; i < module_position.size(); i++){ + fmt::print("Module {} at position: ({},{})\n", i, module_position[i].row, module_position[i].col); + } } Frame RawFile::get_frame(size_t frame_index) { diff --git a/src/RawMasterFile.cpp b/src/RawMasterFile.cpp index 09a0006..07de21e 100644 --- a/src/RawMasterFile.cpp +++ b/src/RawMasterFile.cpp @@ -143,6 +143,8 @@ ScanParameters RawMasterFile::scan_parameters() const { return m_scan_parameters; } +std::optional RawMasterFile::roi() const { return m_roi; } + void RawMasterFile::parse_json(const std::filesystem::path &fpath) { std::ifstream ifs(fpath); json j; @@ -240,6 +242,33 @@ void RawMasterFile::parse_json(const std::filesystem::path &fpath) { // not a scan } + try{ + ROI tmp_roi; + auto obj = j.at("Receiver Roi"); + fmt::print("Receiver ROI: {}\n", obj.dump()); + tmp_roi.xmin = obj.at("xmin"); + tmp_roi.xmax = obj.at("xmax"); + tmp_roi.ymin = obj.at("ymin"); + tmp_roi.ymax = obj.at("ymax"); + + //if any of the values are set update the roi + if (tmp_roi.xmin != 4294967295 || tmp_roi.xmax != 4294967295 || + tmp_roi.ymin != 4294967295 || tmp_roi.ymax != 4294967295) { + m_roi = tmp_roi; + } + + + }catch (const json::out_of_range &e) { + // leave the optional empty + } + + //if we have an roi we need to update the geometry for the subfiles + if (m_roi){ + + } + + + // Update detector type for Moench // TODO! How does this work with old .raw master files? #ifdef AARE_VERBOSE diff --git a/src/SubFile.cpp b/src/SubFile.cpp index 314fec5..04c686b 100644 --- a/src/SubFile.cpp +++ b/src/SubFile.cpp @@ -61,16 +61,7 @@ size_t SubFile::get_part(std::byte *buffer, size_t frame_index) { } } -size_t SubFile::write_part(std::byte *buffer, DetectorHeader header, size_t frame_index) { - if (frame_index > n_frames) { - throw std::runtime_error("Frame number out of range"); - } - fseek(fp, static_cast((sizeof(DetectorHeader) + bytes_per_part()) * frame_index), SEEK_SET); - auto wc = fwrite(reinterpret_cast(&header), sizeof(header), 1, fp); - wc += fwrite(buffer, bytes_per_part(), 1, fp); - return wc; -} size_t SubFile::frame_number(size_t frame_index) { DetectorHeader h{};