mirror of
https://github.com/slsdetectorgroup/aare.git
synced 2025-04-30 10:20:03 +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
|
set(TestSources
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/algorithm.test.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/src/algorithm.test.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/defs.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/Dtype.test.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Frame.test.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/src/Frame.test.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/geo_helpers.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
|
} // namespace aare
|
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <vector>
|
||||||
#include <aare/NDView.hpp>
|
#include <aare/NDView.hpp>
|
||||||
namespace aare {
|
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_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);
|
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
|
} // namespace aare
|
@ -13,6 +13,10 @@ from ._aare import ClusterFinderMT, ClusterCollector, ClusterFileSink, ClusterVe
|
|||||||
|
|
||||||
from ._aare import fit_gaus, fit_pol1
|
from ._aare import fit_gaus, fit_pol1
|
||||||
from ._aare import Interpolator
|
from ._aare import Interpolator
|
||||||
|
|
||||||
|
|
||||||
|
from ._aare import apply_custom_weights
|
||||||
|
|
||||||
from .CtbRawFile import CtbRawFile
|
from .CtbRawFile import CtbRawFile
|
||||||
from .RawFile import RawFile
|
from .RawFile import RawFile
|
||||||
from .ScanParameters import ScanParameters
|
from .ScanParameters import ScanParameters
|
||||||
|
@ -10,6 +10,8 @@
|
|||||||
#include "aare/decode.hpp"
|
#include "aare/decode.hpp"
|
||||||
// #include "aare/fClusterFileV2.hpp"
|
// #include "aare/fClusterFileV2.hpp"
|
||||||
|
|
||||||
|
#include "np_helper.hpp"
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <pybind11/iostream.h>
|
#include <pybind11/iostream.h>
|
||||||
@ -65,7 +67,27 @@ m.def("adc_sar_04_decode64to16", [](py::array_t<uint8_t> input) {
|
|||||||
return output;
|
return output;
|
||||||
});
|
});
|
||||||
|
|
||||||
py::class_<CtbRawFile>(m, "CtbRawFile")
|
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) {
|
||||||
|
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
// 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()});
|
||||||
|
|
||||||
|
apply_custom_weights(input_view, output_view, weights_view);
|
||||||
|
return output;
|
||||||
|
});
|
||||||
|
|
||||||
|
py::class_<CtbRawFile>(m, "CtbRawFile")
|
||||||
.def(py::init<const std::filesystem::path &>())
|
.def(py::init<const std::filesystem::path &>())
|
||||||
.def("read_frame",
|
.def("read_frame",
|
||||||
[](CtbRawFile &self) {
|
[](CtbRawFile &self) {
|
||||||
@ -81,8 +103,7 @@ m.def("adc_sar_04_decode64to16", [](py::array_t<uint8_t> input) {
|
|||||||
// always read bytes
|
// always read bytes
|
||||||
image = py::array_t<uint8_t>(shape);
|
image = py::array_t<uint8_t>(shape);
|
||||||
|
|
||||||
self.read_into(
|
self.read_into(reinterpret_cast<std::byte *>(image.mutable_data()),
|
||||||
reinterpret_cast<std::byte *>(image.mutable_data()),
|
|
||||||
header.mutable_data());
|
header.mutable_data());
|
||||||
|
|
||||||
return py::make_tuple(header, image);
|
return py::make_tuple(header, image);
|
||||||
|
@ -191,3 +191,15 @@ TEST_CASE("compare two views") {
|
|||||||
|
|
||||||
REQUIRE((view1 == view2));
|
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 "aare/decode.hpp"
|
||||||
|
#include <cmath>
|
||||||
namespace aare {
|
namespace aare {
|
||||||
|
|
||||||
uint16_t adc_sar_05_decode64to16(uint64_t input){
|
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){
|
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 i = 0; i < input.shape(0); i++){
|
||||||
for(int64_t j = 0; j < input.shape(1); j++){
|
for(int64_t j = 0; j < input.shape(1); j++){
|
||||||
output(i,j) = adc_sar_05_decode64to16(input(i,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){
|
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 i = 0; i < input.shape(0); i++){
|
||||||
for(int64_t j = 0; j < input.shape(1); j++){
|
for(int64_t j = 0; j < input.shape(1); j++){
|
||||||
output(i,j) = adc_sar_04_decode64to16(input(i,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
|
} // 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