From f62cc229f9b74ef1a7703f442b558317b141c70e Mon Sep 17 00:00:00 2001 From: Bechir Braham Date: Mon, 4 Mar 2024 15:06:52 +0100 Subject: [PATCH] saving work --- src/common/defs.hpp | 1 + src/core/Frame.cpp | 4 +- src/core/Frame.hpp | 21 +++--- src/file_io/file/File.hpp | 36 +++++----- src/file_io/file/FileHandler.hpp | 29 ++++++++ src/file_io/file/JsonFile.cpp | 5 +- src/file_io/file/JsonFile.hpp | 4 +- src/file_io/file/SubFile.cpp | 75 ++++++++++---------- src/file_io/file/SubFile.hpp | 53 +++++--------- src/file_io/file_factory/FileFactory.cpp | 4 +- src/file_io/file_factory/FileFactory.hpp | 5 +- src/file_io/file_factory/JsonFileFactory.cpp | 25 ++++--- src/file_io/file_factory/JsonFileFactory.hpp | 4 +- src/main.cpp | 39 ++++------ 14 files changed, 149 insertions(+), 156 deletions(-) diff --git a/src/common/defs.hpp b/src/common/defs.hpp index 4f4bb8e..826fb80 100644 --- a/src/common/defs.hpp +++ b/src/common/defs.hpp @@ -47,3 +47,4 @@ template <> DetectorType StringTo(std::string); template <> TimingMode StringTo(std::string); using DataTypeVariants = std::variant; + diff --git a/src/core/Frame.cpp b/src/core/Frame.cpp index e1c1ba2..dde8271 100644 --- a/src/core/Frame.cpp +++ b/src/core/Frame.cpp @@ -2,7 +2,7 @@ #include -IFrame::IFrame(std::byte* bytes, ssize_t rows, ssize_t cols, ssize_t bitdepth) +FrameImpl::FrameImpl(std::byte* bytes, ssize_t rows, ssize_t cols, ssize_t bitdepth) { this->rows = rows; this->cols = cols; @@ -10,7 +10,7 @@ IFrame::IFrame(std::byte* bytes, ssize_t rows, ssize_t cols, ssize_t bitdepth) std::memcpy(data, bytes, bitdepth/8 * rows * cols); } -std::byte* IFrame::get(int row, int col) { +std::byte* FrameImpl::get(int row, int col) { if (row < 0 || row >= rows || col < 0 || col >= cols) { std::cerr << "Invalid row or column index" << std::endl; return 0; diff --git a/src/core/Frame.hpp b/src/core/Frame.hpp index aa5d400..cbd65b2 100644 --- a/src/core/Frame.hpp +++ b/src/core/Frame.hpp @@ -13,24 +13,29 @@ * model class * should be able to work with streams coming from files or network */ -class IFrame { - +class FrameImpl { + protected: std::byte* data{nullptr}; ssize_t rows{}; ssize_t cols{}; ssize_t bitdepth{}; public: - IFrame(std::byte* fp, ssize_t rows, ssize_t cols, ssize_t bitdepth); + FrameImpl(std::byte* fp, ssize_t rows, ssize_t cols, ssize_t bitdepth); std::byte* get(int row, int col); - ~IFrame(){ + ~FrameImpl(){ delete[] data; } }; -template class Frame: public IFrame { +template class Frame: public FrameImpl { public: - Frame(std::byte* fp, ssize_t rows, ssize_t cols):IFrame(fp, rows, cols, sizeof(DataType)){} + Frame(std::byte* fp, ssize_t rows, ssize_t cols):FrameImpl(fp, rows, cols, sizeof(DataType)){} DataType get(int row, int col){ - return *((DataType*) IFrame::get(row, col)); + return *((DataType*) FrameImpl::get(row, col)); } -}; \ No newline at end of file + +}; + +typedef Frame Frame16; +typedef Frame Frame8; +typedef Frame Frame32; \ No newline at end of file diff --git a/src/file_io/file/File.hpp b/src/file_io/file/File.hpp index ffdf7f3..cdae0d6 100644 --- a/src/file_io/file/File.hpp +++ b/src/file_io/file/File.hpp @@ -1,14 +1,11 @@ #pragma once +#include "Frame.hpp" +#include "SubFile.hpp" #include "defs.hpp" #include #include -#include "SubFile.hpp" #include -#include "Frame.hpp" - - - struct RawFileConfig { int module_gap_row{}; @@ -23,13 +20,16 @@ struct RawFileConfig { } }; - - class File { - private: - using config = RawFileConfig; + public: - std::vector subfiles; + virtual FrameImpl* get_frame(int frame_number) = 0; + + private: + using config = RawFileConfig; + + public: + std::vector subfiles; std::filesystem::path fname; std::filesystem::path base_path; std::string base_name, ext; @@ -49,13 +49,13 @@ class File { using data_type = uint16_t; std::vector positions; - config cfg{0,0}; + config cfg{0, 0}; // File(); ~File(); inline size_t bytes_per_frame() const { return rows * cols * bitdepth / 8; } inline size_t pixels() const { return rows * cols; } - inline void set_config(int row,int col){ + inline void set_config(int row, int col) { cfg.module_gap_row = row; cfg.module_gap_col = col; } @@ -63,21 +63,17 @@ class File { // TODO! Deal with fast quad and missing files void find_number_of_subfiles() { int n_mod = 0; - while (std::filesystem::exists(data_fname(++n_mod, 0))); + while (std::filesystem::exists(data_fname(++n_mod, 0))) + ; n_subfiles = n_mod; - } inline std::filesystem::path master_fname() { - return base_path / - fmt::format("{}_master_{}{}", base_name, findex, ext); + return base_path / fmt::format("{}_master_{}{}", base_name, findex, ext); } inline std::filesystem::path data_fname(int mod_id, int file_id) { - return base_path / fmt::format("{}_d{}_f{}_{}.raw", base_name, file_id, - mod_id, findex); + return base_path / fmt::format("{}_d{}_f{}_{}.raw", base_name, file_id, mod_id, findex); } - - virtual Frame get_frame(int frame_number)=0; // size_t total_frames(); }; diff --git a/src/file_io/file/FileHandler.hpp b/src/file_io/file/FileHandler.hpp index e69de29..a5cd74d 100644 --- a/src/file_io/file/FileHandler.hpp +++ b/src/file_io/file/FileHandler.hpp @@ -0,0 +1,29 @@ +#include +#include "FileFactory.hpp" +#include "File.hpp" +class FileHandler{ + private: + std::filesystem::path fpath; + FileFactory* fileFactory; + File* f; + + public: + FileHandler(std::filesystem::path fpath){ + this->fpath = fpath; + this->fileFactory= FileFactory::get_factory(fpath); + this->f= fileFactory->load_file(); + delete fileFactory; + } + + template + Frame* get_frame(int index){ + FrameImpl* frame =f->get_frame(index); + return static_cast*>(frame); + } + + + + ~FileHandler(){ + delete f; + } +}; \ No newline at end of file diff --git a/src/file_io/file/JsonFile.cpp b/src/file_io/file/JsonFile.cpp index c0ca62a..c6c424f 100644 --- a/src/file_io/file/JsonFile.cpp +++ b/src/file_io/file/JsonFile.cpp @@ -1,8 +1,7 @@ #include "JsonFile.hpp" #include -template -Frame JsonFile::get_frame(int frame_number){ +FrameImpl* JsonFile::get_frame(int frame_number){ int subfile_id=frame_number/max_frames_per_file; std::byte* buffer; size_t frame_size = subfiles[subfile_id]->bytes_per_frame(); @@ -12,7 +11,7 @@ Frame JsonFile::get_frame(int frame_number){ - auto f = Frame(buffer, rows, cols); + auto f = new FrameImpl(buffer, rows, cols, bitdepth); delete[] buffer; return f; diff --git a/src/file_io/file/JsonFile.hpp b/src/file_io/file/JsonFile.hpp index b8a94f4..40b8440 100644 --- a/src/file_io/file/JsonFile.hpp +++ b/src/file_io/file/JsonFile.hpp @@ -5,9 +5,7 @@ class JsonFile: public File { - template - Frame get_frame(int frame_number); - IFrame get_frame(int frame_number); + FrameImpl* get_frame(int frame_number); }; \ No newline at end of file diff --git a/src/file_io/file/SubFile.cpp b/src/file_io/file/SubFile.cpp index 60e305b..b957484 100644 --- a/src/file_io/file/SubFile.cpp +++ b/src/file_io/file/SubFile.cpp @@ -7,52 +7,42 @@ * * */ -template -SubFile::SubFile(std::filesystem::path fname, ssize_t rows, ssize_t cols) { + +SubFile::SubFile(std::filesystem::path fname, DetectorType detector, ssize_t rows, ssize_t cols, uint16_t bitdepth) { this->rows = rows; this->cols = cols; this->fname = fname; + this->bitdepth = bitdepth; fp = fopen(fname.c_str(), "rb"); if (fp == nullptr) { throw std::runtime_error("Could not open file " + fname.string()); } - std::cout<<"File opened"<; + } else if (detector == DetectorType::Jungfrau) { + read_impl = &SubFile::read_impl_normal; + } + else { + throw std::runtime_error("Detector type not implemented"); + } } - -template -size_t SubFile::get_frame(std::byte *buffer, int frame_number) { +size_t SubFile::get_frame(std::byte *buffer, int frame_number) { if (frame_number >= n_frames or frame_number < 0) { throw std::runtime_error("Frame number out of range"); } - fseek(fp, sizeof(Header)+(sizeof(Header) + bytes_per_frame()) *frame_number, SEEK_SET); - return read_impl(buffer); + fseek(fp, sizeof(sls_detector_header) + (sizeof(sls_detector_header) + bytes_per_frame()) * frame_number, SEEK_SET); + return (this->*read_impl)(buffer); } -/** - * NormalSubFile methods -*/ -template -NormalSubFile::NormalSubFile(std::filesystem::path fname, ssize_t rows, ssize_t cols) - : SubFile(fname, rows, cols){}; +size_t SubFile::read_impl_normal(std::byte *buffer) { return fread(buffer, this->bytes_per_frame(), 1, this->fp); } -template size_t NormalSubFile::read_impl(std::byte *buffer) { - return fread(buffer, this->bytes_per_frame(), 1, this->fp); -}; +template size_t SubFile::read_impl_reorder(std::byte *buffer) { - - -/** - * ReorderM03SubFile methods -*/ -template -ReorderM03SubFile::ReorderM03SubFile(std::filesystem::path fname, ssize_t rows, ssize_t cols) - : SubFile(fname, rows, cols){}; - -template -size_t ReorderM03SubFile::read_impl(std::byte *buffer) { std::vector tmp(this->pixels_per_frame()); size_t rc = fread(reinterpret_cast(&tmp[0]), this->bytes_per_frame(), 1, this->fp); @@ -79,13 +69,24 @@ size_t ReorderM03SubFile::read_impl(std::byte *buffer) { } return rc; }; +template size_t SubFile::read_impl_flip(std::byte *buffer) { -template class NormalSubFile; -template class NormalSubFile; -template class ReorderM03SubFile; + // read to temporary buffer + // TODO! benchmark direct reads + std::vector tmp(this->bytes_per_frame()); + size_t rc = fread(reinterpret_cast(&tmp[0]), this->bytes_per_frame(), 1, this->fp); -// template size_t ReorderM03SubFile::read_impl(std::byte *buffer); -// template size_t ReorderM03SubFile::read_impl(std::byte *buffer); + // copy to place + const size_t start = this->cols * (this->rows - 1) * sizeof(DataType); + const size_t row_size = this->cols * sizeof(DataType); + auto dst = buffer + start; + auto src = &tmp[0]; -// template size_t NormalSubFile::read_impl(std::byte *buffer); -// template size_t NormalSubFile::read_impl(std::byte *buffer); \ No newline at end of file + for (int i = 0; i != this->rows; ++i) { + memcpy(dst, src, row_size); + dst -= row_size; + src += row_size; + } + + return rc; +}; diff --git a/src/file_io/file/SubFile.hpp b/src/file_io/file/SubFile.hpp index 982e52c..08339d1 100644 --- a/src/file_io/file/SubFile.hpp +++ b/src/file_io/file/SubFile.hpp @@ -4,50 +4,29 @@ #include #include -class SubFileBase { +class SubFile { protected: FILE *fp = nullptr; + uint16_t bitdepth; public: - virtual inline size_t bytes_per_frame() =0; - virtual inline size_t pixels_per_frame() =0; - std::filesystem::path fname; + // pointer to a read_impl function. pointer will be set to the appropriate read_impl function in the constructor + size_t (SubFile::*read_impl)(std::byte *buffer) = nullptr; + size_t read_impl_normal(std::byte *buffer); + template size_t read_impl_flip(std::byte *buffer); + template size_t read_impl_reorder(std::byte *buffer); + + SubFile(std::filesystem::path fname,DetectorType detector, ssize_t rows, ssize_t cols, uint16_t bitdepth); + + size_t get_frame(std::byte *buffer, int frame_number); + + // TODO: define the inlines as variables and assign them in constructor + inline size_t bytes_per_frame() { return (bitdepth / 8) * rows * cols; } + inline size_t pixels_per_frame() { return rows * cols; } + std::filesystem::path fname; ssize_t rows{}; ssize_t cols{}; ssize_t n_frames{}; int sub_file_index_{}; - virtual size_t read_impl(std::byte *buffer)=0; - virtual size_t get_frame(std::byte *buffer, int frame_number)=0; - }; - -template class SubFile : public SubFileBase{ - public: - SubFile(std::filesystem::path fname, ssize_t rows, ssize_t cols); - inline size_t bytes_per_frame() override { return sizeof(DataType) * rows * cols; } - inline size_t pixels_per_frame() override { return rows * cols; } - virtual size_t read_impl(std::byte *buffer)=0; - size_t get_frame(std::byte *buffer, int frame_number); - - -}; - -template class NormalSubFile : public SubFile { - public: - NormalSubFile(std::filesystem::path fname, ssize_t rows, ssize_t cols); - size_t read_impl(std::byte *buffer); -}; - -template class ReorderM03SubFile : public SubFile { - public: - ReorderM03SubFile(std::filesystem::path fname, ssize_t rows, ssize_t cols); - size_t read_impl(std::byte *buffer); -}; - -using JungfrauSubFile = NormalSubFile; -using Moench03SubFile = ReorderM03SubFile; -using Mythen3SubFile = NormalSubFile; - -// using SubFileVariants = std::variant; - diff --git a/src/file_io/file_factory/FileFactory.cpp b/src/file_io/file_factory/FileFactory.cpp index aba344d..750b75b 100644 --- a/src/file_io/file_factory/FileFactory.cpp +++ b/src/file_io/file_factory/FileFactory.cpp @@ -6,7 +6,7 @@ - FileFactory* FileFactory::getFactory(std::filesystem::path fpath){ + FileFactory* FileFactory::get_factory(std::filesystem::path fpath, uint16_t bitdepth){ // check if file exists if(!std::filesystem::exists(fpath)){ throw std::runtime_error("File does not exist"); @@ -18,7 +18,7 @@ } else if(fpath.extension() == ".json"){ std::cout<<"Loading json file"<fpath = fpath; + this->bitdepth = bitdepth; } -void JsonFileFactory::parse_metadata(File* file) { +void JsonFileFactory::parse_metadata(File *file) { std::cout << "Parsing metadata" << std::endl; std::ifstream ifs(file->master_fname()); json j; @@ -35,6 +36,9 @@ void JsonFileFactory::parse_metadata(File* file) { std::cerr << "master file does not have Dynamic Range. Defaulting to 16 bit" << '\n'; file->bitdepth = 16; } + // if (file->bitdepth != this->bitdepth) + // throw std::runtime_error("Bitdepth mismatch: file bitdepth (" + std::to_string(file->bitdepth) + + // ") != specified bitdepth (" + std::to_string(this->bitdepth) + ")"); // only Eiger had quad if (file->type == DetectorType::Eiger) { @@ -42,22 +46,17 @@ void JsonFileFactory::parse_metadata(File* file) { } } -void JsonFileFactory::open_subfiles(File* file) { +void JsonFileFactory::open_subfiles(File *file) { for (int i = 0; i != file->n_subfiles; ++i) { - if (file->type == DetectorType::Jungfrau) { - file->subfiles.push_back(new JungfrauSubFile(file->data_fname(i, 0), file->subfile_rows, file->subfile_cols)); - } else if (file->type == DetectorType::Mythen3) - file->subfiles.push_back(new Mythen3SubFile(file->data_fname(i, 0), file->subfile_rows, file->subfile_cols)); - else if (file->type == DetectorType::Moench) - file->subfiles.push_back(new Moench03SubFile(file->data_fname(i, 0), file->subfile_rows, file->subfile_cols)); - else - throw std::runtime_error("File not supported"); + + file->subfiles.push_back( + new SubFile(file->data_fname(i, 0), file->type, file->subfile_rows, file->subfile_cols, file->bitdepth)); } } -File* JsonFileFactory::loadFile() { +File *JsonFileFactory::load_file() { std::cout << "Loading json file" << std::endl; - JsonFile* file = new JsonFile(); + JsonFile *file = new JsonFile(); file->fname = fpath; this->parse_fname(file); this->parse_metadata(file); diff --git a/src/file_io/file_factory/JsonFileFactory.hpp b/src/file_io/file_factory/JsonFileFactory.hpp index fc62bdb..c9bd947 100644 --- a/src/file_io/file_factory/JsonFileFactory.hpp +++ b/src/file_io/file_factory/JsonFileFactory.hpp @@ -5,9 +5,9 @@ class JsonFileFactory: public FileFactory private: /* data */ public: - File* loadFile() override; + File* load_file() override; void parse_metadata(File*) override; - JsonFileFactory(std::filesystem::path fpath); + JsonFileFactory(std::filesystem::path fpath, uint16_t bitdepth); void open_subfiles(File*); diff --git a/src/main.cpp b/src/main.cpp index d1f05b7..d6b4f90 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,37 +1,22 @@ // Your First C++ Program #include -#include "file_io/file_factory/FileFactory.hpp" - -void test(File* f,int frame_number){ +#include +void test(FileHandler* f,int frame_number){ std::cout << "frame number: " << frame_number << std::endl; - auto frame = f->get_frame(frame_number); - std::cout << frame.get(0,0) << ' '; - std::cout << frame.get(0,1) << ' '; - std::cout << frame.get(1,0) << ' '; - std::cout << frame.get(511,1023) << std::endl; - + Frame16* frame = f->get_frame(frame_number); + std::cout << frame->get(0,0) << ' '; + std::cout << frame->get(0,1) << ' '; + std::cout << frame->get(1,0) << ' '; + std::cout << frame->get(511,1023) << std::endl; + delete frame; } int main() { - FileFactory* fileFactory=FileFactory::getFactory(std::filesystem::path("/home/l_bechir/github/aare")/"data"/"jungfrau_single_master_0.json"); - File* f = fileFactory->loadFile(); + std::filesystem::path fpath("/home/l_bechir/github/aare/data/jungfrau_single_master_0.json"); + FileHandler* fileHandler = new FileHandler(fpath); + test(fileHandler,0); - test(f,0); - test(f,1); - test(f,2); - test(f,3); - test(f,4); - test(f,5); - test(f,6); - test(f,7); - test(f,8); - test(f,9); + delete fileHandler; - - - - - delete fileFactory; - delete f; }