mirror of
https://github.com/slsdetectorgroup/aare.git
synced 2025-06-05 12:30:39 +02:00
templates are all you need
This commit is contained in:
parent
f62cc229f9
commit
49ebaf5c81
@ -1,5 +1,21 @@
|
||||
#include "defs.hpp"
|
||||
|
||||
template <> std::string toString(DetectorType type) {
|
||||
switch (type) {
|
||||
case DetectorType::Jungfrau:
|
||||
return "Jungfrau";
|
||||
case DetectorType::Eiger:
|
||||
return "Eiger";
|
||||
case DetectorType::Mythen3:
|
||||
return "Mythen3";
|
||||
case DetectorType::Moench:
|
||||
return "Moench";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <> DetectorType StringTo(std::string name) {
|
||||
if (name == "Jungfrau")
|
||||
return DetectorType::Jungfrau;
|
||||
|
@ -42,7 +42,14 @@ T StringTo(std::string sv){
|
||||
return T(sv);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
std::string toString(T sv){
|
||||
return T(sv);
|
||||
}
|
||||
|
||||
template <> DetectorType StringTo(std::string);
|
||||
template <> std::string toString(DetectorType type);
|
||||
|
||||
|
||||
template <> TimingMode StringTo(std::string);
|
||||
|
||||
|
@ -1,22 +1,23 @@
|
||||
#include "Frame.hpp"
|
||||
#include <iostream>
|
||||
|
||||
template <typename DataType>
|
||||
Frame<DataType>::Frame(std::byte* bytes, ssize_t rows, ssize_t cols):
|
||||
rows(rows), cols(cols) {
|
||||
data = new DataType[rows*cols];
|
||||
std::memcpy(data, bytes, rows*cols*sizeof(DataType));
|
||||
}
|
||||
|
||||
FrameImpl::FrameImpl(std::byte* bytes, ssize_t rows, ssize_t cols, ssize_t bitdepth)
|
||||
{
|
||||
this->rows = rows;
|
||||
this->cols = cols;
|
||||
data = new std::byte[rows * cols*bitdepth/8];
|
||||
std::memcpy(data, bytes, bitdepth/8 * rows * cols);
|
||||
}
|
||||
|
||||
std::byte* FrameImpl::get(int row, int col) {
|
||||
|
||||
template <typename DataType>
|
||||
DataType Frame<DataType>::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;
|
||||
}
|
||||
return data+(row * cols + col)*bitdepth/8;
|
||||
|
||||
|
||||
return data[row*cols + col];
|
||||
}
|
||||
|
||||
|
||||
template class Frame<uint16_t>;
|
||||
|
@ -13,25 +13,21 @@
|
||||
* model class
|
||||
* should be able to work with streams coming from files or network
|
||||
*/
|
||||
class FrameImpl {
|
||||
protected:
|
||||
std::byte* data{nullptr};
|
||||
ssize_t rows{};
|
||||
ssize_t cols{};
|
||||
ssize_t bitdepth{};
|
||||
public:
|
||||
FrameImpl(std::byte* fp, ssize_t rows, ssize_t cols, ssize_t bitdepth);
|
||||
std::byte* get(int row, int col);
|
||||
~FrameImpl(){
|
||||
delete[] data;
|
||||
}
|
||||
};
|
||||
|
||||
template <class DataType> class Frame: public FrameImpl {
|
||||
|
||||
template <class DataType> class Frame{
|
||||
|
||||
public:
|
||||
Frame(std::byte* fp, ssize_t rows, ssize_t cols):FrameImpl(fp, rows, cols, sizeof(DataType)){}
|
||||
DataType get(int row, int col){
|
||||
return *((DataType*) FrameImpl::get(row, col));
|
||||
ssize_t rows;
|
||||
ssize_t cols;
|
||||
DataType* data;
|
||||
ssize_t bitdepth = sizeof(DataType)*8;
|
||||
|
||||
Frame(std::byte* fp, ssize_t rows, ssize_t cols);
|
||||
DataType get(int row, int col);
|
||||
|
||||
~Frame(){
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -1,7 +1,9 @@
|
||||
#include "File.hpp"
|
||||
|
||||
File::~File() {
|
||||
template <DetectorType detector, typename DataType>
|
||||
File<detector,DataType>::~File<detector,DataType>() {
|
||||
for (auto& subfile : subfiles) {
|
||||
delete subfile;
|
||||
}
|
||||
}
|
||||
|
||||
template class File<DetectorType::Jungfrau, uint16_t>;
|
||||
|
@ -19,11 +19,11 @@ struct RawFileConfig {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <DetectorType detector, typename DataType>
|
||||
class File {
|
||||
|
||||
public:
|
||||
virtual FrameImpl* get_frame(int frame_number) = 0;
|
||||
virtual Frame<DataType>* get_frame(int frame_number) = 0;
|
||||
|
||||
private:
|
||||
using config = RawFileConfig;
|
||||
|
@ -1,24 +1,23 @@
|
||||
#include <filesystem>
|
||||
#include "FileFactory.hpp"
|
||||
#include "File.hpp"
|
||||
template <DetectorType detector,typename DataType>
|
||||
class FileHandler{
|
||||
private:
|
||||
std::filesystem::path fpath;
|
||||
FileFactory* fileFactory;
|
||||
File* f;
|
||||
FileFactory<detector,DataType>* fileFactory;
|
||||
File<detector,DataType>* f;
|
||||
|
||||
public:
|
||||
FileHandler(std::filesystem::path fpath){
|
||||
FileHandler<detector,DataType>(std::filesystem::path fpath){
|
||||
this->fpath = fpath;
|
||||
this->fileFactory= FileFactory::get_factory(fpath);
|
||||
this->fileFactory= FileFactory<detector,DataType>::get_factory(fpath);
|
||||
this->f= fileFactory->load_file();
|
||||
delete fileFactory;
|
||||
}
|
||||
|
||||
template <typename DataType>
|
||||
Frame<DataType>* get_frame(int index){
|
||||
FrameImpl* frame =f->get_frame(index);
|
||||
return static_cast<Frame<DataType>*>(frame);
|
||||
return f->get_frame(index);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,17 +1,18 @@
|
||||
#include "JsonFile.hpp"
|
||||
#include <typeinfo>
|
||||
|
||||
FrameImpl* JsonFile::get_frame(int frame_number){
|
||||
int subfile_id=frame_number/max_frames_per_file;
|
||||
template <DetectorType detector,typename DataType>
|
||||
Frame<DataType>* JsonFile<detector,DataType>::get_frame(int frame_number){
|
||||
int subfile_id=frame_number/this->max_frames_per_file;
|
||||
std::byte* buffer;
|
||||
size_t frame_size = subfiles[subfile_id]->bytes_per_frame();
|
||||
size_t frame_size = this->subfiles[subfile_id]->bytes_per_frame();
|
||||
buffer = new std::byte[frame_size];
|
||||
|
||||
subfiles[subfile_id]->get_frame(buffer, frame_number%max_frames_per_file);
|
||||
this->subfiles[subfile_id]->get_frame(buffer, frame_number%this->max_frames_per_file);
|
||||
|
||||
|
||||
|
||||
auto f = new FrameImpl(buffer, rows, cols, bitdepth);
|
||||
auto f = new Frame<DataType>(buffer, this->rows, this->cols);
|
||||
|
||||
delete[] buffer;
|
||||
return f;
|
||||
@ -20,4 +21,7 @@ FrameImpl* JsonFile::get_frame(int frame_number){
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
template class JsonFile<DetectorType::Jungfrau, uint16_t>;
|
||||
|
||||
|
@ -1,11 +1,9 @@
|
||||
#pragma once
|
||||
#include "File.hpp"
|
||||
#include "Frame.hpp"
|
||||
#include "defs.hpp"
|
||||
#include "File.hpp"
|
||||
template <DetectorType detector, typename DataType>
|
||||
class JsonFile : public File<detector, DataType> {
|
||||
|
||||
class JsonFile: public File
|
||||
{
|
||||
|
||||
FrameImpl* get_frame(int frame_number);
|
||||
|
||||
Frame<DataType> *get_frame(int frame_number);
|
||||
};
|
@ -1,35 +1,34 @@
|
||||
#include "FileFactory.hpp"
|
||||
#include "File.hpp"
|
||||
#include "RawFileFactory.hpp"
|
||||
#include "JsonFileFactory.hpp"
|
||||
#include "RawFileFactory.hpp"
|
||||
#include <iostream>
|
||||
|
||||
|
||||
|
||||
FileFactory* FileFactory::get_factory(std::filesystem::path fpath, uint16_t bitdepth){
|
||||
template <DetectorType detector, typename DataType>
|
||||
FileFactory<detector, DataType> *FileFactory<detector, DataType>::get_factory(std::filesystem::path fpath) {
|
||||
// check if file exists
|
||||
if(!std::filesystem::exists(fpath)){
|
||||
if (!std::filesystem::exists(fpath)) {
|
||||
throw std::runtime_error("File does not exist");
|
||||
}
|
||||
|
||||
if(fpath.extension() == ".raw"){
|
||||
std::cout<<"Loading raw file"<<std::endl;
|
||||
if (fpath.extension() == ".raw") {
|
||||
std::cout << "Loading raw file" << std::endl;
|
||||
throw std::runtime_error("Raw file not implemented");
|
||||
} else if (fpath.extension() == ".json") {
|
||||
std::cout << "Loading json file" << std::endl;
|
||||
return new JsonFileFactory<detector, DataType>(fpath);
|
||||
}
|
||||
else if(fpath.extension() == ".json"){
|
||||
std::cout<<"Loading json file"<<std::endl;
|
||||
return new JsonFileFactory(fpath, bitdepth);
|
||||
}
|
||||
//check if extension is numpy
|
||||
else if(fpath.extension() == ".npy"){
|
||||
std::cout<<"Loading numpy file"<<std::endl;
|
||||
// check if extension is numpy
|
||||
else if (fpath.extension() == ".npy") {
|
||||
std::cout << "Loading numpy file" << std::endl;
|
||||
throw std::runtime_error("Numpy file not implemented");
|
||||
}
|
||||
|
||||
throw std::runtime_error("Unsupported file type");
|
||||
|
||||
throw std::runtime_error("Unsupported file type");
|
||||
}
|
||||
|
||||
void FileFactory::parse_fname(File* file) {
|
||||
template <DetectorType detector, typename DataType>
|
||||
void FileFactory<detector, DataType>::parse_fname(File<detector, DataType> *file) {
|
||||
file->base_path = fpath.parent_path();
|
||||
file->base_name = fpath.stem();
|
||||
file->ext = fpath.extension();
|
||||
@ -40,23 +39,22 @@ void FileFactory::parse_fname(File* file) {
|
||||
file->base_name.erase(pos);
|
||||
}
|
||||
|
||||
template <typename Header=sls_detector_header>
|
||||
Header FileFactory::read_header(const std::filesystem::path &fname) {
|
||||
Header h{};
|
||||
template <DetectorType detector, typename DataType>
|
||||
sls_detector_header FileFactory<detector, DataType>::read_header(const std::filesystem::path &fname) {
|
||||
sls_detector_header h{};
|
||||
FILE *fp = fopen(fname.c_str(), "r");
|
||||
if (!fp)
|
||||
throw std::runtime_error(
|
||||
fmt::format("Could not open: {} for reading", fname.c_str()));
|
||||
throw std::runtime_error(fmt::format("Could not open: {} for reading", fname.c_str()));
|
||||
|
||||
size_t rc = fread(reinterpret_cast<char *>(&h), sizeof(h), 1, fp);
|
||||
fclose(fp);
|
||||
if (rc != 1)
|
||||
throw std::runtime_error("Could not read header from file");
|
||||
return h;
|
||||
|
||||
}
|
||||
|
||||
void FileFactory::find_geometry(File* file) {
|
||||
template <DetectorType detector, typename DataType>
|
||||
void FileFactory<detector, DataType>::find_geometry(File<detector, DataType> *file) {
|
||||
uint16_t r{};
|
||||
uint16_t c{};
|
||||
for (int i = 0; i != file->n_subfiles; ++i) {
|
||||
@ -73,4 +71,6 @@ void FileFactory::find_geometry(File* file) {
|
||||
file->cols = c * file->subfile_cols;
|
||||
|
||||
file->rows += (r - 1) * file->cfg.module_gap_row;
|
||||
}
|
||||
}
|
||||
|
||||
template class FileFactory<DetectorType::Jungfrau, uint16_t>;
|
||||
|
@ -1,25 +1,25 @@
|
||||
#pragma once
|
||||
#include <filesystem>
|
||||
#include "File.hpp"
|
||||
|
||||
template <DetectorType detector,typename DataType>
|
||||
class FileFactory{
|
||||
// Class that will be used to create File objects
|
||||
// follows the factory pattern
|
||||
protected:
|
||||
std::filesystem::path fpath;
|
||||
uint16_t bitdepth;
|
||||
public:
|
||||
static FileFactory* get_factory(std::filesystem::path,uint16_t bitdepth=16);
|
||||
static FileFactory<detector,DataType>* get_factory(std::filesystem::path);
|
||||
// virtual int deleteFile() = 0;
|
||||
virtual File* load_file()=0;//TODO: add option to load all file to memory or keep it on disk
|
||||
virtual void parse_metadata(File*)=0;
|
||||
virtual File<detector,DataType>* load_file()=0;//TODO: add option to load all file to memory or keep it on disk
|
||||
virtual void parse_metadata(File<detector,DataType>*)=0;
|
||||
|
||||
|
||||
void find_geometry(File*);
|
||||
void parse_fname(File*);
|
||||
void find_geometry(File<detector,DataType>*);
|
||||
void parse_fname(File<detector,DataType>*);
|
||||
|
||||
template <typename Header> Header read_header(const std::filesystem::path &fname);
|
||||
sls_detector_header read_header(const std::filesystem::path &fname);
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
@ -9,14 +9,15 @@
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
JsonFileFactory::JsonFileFactory(std::filesystem::path fpath, uint16_t bitdepth=16) {
|
||||
template <DetectorType detector,typename DataType>
|
||||
JsonFileFactory<detector,DataType>::JsonFileFactory(std::filesystem::path fpath) {
|
||||
if (not is_master_file(fpath))
|
||||
throw std::runtime_error("Json file is not a master file");
|
||||
this->fpath = fpath;
|
||||
this->bitdepth = bitdepth;
|
||||
}
|
||||
|
||||
void JsonFileFactory::parse_metadata(File *file) {
|
||||
template <DetectorType detector,typename DataType>
|
||||
void JsonFileFactory<detector,DataType>::parse_metadata(File<detector,DataType> *file) {
|
||||
std::cout << "Parsing metadata" << std::endl;
|
||||
std::ifstream ifs(file->master_fname());
|
||||
json j;
|
||||
@ -25,6 +26,9 @@ void JsonFileFactory::parse_metadata(File *file) {
|
||||
std::cout << "Version: " << v << std::endl;
|
||||
file->version = fmt::format("{:.1f}", v);
|
||||
file->type = StringTo<DetectorType>(j["Detector Type"].get<std::string>());
|
||||
if (file->type != detector)
|
||||
throw std::runtime_error("Detector type mismatch: file type (" + toString<DetectorType>(file->type) +
|
||||
") != specified type (" + toString<DetectorType>(detector) + ")");
|
||||
file->timing_mode = StringTo<TimingMode>(j["Timing Mode"].get<std::string>());
|
||||
file->total_frames = j["Frames in File"];
|
||||
file->subfile_cols = j["Pixels"]["x"];
|
||||
@ -36,9 +40,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) + ")");
|
||||
if (file->bitdepth != sizeof(DataType) * 8)
|
||||
throw std::runtime_error("Bitdepth mismatch: file bitdepth (" + std::to_string(file->bitdepth) +
|
||||
") != specified bitdepth (" + std::to_string(sizeof(DataType) * 8) + ")");
|
||||
|
||||
// only Eiger had quad
|
||||
if (file->type == DetectorType::Eiger) {
|
||||
@ -46,7 +50,8 @@ void JsonFileFactory::parse_metadata(File *file) {
|
||||
}
|
||||
}
|
||||
|
||||
void JsonFileFactory::open_subfiles(File *file) {
|
||||
template <DetectorType detector,typename DataType>
|
||||
void JsonFileFactory<detector,DataType>::open_subfiles(File<detector,DataType> *file) {
|
||||
for (int i = 0; i != file->n_subfiles; ++i) {
|
||||
|
||||
file->subfiles.push_back(
|
||||
@ -54,10 +59,11 @@ void JsonFileFactory::open_subfiles(File *file) {
|
||||
}
|
||||
}
|
||||
|
||||
File *JsonFileFactory::load_file() {
|
||||
template <DetectorType detector,typename DataType>
|
||||
File<detector,DataType> *JsonFileFactory<detector,DataType>::load_file() {
|
||||
std::cout << "Loading json file" << std::endl;
|
||||
JsonFile *file = new JsonFile();
|
||||
file->fname = fpath;
|
||||
JsonFile<detector,DataType> *file = new JsonFile<detector,DataType>();
|
||||
file->fname = this->fpath;
|
||||
this->parse_fname(file);
|
||||
this->parse_metadata(file);
|
||||
file->find_number_of_subfiles();
|
||||
@ -65,4 +71,6 @@ File *JsonFileFactory::load_file() {
|
||||
this->open_subfiles(file);
|
||||
|
||||
return file;
|
||||
}
|
||||
}
|
||||
|
||||
template class JsonFileFactory<DetectorType::Jungfrau, uint16_t>;
|
@ -1,14 +1,14 @@
|
||||
#include "FileFactory.hpp"
|
||||
|
||||
class JsonFileFactory: public FileFactory
|
||||
template <DetectorType detector,typename DataType>
|
||||
class JsonFileFactory: public FileFactory<detector,DataType>
|
||||
{
|
||||
private:
|
||||
/* data */
|
||||
public:
|
||||
File* load_file() override;
|
||||
void parse_metadata(File*) override;
|
||||
JsonFileFactory(std::filesystem::path fpath, uint16_t bitdepth);
|
||||
void open_subfiles(File*);
|
||||
File<detector,DataType>* load_file() override;
|
||||
void parse_metadata(File<detector,DataType>*) override;
|
||||
JsonFileFactory<detector,DataType>(std::filesystem::path fpath);
|
||||
void open_subfiles(File<detector,DataType>*);
|
||||
|
||||
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
#include "File.hpp"
|
||||
#include <filesystem>
|
||||
|
||||
template<DetectorType detector,typename DataType>
|
||||
class RawFileFactory{
|
||||
public:
|
||||
// RawFileFactory();
|
||||
// ~RawFileFactory();
|
||||
File loadFile(std::filesystem::path fpath);
|
||||
File<detector,DataType> loadFile(std::filesystem::path fpath);
|
||||
};
|
13
src/main.cpp
13
src/main.cpp
@ -1,9 +1,15 @@
|
||||
// Your First C++ Program
|
||||
#include <iostream>
|
||||
#include <FileHandler.hpp>
|
||||
void test(FileHandler* f,int frame_number){
|
||||
|
||||
using JFileHandler = FileHandler<DetectorType::Jungfrau,uint16_t>;
|
||||
using JFile = File<DetectorType::Jungfrau,uint16_t>;
|
||||
using JFrame = Frame<uint16_t>;
|
||||
|
||||
|
||||
void test(JFileHandler* f,int frame_number){
|
||||
std::cout << "frame number: " << frame_number << std::endl;
|
||||
Frame16* frame = f->get_frame<uint16_t>(frame_number);
|
||||
JFrame* frame = f->get_frame(frame_number);
|
||||
std::cout << frame->get(0,0) << ' ';
|
||||
std::cout << frame->get(0,1) << ' ';
|
||||
std::cout << frame->get(1,0) << ' ';
|
||||
@ -14,8 +20,7 @@ void test(FileHandler* f,int frame_number){
|
||||
|
||||
int main() {
|
||||
std::filesystem::path fpath("/home/l_bechir/github/aare/data/jungfrau_single_master_0.json");
|
||||
FileHandler* fileHandler = new FileHandler(fpath);
|
||||
test(fileHandler,0);
|
||||
auto fileHandler = new JFileHandler (fpath);
|
||||
|
||||
delete fileHandler;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user