mirror of
https://github.com/slsdetectorgroup/aare.git
synced 2025-04-30 02:10:02 +02:00
Custom base for decoding ADC data (#163)
New function apply_custom_weights (can we find a better name) that takes a uint16 and a NDView<double,1> of bases for the conversion. For each supplied weight it is used as base (instead of 2) to convert from bits to a double. --------- Co-authored-by: siebsi <sieb.patr@gmail.com>
This commit is contained in:
parent
84aafa75f6
commit
326941e2b4
@ -427,6 +427,7 @@ if(AARE_TESTS)
|
||||
set(TestSources
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/algorithm.test.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/defs.test.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/decode.test.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Dtype.test.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Frame.test.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/geo_helpers.test.cpp
|
||||
|
@ -184,4 +184,9 @@ std::ostream& operator <<(std::ostream& os, const NDView<T, Ndim>& arr){
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
NDView<T,1> make_view(std::vector<T>& vec){
|
||||
return NDView<T,1>(vec.data(), {static_cast<int64_t>(vec.size())});
|
||||
}
|
||||
|
||||
} // namespace aare
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include <aare/NDView.hpp>
|
||||
namespace aare {
|
||||
|
||||
@ -10,4 +11,16 @@ uint16_t adc_sar_04_decode64to16(uint64_t input);
|
||||
void adc_sar_05_decode64to16(NDView<uint64_t, 2> input, NDView<uint16_t,2> output);
|
||||
void adc_sar_04_decode64to16(NDView<uint64_t, 2> input, NDView<uint16_t,2> output);
|
||||
|
||||
|
||||
/**
|
||||
* @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.
|
||||
* @throws std::out_of_range if weights.size() < 16
|
||||
* @param input 16-bit input value
|
||||
* @param weights vector of weights, size must be less than or equal to 16
|
||||
*/
|
||||
double apply_custom_weights(uint16_t input, const NDView<double, 1> weights);
|
||||
|
||||
void apply_custom_weights(NDView<uint16_t, 1> input, NDView<double, 1> output, const NDView<double, 1> weights);
|
||||
|
||||
} // namespace aare
|
@ -13,6 +13,10 @@ from ._aare import ClusterFinderMT, ClusterCollector, ClusterFileSink, ClusterVe
|
||||
|
||||
from ._aare import fit_gaus, fit_pol1
|
||||
from ._aare import Interpolator
|
||||
|
||||
|
||||
from ._aare import apply_custom_weights
|
||||
|
||||
from .CtbRawFile import CtbRawFile
|
||||
from .RawFile import RawFile
|
||||
from .ScanParameters import ScanParameters
|
||||
|
@ -10,6 +10,8 @@
|
||||
#include "aare/decode.hpp"
|
||||
// #include "aare/fClusterFileV2.hpp"
|
||||
|
||||
#include "np_helper.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <filesystem>
|
||||
#include <pybind11/iostream.h>
|
||||
@ -65,35 +67,54 @@ m.def("adc_sar_04_decode64to16", [](py::array_t<uint8_t> input) {
|
||||
return output;
|
||||
});
|
||||
|
||||
py::class_<CtbRawFile>(m, "CtbRawFile")
|
||||
.def(py::init<const std::filesystem::path &>())
|
||||
.def("read_frame",
|
||||
[](CtbRawFile &self) {
|
||||
size_t image_size = self.image_size_in_bytes();
|
||||
py::array image;
|
||||
std::vector<ssize_t> shape;
|
||||
shape.reserve(2);
|
||||
shape.push_back(1);
|
||||
shape.push_back(image_size);
|
||||
m.def(
|
||||
"apply_custom_weights",
|
||||
[](py::array_t<uint16_t, py::array::c_style | py::array::forcecast> &input,
|
||||
py::array_t<double, py::array::c_style | py::array::forcecast>
|
||||
&weights) {
|
||||
|
||||
py::array_t<DetectorHeader> header(1);
|
||||
|
||||
// always read bytes
|
||||
image = py::array_t<uint8_t>(shape);
|
||||
// Create new array with same shape as the input array (uninitialized values)
|
||||
py::buffer_info buf = input.request();
|
||||
py::array_t<double> output(buf.shape);
|
||||
|
||||
self.read_into(
|
||||
reinterpret_cast<std::byte *>(image.mutable_data()),
|
||||
header.mutable_data());
|
||||
// Use NDViews to call into the C++ library
|
||||
auto weights_view = make_view_1d(weights);
|
||||
NDView<uint16_t, 1> input_view(input.mutable_data(), {input.size()});
|
||||
NDView<double, 1> output_view(output.mutable_data(), {output.size()});
|
||||
|
||||
return py::make_tuple(header, image);
|
||||
})
|
||||
.def("seek", &CtbRawFile::seek)
|
||||
.def("tell", &CtbRawFile::tell)
|
||||
.def("master", &CtbRawFile::master)
|
||||
apply_custom_weights(input_view, output_view, weights_view);
|
||||
return output;
|
||||
});
|
||||
|
||||
.def_property_readonly("image_size_in_bytes",
|
||||
&CtbRawFile::image_size_in_bytes)
|
||||
py::class_<CtbRawFile>(m, "CtbRawFile")
|
||||
.def(py::init<const std::filesystem::path &>())
|
||||
.def("read_frame",
|
||||
[](CtbRawFile &self) {
|
||||
size_t image_size = self.image_size_in_bytes();
|
||||
py::array image;
|
||||
std::vector<ssize_t> shape;
|
||||
shape.reserve(2);
|
||||
shape.push_back(1);
|
||||
shape.push_back(image_size);
|
||||
|
||||
.def_property_readonly("frames_in_file", &CtbRawFile::frames_in_file);
|
||||
py::array_t<DetectorHeader> header(1);
|
||||
|
||||
// always read bytes
|
||||
image = py::array_t<uint8_t>(shape);
|
||||
|
||||
self.read_into(reinterpret_cast<std::byte *>(image.mutable_data()),
|
||||
header.mutable_data());
|
||||
|
||||
return py::make_tuple(header, image);
|
||||
})
|
||||
.def("seek", &CtbRawFile::seek)
|
||||
.def("tell", &CtbRawFile::tell)
|
||||
.def("master", &CtbRawFile::master)
|
||||
|
||||
.def_property_readonly("image_size_in_bytes",
|
||||
&CtbRawFile::image_size_in_bytes)
|
||||
|
||||
.def_property_readonly("frames_in_file", &CtbRawFile::frames_in_file);
|
||||
|
||||
}
|
@ -191,3 +191,15 @@ TEST_CASE("compare two views") {
|
||||
|
||||
REQUIRE((view1 == view2));
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("Create a view over a vector"){
|
||||
std::vector<int> vec;
|
||||
for (int i = 0; i != 12; ++i) {
|
||||
vec.push_back(i);
|
||||
}
|
||||
auto v = aare::make_view(vec);
|
||||
REQUIRE(v.shape()[0] == 12);
|
||||
REQUIRE(v[0] == 0);
|
||||
REQUIRE(v[11] == 11);
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
#include "aare/decode.hpp"
|
||||
|
||||
#include <cmath>
|
||||
namespace aare {
|
||||
|
||||
uint16_t adc_sar_05_decode64to16(uint64_t input){
|
||||
@ -22,6 +22,10 @@ uint16_t adc_sar_05_decode64to16(uint64_t input){
|
||||
}
|
||||
|
||||
void adc_sar_05_decode64to16(NDView<uint64_t, 2> input, NDView<uint16_t,2> output){
|
||||
if(input.shape() != output.shape()){
|
||||
throw std::invalid_argument(LOCATION + " input and output shapes must match");
|
||||
}
|
||||
|
||||
for(int64_t i = 0; i < input.shape(0); i++){
|
||||
for(int64_t j = 0; j < input.shape(1); j++){
|
||||
output(i,j) = adc_sar_05_decode64to16(input(i,j));
|
||||
@ -49,6 +53,9 @@ uint16_t adc_sar_04_decode64to16(uint64_t input){
|
||||
}
|
||||
|
||||
void adc_sar_04_decode64to16(NDView<uint64_t, 2> input, NDView<uint16_t,2> output){
|
||||
if(input.shape() != output.shape()){
|
||||
throw std::invalid_argument(LOCATION + " input and output shapes must match");
|
||||
}
|
||||
for(int64_t i = 0; i < input.shape(0); i++){
|
||||
for(int64_t j = 0; j < input.shape(1); j++){
|
||||
output(i,j) = adc_sar_04_decode64to16(input(i,j));
|
||||
@ -56,6 +63,40 @@ void adc_sar_04_decode64to16(NDView<uint64_t, 2> input, NDView<uint16_t,2> outpu
|
||||
}
|
||||
}
|
||||
|
||||
double apply_custom_weights(uint16_t input, const NDView<double, 1> weights) {
|
||||
if(weights.size() > 16){
|
||||
throw std::invalid_argument("weights size must be less than or equal to 16");
|
||||
}
|
||||
|
||||
double result = 0.0;
|
||||
for (ssize_t i = 0; i < weights.size(); ++i) {
|
||||
result += ((input >> i) & 1) * std::pow(weights[i], i);
|
||||
}
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
void apply_custom_weights(NDView<uint16_t, 1> input, NDView<double, 1> output, const NDView<double,1> weights) {
|
||||
if(input.shape() != output.shape()){
|
||||
throw std::invalid_argument(LOCATION + " input and output shapes must match");
|
||||
}
|
||||
|
||||
//Calculate weights to avoid repeatedly calling std::pow
|
||||
std::vector<double> weights_powers(weights.size());
|
||||
for (ssize_t i = 0; i < weights.size(); ++i) {
|
||||
weights_powers[i] = std::pow(weights[i], i);
|
||||
}
|
||||
|
||||
// Apply custom weights to each element in the input array
|
||||
for (ssize_t i = 0; i < input.shape(0); i++) {
|
||||
double result = 0.0;
|
||||
for (size_t bit_index = 0; bit_index < weights_powers.size(); ++bit_index) {
|
||||
result += ((input(i) >> bit_index) & 1) * weights_powers[bit_index];
|
||||
}
|
||||
output(i) = result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace aare
|
||||
|
80
src/decode.test.cpp
Normal file
80
src/decode.test.cpp
Normal file
@ -0,0 +1,80 @@
|
||||
#include "aare/decode.hpp"
|
||||
|
||||
#include <catch2/matchers/catch_matchers_floating_point.hpp>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include "aare/NDArray.hpp"
|
||||
using Catch::Matchers::WithinAbs;
|
||||
#include <vector>
|
||||
|
||||
TEST_CASE("test_adc_sar_05_decode64to16"){
|
||||
uint64_t input = 0;
|
||||
uint16_t output = aare::adc_sar_05_decode64to16(input);
|
||||
CHECK(output == 0);
|
||||
|
||||
|
||||
// bit 29 on th input is bit 0 on the output
|
||||
input = 1UL << 29;
|
||||
output = aare::adc_sar_05_decode64to16(input);
|
||||
CHECK(output == 1);
|
||||
|
||||
// test all bits by iteratting through the bitlist
|
||||
std::vector<int> bitlist = {29, 19, 28, 18, 31, 21, 27, 20, 24, 23, 25, 22};
|
||||
for (size_t i = 0; i < bitlist.size(); i++) {
|
||||
input = 1UL << bitlist[i];
|
||||
output = aare::adc_sar_05_decode64to16(input);
|
||||
CHECK(output == (1 << i));
|
||||
}
|
||||
|
||||
|
||||
// test a few "random" values
|
||||
input = 0;
|
||||
input |= (1UL << 29);
|
||||
input |= (1UL << 19);
|
||||
input |= (1UL << 28);
|
||||
output = aare::adc_sar_05_decode64to16(input);
|
||||
CHECK(output == 7UL);
|
||||
|
||||
|
||||
input = 0;
|
||||
input |= (1UL << 18);
|
||||
input |= (1UL << 27);
|
||||
input |= (1UL << 25);
|
||||
output = aare::adc_sar_05_decode64to16(input);
|
||||
CHECK(output == 1096UL);
|
||||
|
||||
input = 0;
|
||||
input |= (1UL << 25);
|
||||
input |= (1UL << 22);
|
||||
output = aare::adc_sar_05_decode64to16(input);
|
||||
CHECK(output == 3072UL);
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("test_apply_custom_weights") {
|
||||
|
||||
uint16_t input = 1;
|
||||
aare::NDArray<double, 1> weights_data({3}, 0.0);
|
||||
weights_data(0) = 1.7;
|
||||
weights_data(1) = 2.1;
|
||||
weights_data(2) = 1.8;
|
||||
|
||||
auto weights = weights_data.view();
|
||||
|
||||
|
||||
double output = aare::apply_custom_weights(input, weights);
|
||||
CHECK_THAT(output, WithinAbs(1.0, 0.001));
|
||||
|
||||
input = 1UL << 1;
|
||||
output = aare::apply_custom_weights(input, weights);
|
||||
CHECK_THAT(output, WithinAbs(2.1, 0.001));
|
||||
|
||||
|
||||
input = 1UL << 2;
|
||||
output = aare::apply_custom_weights(input, weights);
|
||||
CHECK_THAT(output, WithinAbs(3.24, 0.001));
|
||||
|
||||
input = 0b111;
|
||||
output = aare::apply_custom_weights(input, weights);
|
||||
CHECK_THAT(output, WithinAbs(6.34, 0.001));
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user