mirror of
https://github.com/slsdetectorgroup/aare.git
synced 2026-02-19 02:08:40 +01:00
templated calculate_pedestal with boolean template argument only_gain0, added drop_dimension to NDArray and reference pointer to data
This commit is contained in:
@@ -438,6 +438,7 @@ endif()
|
||||
if(AARE_TESTS)
|
||||
set(TestSources
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/algorithm.test.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/calibration.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
|
||||
|
||||
@@ -33,7 +33,7 @@ class NDArray : public ArrayExpr<NDArray<T, Ndim>, Ndim> {
|
||||
* @brief Default constructor. Will construct an empty NDArray.
|
||||
*
|
||||
*/
|
||||
NDArray() : shape_(), strides_(c_strides<Ndim>(shape_)), data_(nullptr){};
|
||||
NDArray() : shape_(), strides_(c_strides<Ndim>(shape_)), data_(nullptr) {};
|
||||
|
||||
/**
|
||||
* @brief Construct a new NDArray object with a given shape.
|
||||
@@ -185,6 +185,7 @@ class NDArray : public ArrayExpr<NDArray<T, Ndim>, Ndim> {
|
||||
const T &operator[](ssize_t i) const { return data_[i]; }
|
||||
|
||||
T *data() { return data_; }
|
||||
T *&data_ref() { return data_; }
|
||||
std::byte *buffer() { return reinterpret_cast<std::byte *>(data_); }
|
||||
ssize_t size() const { return static_cast<ssize_t>(size_); }
|
||||
size_t total_bytes() const { return size_ * sizeof(T); }
|
||||
@@ -211,13 +212,30 @@ class NDArray : public ArrayExpr<NDArray<T, Ndim>, Ndim> {
|
||||
void Print_all();
|
||||
void Print_some();
|
||||
|
||||
template <ssize_t M = Ndim, typename = std::enable_if_t<(M > 2)>>
|
||||
NDArray<T, Ndim - 1> drop_dimension() && {
|
||||
|
||||
std::array<ssize_t, Ndim - 1> new_shape;
|
||||
|
||||
std::copy(shape_.begin() + 1, shape_.begin() + Ndim, new_shape.begin());
|
||||
|
||||
NDArray<T, Ndim - 1> new_array(new_shape);
|
||||
|
||||
delete new_array.data();
|
||||
|
||||
new_array.data_ref() = data_;
|
||||
|
||||
this->reset();
|
||||
|
||||
return new_array;
|
||||
}
|
||||
|
||||
void reset() {
|
||||
data_ = nullptr;
|
||||
size_ = 0;
|
||||
std::fill(shape_.begin(), shape_.end(), 0);
|
||||
std::fill(strides_.begin(), strides_.end(), 0);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Move assign
|
||||
@@ -382,8 +400,6 @@ NDArray<T, Ndim> NDArray<T, Ndim>::operator*(const T &value) {
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename T, ssize_t Ndim>
|
||||
std::ostream &operator<<(std::ostream &os, const NDArray<T, Ndim> &arr) {
|
||||
for (auto row = 0; row < arr.shape(0); ++row) {
|
||||
@@ -434,17 +450,18 @@ NDArray<T, Ndim> load(const std::string &pathname,
|
||||
return img;
|
||||
}
|
||||
|
||||
|
||||
template <typename RT, typename NT, typename DT, ssize_t Ndim>
|
||||
NDArray<RT, Ndim> safe_divide(const NDArray<NT, Ndim> &numerator,
|
||||
const NDArray<DT, Ndim> &denominator) {
|
||||
const NDArray<DT, Ndim> &denominator) {
|
||||
if (numerator.shape() != denominator.shape()) {
|
||||
throw std::runtime_error("Shapes of numerator and denominator must match");
|
||||
throw std::runtime_error(
|
||||
"Shapes of numerator and denominator must match");
|
||||
}
|
||||
NDArray<RT, Ndim> result(numerator.shape());
|
||||
for (ssize_t i = 0; i < numerator.size(); ++i) {
|
||||
if (denominator[i] != 0) {
|
||||
result[i] = static_cast<RT>(numerator[i]) / static_cast<RT>(denominator[i]);
|
||||
result[i] =
|
||||
static_cast<RT>(numerator[i]) / static_cast<RT>(denominator[i]);
|
||||
} else {
|
||||
result[i] = RT{0}; // or handle division by zero as needed
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ void apply_calibration_impl(NDView<T, 3> res, NDView<uint16_t, 3> raw_data,
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, ssize_t Ndim=3>
|
||||
template <class T, ssize_t Ndim = 3>
|
||||
void apply_calibration(NDView<T, 3> res, NDView<uint16_t, 3> raw_data,
|
||||
NDView<T, Ndim> ped, NDView<T, Ndim> cal,
|
||||
ssize_t n_threads = 4) {
|
||||
@@ -113,52 +113,44 @@ void apply_calibration(NDView<T, 3> res, NDView<uint16_t, 3> raw_data,
|
||||
for (const auto &lim : limits)
|
||||
futures.push_back(std::async(
|
||||
static_cast<void (*)(NDView<T, 3>, NDView<uint16_t, 3>,
|
||||
NDView<T, Ndim>, NDView<T, Ndim>, int,
|
||||
int)>(
|
||||
NDView<T, Ndim>, NDView<T, Ndim>, int, int)>(
|
||||
apply_calibration_impl),
|
||||
res, raw_data, ped, cal, lim.first, lim.second));
|
||||
for (auto &f : futures)
|
||||
f.get();
|
||||
}
|
||||
|
||||
|
||||
template <bool only_gain0>
|
||||
std::pair<NDArray<size_t, 3>, NDArray<size_t, 3>>
|
||||
sum_and_count_per_gain(NDView<uint16_t, 3> raw_data);
|
||||
|
||||
std::pair<NDArray<size_t, 2>, NDArray<size_t, 2>>
|
||||
sum_and_count_g0(NDView<uint16_t, 3> raw_data);
|
||||
|
||||
template <typename T>
|
||||
NDArray<T, 2> calculate_pedestal_g0(NDView<uint16_t, 3> raw_data,
|
||||
ssize_t n_threads) {
|
||||
std::vector<std::future<std::pair<NDArray<size_t, 2>, NDArray<size_t, 2>>>>
|
||||
futures;
|
||||
futures.reserve(n_threads);
|
||||
|
||||
auto subviews = make_subviews(raw_data, n_threads);
|
||||
|
||||
for (auto view : subviews) {
|
||||
futures.push_back(std::async(
|
||||
static_cast<std::pair<NDArray<size_t, 2>, NDArray<size_t, 2>> (*)(
|
||||
NDView<uint16_t, 3>)>(&sum_and_count_g0),
|
||||
view));
|
||||
}
|
||||
NDArray<size_t, 2> accumulator(
|
||||
std::array<ssize_t, 2>{raw_data.shape(1), raw_data.shape(2)}, 0);
|
||||
NDArray<size_t, 2> count(
|
||||
std::array<ssize_t, 2>{raw_data.shape(1), raw_data.shape(2)}, 0);
|
||||
for (auto &f : futures) {
|
||||
auto [acc, cnt] = f.get();
|
||||
accumulator += acc;
|
||||
count += cnt;
|
||||
sum_and_count_per_gain(NDView<uint16_t, 3> raw_data) {
|
||||
constexpr ssize_t num_gains = only_gain0 ? 1 : 3;
|
||||
NDArray<size_t, 3> accumulator(
|
||||
std::array<ssize_t, 3>{num_gains, raw_data.shape(1), raw_data.shape(2)},
|
||||
0);
|
||||
NDArray<size_t, 3> count(
|
||||
std::array<ssize_t, 3>{num_gains, raw_data.shape(1), raw_data.shape(2)},
|
||||
0);
|
||||
for (int frame_nr = 0; frame_nr != raw_data.shape(0); ++frame_nr) {
|
||||
for (int row = 0; row != raw_data.shape(1); ++row) {
|
||||
for (int col = 0; col != raw_data.shape(2); ++col) {
|
||||
auto [value, gain] =
|
||||
get_value_and_gain(raw_data(frame_nr, row, col));
|
||||
if (gain != 0 && only_gain0)
|
||||
continue;
|
||||
accumulator(gain, row, col) += value;
|
||||
count(gain, row, col) += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return safe_divide<T>(accumulator, count);
|
||||
return {std::move(accumulator), std::move(count)};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
NDArray<T, 3> calculate_pedestal(NDView<uint16_t, 3> raw_data,
|
||||
ssize_t n_threads) {
|
||||
template <typename T, bool only_gain0 = false>
|
||||
NDArray<T, 3 - static_cast<ssize_t>(only_gain0)>
|
||||
calculate_pedestal(NDView<uint16_t, 3> raw_data, ssize_t n_threads) {
|
||||
|
||||
constexpr ssize_t num_gains = only_gain0 ? 1 : 3;
|
||||
std::vector<std::future<std::pair<NDArray<size_t, 3>, NDArray<size_t, 3>>>>
|
||||
futures;
|
||||
futures.reserve(n_threads);
|
||||
@@ -168,21 +160,27 @@ NDArray<T, 3> calculate_pedestal(NDView<uint16_t, 3> raw_data,
|
||||
for (auto view : subviews) {
|
||||
futures.push_back(std::async(
|
||||
static_cast<std::pair<NDArray<size_t, 3>, NDArray<size_t, 3>> (*)(
|
||||
NDView<uint16_t, 3>)>(&sum_and_count_per_gain),
|
||||
NDView<uint16_t, 3>)>(&sum_and_count_per_gain<only_gain0>),
|
||||
view));
|
||||
}
|
||||
|
||||
NDArray<size_t, 3> accumulator(
|
||||
std::array<ssize_t, 3>{3, raw_data.shape(1), raw_data.shape(2)}, 0);
|
||||
std::array<ssize_t, 3>{num_gains, raw_data.shape(1), raw_data.shape(2)},
|
||||
0);
|
||||
NDArray<size_t, 3> count(
|
||||
std::array<ssize_t, 3>{3, raw_data.shape(1), raw_data.shape(2)}, 0);
|
||||
std::array<ssize_t, 3>{num_gains, raw_data.shape(1), raw_data.shape(2)},
|
||||
0);
|
||||
for (auto &f : futures) {
|
||||
auto [acc, cnt] = f.get();
|
||||
accumulator += acc;
|
||||
count += cnt;
|
||||
}
|
||||
|
||||
return safe_divide<T>(accumulator, count);
|
||||
if constexpr (only_gain0) {
|
||||
return safe_divide<T>(accumulator, count).drop_dimension();
|
||||
} else {
|
||||
return safe_divide<T>(accumulator, count);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -205,4 +203,9 @@ NDArray<int, 2> count_switching_pixels(NDView<uint16_t, 3> raw_data);
|
||||
NDArray<int, 2> count_switching_pixels(NDView<uint16_t, 3> raw_data,
|
||||
ssize_t n_threads);
|
||||
|
||||
template <typename T>
|
||||
auto calculate_pedestal_g0(NDView<uint16_t, 3> raw_data, ssize_t n_threads) {
|
||||
return calculate_pedestal<T, true>(raw_data, n_threads);
|
||||
}
|
||||
|
||||
} // namespace aare
|
||||
@@ -56,7 +56,7 @@ py::array_t<T> pybind_calculate_pedestal(
|
||||
|
||||
auto data_span = make_view_3d(data);
|
||||
auto arr = new NDArray<T, 3>{};
|
||||
*arr = aare::calculate_pedestal<T>(data_span, n_threads);
|
||||
*arr = aare::calculate_pedestal<T, false>(data_span, n_threads);
|
||||
return return_image_data(arr);
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ py::array_t<T> pybind_calculate_pedestal_g0(
|
||||
|
||||
auto data_span = make_view_3d(data);
|
||||
auto arr = new NDArray<T, 2>{};
|
||||
*arr = aare::calculate_pedestal_g0<T>(data_span, n_threads);
|
||||
*arr = aare::calculate_pedestal<T, true>(data_span, n_threads);
|
||||
return return_image_data(arr);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,46 +2,14 @@
|
||||
|
||||
namespace aare {
|
||||
|
||||
std::pair<NDArray<size_t, 3>, NDArray<size_t,3>> sum_and_count_per_gain(NDView<uint16_t,3> raw_data){
|
||||
NDArray<size_t, 3> accumulator(std::array<ssize_t, 3>{3, raw_data.shape(1), raw_data.shape(2)}, 0);
|
||||
NDArray<size_t, 3> count(std::array<ssize_t, 3>{3, raw_data.shape(1), raw_data.shape(2)}, 0);
|
||||
for (int frame_nr = 0; frame_nr != raw_data.shape(0); ++frame_nr) {
|
||||
for (int row = 0; row != raw_data.shape(1); ++row) {
|
||||
for (int col = 0; col != raw_data.shape(2); ++col) {
|
||||
auto [value, gain] = get_value_and_gain(raw_data(frame_nr, row, col));
|
||||
accumulator(gain, row, col) += value;
|
||||
count(gain, row, col) += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {std::move(accumulator), std::move(count)};
|
||||
}
|
||||
|
||||
std::pair<NDArray<size_t, 2>, NDArray<size_t,2>> sum_and_count_g0(NDView<uint16_t, 3> raw_data){
|
||||
NDArray<size_t, 2> accumulator(std::array<ssize_t, 2>{raw_data.shape(1), raw_data.shape(2)}, 0);
|
||||
NDArray<size_t, 2> count(std::array<ssize_t, 2>{raw_data.shape(1), raw_data.shape(2)}, 0);
|
||||
for (int frame_nr = 0; frame_nr != raw_data.shape(0); ++frame_nr) {
|
||||
for (int row = 0; row != raw_data.shape(1); ++row) {
|
||||
for (int col = 0; col != raw_data.shape(2); ++col) {
|
||||
auto [value, gain] = get_value_and_gain(raw_data(frame_nr, row, col));
|
||||
if (gain != 0)
|
||||
continue; // we only care about gain 0
|
||||
accumulator(row, col) += value;
|
||||
count(row, col) += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {std::move(accumulator), std::move(count)};
|
||||
}
|
||||
|
||||
NDArray<int, 2> count_switching_pixels(NDView<uint16_t, 3> raw_data) {
|
||||
NDArray<int, 2> switched(std::array<ssize_t, 2>{raw_data.shape(1), raw_data.shape(2)},0);
|
||||
NDArray<int, 2> switched(
|
||||
std::array<ssize_t, 2>{raw_data.shape(1), raw_data.shape(2)}, 0);
|
||||
for (int frame_nr = 0; frame_nr != raw_data.shape(0); ++frame_nr) {
|
||||
for (int row = 0; row != raw_data.shape(1); ++row) {
|
||||
for (int col = 0; col != raw_data.shape(2); ++col) {
|
||||
auto [value, gain] = get_value_and_gain(raw_data(frame_nr, row, col));
|
||||
auto [value, gain] =
|
||||
get_value_and_gain(raw_data(frame_nr, row, col));
|
||||
if (gain != 0) {
|
||||
switched(row, col) += 1;
|
||||
}
|
||||
@@ -51,22 +19,26 @@ NDArray<int, 2> count_switching_pixels(NDView<uint16_t, 3> raw_data) {
|
||||
return switched;
|
||||
}
|
||||
|
||||
|
||||
NDArray<int, 2> count_switching_pixels(NDView<uint16_t, 3> raw_data, ssize_t n_threads){
|
||||
NDArray<int, 2> switched(std::array<ssize_t, 2>{raw_data.shape(1), raw_data.shape(2)},0);
|
||||
NDArray<int, 2> count_switching_pixels(NDView<uint16_t, 3> raw_data,
|
||||
ssize_t n_threads) {
|
||||
NDArray<int, 2> switched(
|
||||
std::array<ssize_t, 2>{raw_data.shape(1), raw_data.shape(2)}, 0);
|
||||
std::vector<std::future<NDArray<int, 2>>> futures;
|
||||
futures.reserve(n_threads);
|
||||
|
||||
auto subviews = make_subviews(raw_data, n_threads);
|
||||
|
||||
for (auto view : subviews) {
|
||||
futures.push_back(std::async(static_cast<NDArray<int, 2>(*)(NDView<uint16_t, 3>)>(&count_switching_pixels), view));
|
||||
futures.push_back(
|
||||
std::async(static_cast<NDArray<int, 2> (*)(NDView<uint16_t, 3>)>(
|
||||
&count_switching_pixels),
|
||||
view));
|
||||
}
|
||||
|
||||
|
||||
for (auto &f : futures) {
|
||||
switched += f.get();
|
||||
}
|
||||
return switched;
|
||||
}
|
||||
|
||||
}// namespace aare
|
||||
} // namespace aare
|
||||
Reference in New Issue
Block a user