added simple decoding of scan parameters

This commit is contained in:
Erik Fröjdh 2024-11-07 08:14:33 +01:00
parent b2e5c71f9c
commit 9c220bff51
13 changed files with 153 additions and 88 deletions

View File

@ -244,7 +244,6 @@ set(PUBLICHEADERS
include/aare/FileInterface.hpp
include/aare/RawMasterFile.hpp
include/aare/Frame.hpp
include/aare/json.hpp
include/aare/NDArray.hpp
include/aare/NDView.hpp
include/aare/NumpyFile.hpp

View File

@ -23,7 +23,7 @@ class RawFileNameComponents {
RawFileNameComponents(const std::filesystem::path &fname);
/// @brief Get the filename including path of the master file.
/// (i.e. what was passed in to the constructor))
/// (i.e. what was passed in to the constructor))
std::filesystem::path master_fname() const;
/// @brief Get the filename including path of the data file.
@ -31,16 +31,36 @@ class RawFileNameComponents {
/// @param file_id file id run_d0_f[file_id]_0
std::filesystem::path data_fname(size_t mod_id, size_t file_id) const;
const std::filesystem::path &base_path() const;
const std::string &base_name() const;
const std::string &ext() const;
int file_index() const;
};
class ScanParameters {
bool m_enabled = false;
std::string m_dac;
int m_start = 0;
int m_stop = 0;
int m_step = 0;
//TODO! add settleTime, requires string to time conversion
public:
ScanParameters(const std::string &par);
ScanParameters() = default;
ScanParameters(const ScanParameters &) = default;
ScanParameters &operator=(const ScanParameters &) = default;
ScanParameters(ScanParameters &&) = default;
int start() const;
int stop() const;
int step() const;
const std::string &dac() const;
bool enabled() const;
};
/**
* @brief Class for parsing a master file either in our .json format or the old .raw format
* @brief Class for parsing a master file either in our .json format or the old
* .raw format
*/
class RawMasterFile {
RawFileNameComponents m_fnc;
@ -62,11 +82,13 @@ class RawMasterFile {
FrameDiscardPolicy m_frame_discard_policy{};
size_t m_frame_padding{};
//TODO! should these be bool?
// TODO! should these be bool?
uint8_t m_analog_flag{};
uint8_t m_digital_flag{};
uint8_t m_transceiver_flag{};
ScanParameters m_scan_parameters;
std::optional<size_t> m_analog_samples;
std::optional<size_t> m_digital_samples;
std::optional<size_t> m_transceiver_samples;
@ -78,7 +100,7 @@ class RawMasterFile {
std::filesystem::path data_fname(size_t mod_id, size_t file_id) const;
const std::string &version() const; //!< For example "7.2"
const std::string &version() const; //!< For example "7.2"
const DetectorType &detector_type() const;
const TimingMode &timing_mode() const;
size_t image_size_in_bytes() const;
@ -98,6 +120,9 @@ class RawMasterFile {
std::optional<size_t> transceiver_samples() const;
std::optional<size_t> number_of_rows() const;
std::optional<uint8_t> quad() const;
ScanParameters scan_parameters() const;
private:
void parse_json(const std::filesystem::path &fpath);
void parse_raw(const std::filesystem::path &fpath);

View File

@ -1,68 +0,0 @@
#pragma once
#include <array>
#include <map>
#include <string>
#include <vector>
// helper functions to write json
// append to string for better performance (not tested)
namespace aare {
/**
* @brief write a digit to a string
* takes key and value and outputs->"key": value,
* @tparam T type of value (int, uint32_t, ...)
* @param s string to append to
* @param key key to write
* @param value value to write
* @return void
* @note
* - can't use concepts here because we are using c++17
*/
template <typename T> inline void write_digit(std::string &s, const std::string &key, const T &value) {
s += "\"";
s += key;
s += "\": ";
s += std::to_string(value);
s += ", ";
}
inline void write_str(std::string &s, const std::string &key, const std::string &value) {
s += "\"";
s += key;
s += "\": \"";
s += value;
s += "\", ";
}
inline void write_map(std::string &s, const std::string &key, const std::map<std::string, std::string> &value) {
s += "\"";
s += key;
s += "\": {";
for (const auto &kv : value) {
write_str(s, kv.first, kv.second);
}
// remove last comma or trailing spaces
for (size_t i = s.size() - 1; i > 0; i--) {
if ((s[i] == ',') || (s[i] == ' ')) {
s.pop_back();
} else
break;
}
s += "}, ";
}
template <typename T, int N> void write_array(std::string &s, const std::string &key, const std::array<T, N> &value) {
s += "\"";
s += key;
s += "\": [";
for (size_t i = 0; i < N - 1; i++) {
s += std::to_string(value[i]);
s += ", ";
}
s += std::to_string(value[N - 1]);
s += "], ";
}
} // namespace aare

View File

@ -29,6 +29,7 @@ set( PYTHON_FILES
aare/__init__.py
aare/CtbRawFile.py
aare/transform.py
aare/ScanParameters.py
)
# Copy the python files to the build directory

View File

@ -1,7 +1,7 @@
from . import _aare
import numpy as np
from .ScanParameters import ScanParameters
class CtbRawFile(_aare.CtbRawFile):
"""File reader for the CTB raw file format.
@ -108,7 +108,24 @@ class CtbRawFile(_aare.CtbRawFile):
int: Frame position in file.
"""
return super().tell()
@property
def scan_parameters(self):
"""Return the scan parameters.
Returns:
ScanParameters: Scan parameters.
"""
return ScanParameters(self.master.scan_parameters)
@property
def master(self):
"""Return the master file.
Returns:
RawMasterFile: Master file.
"""
return super().master()
@property
def image_size_in_bytes(self) -> int:

View File

@ -0,0 +1,16 @@
from . import _aare
class ScanParameters(_aare.ScanParameters):
def __init__(self, s):
super().__init__(s)
def __iter__(self):
return [getattr(self, a) for a in ['start', 'stop', 'step']].__iter__()
def __str__(self):
return f'ScanParameters({self.dac}: {self.start}, {self.stop}, {self.step})'
def __repr__(self):
return self.__str__()

View File

@ -3,4 +3,5 @@ from . import _aare
from ._aare import VarClusterFinder, File, RawMasterFile
from ._aare import Pedestal, ClusterFinder
from .CtbRawFile import CtbRawFile
from .CtbRawFile import CtbRawFile
from .ScanParameters import ScanParameters

View File

@ -5,7 +5,6 @@ from . import _aare
class Moench05Transform:
#Could be moved to C++ without changing the interface
def __init__(self):
print('map created')
self.pixel_map = _aare.GenerateMoench05PixelMap()
def __call__(self, data):
@ -23,6 +22,7 @@ class Matterhorn02Transform:
else:
return np.take(data.view(np.uint16), self.pixel_map[0:counters])
#on import generate the pixel maps to avoid doing it every time
moench05 = Moench05Transform()
matterhorn02 = Matterhorn02Transform()

View File

@ -95,11 +95,11 @@ 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')
# fpath = Path(base / 'scan_all15keV_vrf500_vrsh700_th0_master_0.json')
f = aare.CtbRawFile(fpath, transform=transform.matterhorn02)
f.seek(100)
header4, image4 = f.read_frame()
# f = aare.CtbRawFile(fpath, transform=transform.matterhorn02)
# f.seek(100)
# header4, image4 = f.read_frame()
# n_counters = image.shape[1] / 48**2 / 2
@ -112,7 +112,7 @@ header4, image4 = f.read_frame()
#Data come in "blocks" of 4 pixels/receiver
data = get_Mh02_frames(fpath.as_posix())
# data = get_Mh02_frames(fpath.as_posix())
# rawi = np.zeros(48*48*4+56, dtype = np.uint16)
# for i,v in enumerate(rawi[56:]):
@ -130,7 +130,7 @@ data = get_Mh02_frames(fpath.as_posix())
# pm[counter, row, col] = row*48 + col+counter*48*48
f2 = aare.CtbRawFile(fpath, transform=transform.matterhorn02)
header, data = f2.read()
plt.plot(data[:,0,20,20])
# f2 = aare.CtbRawFile(fpath, transform=transform.matterhorn02)
# header, data = f2.read()
# plt.plot(data[:,0,20,20])

View File

@ -166,11 +166,29 @@ void define_file_io_bindings(py::module &m) {
.def_property_readonly("max_frames_per_file",
&RawMasterFile::max_frames_per_file)
.def_property_readonly("bitdepth", &RawMasterFile::bitdepth)
.def_property_readonly("frame_padding", &RawMasterFile::frame_padding)
.def_property_readonly("frame_discard_policy",
&RawMasterFile::frame_discard_policy)
.def_property_readonly("total_frames_expected", &RawMasterFile::total_frames_expected)
.def_property_readonly("geometry", &RawMasterFile::geometry)
.def_property_readonly("analog_samples", &RawMasterFile::analog_samples)
.def_property_readonly("digital_samples",
&RawMasterFile::digital_samples)
.def_property_readonly("transceiver_samples", &RawMasterFile::transceiver_samples);
.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);
py::class_<ScanParameters>(m, "ScanParameters")
.def(py::init<const std::string &>())
.def(py::init<const ScanParameters&>())
.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_<ClusterHeader>(m, "ClusterHeader")
// .def(py::init<>())
// .def_readwrite("frame_number", &ClusterHeader::frame_number)

View File

@ -1,7 +1,6 @@
#include "aare/RawFile.hpp"
#include "aare/PixelMap.hpp"
#include "aare/defs.hpp"
#include "aare/json.hpp"
#include <fmt/format.h>
#include <nlohmann/json.hpp>

View File

@ -1,5 +1,5 @@
#include "aare/RawMasterFile.hpp"
#include <sstream>
namespace aare {
RawFileNameComponents::RawFileNameComponents(
@ -51,6 +51,32 @@ const std::string &RawFileNameComponents::base_name() const {
const std::string &RawFileNameComponents::ext() const { return m_ext; }
int RawFileNameComponents::file_index() const { return m_file_index; }
// "[enabled\ndac dac 4\nstart 500\nstop 2200\nstep 5\nsettleTime 100us\n]"
ScanParameters::ScanParameters(const std::string& par){
std::istringstream iss(par.substr(1, par.size()-2));
std::string line;
while(std::getline(iss, line)){
if(line == "enabled"){
m_enabled = true;
}else if(line.find("dac") != std::string::npos){
m_dac = line.substr(4);
}else if(line.find("start") != std::string::npos){
m_start = std::stoi(line.substr(6));
}else if(line.find("stop") != std::string::npos){
m_stop = std::stoi(line.substr(5));
}else if(line.find("step") != std::string::npos){
m_step = std::stoi(line.substr(5));
}
}
}
int ScanParameters::start() const { return m_start; }
int ScanParameters::stop() const { return m_stop; }
int ScanParameters::step() const { return m_step; }
const std::string &ScanParameters::dac() const { return m_dac; }
bool ScanParameters::enabled() const { return m_enabled; }
RawMasterFile::RawMasterFile(const std::filesystem::path &fpath)
: m_fnc(fpath) {
if (!std::filesystem::exists(fpath)) {
@ -113,6 +139,10 @@ std::optional<size_t> RawMasterFile::transceiver_samples() const {
return m_transceiver_samples;
}
ScanParameters RawMasterFile::scan_parameters() const {
return m_scan_parameters;
}
void RawMasterFile::parse_json(const std::filesystem::path &fpath) {
std::ifstream ifs(fpath);
json j;
@ -203,6 +233,13 @@ void RawMasterFile::parse_json(const std::filesystem::path &fpath) {
// keep the optional empty
}
try{
std::string scan_parameters = j.at("Scan Parameters");
m_scan_parameters = ScanParameters(scan_parameters);
}catch (const json::out_of_range &e) {
// not a scan
}
// Update detector type for Moench
// TODO! How does this work with old .raw master files?
#ifdef AARE_VERBOSE

View File

@ -38,6 +38,26 @@ TEST_CASE("Master file name does not fit pattern"){
}
TEST_CASE("Parse scan parameters"){
ScanParameters s("[enabled\ndac dac 4\nstart 500\nstop 2200\nstep 5\nsettleTime 100us\n]");
REQUIRE(s.enabled());
REQUIRE(s.dac() == "dac 4");
REQUIRE(s.start() == 500);
REQUIRE(s.stop() == 2200);
REQUIRE(s.step() == 5);
}
TEST_CASE("A disabled scan"){
ScanParameters s("[disabled]");
REQUIRE_FALSE(s.enabled());
REQUIRE(s.dac() == "");
REQUIRE(s.start() == 0);
REQUIRE(s.stop() == 0);
REQUIRE(s.step() == 0);
}
TEST_CASE("Parse a master file in .json format"){
auto fpath = test_data_path() / "jungfrau" / "jungfrau_single_master_0.json";
REQUIRE(std::filesystem::exists(fpath));