mirror of
https://github.com/slsdetectorgroup/aare.git
synced 2026-02-20 23:08:42 +01:00
Dev/stuff from pyctbgui (#273)
Matterhorn10 Transform some other Transformations from pyctbGUI added method get_reading_mode for easier error handling in decoders ## TODO: - proper error handling for all other decoders - proper documentation for all other decoders - refactoring all other decoders to store hard coded values in a Struct ChipSpecification
This commit is contained in:
@@ -10,11 +10,21 @@ NDArray<ssize_t, 2> GenerateMoench03PixelMap();
|
|||||||
NDArray<ssize_t, 2> GenerateMoench05PixelMap();
|
NDArray<ssize_t, 2> GenerateMoench05PixelMap();
|
||||||
NDArray<ssize_t, 2> GenerateMoench05PixelMap1g();
|
NDArray<ssize_t, 2> GenerateMoench05PixelMap1g();
|
||||||
NDArray<ssize_t, 2> GenerateMoench05PixelMapOld();
|
NDArray<ssize_t, 2> GenerateMoench05PixelMapOld();
|
||||||
|
NDArray<ssize_t, 2> GenerateMoench04AnalogPixelMap();
|
||||||
|
|
||||||
// Matterhorn02
|
// Matterhorn02
|
||||||
NDArray<ssize_t, 2> GenerateMH02SingleCounterPixelMap();
|
NDArray<ssize_t, 2> GenerateMH02SingleCounterPixelMap();
|
||||||
NDArray<ssize_t, 3> GenerateMH02FourCounterPixelMap();
|
NDArray<ssize_t, 3> GenerateMH02FourCounterPixelMap();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generate pixel map for Matterhorn10 detector
|
||||||
|
* @param dynamic_range Dynamic range of the detector (16, 8, or 4)
|
||||||
|
* @param n_counters Number of counters (1 to 4)
|
||||||
|
*/
|
||||||
|
NDArray<ssize_t, 2>
|
||||||
|
GenerateMatterhorn10PixelMap(const size_t dynamic_range = 16,
|
||||||
|
const size_t n_counters = 1);
|
||||||
|
|
||||||
// Eiger
|
// Eiger
|
||||||
NDArray<ssize_t, 2> GenerateEigerFlipRowsPixelMap();
|
NDArray<ssize_t, 2> GenerateEigerFlipRowsPixelMap();
|
||||||
|
|
||||||
|
|||||||
@@ -97,9 +97,9 @@ class RawMasterFile {
|
|||||||
size_t m_frame_padding{};
|
size_t m_frame_padding{};
|
||||||
|
|
||||||
// TODO! should these be bool?
|
// TODO! should these be bool?
|
||||||
uint8_t m_analog_flag{};
|
bool m_analog_flag{};
|
||||||
uint8_t m_digital_flag{};
|
bool m_digital_flag{};
|
||||||
uint8_t m_transceiver_flag{};
|
bool m_transceiver_flag{};
|
||||||
|
|
||||||
ScanParameters m_scan_parameters;
|
ScanParameters m_scan_parameters;
|
||||||
|
|
||||||
@@ -135,6 +135,8 @@ class RawMasterFile {
|
|||||||
size_t n_modules() const;
|
size_t n_modules() const;
|
||||||
uint8_t quad() const;
|
uint8_t quad() const;
|
||||||
|
|
||||||
|
ReadoutMode get_reading_mode() const;
|
||||||
|
|
||||||
std::optional<size_t> analog_samples() const;
|
std::optional<size_t> analog_samples() const;
|
||||||
std::optional<size_t> digital_samples() const;
|
std::optional<size_t> digital_samples() const;
|
||||||
std::optional<size_t> transceiver_samples() const;
|
std::optional<size_t> transceiver_samples() const;
|
||||||
|
|||||||
@@ -38,6 +38,13 @@ uint32_t mask32to24bits(uint32_t input, BitOffset offset = {});
|
|||||||
void expand24to32bit(NDView<uint8_t, 1> input, NDView<uint32_t, 1> output,
|
void expand24to32bit(NDView<uint8_t, 1> input, NDView<uint32_t, 1> output,
|
||||||
BitOffset offset = {});
|
BitOffset offset = {});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief expands the two 4 bit values of an 8 bit buffer into two 8 bit values
|
||||||
|
* @param input input buffer with 4 bit values packed into 8 bit
|
||||||
|
* @param output output buffer with 8 bit values
|
||||||
|
*/
|
||||||
|
void expand4to8bit(NDView<uint8_t, 1> input, NDView<uint8_t, 1> output);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Apply custom weights to a 16-bit input value. Will sum up
|
* @brief Apply custom weights to a 16-bit input value. Will sum up
|
||||||
* weights[i]**i for each bit i that is set in the input value.
|
* weights[i]**i for each bit i that is set in the input value.
|
||||||
|
|||||||
@@ -188,6 +188,46 @@ struct ROI {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// @brief Chip specifications for Matterhorn1
|
||||||
|
struct Matterhorn10 {
|
||||||
|
constexpr static size_t nRows = 256;
|
||||||
|
constexpr static size_t nCols = 256;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @brief Chip specifications for Matterhorn2
|
||||||
|
struct Matterhorn02 {
|
||||||
|
constexpr static size_t nRows = 48;
|
||||||
|
constexpr static size_t nCols = 48;
|
||||||
|
constexpr static size_t nHalfCols = 24;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @brief Chip specifications for Moench04
|
||||||
|
struct Moench04 {
|
||||||
|
constexpr static size_t nRows = 400;
|
||||||
|
constexpr static size_t nCols = 400;
|
||||||
|
constexpr static std::array<int, 32>
|
||||||
|
adcNumbers =
|
||||||
|
{
|
||||||
|
9, 8, 11, 10, 13, 12, 15, 14, 1, 0, 3,
|
||||||
|
2, 5, 4, 7, 6, 23, 22, 21, 20, 19, 18,
|
||||||
|
17, 16, 31, 30, 29, 28, 27, 26, 25, 24}; // TODO : should we
|
||||||
|
// only have chip
|
||||||
|
// specifications or
|
||||||
|
// also wiring in
|
||||||
|
// chiptestboard?
|
||||||
|
constexpr static size_t nPixelsPerSuperColumn = 5000;
|
||||||
|
constexpr static size_t superColumnWidth = 25;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ReadoutMode : uint8_t {
|
||||||
|
ANALOG_ONLY = 0,
|
||||||
|
DIGITAL_ONLY = 1,
|
||||||
|
ANALOG_AND_DIGITAL = 2,
|
||||||
|
TRANSCEIVER_ONLY = 3,
|
||||||
|
DIGITAL_AND_TRANSCEIVER = 4,
|
||||||
|
UNKNOWN = 5
|
||||||
|
};
|
||||||
|
|
||||||
using dynamic_shape = std::vector<ssize_t>;
|
using dynamic_shape = std::vector<ssize_t>;
|
||||||
|
|
||||||
// TODO! Can we uniform enums between the libraries?
|
// TODO! Can we uniform enums between the libraries?
|
||||||
|
|||||||
@@ -18,6 +18,9 @@ class CtbRawFile(_aare.CtbRawFile):
|
|||||||
super().__init__(fname)
|
super().__init__(fname)
|
||||||
self._chunk_size = chunk_size
|
self._chunk_size = chunk_size
|
||||||
self._transform = transform
|
self._transform = transform
|
||||||
|
if self._transform:
|
||||||
|
if hasattr(self._transform, "compatibility") and callable(getattr(self._transform, "compatibility")):
|
||||||
|
self._transform.compatibility(self.master.reading_mode)
|
||||||
|
|
||||||
|
|
||||||
def read_frame(self, frame_index: int | None = None ) -> tuple:
|
def read_frame(self, frame_index: int | None = None ) -> tuple:
|
||||||
@@ -45,7 +48,6 @@ class CtbRawFile(_aare.CtbRawFile):
|
|||||||
if header.shape == (1,):
|
if header.shape == (1,):
|
||||||
header = header[0]
|
header = header[0]
|
||||||
|
|
||||||
|
|
||||||
if self._transform:
|
if self._transform:
|
||||||
res = self._transform(data)
|
res = self._transform(data)
|
||||||
if isinstance(res, tuple):
|
if isinstance(res, tuple):
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ from . import _aare
|
|||||||
|
|
||||||
from ._aare import File, RawMasterFile, RawSubFile, JungfrauDataFile
|
from ._aare import File, RawMasterFile, RawSubFile, JungfrauDataFile
|
||||||
from ._aare import Pedestal_d, Pedestal_f, ClusterFinder_Cluster3x3i, VarClusterFinder
|
from ._aare import Pedestal_d, Pedestal_f, ClusterFinder_Cluster3x3i, VarClusterFinder
|
||||||
from ._aare import DetectorType
|
from ._aare import DetectorType, ReadoutMode
|
||||||
from ._aare import hitmap
|
from ._aare import hitmap
|
||||||
from ._aare import ROI
|
from ._aare import ROI
|
||||||
from ._aare import corner
|
from ._aare import corner
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
# SPDX-License-Identifier: MPL-2.0
|
# SPDX-License-Identifier: MPL-2.0
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from . import _aare
|
from . import _aare
|
||||||
|
from aare import ReadoutMode
|
||||||
|
from aare._aare import Matterhorn10
|
||||||
|
|
||||||
class AdcSar04Transform64to16:
|
class AdcSar04Transform64to16:
|
||||||
def __call__(self, data):
|
def __call__(self, data):
|
||||||
@@ -24,6 +25,14 @@ class Moench05Transform:
|
|||||||
return np.take(data.view(np.uint16), self.pixel_map)
|
return np.take(data.view(np.uint16), self.pixel_map)
|
||||||
|
|
||||||
|
|
||||||
|
class Moench03Transform:
|
||||||
|
def __init__(self):
|
||||||
|
self.pixel_map = _aare.GenerateMoench03PixelMap()
|
||||||
|
|
||||||
|
def __call__(self, data):
|
||||||
|
return np.take(data.view(np.uint16), self.pixel_map)
|
||||||
|
|
||||||
|
|
||||||
class Moench05Transform1g:
|
class Moench05Transform1g:
|
||||||
#Could be moved to C++ without changing the interface
|
#Could be moved to C++ without changing the interface
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@@ -41,17 +50,79 @@ class Moench05TransformOld:
|
|||||||
def __call__(self, data):
|
def __call__(self, data):
|
||||||
return np.take(data.view(np.uint16), self.pixel_map)
|
return np.take(data.view(np.uint16), self.pixel_map)
|
||||||
|
|
||||||
|
class Moench04AnalogTransform:
|
||||||
class Matterhorn02Transform:
|
#Could be moved to C++ without changing the interface
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.pixel_map = _aare.GenerateMH02FourCounterPixelMap()
|
self.pixel_map = _aare.GenerateMoench04AnalogPixelMap()
|
||||||
|
|
||||||
def __call__(self, data):
|
def __call__(self, data):
|
||||||
counters = int(data.size / 48**2 / 2)
|
return np.take(data.view(np.uint16), self.pixel_map)
|
||||||
if counters == 1:
|
|
||||||
return np.take(data.view(np.uint16), self.pixel_map[0])
|
class Matterhorn02TransceiverTransform:
|
||||||
else:
|
#Could be moved to C++ without changing the interface
|
||||||
return np.take(data.view(np.uint16), self.pixel_map[0:counters])
|
def __init__(self):
|
||||||
|
self.pixel_map = _aare.GenerateMH02SingleCounterPixelMap()
|
||||||
|
|
||||||
|
def __call__(self, data):
|
||||||
|
return np.take(data.view(np.uint16), self.pixel_map)
|
||||||
|
|
||||||
|
class Matterhorn10Transform:
|
||||||
|
"""
|
||||||
|
Transforms Matterhorn10 chip data from a buffer of bytes (uint8_t)
|
||||||
|
to a numpy array of uint8, uint16 depending on dynamic range.
|
||||||
|
Assumes data taken with transceiver samples only.
|
||||||
|
|
||||||
|
:param dynamic_range: How many bits a pixel is encoded dynamic range (4, 8, or 16)
|
||||||
|
:type dynamic_range: int
|
||||||
|
:param num_counters: num counters used (1 to 4)
|
||||||
|
:type num_counters: int
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
A matterhorn chip has 256 columns and 256 rows.
|
||||||
|
A matterhornchip with dynamic range 16 and 2 counters thus requires
|
||||||
|
256*256*16*2/(2*64) = 1024 transceiver samples. (Per default 2 channels are enabled per transceiver sample, each channel storing 64 bits)
|
||||||
|
"""
|
||||||
|
def __init__(self, dynamic_range : int, num_counters : int):
|
||||||
|
self.pixel_map = _aare.GenerateMatterhorn10PixelMap(dynamic_range, num_counters)
|
||||||
|
self.dynamic_range = dynamic_range
|
||||||
|
self.num_counters = num_counters
|
||||||
|
|
||||||
|
def compatibility(self, readingmode : ReadoutMode):
|
||||||
|
"""
|
||||||
|
checks if Matterhorn10Transform is compatible with given parameters
|
||||||
|
|
||||||
|
:param readingmode: Reading mode set
|
||||||
|
:type readingmode: ReadoutMode
|
||||||
|
:raises ValueError: if not compatible
|
||||||
|
"""
|
||||||
|
if(readingmode != ReadoutMode.TRANSCEIVER_ONLY):
|
||||||
|
raise ValueError(f"Incompatible Transformation. Matterhorn10Transform only requires transceiver samples. However reading mode is {readingmode}.")
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
|
def data_compatibility(self, data):
|
||||||
|
"""
|
||||||
|
checks if data is compatible for transformation
|
||||||
|
|
||||||
|
:param data: data to be transformed, expected to be a 1D numpy array of uint8
|
||||||
|
:type data: np.ndarray
|
||||||
|
:raises ValueError: if not compatible
|
||||||
|
"""
|
||||||
|
expected_size = (Matterhorn10.nRows*Matterhorn10.nCols*self.num_counters*self.dynamic_range)//8 # read_frame returns data in uint8_t
|
||||||
|
|
||||||
|
if(data.size != expected_size):
|
||||||
|
raise ValueError(f"Data size {data.size} does not match expected size {expected_size} for Matterhorn10 with dynamic range {self.dynamic_range} and num_counters {self.num_counters}.")
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
|
def __call__(self, data):
|
||||||
|
self.data_compatibility(data)
|
||||||
|
if self.dynamic_range == 16:
|
||||||
|
return np.take(data.view(np.uint16), self.pixel_map)
|
||||||
|
elif self.dynamic_range == 8:
|
||||||
|
return np.take(data.view(np.uint8), self.pixel_map)
|
||||||
|
else: #dynamic range 4
|
||||||
|
return np.take(_aare.expand4to8bit(data.view(np.uint8)), self.pixel_map)
|
||||||
|
|
||||||
class Mythen302Transform:
|
class Mythen302Transform:
|
||||||
"""
|
"""
|
||||||
@@ -95,7 +166,7 @@ class Mythen302Transform:
|
|||||||
moench05 = Moench05Transform()
|
moench05 = Moench05Transform()
|
||||||
moench05_1g = Moench05Transform1g()
|
moench05_1g = Moench05Transform1g()
|
||||||
moench05_old = Moench05TransformOld()
|
moench05_old = Moench05TransformOld()
|
||||||
matterhorn02 = Matterhorn02Transform()
|
matterhorn02 = Matterhorn02TransceiverTransform()
|
||||||
adc_sar_04_64to16 = AdcSar04Transform64to16()
|
adc_sar_04_64to16 = AdcSar04Transform64to16()
|
||||||
adc_sar_05_64to16 = AdcSar05Transform64to16()
|
adc_sar_05_64to16 = AdcSar05Transform64to16()
|
||||||
adc_sar_05_06_07_08_64to16 = AdcSar05060708Transform64to16()
|
adc_sar_05_06_07_08_64to16 = AdcSar05060708Transform64to16()
|
||||||
25
python/src/bind_Defs.hpp
Normal file
25
python/src/bind_Defs.hpp
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#include <pybind11/pybind11.h>
|
||||||
|
#include <pybind11/stl.h>
|
||||||
|
|
||||||
|
#include "aare/defs.hpp"
|
||||||
|
|
||||||
|
namespace py = pybind11;
|
||||||
|
using namespace aare;
|
||||||
|
|
||||||
|
void define_defs_bindings(py::module &m) {
|
||||||
|
auto matterhorn10 = py::class_<Matterhorn10>(m, "Matterhorn10");
|
||||||
|
matterhorn10.attr("nRows") = Matterhorn10::nRows;
|
||||||
|
matterhorn10.attr("nCols") = Matterhorn10::nCols;
|
||||||
|
|
||||||
|
auto matterhorn02 = py::class_<Matterhorn02>(m, "Matterhorn02");
|
||||||
|
matterhorn02.attr("nRows") = Matterhorn02::nRows;
|
||||||
|
matterhorn02.attr("nCols") = Matterhorn02::nCols;
|
||||||
|
matterhorn02.attr("nHalfCols") = Matterhorn02::nHalfCols;
|
||||||
|
|
||||||
|
auto moench04 = py::class_<Moench04>(m, "Moench04");
|
||||||
|
moench04.attr("nRows") = Moench04::nRows;
|
||||||
|
moench04.attr("nCols") = Moench04::nCols;
|
||||||
|
moench04.attr("nPixelsPerSuperColumn") = Moench04::nPixelsPerSuperColumn;
|
||||||
|
moench04.attr("superColumnWidth") = Moench04::superColumnWidth;
|
||||||
|
moench04.attr("adcNumbers") = Moench04::adcNumbers;
|
||||||
|
}
|
||||||
@@ -33,15 +33,35 @@ void define_pixel_map_bindings(py::module &m) {
|
|||||||
new NDArray<ssize_t, 2>(GenerateMoench05PixelMapOld());
|
new NDArray<ssize_t, 2>(GenerateMoench05PixelMapOld());
|
||||||
return return_image_data(ptr);
|
return return_image_data(ptr);
|
||||||
})
|
})
|
||||||
|
|
||||||
|
.def("GenerateMoench04AnalogPixelMap",
|
||||||
|
[]() {
|
||||||
|
auto ptr =
|
||||||
|
new NDArray<ssize_t, 2>(GenerateMoench04AnalogPixelMap());
|
||||||
|
return return_image_data(ptr);
|
||||||
|
})
|
||||||
|
|
||||||
.def("GenerateMH02SingleCounterPixelMap",
|
.def("GenerateMH02SingleCounterPixelMap",
|
||||||
[]() {
|
[]() {
|
||||||
auto ptr = new NDArray<ssize_t, 2>(
|
auto ptr = new NDArray<ssize_t, 2>(
|
||||||
GenerateMH02SingleCounterPixelMap());
|
GenerateMH02SingleCounterPixelMap());
|
||||||
return return_image_data(ptr);
|
return return_image_data(ptr);
|
||||||
})
|
})
|
||||||
.def("GenerateMH02FourCounterPixelMap", []() {
|
.def("GenerateMH02FourCounterPixelMap",
|
||||||
|
[]() {
|
||||||
auto ptr =
|
auto ptr =
|
||||||
new NDArray<ssize_t, 3>(GenerateMH02FourCounterPixelMap());
|
new NDArray<ssize_t, 3>(GenerateMH02FourCounterPixelMap());
|
||||||
return return_image_data(ptr);
|
return return_image_data(ptr);
|
||||||
});
|
})
|
||||||
|
|
||||||
|
.def(
|
||||||
|
"GenerateMatterhorn10PixelMap",
|
||||||
|
[](const size_t dynamic_range, const size_t n_counters) {
|
||||||
|
auto ptr = new NDArray<ssize_t, 2>(
|
||||||
|
GenerateMatterhorn10PixelMap(dynamic_range, n_counters));
|
||||||
|
return return_image_data(ptr);
|
||||||
|
},
|
||||||
|
py::arg("dynamic_range") = 16, py::arg("n_counters") = 1,
|
||||||
|
R"(
|
||||||
|
Generate pixel map for Matterhorn02 detector)");
|
||||||
}
|
}
|
||||||
@@ -139,6 +139,22 @@ void define_ctb_raw_file_io_bindings(py::module &m) {
|
|||||||
return output;
|
return output;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
m.def("expand4to8bit",
|
||||||
|
[](py::array_t<uint8_t, py::array::c_style | py::array::forcecast>
|
||||||
|
&input) {
|
||||||
|
py::buffer_info buf = input.request();
|
||||||
|
|
||||||
|
py::array_t<uint8_t> output(buf.size * 2);
|
||||||
|
|
||||||
|
NDView<uint8_t, 1> input_view(input.mutable_data(),
|
||||||
|
{input.size()});
|
||||||
|
NDView<uint8_t, 1> output_view(output.mutable_data(),
|
||||||
|
{output.size()});
|
||||||
|
|
||||||
|
aare::expand4to8bit(input_view, output_view);
|
||||||
|
return output;
|
||||||
|
});
|
||||||
|
|
||||||
m.def("decode_my302",
|
m.def("decode_my302",
|
||||||
[](py::array_t<uint8_t, py::array::c_style | py::array::forcecast>
|
[](py::array_t<uint8_t, py::array::c_style | py::array::forcecast>
|
||||||
&input,
|
&input,
|
||||||
|
|||||||
@@ -9,8 +9,10 @@
|
|||||||
#include "bind_ClusterFinder.hpp"
|
#include "bind_ClusterFinder.hpp"
|
||||||
#include "bind_ClusterFinderMT.hpp"
|
#include "bind_ClusterFinderMT.hpp"
|
||||||
#include "bind_ClusterVector.hpp"
|
#include "bind_ClusterVector.hpp"
|
||||||
|
#include "bind_Defs.hpp"
|
||||||
#include "bind_Eta.hpp"
|
#include "bind_Eta.hpp"
|
||||||
#include "bind_Interpolator.hpp"
|
#include "bind_Interpolator.hpp"
|
||||||
|
#include "bind_PixelMap.hpp"
|
||||||
#include "bind_RawFile.hpp"
|
#include "bind_RawFile.hpp"
|
||||||
#include "bind_calibration.hpp"
|
#include "bind_calibration.hpp"
|
||||||
|
|
||||||
@@ -20,7 +22,6 @@
|
|||||||
#include "fit.hpp"
|
#include "fit.hpp"
|
||||||
#include "jungfrau_data_file.hpp"
|
#include "jungfrau_data_file.hpp"
|
||||||
#include "pedestal.hpp"
|
#include "pedestal.hpp"
|
||||||
#include "pixel_map.hpp"
|
|
||||||
#include "raw_master_file.hpp"
|
#include "raw_master_file.hpp"
|
||||||
#include "raw_sub_file.hpp"
|
#include "raw_sub_file.hpp"
|
||||||
#include "var_cluster.hpp"
|
#include "var_cluster.hpp"
|
||||||
@@ -140,6 +141,8 @@ PYBIND11_MODULE(_aare, m) {
|
|||||||
register_calculate_3x3eta<float, 3, 3, uint16_t>(m);
|
register_calculate_3x3eta<float, 3, 3, uint16_t>(m);
|
||||||
register_calculate_3x3eta<int16_t, 3, 3, uint16_t>(m);
|
register_calculate_3x3eta<int16_t, 3, 3, uint16_t>(m);
|
||||||
|
|
||||||
|
define_defs_bindings(m);
|
||||||
|
|
||||||
using Sum_index_pair_d = Sum_index_pair<double, corner>;
|
using Sum_index_pair_d = Sum_index_pair<double, corner>;
|
||||||
PYBIND11_NUMPY_DTYPE(Sum_index_pair_d, sum, index);
|
PYBIND11_NUMPY_DTYPE(Sum_index_pair_d, sum, index);
|
||||||
using Sum_index_pair_f = Sum_index_pair<float, corner>;
|
using Sum_index_pair_f = Sum_index_pair<float, corner>;
|
||||||
|
|||||||
@@ -23,6 +23,16 @@ namespace py = pybind11;
|
|||||||
using namespace ::aare;
|
using namespace ::aare;
|
||||||
|
|
||||||
void define_raw_master_file_bindings(py::module &m) {
|
void define_raw_master_file_bindings(py::module &m) {
|
||||||
|
|
||||||
|
py::enum_<ReadoutMode>(m, "ReadoutMode")
|
||||||
|
.value("ANALOG_ONLY", ReadoutMode::ANALOG_ONLY)
|
||||||
|
.value("DIGITAL_ONLY", ReadoutMode::DIGITAL_ONLY)
|
||||||
|
.value("ANALOG_AND_DIGITAL", ReadoutMode::ANALOG_AND_DIGITAL)
|
||||||
|
.value("TRANSCEIVER_ONLY", ReadoutMode::TRANSCEIVER_ONLY)
|
||||||
|
.value("DIGITAL_AND_TRANSCEIVER", ReadoutMode::DIGITAL_AND_TRANSCEIVER)
|
||||||
|
.value("UNKNOWN", ReadoutMode::UNKNOWN)
|
||||||
|
.export_values();
|
||||||
|
|
||||||
py::class_<RawMasterFile>(m, "RawMasterFile")
|
py::class_<RawMasterFile>(m, "RawMasterFile")
|
||||||
.def(py::init<const std::filesystem::path &>())
|
.def(py::init<const std::filesystem::path &>())
|
||||||
.def("data_fname", &RawMasterFile::data_fname, R"(
|
.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",
|
.def_property_readonly("transceiver_samples",
|
||||||
&RawMasterFile::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("number_of_rows", &RawMasterFile::number_of_rows)
|
||||||
.def_property_readonly("quad", &RawMasterFile::quad)
|
.def_property_readonly("quad", &RawMasterFile::quad)
|
||||||
.def_property_readonly("scan_parameters",
|
.def_property_readonly("scan_parameters",
|
||||||
|
|||||||
@@ -14,6 +14,9 @@ def test_read_rawfile_with_roi_spanning_over_one_module(test_data_path):
|
|||||||
assert headers.size == 10100
|
assert headers.size == 10100
|
||||||
assert frames.shape == (10100, 256, 256)
|
assert frames.shape == (10100, 256, 256)
|
||||||
|
|
||||||
|
assert headers.size == 10100
|
||||||
|
assert frames.shape == (10100, 256, 256)
|
||||||
|
|
||||||
@pytest.mark.withdata
|
@pytest.mark.withdata
|
||||||
def test_read_rawfile_with_multiple_rois(test_data_path):
|
def test_read_rawfile_with_multiple_rois(test_data_path):
|
||||||
with RawFile(test_data_path / "raw/ROITestData/MultipleROIs/run_master_0.json") as f:
|
with RawFile(test_data_path / "raw/ROITestData/MultipleROIs/run_master_0.json") as f:
|
||||||
@@ -44,6 +47,8 @@ def test_read_rawfile_with_multiple_rois(test_data_path):
|
|||||||
assert frame[0].shape == (301, 101)
|
assert frame[0].shape == (301, 101)
|
||||||
assert f.tell() == 2
|
assert f.tell() == 2
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.withdata
|
@pytest.mark.withdata
|
||||||
def test_read_rawfile_quad_eiger_and_compare_to_numpy(test_data_path):
|
def test_read_rawfile_quad_eiger_and_compare_to_numpy(test_data_path):
|
||||||
|
|
||||||
@@ -68,7 +73,6 @@ def test_read_rawfile_quad_eiger_and_compare_to_numpy(test_data_path):
|
|||||||
|
|
||||||
assert (image == image1).all()
|
assert (image == image1).all()
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.withdata
|
@pytest.mark.withdata
|
||||||
def test_read_rawfile_eiger_and_compare_to_numpy(test_data_path):
|
def test_read_rawfile_eiger_and_compare_to_numpy(test_data_path):
|
||||||
d0 = test_data_path/'raw/eiger/Lab6_20500eV_2deg_20240629_d0_f0_7.raw'
|
d0 = test_data_path/'raw/eiger/Lab6_20500eV_2deg_20240629_d0_f0_7.raw'
|
||||||
|
|||||||
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, ReadoutMode, 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 == ReadoutMode.UNKNOWN)
|
||||||
|
assert(f.detector_type == DetectorType.Jungfrau)
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
// SPDX-License-Identifier: MPL-2.0
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
#include "aare/PixelMap.hpp"
|
#include "aare/PixelMap.hpp"
|
||||||
|
#include "aare/defs.hpp"
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
@@ -31,6 +32,29 @@ NDArray<ssize_t, 2> GenerateMoench03PixelMap() {
|
|||||||
return order_map;
|
return order_map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NDArray<ssize_t, 2> GenerateMoench04AnalogPixelMap() {
|
||||||
|
std::array<int, 32> const adc_nr = Moench04::adcNumbers;
|
||||||
|
int const nadc = adc_nr.size();
|
||||||
|
NDArray<ssize_t, 2> order_map({Moench04::nRows, Moench04::nCols});
|
||||||
|
|
||||||
|
int pixel = 0;
|
||||||
|
for (size_t i = 0; i != Moench04::nPixelsPerSuperColumn; ++i) {
|
||||||
|
for (size_t i_adc = 0; i_adc != nadc; ++i_adc) {
|
||||||
|
int const col =
|
||||||
|
(adc_nr[i_adc] % 16) * 25 + (i % Moench04::superColumnWidth);
|
||||||
|
int row = 0;
|
||||||
|
if (i_adc < 16)
|
||||||
|
row = 199 - (i / Moench04::superColumnWidth);
|
||||||
|
else
|
||||||
|
row = 200 + (i / Moench04::superColumnWidth);
|
||||||
|
|
||||||
|
order_map(row, col) = pixel;
|
||||||
|
pixel++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return order_map;
|
||||||
|
}
|
||||||
|
|
||||||
NDArray<ssize_t, 2> GenerateMoench05PixelMap() {
|
NDArray<ssize_t, 2> GenerateMoench05PixelMap() {
|
||||||
std::array<int, 3> adc_numbers = {5, 9, 1};
|
std::array<int, 3> adc_numbers = {5, 9, 1};
|
||||||
NDArray<ssize_t, 2> order_map({160, 150});
|
NDArray<ssize_t, 2> order_map({160, 150});
|
||||||
@@ -104,16 +128,18 @@ NDArray<ssize_t, 2> GenerateEigerFlipRowsPixelMap() {
|
|||||||
return order_map;
|
return order_map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// transceiver pixel map for Matterhorn02
|
||||||
NDArray<ssize_t, 2> GenerateMH02SingleCounterPixelMap() {
|
NDArray<ssize_t, 2> GenerateMH02SingleCounterPixelMap() {
|
||||||
// This is the pixel map for a single counter Matterhorn02, i.e. 48x48
|
// This is the pixel map for a single counter Matterhorn02, i.e. 48x48
|
||||||
// pixels. Data is read from two transceivers in blocks of 4 pixels.
|
// pixels. Data is read from two transceivers in blocks of 4 pixels.
|
||||||
NDArray<ssize_t, 2> order_map({48, 48});
|
NDArray<ssize_t, 2> order_map({Matterhorn02::nRows, Matterhorn02::nCols});
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
size_t nSamples = 4;
|
size_t nSamples = 4;
|
||||||
for (int row = 0; row < 48; row++) {
|
for (size_t row = 0; row < Matterhorn02::nRows; row++) {
|
||||||
for (int col = 0; col < 24; col++) {
|
for (size_t col = 0; col < Matterhorn02::nHalfCols; col++) {
|
||||||
for (int iTrans = 0; iTrans < 2; iTrans++) {
|
for (size_t iTrans = 0; iTrans < 2; iTrans++) {
|
||||||
order_map(row, iTrans * 24 + col) = offset + nSamples * iTrans;
|
order_map(row, iTrans * Matterhorn02::nHalfCols + col) =
|
||||||
|
offset + nSamples * iTrans;
|
||||||
}
|
}
|
||||||
offset += 1;
|
offset += 1;
|
||||||
if ((col + 1) % nSamples == 0) {
|
if ((col + 1) % nSamples == 0) {
|
||||||
@@ -126,16 +152,64 @@ NDArray<ssize_t, 2> GenerateMH02SingleCounterPixelMap() {
|
|||||||
|
|
||||||
NDArray<ssize_t, 3> GenerateMH02FourCounterPixelMap() {
|
NDArray<ssize_t, 3> GenerateMH02FourCounterPixelMap() {
|
||||||
auto single_counter_map = GenerateMH02SingleCounterPixelMap();
|
auto single_counter_map = GenerateMH02SingleCounterPixelMap();
|
||||||
NDArray<ssize_t, 3> order_map({4, 48, 48});
|
NDArray<ssize_t, 3> order_map(
|
||||||
for (int counter = 0; counter < 4; counter++) {
|
{4, Matterhorn02::nRows, Matterhorn02::nCols});
|
||||||
for (int row = 0; row < 48; row++) {
|
for (size_t counter = 0; counter < 4; counter++) {
|
||||||
for (int col = 0; col < 48; col++) {
|
for (size_t row = 0; row < Matterhorn02::nRows; row++) {
|
||||||
|
for (size_t col = 0; col < Matterhorn02::nCols; col++) {
|
||||||
order_map(counter, row, col) =
|
order_map(counter, row, col) =
|
||||||
single_counter_map(row, col) + counter * 48 * 48;
|
single_counter_map(row, col) +
|
||||||
|
counter * Matterhorn02::nRows * Matterhorn02::nCols;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return order_map;
|
return order_map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NDArray<ssize_t, 2> GenerateMatterhorn10PixelMap(const size_t dynamic_range,
|
||||||
|
const size_t n_counters) {
|
||||||
|
|
||||||
|
// Matterhorn10 uses transceiver samples (each transceiver sample has 1-4
|
||||||
|
// channels storing 8 bytes each)
|
||||||
|
constexpr size_t n_cols = Matterhorn10::nCols;
|
||||||
|
constexpr size_t n_rows = Matterhorn10::nRows;
|
||||||
|
NDArray<ssize_t, 2> pixel_map(
|
||||||
|
{static_cast<ssize_t>(n_rows * n_counters), n_cols});
|
||||||
|
|
||||||
|
size_t num_consecutive_pixels{};
|
||||||
|
switch (dynamic_range) {
|
||||||
|
case 16:
|
||||||
|
num_consecutive_pixels = 4;
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
num_consecutive_pixels = 8;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
num_consecutive_pixels = 16;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw std::runtime_error("Unsupported dynamic range for Matterhorn02");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t row = 0; row < n_rows; ++row) {
|
||||||
|
for (size_t counter = 0; counter < n_counters; ++counter) {
|
||||||
|
size_t col = 0;
|
||||||
|
for (size_t offset = 0; offset < 64;
|
||||||
|
offset += num_consecutive_pixels) {
|
||||||
|
for (size_t pkg = offset; pkg < Matterhorn10::nCols;
|
||||||
|
pkg += 64) {
|
||||||
|
for (size_t pixel = 0; pixel < num_consecutive_pixels;
|
||||||
|
++pixel) {
|
||||||
|
pixel_map(row + counter * n_rows, col) =
|
||||||
|
pkg + pixel + row * n_cols * n_counters +
|
||||||
|
n_cols * counter;
|
||||||
|
++col;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pixel_map;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace aare
|
} // namespace aare
|
||||||
@@ -206,6 +206,30 @@ std::optional<ROI> RawMasterFile::roi() const {
|
|||||||
|
|
||||||
std::optional<std::vector<ROI>> RawMasterFile::rois() const { return m_rois; }
|
std::optional<std::vector<ROI>> RawMasterFile::rois() const { return m_rois; }
|
||||||
|
|
||||||
|
ReadoutMode 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 ReadoutMode::UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_analog_flag && m_digital_flag) {
|
||||||
|
return ReadoutMode::ANALOG_AND_DIGITAL;
|
||||||
|
} else if (m_analog_flag) {
|
||||||
|
return ReadoutMode::ANALOG_ONLY;
|
||||||
|
} else if (m_digital_flag && m_transceiver_flag) {
|
||||||
|
return ReadoutMode::DIGITAL_AND_TRANSCEIVER;
|
||||||
|
} else if (m_digital_flag) {
|
||||||
|
return ReadoutMode::DIGITAL_ONLY;
|
||||||
|
} else if (m_transceiver_flag) {
|
||||||
|
return ReadoutMode::TRANSCEIVER_ONLY;
|
||||||
|
} else {
|
||||||
|
return ReadoutMode::UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RawMasterFile::parse_json(std::istream &is) {
|
void RawMasterFile::parse_json(std::istream &is) {
|
||||||
json j;
|
json j;
|
||||||
is >> j;
|
is >> j;
|
||||||
@@ -216,9 +240,9 @@ void RawMasterFile::parse_json(std::istream &is) {
|
|||||||
m_type = string_to<DetectorType>(j["Detector Type"].get<std::string>());
|
m_type = string_to<DetectorType>(j["Detector Type"].get<std::string>());
|
||||||
m_timing_mode = string_to<TimingMode>(j["Timing Mode"].get<std::string>());
|
m_timing_mode = string_to<TimingMode>(j["Timing Mode"].get<std::string>());
|
||||||
|
|
||||||
m_geometry = {
|
m_geometry = {j["Geometry"]["y"],
|
||||||
j["Geometry"]["y"],
|
j["Geometry"]["x"]}; // TODO: isnt it only available for
|
||||||
j["Geometry"]["x"]}; // TODO: isnt it only available for version > 7.1?
|
// version > 7.1?
|
||||||
// - try block default should be 1x1
|
// - try block default should be 1x1
|
||||||
|
|
||||||
m_image_size_in_bytes =
|
m_image_size_in_bytes =
|
||||||
@@ -272,22 +296,15 @@ void RawMasterFile::parse_json(std::istream &is) {
|
|||||||
|
|
||||||
// ----------------------------------------------------------------
|
// ----------------------------------------------------------------
|
||||||
// Special treatment of analog flag because of Moench03
|
// Special treatment of analog flag because of Moench03
|
||||||
|
m_analog_flag = v < 8.0 && (m_type == DetectorType::Moench);
|
||||||
|
|
||||||
try {
|
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;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
if (m_analog_flag) {
|
if (m_analog_flag) {
|
||||||
m_analog_samples = j.at("Analog Samples");
|
m_analog_samples = j.at("Analog Samples");
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (const json::out_of_range &e) {
|
} catch (const json::out_of_range &e) {
|
||||||
// keep the optional empty
|
// keep the optional empty
|
||||||
// and set analog flag to 0
|
|
||||||
m_analog_flag = 0;
|
|
||||||
}
|
}
|
||||||
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
||||||
try {
|
try {
|
||||||
@@ -302,7 +319,7 @@ void RawMasterFile::parse_json(std::istream &is) {
|
|||||||
// m_adc_mask = 0;
|
// m_adc_mask = 0;
|
||||||
// }
|
// }
|
||||||
try {
|
try {
|
||||||
int digital_flag = j.at("Digital Flag");
|
bool digital_flag = static_cast<bool>(j.at("Digital Flag").get<int>());
|
||||||
if (digital_flag) {
|
if (digital_flag) {
|
||||||
m_digital_samples = j.at("Digital Samples");
|
m_digital_samples = j.at("Digital Samples");
|
||||||
}
|
}
|
||||||
@@ -310,7 +327,8 @@ void RawMasterFile::parse_json(std::istream &is) {
|
|||||||
// keep the optional empty
|
// keep the optional empty
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
m_transceiver_flag = j.at("Transceiver Flag");
|
m_transceiver_flag =
|
||||||
|
static_cast<bool>(j.at("Transceiver Flag").get<int>());
|
||||||
if (m_transceiver_flag) {
|
if (m_transceiver_flag) {
|
||||||
m_transceiver_samples = j.at("Transceiver Samples");
|
m_transceiver_samples = j.at("Transceiver Samples");
|
||||||
}
|
}
|
||||||
@@ -444,9 +462,9 @@ void RawMasterFile::parse_raw(std::istream &is) {
|
|||||||
// } else if (key == "Number of rows"){
|
// } else if (key == "Number of rows"){
|
||||||
// m_number_of_rows = std::stoi(value);
|
// m_number_of_rows = std::stoi(value);
|
||||||
} else if (key == "Analog Flag") {
|
} 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") {
|
} 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") {
|
} else if (key == "Analog Samples") {
|
||||||
if (m_analog_flag == 1) {
|
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.analog_samples());
|
||||||
REQUIRE_FALSE(f.digital_samples());
|
REQUIRE_FALSE(f.digital_samples());
|
||||||
|
|
||||||
|
REQUIRE(f.get_reading_mode() == ReadoutMode::UNKNOWN);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Parse a master file in old .raw format",
|
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
|
// Frames in File : 100
|
||||||
REQUIRE(f.frames_in_file() == 100);
|
REQUIRE(f.frames_in_file() == 100);
|
||||||
|
|
||||||
|
REQUIRE(f.get_reading_mode() == ReadoutMode::ANALOG_AND_DIGITAL);
|
||||||
|
|
||||||
// #Frame Header
|
// #Frame Header
|
||||||
// Frame Number : 8 bytes
|
// Frame Number : 8 bytes
|
||||||
// SubFrame Number/ExpLength : 4 bytes
|
// SubFrame Number/ExpLength : 4 bytes
|
||||||
@@ -560,6 +564,7 @@ TEST_CASE("Parse a CTB file from stream") {
|
|||||||
REQUIRE(f.digital_samples() == std::nullopt); // Digital Flag is 0
|
REQUIRE(f.digital_samples() == std::nullopt); // Digital Flag is 0
|
||||||
REQUIRE(f.transceiver_samples() == 1152);
|
REQUIRE(f.transceiver_samples() == 1152);
|
||||||
REQUIRE(f.frames_in_file() == 40);
|
REQUIRE(f.frames_in_file() == 40);
|
||||||
|
REQUIRE(f.get_reading_mode() == ReadoutMode::TRANSCEIVER_ONLY);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Parse v8.0 MYTHEN3 from stream") {
|
TEST_CASE("Parse v8.0 MYTHEN3 from stream") {
|
||||||
|
|||||||
@@ -144,6 +144,24 @@ uint32_t mask32to24bits(uint32_t input, BitOffset offset) {
|
|||||||
return (input >> offset.value()) & mask24bits;
|
return (input >> offset.value()) & mask24bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void expand4to8bit(NDView<uint8_t, 1> input, NDView<uint8_t, 1> output) {
|
||||||
|
|
||||||
|
if (2 * input.size() != output.size())
|
||||||
|
throw std::runtime_error(
|
||||||
|
fmt::format("Mismatch between input and output size. Input "
|
||||||
|
"size of {} requires an output of at least {} "
|
||||||
|
"bytes. Called with input size: {} output size: {}",
|
||||||
|
LOCATION, input.size(), 2 * input.size(), input.size(),
|
||||||
|
output.size()));
|
||||||
|
|
||||||
|
// assumes little-endian
|
||||||
|
for (ssize_t i = 0; i < input.size(); ++i) {
|
||||||
|
uint8_t val = input(i);
|
||||||
|
output[2 * i] = (val & 0x0F);
|
||||||
|
output[2 * i + 1] = (val & 0xF0) >> 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void expand24to32bit(NDView<uint8_t, 1> input, NDView<uint32_t, 1> output,
|
void expand24to32bit(NDView<uint8_t, 1> input, NDView<uint32_t, 1> output,
|
||||||
BitOffset bit_offset) {
|
BitOffset bit_offset) {
|
||||||
|
|
||||||
|
|||||||
@@ -153,3 +153,23 @@ TEST_CASE("Expand container with 24 bit data to 32") {
|
|||||||
CHECK(out(2) == 0xFF0);
|
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}; // assuming little endian
|
||||||
|
|
||||||
|
for (size_t i = 0; i < 12; ++i) {
|
||||||
|
CHECK(out(i) == expected_output[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user