mirror of
https://github.com/slsdetectorgroup/aare.git
synced 2026-02-19 13:38:40 +01:00
added ReadingMode member to RawMasterFile adapted error in Matterhorntransformer
This commit is contained in:
@@ -2,11 +2,11 @@
|
||||
#pragma once
|
||||
#include "aare/defs.hpp"
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <filesystem>
|
||||
#include <fmt/format.h>
|
||||
#include <fstream>
|
||||
#include <optional>
|
||||
#include <chrono>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
using json = nlohmann::json;
|
||||
@@ -97,9 +97,9 @@ class RawMasterFile {
|
||||
size_t m_frame_padding{};
|
||||
|
||||
// TODO! should these be bool?
|
||||
uint8_t m_analog_flag{};
|
||||
uint8_t m_digital_flag{};
|
||||
uint8_t m_transceiver_flag{};
|
||||
bool m_analog_flag{};
|
||||
bool m_digital_flag{};
|
||||
bool m_transceiver_flag{};
|
||||
|
||||
ScanParameters m_scan_parameters;
|
||||
|
||||
@@ -135,6 +135,8 @@ class RawMasterFile {
|
||||
size_t n_modules() const;
|
||||
uint8_t quad() const;
|
||||
|
||||
ReadingMode get_reading_mode() const;
|
||||
|
||||
std::optional<size_t> analog_samples() const;
|
||||
std::optional<size_t> digital_samples() const;
|
||||
std::optional<size_t> transceiver_samples() const;
|
||||
@@ -145,7 +147,9 @@ class RawMasterFile {
|
||||
|
||||
ScanParameters scan_parameters() const;
|
||||
|
||||
std::optional<std::chrono::nanoseconds> exptime() const { return m_exptime; }
|
||||
std::optional<std::chrono::nanoseconds> exptime() const {
|
||||
return m_exptime;
|
||||
}
|
||||
std::chrono::nanoseconds period() const { return m_period; }
|
||||
|
||||
private:
|
||||
|
||||
@@ -188,6 +188,15 @@ struct ROI {
|
||||
}
|
||||
};
|
||||
|
||||
enum ReadingMode : uint8_t {
|
||||
Analog = 0,
|
||||
Digital = 1,
|
||||
AnalogAndDigital = 2,
|
||||
Transceiver = 3,
|
||||
DigitalAndTransceiver = 4,
|
||||
Unknown = 5
|
||||
};
|
||||
|
||||
using dynamic_shape = std::vector<ssize_t>;
|
||||
|
||||
// TODO! Can we uniform enums between the libraries?
|
||||
@@ -353,16 +362,15 @@ using DataTypeVariants = std::variant<uint16_t, uint32_t>;
|
||||
constexpr uint16_t ADC_MASK =
|
||||
0x3FFF; // used to mask out the gain bits in Jungfrau
|
||||
|
||||
|
||||
class BitOffset{
|
||||
class BitOffset {
|
||||
uint8_t m_offset{};
|
||||
public:
|
||||
|
||||
public:
|
||||
BitOffset() = default;
|
||||
explicit BitOffset(uint32_t offset);
|
||||
uint8_t value() const {return m_offset;}
|
||||
bool operator==(const BitOffset& other) const;
|
||||
bool operator<(const BitOffset& other) const;
|
||||
|
||||
uint8_t value() const { return m_offset; }
|
||||
bool operator==(const BitOffset &other) const;
|
||||
bool operator<(const BitOffset &other) const;
|
||||
};
|
||||
|
||||
} // namespace aare
|
||||
@@ -5,7 +5,7 @@ from . import _aare
|
||||
|
||||
from ._aare import File, RawMasterFile, RawSubFile, JungfrauDataFile
|
||||
from ._aare import Pedestal_d, Pedestal_f, ClusterFinder_Cluster3x3i, VarClusterFinder
|
||||
from ._aare import DetectorType
|
||||
from ._aare import DetectorType, ReadingMode
|
||||
from ._aare import hitmap
|
||||
from ._aare import ROI
|
||||
from ._aare import corner
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
import numpy as np
|
||||
from . import _aare
|
||||
|
||||
from aare import ReadingMode
|
||||
|
||||
class AdcSar04Transform64to16:
|
||||
def __call__(self, data):
|
||||
@@ -71,20 +71,16 @@ class Matterhorn10Transform:
|
||||
self.dynamic_range = dynamic_range
|
||||
self.num_counters = num_counters
|
||||
|
||||
def compatibility(self, num_digital_samples : int, num_analog_samples : int):
|
||||
def compatibility(self, readingmode : ReadingMode):
|
||||
"""
|
||||
checks if Matterhorn10Transform is compatible with given parameters
|
||||
|
||||
:param num_digital_samples: Number of digital samples set
|
||||
:type num_digital_samples: int
|
||||
:param num_analog_samples: Number of analog samples set
|
||||
:type num_analog_samples: int
|
||||
:param readingmode: Reading mode set
|
||||
:type readingmode: ReadingMode
|
||||
:raises ValueError: if not compatible
|
||||
"""
|
||||
if(num_digital_samples != 0 and num_digital_samples is not None):
|
||||
raise ValueError(f"Incompatible Transformation. Matterhorn10Transform does not support digital samples, but num_digital_samples is {num_digital_samples}.")
|
||||
if(num_analog_samples != 0 and num_analog_samples is not None):
|
||||
raise ValueError(f"Incompatible Transformation. Matterhorn10Transform does not support analog samples, but num_analog_samples is {num_analog_samples}.")
|
||||
if(readingmode != ReadingMode.Transceiver):
|
||||
raise ValueError(f"Incompatible Transformation. Matterhorn10Transform only requires transceiver samples. However reading mode is {readingmode}.")
|
||||
|
||||
pass
|
||||
|
||||
|
||||
@@ -23,6 +23,16 @@ namespace py = pybind11;
|
||||
using namespace ::aare;
|
||||
|
||||
void define_raw_master_file_bindings(py::module &m) {
|
||||
|
||||
py::enum_<ReadingMode>(m, "ReadingMode")
|
||||
.value("Analog", ReadingMode::Analog)
|
||||
.value("Digital", ReadingMode::Digital)
|
||||
.value("AnalogAndDigital", ReadingMode::AnalogAndDigital)
|
||||
.value("Transceiver", ReadingMode::Transceiver)
|
||||
.value("DigitalAndTransceiver", ReadingMode::DigitalAndTransceiver)
|
||||
.value("Unknown", ReadingMode::Unknown)
|
||||
.export_values();
|
||||
|
||||
py::class_<RawMasterFile>(m, "RawMasterFile")
|
||||
.def(py::init<const std::filesystem::path &>())
|
||||
.def("data_fname", &RawMasterFile::data_fname, R"(
|
||||
@@ -81,6 +91,7 @@ void define_raw_master_file_bindings(py::module &m) {
|
||||
|
||||
.def_property_readonly("transceiver_samples",
|
||||
&RawMasterFile::transceiver_samples)
|
||||
.def_property_readonly("reading_mode", &RawMasterFile::get_reading_mode)
|
||||
.def_property_readonly("number_of_rows", &RawMasterFile::number_of_rows)
|
||||
.def_property_readonly("quad", &RawMasterFile::quad)
|
||||
.def_property_readonly("scan_parameters",
|
||||
|
||||
14
python/tests/test_RawMasterFile.py
Normal file
14
python/tests/test_RawMasterFile.py
Normal file
@@ -0,0 +1,14 @@
|
||||
|
||||
|
||||
import pytest
|
||||
from aare import RawMasterFile, ReadingMode, DetectorType
|
||||
|
||||
|
||||
@pytest.mark.withdata
|
||||
def test_read_rawfile_quad_eiger_and_compare_to_numpy(test_data_path):
|
||||
|
||||
file_name = test_data_path/'raw/jungfrau/jungfrau_single_master_0.json'
|
||||
|
||||
f = RawMasterFile(file_name)
|
||||
assert(f.reading_mode == ReadingMode.Unknown)
|
||||
assert(f.detector_type == DetectorType.Jungfrau)
|
||||
@@ -71,7 +71,7 @@ ScanParameters::ScanParameters(const bool enabled, const DACIndex dac,
|
||||
const int start, const int stop, const int step,
|
||||
const int64_t settleTime)
|
||||
: m_enabled(enabled), m_dac(dac), m_start(start), m_stop(stop),
|
||||
m_step(step), m_settleTime(settleTime) {};
|
||||
m_step(step), m_settleTime(settleTime){};
|
||||
|
||||
// "[enabled\ndac dac 4\nstart 500\nstop 2200\nstep 5\nsettleTime 100us\n]"
|
||||
ScanParameters::ScanParameters(const std::string &par) {
|
||||
@@ -195,6 +195,30 @@ ScanParameters RawMasterFile::scan_parameters() const {
|
||||
|
||||
std::optional<ROI> RawMasterFile::roi() const { return m_roi; }
|
||||
|
||||
ReadingMode RawMasterFile::get_reading_mode() const {
|
||||
|
||||
if (m_type != DetectorType::ChipTestBoard &&
|
||||
m_type != DetectorType::Xilinx_ChipTestBoard) {
|
||||
LOG(TLogLevel::logINFO)
|
||||
<< "reading mode is only available for CTB detectors.";
|
||||
return ReadingMode::Unknown;
|
||||
}
|
||||
|
||||
if (m_analog_flag && m_digital_flag) {
|
||||
return ReadingMode::AnalogAndDigital;
|
||||
} else if (m_analog_flag) {
|
||||
return ReadingMode::Analog;
|
||||
} else if (m_digital_flag && m_transceiver_flag) {
|
||||
return ReadingMode::DigitalAndTransceiver;
|
||||
} else if (m_digital_flag) {
|
||||
return ReadingMode::Digital;
|
||||
} else if (m_transceiver_flag) {
|
||||
return ReadingMode::Transceiver;
|
||||
} else {
|
||||
return ReadingMode::Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
void RawMasterFile::parse_json(std::istream &is) {
|
||||
json j;
|
||||
is >> j;
|
||||
@@ -205,10 +229,10 @@ void RawMasterFile::parse_json(std::istream &is) {
|
||||
m_type = string_to<DetectorType>(j["Detector Type"].get<std::string>());
|
||||
m_timing_mode = string_to<TimingMode>(j["Timing Mode"].get<std::string>());
|
||||
|
||||
m_geometry = {
|
||||
j["Geometry"]["y"],
|
||||
j["Geometry"]["x"]}; // TODO: isnt it only available for version > 7.1?
|
||||
// - try block default should be 1x1
|
||||
m_geometry = {j["Geometry"]["y"],
|
||||
j["Geometry"]["x"]}; // TODO: isnt it only available for
|
||||
// version > 7.1?
|
||||
// - try block default should be 1x1
|
||||
|
||||
m_image_size_in_bytes =
|
||||
v < 8.0 ? j["Image Size in bytes"] : j["Image Size"];
|
||||
@@ -244,7 +268,7 @@ void RawMasterFile::parse_json(std::istream &is) {
|
||||
// TODO! Not valid for CTB but not changing api right now!
|
||||
// Not all detectors write the bitdepth but in case
|
||||
// its not there it is 16
|
||||
if(j.contains("Dynamic Range") && j["Dynamic Range"].is_number()){
|
||||
if (j.contains("Dynamic Range") && j["Dynamic Range"].is_number()) {
|
||||
m_bitdepth = j["Dynamic Range"];
|
||||
} else {
|
||||
m_bitdepth = 16;
|
||||
@@ -255,18 +279,18 @@ void RawMasterFile::parse_json(std::istream &is) {
|
||||
m_frame_discard_policy = string_to<FrameDiscardPolicy>(
|
||||
j["Frame Discard Policy"].get<std::string>());
|
||||
|
||||
if(j.contains("Number of rows") && j["Number of rows"].is_number()){
|
||||
if (j.contains("Number of rows") && j["Number of rows"].is_number()) {
|
||||
m_number_of_rows = j["Number of rows"];
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Special treatment of analog flag because of Moench03
|
||||
try {
|
||||
m_analog_flag = j.at("Analog Flag");
|
||||
m_analog_flag = static_cast<bool>(j.at("Analog Flag").get<int>());
|
||||
} catch (const json::out_of_range &e) {
|
||||
// if it doesn't work still set it to one
|
||||
// to try to decode analog samples (Old Moench03)
|
||||
m_analog_flag = 1;
|
||||
m_analog_flag = true;
|
||||
}
|
||||
try {
|
||||
if (m_analog_flag) {
|
||||
@@ -276,7 +300,7 @@ void RawMasterFile::parse_json(std::istream &is) {
|
||||
} catch (const json::out_of_range &e) {
|
||||
// keep the optional empty
|
||||
// and set analog flag to 0
|
||||
m_analog_flag = 0;
|
||||
m_analog_flag = false;
|
||||
}
|
||||
//-----------------------------------------------------------------
|
||||
try {
|
||||
@@ -291,7 +315,7 @@ void RawMasterFile::parse_json(std::istream &is) {
|
||||
// m_adc_mask = 0;
|
||||
// }
|
||||
try {
|
||||
int digital_flag = j.at("Digital Flag");
|
||||
bool digital_flag = static_cast<bool>(j.at("Digital Flag").get<int>());
|
||||
if (digital_flag) {
|
||||
m_digital_samples = j.at("Digital Samples");
|
||||
}
|
||||
@@ -299,7 +323,8 @@ void RawMasterFile::parse_json(std::istream &is) {
|
||||
// keep the optional empty
|
||||
}
|
||||
try {
|
||||
m_transceiver_flag = j.at("Transceiver Flag");
|
||||
m_transceiver_flag =
|
||||
static_cast<bool>(j.at("Transceiver Flag").get<int>());
|
||||
if (m_transceiver_flag) {
|
||||
m_transceiver_samples = j.at("Transceiver Samples");
|
||||
}
|
||||
@@ -379,7 +404,6 @@ void RawMasterFile::parse_json(std::istream &is) {
|
||||
m_counter_mask =
|
||||
std::stoi(j["Counter Mask"].get<std::string>(), nullptr, 16);
|
||||
}
|
||||
|
||||
|
||||
// Update detector type for Moench
|
||||
// TODO! How does this work with old .raw master files?
|
||||
@@ -433,9 +457,9 @@ void RawMasterFile::parse_raw(std::istream &is) {
|
||||
// } else if (key == "Number of rows"){
|
||||
// m_number_of_rows = std::stoi(value);
|
||||
} else if (key == "Analog Flag") {
|
||||
m_analog_flag = std::stoi(value);
|
||||
m_analog_flag = static_cast<bool>(std::stoi(value));
|
||||
} else if (key == "Digital Flag") {
|
||||
m_digital_flag = std::stoi(value);
|
||||
m_digital_flag = static_cast<bool>(std::stoi(value));
|
||||
|
||||
} else if (key == "Analog Samples") {
|
||||
if (m_analog_flag == 1) {
|
||||
|
||||
@@ -146,6 +146,8 @@ TEST_CASE("Parse a master file in .json format", "[.integration]") {
|
||||
|
||||
REQUIRE_FALSE(f.analog_samples());
|
||||
REQUIRE_FALSE(f.digital_samples());
|
||||
|
||||
REQUIRE(f.get_reading_mode() == ReadingMode::Unknown);
|
||||
}
|
||||
|
||||
TEST_CASE("Parse a master file in old .raw format",
|
||||
@@ -211,6 +213,8 @@ TEST_CASE("Parse a master file in .raw format", "[.integration]") {
|
||||
// Frames in File : 100
|
||||
REQUIRE(f.frames_in_file() == 100);
|
||||
|
||||
REQUIRE(f.get_reading_mode() == ReadingMode::Unknown);
|
||||
|
||||
// #Frame Header
|
||||
// Frame Number : 8 bytes
|
||||
// SubFrame Number/ExpLength : 4 bytes
|
||||
@@ -398,7 +402,7 @@ TEST_CASE("Parse EIGER 7.2 master from string stream") {
|
||||
REQUIRE(f.timing_mode() == TimingMode::Auto);
|
||||
REQUIRE(f.geometry().col == 2);
|
||||
REQUIRE(f.geometry().row == 2);
|
||||
|
||||
|
||||
REQUIRE(f.image_size_in_bytes() == 524288);
|
||||
REQUIRE(f.pixels_x() == 512);
|
||||
REQUIRE(f.pixels_y() == 256);
|
||||
@@ -560,6 +564,7 @@ TEST_CASE("Parse a CTB file from stream") {
|
||||
REQUIRE(f.digital_samples() == std::nullopt); // Digital Flag is 0
|
||||
REQUIRE(f.transceiver_samples() == 1152);
|
||||
REQUIRE(f.frames_in_file() == 40);
|
||||
REQUIRE(f.get_reading_mode() == ReadingMode::Transceiver);
|
||||
}
|
||||
|
||||
TEST_CASE("Parse v8.0 MYTHEN3 from stream") {
|
||||
|
||||
@@ -75,35 +75,32 @@ TEST_CASE("test_apply_custom_weights") {
|
||||
CHECK_THAT(output, WithinAbs(6.34, 0.001));
|
||||
}
|
||||
|
||||
TEST_CASE("Mask 32 bit unsigned integer to 24 bit"){
|
||||
//any number less than 2**24 (16777216) should be the same
|
||||
CHECK(aare::mask32to24bits(0)==0);
|
||||
CHECK(aare::mask32to24bits(19)==19);
|
||||
CHECK(aare::mask32to24bits(29875)==29875);
|
||||
CHECK(aare::mask32to24bits(1092177)==1092177);
|
||||
CHECK(aare::mask32to24bits(0xFFFF)==0xFFFF);
|
||||
CHECK(aare::mask32to24bits(0xFFFFFFFF)==0xFFFFFF);
|
||||
TEST_CASE("Mask 32 bit unsigned integer to 24 bit") {
|
||||
// any number less than 2**24 (16777216) should be the same
|
||||
CHECK(aare::mask32to24bits(0) == 0);
|
||||
CHECK(aare::mask32to24bits(19) == 19);
|
||||
CHECK(aare::mask32to24bits(29875) == 29875);
|
||||
CHECK(aare::mask32to24bits(1092177) == 1092177);
|
||||
CHECK(aare::mask32to24bits(0xFFFF) == 0xFFFF);
|
||||
CHECK(aare::mask32to24bits(0xFFFFFFFF) == 0xFFFFFF);
|
||||
|
||||
// Offset specifies that the should ignore 0-7 bits
|
||||
// at the start
|
||||
CHECK(aare::mask32to24bits(0xFFFF, BitOffset(4))==0xFFF);
|
||||
CHECK(aare::mask32to24bits(0xFF0000d9)==0xd9);
|
||||
CHECK(aare::mask32to24bits(0xFF000d9F, BitOffset(4))==0xF000d9);
|
||||
CHECK(aare::mask32to24bits(16777217)==1);
|
||||
CHECK(aare::mask32to24bits(15,BitOffset(7))==0);
|
||||
|
||||
//Highest bit set to 1 should just be excluded
|
||||
//lowest 4 bits set to 1
|
||||
CHECK(aare::mask32to24bits(0x8000000f,BitOffset(7))==0);
|
||||
|
||||
CHECK(aare::mask32to24bits(0xFFFF, BitOffset(4)) == 0xFFF);
|
||||
CHECK(aare::mask32to24bits(0xFF0000d9) == 0xd9);
|
||||
CHECK(aare::mask32to24bits(0xFF000d9F, BitOffset(4)) == 0xF000d9);
|
||||
CHECK(aare::mask32to24bits(16777217) == 1);
|
||||
CHECK(aare::mask32to24bits(15, BitOffset(7)) == 0);
|
||||
|
||||
// Highest bit set to 1 should just be excluded
|
||||
// lowest 4 bits set to 1
|
||||
CHECK(aare::mask32to24bits(0x8000000f, BitOffset(7)) == 0);
|
||||
}
|
||||
|
||||
TEST_CASE("Expand container with 24 bit data to 32"){
|
||||
TEST_CASE("Expand container with 24 bit data to 32") {
|
||||
{
|
||||
uint8_t buffer[] = {
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
aare::NDView<uint8_t, 1> input(&buffer[0], {9});
|
||||
@@ -116,9 +113,7 @@ TEST_CASE("Expand container with 24 bit data to 32"){
|
||||
}
|
||||
{
|
||||
uint8_t buffer[] = {
|
||||
0x0F, 0x00, 0x00,
|
||||
0xFF, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF,
|
||||
0x0F, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF,
|
||||
};
|
||||
|
||||
aare::NDView<uint8_t, 1> input(&buffer[0], {9});
|
||||
@@ -131,9 +126,7 @@ TEST_CASE("Expand container with 24 bit data to 32"){
|
||||
}
|
||||
{
|
||||
uint8_t buffer[] = {
|
||||
0x00, 0x00, 0xFF,
|
||||
0xFF, 0xFF, 0x00,
|
||||
0x00, 0xFF, 0x00,
|
||||
0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0x00,
|
||||
};
|
||||
|
||||
aare::NDView<uint8_t, 1> input(&buffer[0], {9});
|
||||
@@ -147,20 +140,36 @@ TEST_CASE("Expand container with 24 bit data to 32"){
|
||||
REQUIRE_THROWS(aare::expand24to32bit(input, out.view(), BitOffset(4)));
|
||||
}
|
||||
{
|
||||
//For use with offset we need an extra byte
|
||||
uint8_t buffer[] = {
|
||||
0x00, 0x00, 0xFF,
|
||||
0xFF, 0xFF, 0x00,
|
||||
0x00, 0xFF, 0x00, 0x00
|
||||
};
|
||||
// For use with offset we need an extra byte
|
||||
uint8_t buffer[] = {0x00, 0x00, 0xFF, 0xFF, 0xFF,
|
||||
0x00, 0x00, 0xFF, 0x00, 0x00};
|
||||
|
||||
aare::NDView<uint8_t, 1> input(&buffer[0], {10});
|
||||
aare::NDArray<uint32_t, 1> out({3}); //still output.size == 3
|
||||
aare::NDArray<uint32_t, 1> out({3}); // still output.size == 3
|
||||
aare::expand24to32bit(input, out.view(), BitOffset(4));
|
||||
|
||||
CHECK(out(0) == 0xFFF000);
|
||||
CHECK(out(1) == 0xFFF);
|
||||
CHECK(out(2) == 0xFF0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Expand 4 bit values packed into 8 bit to 8 bit values") {
|
||||
{
|
||||
uint8_t buffer[] = {
|
||||
0x00, 0xF0, 0xFF, 0x00, 0xF0, 0xFF,
|
||||
};
|
||||
|
||||
aare::NDView<uint8_t, 1> input(&buffer[0], {6});
|
||||
aare::NDArray<uint8_t, 1> out({12});
|
||||
aare::expand4to8bit(input, out.view());
|
||||
|
||||
uint8_t expected_output[] = {
|
||||
0x0, 0x0, 0x0, 0xF, 0xF, 0xF,
|
||||
0x0, 0x0, 0x0, 0xF, 0xF, 0xF}; // is it first little or big endian?
|
||||
|
||||
for (size_t i = 0; i < 12; ++i) {
|
||||
CHECK(out(i) == expected_output[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user