diff --git a/CMakeLists.txt b/CMakeLists.txt index 3f50fc6c..5d271919 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -232,10 +232,12 @@ endif() set(PUBLICHEADERS include/aare/ClusterFinder.hpp + include/aare/CtbRawFile.hpp include/aare/defs.hpp include/aare/Dtype.hpp include/aare/File.hpp include/aare/FileInterface.hpp + include/aare/file_utils.hpp include/aare/Frame.hpp include/aare/json.hpp include/aare/NDArray.hpp @@ -253,9 +255,11 @@ set(PUBLICHEADERS set(SourceFiles ${CMAKE_CURRENT_SOURCE_DIR}/src/defs.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/CtbRawFile.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Dtype.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Frame.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/File.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/file_utils.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/NumpyFile.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/PixelMap.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/RawFile.cpp @@ -286,6 +290,7 @@ if(AARE_TESTS) ${CMAKE_CURRENT_SOURCE_DIR}/src/defs.test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Dtype.test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Frame.test.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/file_utils.test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/NDArray.test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/NDView.test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/ClusterFinder.test.cpp diff --git a/include/aare/CtbRawFile.hpp b/include/aare/CtbRawFile.hpp new file mode 100644 index 00000000..8dbd1aad --- /dev/null +++ b/include/aare/CtbRawFile.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include "aare/FileInterface.hpp" +#include "aare/file_utils.hpp" +#include "aare/Frame.hpp" + +#include + +namespace aare{ + +class CtbRawFile{ + FileNameComponents m_fnc{}; +public: + CtbRawFile(const std::filesystem::path &fname); + + + +}; + +} \ No newline at end of file diff --git a/include/aare/file_utils.hpp b/include/aare/file_utils.hpp new file mode 100644 index 00000000..abccfb6b --- /dev/null +++ b/include/aare/file_utils.hpp @@ -0,0 +1,119 @@ +#pragma once +#include "aare/defs.hpp" +#include +#include +#include + +#include +using json = nlohmann::json; + +namespace aare { +bool is_master_file(const std::filesystem::path &fpath); + + +struct FileNameComponents { + std::filesystem::path base_path{}; + std::string base_name{}; + std::string ext{}; + int findex{}; + bool valid{false}; // TODO! how do we do error handling? + + std::filesystem::path master_fname() const { + return base_path / + fmt::format("{}_master_{}{}", base_name, findex, ext); + } + + std::filesystem::path data_fname(size_t mod_id, size_t file_id) { + return base_path / fmt::format("{}_d{}_f{}_{}.raw", base_name, file_id, + mod_id, findex); + } +}; + +FileNameComponents parse_fname(const std::filesystem::path &fname); + +class MasterFile { + FileNameComponents m_fnc; + std::string m_version; + DetectorType m_type; + TimingMode m_timing_mode; + size_t m_total_frames; + size_t m_subfile_rows; + size_t m_subfile_cols; + size_t m_bitdepth; + size_t m_analog_samples; + size_t m_digital_samples; + size_t m_max_frames_per_file; + uint32_t m_adc_mask; +public: + MasterFile(const std::filesystem::path &fpath) { + m_fnc = parse_fname(fpath); + + + + std::ifstream ifs(fpath); + json j; + ifs >> j; + double v = j["Version"]; + m_version = fmt::format("{:.1f}", v); + + m_type = StringTo(j["Detector// Type"].get()); + m_timing_mode = + StringTo(j["Timing Mode"].get()); + m_total_frames = j["Frames in File"]; + m_subfile_rows = j["Pixels"]["y"]; + m_subfile_cols = j["Pixels"]["x"]; + m_max_frames_per_file = j["Max Frames Per File"]; + try { + m_bitdepth = j.at("Dynamic Range"); + } catch (const json::out_of_range &e) { + m_bitdepth = 16; + } + + try { + m_analog_samples = j.at("Analog Samples"); + }catch (const json::out_of_range &e) { + m_analog_samples = 0; + } + try{ + std::string adc_mask = j.at("ADC Mask"); + m_adc_mask = std::stoul(adc_mask, nullptr, 16); + }catch (const json::out_of_range &e) { + m_adc_mask = 0; + } + + try { + m_digital_samples = j.at("Digital Samples"); + }catch (const json::out_of_range &e) { + m_digital_samples = 0; + } + + //Update detector type for Moench + //TODO! How does this work with old .raw master files? + if (m_type == DetectorType::Moench && m_analog_samples == 0 && + m_subfile_rows == 400) { + m_type = DetectorType::Moench03; + }else if (m_type == DetectorType::Moench && m_subfile_rows == 400 && + m_analog_samples == 5000) { + m_type = DetectorType::Moench03_old; + } + + // //Here we know we have a ChipTestBoard file update the geometry? + // //TODO! Carry on information about digtial, and transceivers + // if (m_type == DetectorType::ChipTestBoard) { + // subfile_rows = 1; + // subfile_cols = m_analog_samples*__builtin_popcount(m_adc_mask); + // } + + // // only Eiger had quad + // if (m_type == DetectorType::Eiger) { + // quad = (j["Quad"] == 1); + // } + + // m_geometry = {j["Geometry"]["y"], j["Geometry"]["x"]}; + } + +}; + + + +} // namespace aare \ No newline at end of file diff --git a/python/src/file.hpp b/python/src/file.hpp index 65f841db..88bf7476 100644 --- a/python/src/file.hpp +++ b/python/src/file.hpp @@ -1,5 +1,6 @@ #include "aare/Frame.hpp" #include "aare/File.hpp" +#include "aare/CtbRawFile.hpp" #include "aare/defs.hpp" // #include "aare/fClusterFileV2.hpp" @@ -16,6 +17,11 @@ namespace py = pybind11; using namespace::aare; void define_file_io_bindings(py::module &m) { + + py::class_(m, "CtbRawFile") + .def(py::init()); + + py::class_(m, "File") .def(py::init([](const std::filesystem::path &fname) { return File(fname, "r", {}); })) .def( diff --git a/src/CtbRawFile.cpp b/src/CtbRawFile.cpp new file mode 100644 index 00000000..b70b44fd --- /dev/null +++ b/src/CtbRawFile.cpp @@ -0,0 +1,22 @@ +#include "aare/CtbRawFile.hpp" + + + +namespace aare{ + +CtbRawFile::CtbRawFile(const std::filesystem::path &fname){ + + if(!std::filesystem::exists(fname)){ + throw std::runtime_error(LOCATION + "File does not exist"); + } + + m_fnc = parse_fname(fname); + if(!m_fnc.valid){ + throw std::runtime_error(LOCATION + "Could not parse master file name"); + } + + +} + + +} // namespace aare \ No newline at end of file diff --git a/src/RawFile.cpp b/src/RawFile.cpp index eab6e729..ef623ce2 100644 --- a/src/RawFile.cpp +++ b/src/RawFile.cpp @@ -71,11 +71,11 @@ void RawFile::find_number_of_subfiles() { ; n_subfiles = n_mod; } -inline std::filesystem::path RawFile::data_fname(size_t mod_id, size_t file_id) { +std::filesystem::path RawFile::data_fname(size_t mod_id, size_t file_id) { return this->m_base_path / fmt::format("{}_d{}_f{}_{}.raw", this->m_base_name, file_id, mod_id, this->m_findex); } -inline std::filesystem::path RawFile::master_fname() { +std::filesystem::path RawFile::master_fname() { return this->m_base_path / fmt::format("{}_master_{}{}", this->m_base_name, this->m_findex, this->m_ext); } diff --git a/src/file_utils.cpp b/src/file_utils.cpp new file mode 100644 index 00000000..01f0e441 --- /dev/null +++ b/src/file_utils.cpp @@ -0,0 +1,33 @@ +#include "aare/file_utils.hpp" + +namespace aare { + + + +bool is_master_file(const std::filesystem::path &fpath) { + std::string const stem = fpath.stem().string(); + return stem.find("_master_") != std::string::npos; +} + +FileNameComponents parse_fname(const std::filesystem::path &fname) { + FileNameComponents fnc; + fnc.base_path = fname.parent_path(); + fnc.base_name = fname.stem(); + fnc.ext = fname.extension(); + try { + auto pos = fnc.base_name.rfind('_'); + fnc.findex = std::stoi(fnc.base_name.substr(pos + 1)); + } catch (const std::invalid_argument &e) { + fnc.valid = false; + } + auto pos = fnc.base_name.find("_master_"); + if (pos != std::string::npos) { + fnc.base_name.erase(pos); + }else{ + fnc.valid = false; + } + fnc.valid = true; + return fnc; +} + +} // namespace aare \ No newline at end of file diff --git a/src/file_utils.test.cpp b/src/file_utils.test.cpp new file mode 100644 index 00000000..e46ac3d8 --- /dev/null +++ b/src/file_utils.test.cpp @@ -0,0 +1,20 @@ +#include "aare/file_utils.hpp" + +#include + +using namespace aare; + +TEST_CASE("Use filename to determine if it is a master file") { + + REQUIRE(is_master_file("test_master_1.json")); +} + +TEST_CASE("Parse a master file fname"){ + auto fnc = parse_fname("test_master_1.json"); + REQUIRE(fnc.base_name == "test"); + REQUIRE(fnc.ext == ".json"); + REQUIRE(fnc.findex == 1); + + REQUIRE(fnc.master_fname() == "test_master_1.json"); + REQUIRE(fnc.data_fname(1, 2) == "test_d2_f1_1.raw"); +} \ No newline at end of file