mirror of
https://github.com/slsdetectorgroup/aare.git
synced 2026-02-19 20:48:40 +01:00
added g0 calibration, pedestal and pixel counting
This commit is contained in:
@@ -66,17 +66,28 @@ class NDView : public ArrayExpr<NDView<T, Ndim>, Ndim> {
|
||||
: buffer_(buffer), strides_(c_strides<Ndim>(shape)), shape_(shape),
|
||||
size_(std::accumulate(std::begin(shape), std::end(shape), 1,
|
||||
std::multiplies<>())) {}
|
||||
|
||||
|
||||
template <typename... Ix>
|
||||
std::enable_if_t<sizeof...(Ix) == Ndim, T &> operator()(Ix... index) {
|
||||
return buffer_[element_offset(strides_, index...)];
|
||||
}
|
||||
|
||||
template <typename... Ix>
|
||||
const std::enable_if_t<sizeof...(Ix) == Ndim, T &> operator()(Ix... index) const {
|
||||
std::enable_if_t<sizeof...(Ix) == 1 && (Ndim > 1), NDView<T, Ndim - 1>> operator()(Ix... index) {
|
||||
// return a view of the next dimension
|
||||
std::array<ssize_t, Ndim - 1> new_shape{};
|
||||
std::copy_n(shape_.begin() + 1, Ndim - 1, new_shape.begin());
|
||||
return NDView<T, Ndim - 1>(&buffer_[element_offset(strides_, index...)],
|
||||
new_shape);
|
||||
|
||||
}
|
||||
|
||||
template <typename... Ix>
|
||||
std::enable_if_t<sizeof...(Ix) == Ndim, const T &> operator()(Ix... index) const {
|
||||
return buffer_[element_offset(strides_, index...)];
|
||||
}
|
||||
|
||||
|
||||
ssize_t size() const { return static_cast<ssize_t>(size_); }
|
||||
size_t total_bytes() const { return size_ * sizeof(T); }
|
||||
std::array<ssize_t, Ndim> strides() const noexcept { return strides_; }
|
||||
@@ -85,9 +96,19 @@ class NDView : public ArrayExpr<NDView<T, Ndim>, Ndim> {
|
||||
T *end() { return buffer_ + size_; }
|
||||
T const *begin() const { return buffer_; }
|
||||
T const *end() const { return buffer_ + size_; }
|
||||
T &operator()(ssize_t i) { return buffer_[i]; }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Access element at index i.
|
||||
*/
|
||||
T &operator[](ssize_t i) { return buffer_[i]; }
|
||||
const T &operator()(ssize_t i) const { return buffer_[i]; }
|
||||
|
||||
/**
|
||||
* @brief Access element at index i.
|
||||
*/
|
||||
const T &operator[](ssize_t i) const { return buffer_[i]; }
|
||||
|
||||
bool operator==(const NDView &other) const {
|
||||
|
||||
@@ -240,14 +240,14 @@ template <typename T> void VarClusterFinder<T>::first_pass() {
|
||||
|
||||
for (ssize_t i = 0; i < original_.size(); ++i) {
|
||||
if (use_noise_map)
|
||||
threshold_ = 5 * noiseMap(i);
|
||||
binary_(i) = (original_(i) > threshold_);
|
||||
threshold_ = 5 * noiseMap[i];
|
||||
binary_[i] = (original_[i] > threshold_);
|
||||
}
|
||||
|
||||
for (int i = 0; i < shape_[0]; ++i) {
|
||||
for (int j = 0; j < shape_[1]; ++j) {
|
||||
|
||||
// do we have someting to process?
|
||||
// do we have something to process?
|
||||
if (binary_(i, j)) {
|
||||
auto tmp = check_neighbours(i, j);
|
||||
if (tmp != 0) {
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "aare/NDArray.hpp"
|
||||
#include "aare/NDView.hpp"
|
||||
#include "aare/defs.hpp"
|
||||
#include "aare/utils/task.hpp"
|
||||
#include <cstdint>
|
||||
@@ -55,32 +57,227 @@ ALWAYS_INLINE std::pair<uint16_t, int16_t> get_value_and_gain(uint16_t raw) {
|
||||
|
||||
template <class T>
|
||||
void apply_calibration_impl(NDView<T, 3> res, NDView<uint16_t, 3> raw_data,
|
||||
NDView<T, 3> ped, NDView<T, 3> cal, int start,
|
||||
int stop) {
|
||||
NDView<T, 3> ped, NDView<T, 3> cal, int start,
|
||||
int stop) {
|
||||
|
||||
for (int frame_nr = start; frame_nr != stop; ++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));
|
||||
|
||||
// Using multiplication does not seem to speed up the code here
|
||||
// ADU/keV is the standard unit for the calibration which
|
||||
// means rewriting the formula is not worth it.
|
||||
res(frame_nr, row, col) =
|
||||
(value - ped(gain, row, col)) / cal(gain, row, col); //TODO! use multiplication
|
||||
(value - ped(gain, row, col)) / cal(gain, row, col);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void apply_calibration_impl(NDView<T, 3> res, NDView<uint16_t, 3> raw_data,
|
||||
NDView<T, 2> ped, NDView<T, 2> cal, int start,
|
||||
int stop) {
|
||||
|
||||
for (int frame_nr = start; frame_nr != stop; ++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));
|
||||
|
||||
// Using multiplication does not seem to speed up the code here
|
||||
// ADU/keV is the standard unit for the calibration which
|
||||
// means rewriting the formula is not worth it.
|
||||
|
||||
// ignore anything that is not gain 0
|
||||
// TODO! deal with fixed gain?
|
||||
if (gain == 0)
|
||||
res(frame_nr, row, col) =
|
||||
(value - ped(row, col)) / cal(row, col);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, ssize_t Ndim=3>
|
||||
void apply_calibration(NDView<T, 3> res, NDView<uint16_t, 3> raw_data,
|
||||
NDView<T, 3> ped, NDView<T, 3> cal,
|
||||
NDView<T, Ndim> ped, NDView<T, Ndim> cal,
|
||||
ssize_t n_threads = 4) {
|
||||
std::vector<std::future<void>> futures;
|
||||
futures.reserve(n_threads);
|
||||
auto limits = split_task(0, raw_data.shape(0), n_threads);
|
||||
for (const auto &lim : limits)
|
||||
futures.push_back(std::async(&apply_calibration_impl<T>, res, raw_data, ped, cal,
|
||||
lim.first, lim.second));
|
||||
futures.push_back(std::async(
|
||||
static_cast<void (*)(NDView<T, 3>, NDView<uint16_t, 3>,
|
||||
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();
|
||||
}
|
||||
|
||||
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, 3> calculate_pedestal(NDView<uint16_t, 3> raw_data) {
|
||||
auto [accumulator, count] = sum_and_count_per_gain(raw_data);
|
||||
|
||||
NDArray<T, 3> pedestal(
|
||||
std::array<ssize_t, 3>{3, raw_data.shape(1), raw_data.shape(2)}, 0);
|
||||
for (int gain = 0; gain < 3; ++gain) {
|
||||
for (int row = 0; row < raw_data.shape(1); ++row) {
|
||||
for (int col = 0; col < raw_data.shape(2); ++col) {
|
||||
if (count(gain, row, col) != 0) {
|
||||
pedestal(gain, row, col) =
|
||||
static_cast<T>(accumulator(gain, row, col)) /
|
||||
static_cast<T>(count(gain, row, col));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return pedestal;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
NDArray<T, 2> calculate_pedestal_g0(NDView<uint16_t, 3> raw_data) {
|
||||
auto [accumulator, count] = sum_and_count_g0(raw_data);
|
||||
|
||||
NDArray<T, 2> pedestal(
|
||||
std::array<ssize_t, 2>{raw_data.shape(1), raw_data.shape(2)}, 0);
|
||||
for (int row = 0; row < raw_data.shape(1); ++row) {
|
||||
for (int col = 0; col < raw_data.shape(2); ++col) {
|
||||
if (count(row, col) != 0) {
|
||||
pedestal(row, col) =
|
||||
static_cast<T>(accumulator(row, col)) /
|
||||
static_cast<T>(count(row, col));
|
||||
}
|
||||
}
|
||||
}
|
||||
return pedestal;
|
||||
}
|
||||
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 limits = split_task(0, raw_data.shape(0), n_threads);
|
||||
// make subviews for each thread
|
||||
std::vector<NDView<uint16_t, 3>> subviews;
|
||||
for (const auto &lim : limits) {
|
||||
subviews.emplace_back(
|
||||
raw_data.data() + lim.first * raw_data.strides()[0],
|
||||
std::array<ssize_t, 3>{lim.second - lim.first, raw_data.shape(1),
|
||||
raw_data.shape(2)});
|
||||
}
|
||||
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;
|
||||
}
|
||||
NDArray<T, 2> pedestal(
|
||||
std::array<ssize_t,2>{raw_data.shape(1), raw_data.shape(2)}, 0);
|
||||
for (int gain = 0; gain < 3; ++gain) {
|
||||
for (int row = 0; row < raw_data.shape(1); ++row) {
|
||||
for (int col = 0; col < raw_data.shape(2); ++col) {
|
||||
if (count(row, col) != 0) {
|
||||
pedestal(row, col) =
|
||||
static_cast<T>(accumulator(row, col)) /
|
||||
static_cast<T>(count(row, col));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return pedestal;
|
||||
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
NDArray<T, 3> calculate_pedestal(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<std::pair<NDArray<size_t, 3>, NDArray<size_t, 3>>>>
|
||||
futures;
|
||||
futures.reserve(n_threads);
|
||||
auto limits = split_task(0, raw_data.shape(0), n_threads);
|
||||
|
||||
// make subviews for each thread
|
||||
std::vector<NDView<uint16_t, 3>> subviews;
|
||||
for (const auto &lim : limits) {
|
||||
subviews.emplace_back(
|
||||
raw_data.data() + lim.first * raw_data.strides()[0],
|
||||
std::array<ssize_t, 3>{lim.second - lim.first, raw_data.shape(1),
|
||||
raw_data.shape(2)});
|
||||
}
|
||||
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),
|
||||
view));
|
||||
}
|
||||
|
||||
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 (auto &f : futures) {
|
||||
auto [acc, cnt] = f.get();
|
||||
accumulator += acc;
|
||||
count += cnt;
|
||||
}
|
||||
|
||||
NDArray<T, 3> pedestal(
|
||||
std::array<ssize_t, 3>{3, raw_data.shape(1), raw_data.shape(2)}, 0);
|
||||
for (int gain = 0; gain < 3; ++gain) {
|
||||
for (int row = 0; row < raw_data.shape(1); ++row) {
|
||||
for (int col = 0; col < raw_data.shape(2); ++col) {
|
||||
if (count(gain, row, col) != 0) {
|
||||
pedestal(gain, row, col) =
|
||||
static_cast<T>(accumulator(gain, row, col)) /
|
||||
static_cast<T>(count(gain, row, col));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return pedestal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Count the number of switching pixels in the raw data.
|
||||
* This function counts the number of pixels that switch between G1 and G2 gain.
|
||||
* It returns an NDArray with the number of switching pixels per pixel.
|
||||
* @param raw_data The NDView containing the raw data
|
||||
* @return An NDArray with the number of switching pixels per pixel
|
||||
*/
|
||||
NDArray<int, 2> count_switching_pixels(NDView<uint16_t, 3> raw_data);
|
||||
|
||||
/**
|
||||
* @brief Count the number of switching pixels in the raw data.
|
||||
* This function counts the number of pixels that switch between G1 and G2 gain.
|
||||
* It returns an NDArray with the number of switching pixels per pixel.
|
||||
* @param raw_data The NDView containing the raw data
|
||||
* @param n_threads The number of threads to use for parallel processing
|
||||
* @return An NDArray with the number of switching pixels per pixel
|
||||
*/
|
||||
NDArray<int, 2> count_switching_pixels(NDView<uint16_t, 3> raw_data,
|
||||
ssize_t n_threads);
|
||||
|
||||
} // namespace aare
|
||||
Reference in New Issue
Block a user