From 19c6a4091fcce9706b9f21dd4a0cb5a2e5766f3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Fr=C3=B6jdh?= Date: Thu, 31 Oct 2024 08:56:12 +0100 Subject: [PATCH] improved docs and added PixelMap --- CMakeLists.txt | 2 + docs/src/File.rst | 3 +- docs/src/Frame.rst | 3 +- include/aare/File.hpp | 43 ++++++++++++-------- include/aare/Frame.hpp | 82 +++++++++++++++++++++++++++++++-------- include/aare/PixelMap.hpp | 10 +++++ python/src/module.cpp | 8 ++-- python/src/pixel_map.hpp | 21 ++++++++++ src/File.cpp | 70 +++++++++++++++++++++------------ src/Frame.cpp | 58 ++++++--------------------- src/PixelMap.cpp | 31 +++++++++++++++ 11 files changed, 220 insertions(+), 111 deletions(-) create mode 100644 include/aare/PixelMap.hpp create mode 100644 python/src/pixel_map.hpp create mode 100644 src/PixelMap.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 905816c..3f50fc6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -243,6 +243,7 @@ set(PUBLICHEADERS include/aare/NumpyFile.hpp include/aare/NumpyHelpers.hpp include/aare/Pedestal.hpp + include/aare/PixelMap.hpp include/aare/RawFile.hpp include/aare/SubFile.hpp include/aare/VarClusterFinder.hpp @@ -256,6 +257,7 @@ set(SourceFiles ${CMAKE_CURRENT_SOURCE_DIR}/src/Frame.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/File.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/NumpyFile.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/PixelMap.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/RawFile.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/SubFile.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/NumpyHelpers.cpp diff --git a/docs/src/File.rst b/docs/src/File.rst index ddce281..784a272 100644 --- a/docs/src/File.rst +++ b/docs/src/File.rst @@ -4,4 +4,5 @@ File .. doxygenclass:: aare::File :members: - :undoc-members: \ No newline at end of file + :undoc-members: + :private-members: \ No newline at end of file diff --git a/docs/src/Frame.rst b/docs/src/Frame.rst index 3b70916..65986e4 100644 --- a/docs/src/Frame.rst +++ b/docs/src/Frame.rst @@ -4,4 +4,5 @@ Frame .. doxygenclass:: aare::Frame :members: - :undoc-members: \ No newline at end of file + :undoc-members: + :private-members: \ No newline at end of file diff --git a/include/aare/File.hpp b/include/aare/File.hpp index a12f64f..b29171a 100644 --- a/include/aare/File.hpp +++ b/include/aare/File.hpp @@ -1,17 +1,19 @@ #pragma once #include "aare/FileInterface.hpp" - +#include namespace aare { /** - * @brief RAII File class for reading and writing image files in various formats - * wrapper on a FileInterface to abstract the underlying file format - * @note documentation for each function is in the FileInterface class + * @brief RAII File class for reading, and in the future potentially writing + * image files in various formats. Minimal generic interface. For specail fuctions + * plase use the RawFile or NumpyFile classes directly. + * Wraps FileInterface to abstract the underlying file format + * @note **frame_number** refers the the frame number sent by the detector while **frame_index** + * is the position of the frame in the file */ class File { - private: - FileInterface *file_impl; + std::unique_ptr file_impl; public: /** @@ -24,29 +26,38 @@ class File { * */ File(const std::filesystem::path &fname, const std::string &mode="r", const FileConfig &cfg = {}); + + /**Since the object is responsible for managing the file we disable copy construction */ + File(File const &other) = delete; + + /**The same goes for copy assignment */ + File& operator=(File const &other) = delete; + + File(File &&other) noexcept; + File& operator=(File &&other) noexcept; + ~File() = default; Frame read_frame(); //!< read one frame from the file at the current position - Frame read_frame(size_t frame_number); //!< read the frame at the position given by frame number + Frame read_frame(size_t frame_index); //!< read one frame at the position given by frame number std::vector read_n(size_t n_frames); //!< read n_frames from the file at the current position void read_into(std::byte *image_buf); void read_into(std::byte *image_buf, size_t n_frames); size_t frame_number(size_t frame_index); //!< get the frame number at the given frame index - size_t bytes_per_frame(); - size_t pixels_per_frame(); - void seek(size_t frame_number); - size_t tell() const; + size_t bytes_per_frame() const; + size_t pixels_per_frame() const; + size_t bytes_per_pixel() const; + size_t bitdepth() const; + void seek(size_t frame_index); //!< seek to the given frame index + size_t tell() const; //!< get the frame index of the file pointer size_t total_frames() const; size_t rows() const; size_t cols() const; - size_t bitdepth() const; - size_t bytes_per_pixel() const; - void set_total_frames(size_t total_frames); + DetectorType detector_type() const; - File(File &&other) noexcept; - ~File(); + }; } // namespace aare \ No newline at end of file diff --git a/include/aare/Frame.hpp b/include/aare/Frame.hpp index 88e4ab2..5ce63ac 100644 --- a/include/aare/Frame.hpp +++ b/include/aare/Frame.hpp @@ -11,31 +11,49 @@ namespace aare { /** - * @brief Frame class to represent a single frame of data - * model class - * should be able to work with streams coming from files or network + * @brief Frame class to represent a single frame of data. Not much more than a + * pointer and some info. Limited interface to accept frames from many sources. */ class Frame { uint32_t m_rows; uint32_t m_cols; Dtype m_dtype; std::byte *m_data; + //TODO! Add frame number? public: + /** + * @brief Construct a new Frame + * @param rows number of rows + * @param cols number of columns + * @param dtype data type of the pixels + * @note the data is initialized to zero + */ Frame(uint32_t rows, uint32_t cols, Dtype dtype); - Frame(const std::byte *bytes, uint32_t rows, uint32_t cols, Dtype dtype); - ~Frame() noexcept; - // disable copy and assignment - Frame &operator=(const Frame &other)=delete; - Frame(const Frame &other)=delete; + /** + * @brief Construct a new Frame + * @param bytes pointer to the data to be copied into the frame + * @param rows number of rows + * @param cols number of columns + * @param dtype data type of the pixels + */ + Frame(const std::byte *bytes, uint32_t rows, uint32_t cols, Dtype dtype); + ~Frame(){ delete[] m_data; }; + + /** @warning Copy is disabled to ensure performance when passing + * frames around. Can discuss enabling it. + * + */ + Frame &operator=(const Frame &other) = delete; + Frame(const Frame &other) = delete; // enable move Frame &operator=(Frame &&other) noexcept; Frame(Frame &&other) noexcept; - // explicit copy - Frame copy() const; + + Frame clone() const; //<- Explicit copy uint32_t rows() const; uint32_t cols() const; @@ -45,32 +63,62 @@ class Frame { size_t bytes() const; std::byte *data() const; - std::byte *get(uint32_t row, uint32_t col); + /** + * @brief Get the pointer to the pixel at the given row and column + * @param row row index + * @param col column index + * @return pointer to the pixel + * @warning The user should cast the pointer to the appropriate type. Think + * twice if this is the function you want to use. + */ + std::byte *pixel_ptr(uint32_t row, uint32_t col) const; - // TODO! can we, or even want to remove the template? + /** + * @brief Set the pixel at the given row and column to the given value + * @tparam T type of the value + * @param row row index + * @param col column index + * @param data value to set + */ template void set(uint32_t row, uint32_t col, T data) { assert(sizeof(T) == m_dtype.bytes()); if (row >= m_rows || col >= m_cols) { throw std::out_of_range("Invalid row or column index"); } - std::memcpy(m_data + (row * m_cols + col) * m_dtype.bytes(), &data, m_dtype.bytes()); + std::memcpy(m_data + (row * m_cols + col) * m_dtype.bytes(), &data, + m_dtype.bytes()); } - template T get_t(uint32_t row, uint32_t col) { + template T get(uint32_t row, uint32_t col) { assert(sizeof(T) == m_dtype.bytes()); if (row >= m_rows || col >= m_cols) { throw std::out_of_range("Invalid row or column index"); } + //TODO! add tests then reimplement using pixel_ptr T data; - std::memcpy(&data, m_data + (row * m_cols + col) * m_dtype.bytes(), m_dtype.bytes()); + std::memcpy(&data, m_data + (row * m_cols + col) * m_dtype.bytes(), + m_dtype.bytes()); return data; } + /** + * @brief Return an NDView of the frame. This is the preferred way to access + * data in the frame. + * + * @tparam T type of the pixels + * @return NDView + */ template NDView view() { - std::array shape = {static_cast(m_rows), static_cast(m_cols)}; + std::array shape = {static_cast(m_rows), + static_cast(m_cols)}; T *data = reinterpret_cast(m_data); return NDView(data, shape); } - template NDArray image() { return NDArray(this->view()); } + /** + * @brief Copy the frame data into a new NDArray. This is a deep copy. + */ + template NDArray image() { + return NDArray(this->view()); + } }; } // namespace aare \ No newline at end of file diff --git a/include/aare/PixelMap.hpp b/include/aare/PixelMap.hpp new file mode 100644 index 0000000..2967ef1 --- /dev/null +++ b/include/aare/PixelMap.hpp @@ -0,0 +1,10 @@ +#pragma once + +#include "aare/defs.hpp" +#include "aare/NDArray.hpp" + +namespace aare { + +NDArray GenerateMoench03PixelMap(); + +} // namespace aare \ No newline at end of file diff --git a/python/src/module.cpp b/python/src/module.cpp index 7d1d822..e1e1b53 100644 --- a/python/src/module.cpp +++ b/python/src/module.cpp @@ -1,16 +1,16 @@ - +//Files with bindings to the different classes #include "file.hpp" #include "var_cluster.hpp" +#include "pixel_map.hpp" +//Pybind stuff #include #include namespace py = pybind11; PYBIND11_MODULE(_aare, m) { - - - define_file_io_bindings(m); define_var_cluster_finder_bindings(m); + define_pixel_map_bindings(m); } \ No newline at end of file diff --git a/python/src/pixel_map.hpp b/python/src/pixel_map.hpp new file mode 100644 index 0000000..31b8f31 --- /dev/null +++ b/python/src/pixel_map.hpp @@ -0,0 +1,21 @@ +#include "aare/PixelMap.hpp" +#include "np_helper.hpp" + + +#include +#include +#include +#include + + +namespace py = pybind11; +using namespace::aare; + + +void define_pixel_map_bindings(py::module &m) { + m.def("GenerateMoench03PixelMap", []() { + auto ptr = new NDArray(GenerateMoench03PixelMap()); + return return_image_data(ptr); + }); + +} \ No newline at end of file diff --git a/src/File.cpp b/src/File.cpp index 2e2a1a3..ea7497e 100644 --- a/src/File.cpp +++ b/src/File.cpp @@ -6,52 +6,72 @@ namespace aare { -File::File(const std::filesystem::path &fname, const std::string &mode, const FileConfig &cfg) - : file_impl(nullptr){ - if (mode != "r" && mode != "w" && mode != "a") { - throw std::invalid_argument("Unsupported file mode"); +File::File(const std::filesystem::path &fname, const std::string &mode, + const FileConfig &cfg) + : file_impl(nullptr) { + if (mode != "r") { + throw std::invalid_argument("At the moment only reading is supported"); } - if ((mode == "r" || mode == "a") && !std::filesystem::exists(fname)) { - throw std::runtime_error(fmt::format("File does not exist: {}", fname.string())); + if ((mode == "r") && !std::filesystem::exists(fname)) { + throw std::runtime_error( + fmt::format("File does not exist: {}", fname.string())); } + // Assuming we are pointing at a master file? + // TODO! How do we read raw files directly? if (fname.extension() == ".raw" || fname.extension() == ".json") { - // aare::logger::debug("Loading raw file"); - file_impl = new RawFile(fname, mode, cfg); + // file_impl = new RawFile(fname, mode, cfg); + file_impl = std::make_unique(fname, mode, cfg); } - // check if extension is numpy else if (fname.extension() == ".npy") { - // aare::logger::debug("Loading numpy file"); - file_impl = new NumpyFile(fname, mode, cfg); + // file_impl = new NumpyFile(fname, mode, cfg); + file_impl = std::make_unique(fname, mode, cfg); } else { throw std::runtime_error("Unsupported file type"); } } +File::File(File &&other) noexcept{ + std::swap(file_impl, other.file_impl); +} + +File& File::operator=(File &&other) noexcept { + if (this != &other) { + File tmp(std::move(other)); + std::swap(file_impl, tmp.file_impl); + } + return *this; +} + Frame File::read_frame() { return file_impl->read_frame(); } +Frame File::read_frame(size_t frame_index) { + return file_impl->read_frame(frame_index); +} size_t File::total_frames() const { return file_impl->total_frames(); } -std::vector File::read_n(size_t n_frames) { return file_impl->read_n(n_frames); } +std::vector File::read_n(size_t n_frames) { + return file_impl->read_n(n_frames); +} + void File::read_into(std::byte *image_buf) { file_impl->read_into(image_buf); } -void File::read_into(std::byte *image_buf, size_t n_frames) { file_impl->read_into(image_buf, n_frames); } -size_t File::frame_number(size_t frame_index) { return file_impl->frame_number(frame_index); } -size_t File::bytes_per_frame() { return file_impl->bytes_per_frame(); } -size_t File::pixels_per_frame() { return file_impl->pixels_per_frame(); } -void File::seek(size_t frame_number) { file_impl->seek(frame_number); } +void File::read_into(std::byte *image_buf, size_t n_frames) { + file_impl->read_into(image_buf, n_frames); +} +size_t File::frame_number(size_t frame_index) { + return file_impl->frame_number(frame_index); +} + +size_t File::bytes_per_frame() const { return file_impl->bytes_per_frame(); } +size_t File::pixels_per_frame() const{ return file_impl->pixels_per_frame(); } +void File::seek(size_t frame_index) { file_impl->seek(frame_index); } size_t File::tell() const { return file_impl->tell(); } size_t File::rows() const { return file_impl->rows(); } size_t File::cols() const { return file_impl->cols(); } size_t File::bitdepth() const { return file_impl->bitdepth(); } -size_t File::bytes_per_pixel() const { return file_impl->bitdepth()/8; } -File::~File() { delete file_impl; } +size_t File::bytes_per_pixel() const { return file_impl->bitdepth() / 8; } + DetectorType File::detector_type() const { return file_impl->detector_type(); } -Frame File::read_frame(size_t frame_number) { return file_impl->read_frame(frame_number); } - -File::File(File &&other) noexcept : file_impl(other.file_impl) { other.file_impl = nullptr; } - -// write move assignment operator - } // namespace aare \ No newline at end of file diff --git a/src/Frame.cpp b/src/Frame.cpp index 98bf92a..d44bed5 100644 --- a/src/Frame.cpp +++ b/src/Frame.cpp @@ -7,28 +7,16 @@ namespace aare { -/** - * @brief Construct a new Frame - * @param bytes pointer to the data to be copied into the frame - * @param rows number of rows - * @param cols number of columns - * @param bitdepth bitdepth of the pixels - */ Frame::Frame(const std::byte *bytes, uint32_t rows, uint32_t cols, Dtype dtype) - : m_rows(rows), m_cols(cols), m_dtype(dtype), m_data(new std::byte[rows * cols * m_dtype.bytes()]) { + : m_rows(rows), m_cols(cols), m_dtype(dtype), + m_data(new std::byte[rows * cols * m_dtype.bytes()]) { std::memcpy(m_data, bytes, rows * cols * m_dtype.bytes()); } -/** - * @brief Construct a new Frame - * @param rows number of rows - * @param cols number of columns - * @param bitdepth bitdepth of the pixels - * @note the data is initialized to zero - */ Frame::Frame(uint32_t rows, uint32_t cols, Dtype dtype) - : m_rows(rows), m_cols(cols), m_dtype(dtype), m_data(new std::byte[rows * cols * dtype.bytes()]) { + : m_rows(rows), m_cols(cols), m_dtype(dtype), + m_data(new std::byte[rows * cols * dtype.bytes()]) { std::memset(m_data, 0, rows * cols * dtype.bytes()); } @@ -41,14 +29,8 @@ uint64_t Frame::size() const { return m_rows * m_cols; } size_t Frame::bytes() const { return m_rows * m_cols * m_dtype.bytes(); } std::byte *Frame::data() const { return m_data; } -/** - * @brief Get the pointer to the pixel at the given row and column - * @param row row index - * @param col column index - * @return pointer to the pixel - * @note the user should cast the pointer to the appropriate type - */ -std::byte *Frame::get(uint32_t row, uint32_t col) { + +std::byte *Frame::pixel_ptr(uint32_t row, uint32_t col) const{ if ((row >= m_rows) || (col >= m_cols)) { std::cerr << "Invalid row or column index" << '\n'; return nullptr; @@ -56,20 +38,7 @@ std::byte *Frame::get(uint32_t row, uint32_t col) { return m_data + (row * m_cols + col) * (m_dtype.bytes()); } -// Frame &Frame::operator=(const Frame &other) { -// if (this == &other) { -// return *this; -// } -// m_rows = other.rows(); -// m_cols = other.cols(); -// m_dtype = other.dtype(); -// m_data = new std::byte[m_rows * m_cols * m_dtype.bytes()]; -// if (m_data == nullptr) { -// throw std::bad_alloc(); -// } -// std::memcpy(m_data, other.m_data, m_rows * m_cols * m_dtype.bytes()); -// return *this; -// } + Frame &Frame::operator=(Frame &&other) noexcept { if (this == &other) { return *this; @@ -87,24 +56,19 @@ Frame &Frame::operator=(Frame &&other) noexcept { return *this; } Frame::Frame(Frame &&other) noexcept - : m_rows(other.rows()), m_cols(other.cols()), m_dtype(other.dtype()), m_data(other.m_data) { + : m_rows(other.rows()), m_cols(other.cols()), m_dtype(other.dtype()), + m_data(other.m_data) { other.m_data = nullptr; other.m_rows = other.m_cols = 0; other.m_dtype = Dtype(Dtype::TypeIndex::ERROR); } -// Frame::Frame(const Frame &other) -// : m_rows(other.rows()), m_cols(other.cols()), m_dtype(other.dtype()), -// m_data(new std::byte[m_rows * m_cols * m_dtype.bytes()]) { -// std::memcpy(m_data, other.m_data, m_rows * m_cols * m_dtype.bytes()); -// } - -Frame Frame::copy() const { +Frame Frame::clone() const { Frame frame(m_rows, m_cols, m_dtype); std::memcpy(frame.m_data, m_data, m_rows * m_cols * m_dtype.bytes()); return frame; } -Frame::~Frame() noexcept { delete[] m_data; } + } // namespace aare diff --git a/src/PixelMap.cpp b/src/PixelMap.cpp new file mode 100644 index 0000000..e0d82bc --- /dev/null +++ b/src/PixelMap.cpp @@ -0,0 +1,31 @@ +#include "aare/PixelMap.hpp" + +#include + +namespace aare { +NDArray GenerateMoench03PixelMap() { + std::array const adc_nr = {300, 325, 350, 375, 300, 325, 350, 375, 200, 225, 250, + 275, 200, 225, 250, 275, 100, 125, 150, 175, 100, 125, + 150, 175, 0, 25, 50, 75, 0, 25, 50, 75}; + int const sc_width = 25; + int const nadc = 32; + int const pixels_per_sc = 5000; + NDArray order_map({400, 400}); + + int pixel = 0; + for (int i = 0; i != pixels_per_sc; ++i) { + for (int i_adc = 0; i_adc != nadc; ++i_adc) { + int const col = adc_nr[i_adc] + (i % sc_width); + int row = 0; + if ((i_adc / 4) % 2 == 0) + row = 199 - (i / sc_width); + else + row = 200 + (i / sc_width); + + order_map(row, col) = pixel; + pixel++; + } + } + return order_map; +} +} // namespace aare \ No newline at end of file