mirror of
https://github.com/slsdetectorgroup/aare.git
synced 2025-04-20 22:00:02 +02:00
ClusterFinder
This commit is contained in:
parent
5b2809d6b0
commit
cbfd1f0b6c
@ -5,3 +5,4 @@ Pedestal
|
||||
.. doxygenclass:: aare::Pedestal
|
||||
:members:
|
||||
:undoc-members:
|
||||
:private-members:
|
@ -3,33 +3,60 @@
|
||||
#include "aare/NDArray.hpp"
|
||||
#include "aare/NDView.hpp"
|
||||
#include "aare/Pedestal.hpp"
|
||||
#include "aare/defs.hpp"
|
||||
#include <cstddef>
|
||||
|
||||
namespace aare {
|
||||
|
||||
/** enum to define the event types */
|
||||
enum eventType {
|
||||
PEDESTAL, /** pedestal */
|
||||
NEIGHBOUR, /** neighbour i.e. below threshold, but in the cluster of a photon */
|
||||
PHOTON, /** photon i.e. above threshold */
|
||||
PHOTON_MAX, /** maximum of a cluster satisfying the photon conditions */
|
||||
NEGATIVE_PEDESTAL, /** negative value, will not be accounted for as pedestal in order to
|
||||
avoid drift of the pedestal towards negative values */
|
||||
PEDESTAL, /** pedestal */
|
||||
NEIGHBOUR, /** neighbour i.e. below threshold, but in the cluster of a
|
||||
photon */
|
||||
PHOTON, /** photon i.e. above threshold */
|
||||
PHOTON_MAX, /** maximum of a cluster satisfying the photon conditions */
|
||||
NEGATIVE_PEDESTAL, /** negative value, will not be accounted for as pedestal
|
||||
in order to avoid drift of the pedestal towards
|
||||
negative values */
|
||||
UNDEFINED_EVENT = -1 /** undefined */
|
||||
};
|
||||
|
||||
template <typename FRAME_TYPE = uint16_t, typename PEDESTAL_TYPE = double>
|
||||
class ClusterFinder {
|
||||
Shape<2> m_image_size;
|
||||
const int m_cluster_sizeX;
|
||||
const int m_cluster_sizeY;
|
||||
const double m_threshold;
|
||||
const double m_nSigma;
|
||||
const double c2;
|
||||
const double c3;
|
||||
Pedestal<PEDESTAL_TYPE> m_pedestal;
|
||||
|
||||
public:
|
||||
ClusterFinder(int cluster_sizeX, int cluster_sizeY, double nSigma = 5.0, double threshold = 0.0)
|
||||
: m_cluster_sizeX(cluster_sizeX), m_cluster_sizeY(cluster_sizeY), m_threshold(threshold), m_nSigma(nSigma) {
|
||||
ClusterFinder(Shape<2> image_size, Shape<2>cluster_size, double nSigma = 5.0,
|
||||
double threshold = 0.0)
|
||||
: m_image_size(image_size), m_cluster_sizeX(cluster_size[0]), m_cluster_sizeY(cluster_size[1]),
|
||||
m_threshold(threshold), m_nSigma(nSigma),
|
||||
c2(sqrt((m_cluster_sizeY + 1) / 2 * (m_cluster_sizeX + 1) / 2)),
|
||||
c3(sqrt(m_cluster_sizeX * m_cluster_sizeY)),
|
||||
m_pedestal(image_size[0], image_size[1]) {
|
||||
|
||||
c2 = sqrt((cluster_sizeY + 1) / 2 * (cluster_sizeX + 1) / 2);
|
||||
c3 = sqrt(cluster_sizeX * cluster_sizeY);
|
||||
};
|
||||
// c2 = sqrt((cluster_sizeY + 1) / 2 * (cluster_sizeX + 1) / 2);
|
||||
// c3 = sqrt(cluster_sizeX * cluster_sizeY);
|
||||
};
|
||||
|
||||
template <typename FRAME_TYPE, typename PEDESTAL_TYPE>
|
||||
std::vector<Cluster> find_clusters_without_threshold(NDView<FRAME_TYPE, 2> frame, Pedestal<PEDESTAL_TYPE> &pedestal,
|
||||
bool late_update = false) {
|
||||
void push_pedestal_frame(NDView<FRAME_TYPE, 2> frame) {
|
||||
m_pedestal.push(frame);
|
||||
}
|
||||
|
||||
NDArray<PEDESTAL_TYPE, 2> pedestal() {
|
||||
return m_pedestal.mean();
|
||||
}
|
||||
|
||||
std::vector<Cluster>
|
||||
find_clusters_without_threshold(NDView<FRAME_TYPE, 2> frame,
|
||||
// Pedestal<PEDESTAL_TYPE> &pedestal,
|
||||
bool late_update = false) {
|
||||
struct pedestal_update {
|
||||
int x;
|
||||
int y;
|
||||
@ -52,10 +79,14 @@ class ClusterFinder {
|
||||
long double total = 0;
|
||||
eventMask[iy][ix] = PEDESTAL;
|
||||
|
||||
for (short ir = -(m_cluster_sizeY / 2); ir < (m_cluster_sizeY / 2) + 1; ir++) {
|
||||
for (short ic = -(m_cluster_sizeX / 2); ic < (m_cluster_sizeX / 2) + 1; ic++) {
|
||||
if (ix + ic >= 0 && ix + ic < frame.shape(1) && iy + ir >= 0 && iy + ir < frame.shape(0)) {
|
||||
val = frame(iy + ir, ix + ic) - pedestal.mean(iy + ir, ix + ic);
|
||||
for (short ir = -(m_cluster_sizeY / 2);
|
||||
ir < (m_cluster_sizeY / 2) + 1; ir++) {
|
||||
for (short ic = -(m_cluster_sizeX / 2);
|
||||
ic < (m_cluster_sizeX / 2) + 1; ic++) {
|
||||
if (ix + ic >= 0 && ix + ic < frame.shape(1) &&
|
||||
iy + ir >= 0 && iy + ir < frame.shape(0)) {
|
||||
val = frame(iy + ir, ix + ic) -
|
||||
m_pedestal.mean(iy + ir, ix + ic);
|
||||
total += val;
|
||||
if (val > max) {
|
||||
max = val;
|
||||
@ -63,9 +94,9 @@ class ClusterFinder {
|
||||
}
|
||||
}
|
||||
}
|
||||
auto rms = pedestal.standard_deviation(iy, ix);
|
||||
auto rms = m_pedestal.std(iy, ix);
|
||||
|
||||
if (frame(iy, ix) - pedestal.mean(iy, ix) < -m_nSigma * rms) {
|
||||
if (frame(iy, ix) - m_pedestal.mean(iy, ix) < -m_nSigma * rms) {
|
||||
eventMask[iy][ix] = NEGATIVE_PEDESTAL;
|
||||
continue;
|
||||
} else if (max > m_nSigma * rms) {
|
||||
@ -73,26 +104,33 @@ class ClusterFinder {
|
||||
|
||||
} else if (total > c3 * m_nSigma * rms) {
|
||||
eventMask[iy][ix] = PHOTON;
|
||||
} else{
|
||||
} else {
|
||||
if (late_update) {
|
||||
pedestal_updates.push_back({ix, iy, frame(iy, ix)});
|
||||
} else {
|
||||
pedestal.push(iy, ix, frame(iy, ix));
|
||||
m_pedestal.push(iy, ix, frame(iy, ix));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (eventMask[iy][ix] == PHOTON && (frame(iy, ix) - pedestal.mean(iy, ix)) >= max) {
|
||||
if (eventMask[iy][ix] == PHOTON &&
|
||||
(frame(iy, ix) - m_pedestal.mean(iy, ix)) >= max) {
|
||||
eventMask[iy][ix] = PHOTON_MAX;
|
||||
Cluster cluster(m_cluster_sizeX, m_cluster_sizeY, Dtype(typeid(PEDESTAL_TYPE)));
|
||||
Cluster cluster(m_cluster_sizeX, m_cluster_sizeY,
|
||||
Dtype(typeid(PEDESTAL_TYPE)));
|
||||
cluster.x = ix;
|
||||
cluster.y = iy;
|
||||
short i = 0;
|
||||
|
||||
for (short ir = -(m_cluster_sizeY / 2); ir < (m_cluster_sizeY / 2) + 1; ir++) {
|
||||
for (short ic = -(m_cluster_sizeX / 2); ic < (m_cluster_sizeX / 2) + 1; ic++) {
|
||||
if (ix + ic >= 0 && ix + ic < frame.shape(1) && iy + ir >= 0 && iy + ir < frame.shape(0)) {
|
||||
PEDESTAL_TYPE tmp = static_cast<PEDESTAL_TYPE>(frame(iy + ir, ix + ic)) -
|
||||
pedestal.mean(iy + ir, ix + ic);
|
||||
for (short ir = -(m_cluster_sizeY / 2);
|
||||
ir < (m_cluster_sizeY / 2) + 1; ir++) {
|
||||
for (short ic = -(m_cluster_sizeX / 2);
|
||||
ic < (m_cluster_sizeX / 2) + 1; ic++) {
|
||||
if (ix + ic >= 0 && ix + ic < frame.shape(1) &&
|
||||
iy + ir >= 0 && iy + ir < frame.shape(0)) {
|
||||
PEDESTAL_TYPE tmp =
|
||||
static_cast<PEDESTAL_TYPE>(
|
||||
frame(iy + ir, ix + ic)) -
|
||||
m_pedestal.mean(iy + ir, ix + ic);
|
||||
cluster.set<PEDESTAL_TYPE>(i, tmp);
|
||||
i++;
|
||||
}
|
||||
@ -104,14 +142,16 @@ class ClusterFinder {
|
||||
}
|
||||
if (late_update) {
|
||||
for (auto &update : pedestal_updates) {
|
||||
pedestal.push(update.y, update.x, update.value);
|
||||
m_pedestal.push(update.y, update.x, update.value);
|
||||
}
|
||||
}
|
||||
return clusters;
|
||||
}
|
||||
|
||||
template <typename FRAME_TYPE, typename PEDESTAL_TYPE>
|
||||
std::vector<Cluster> find_clusters_with_threshold(NDView<FRAME_TYPE, 2> frame, Pedestal<PEDESTAL_TYPE> &pedestal) {
|
||||
// template <typename FRAME_TYPE, typename PEDESTAL_TYPE>
|
||||
std::vector<Cluster>
|
||||
find_clusters_with_threshold(NDView<FRAME_TYPE, 2> frame,
|
||||
Pedestal<PEDESTAL_TYPE> &pedestal) {
|
||||
assert(m_threshold > 0);
|
||||
std::vector<Cluster> clusters;
|
||||
std::vector<std::vector<eventType>> eventMask;
|
||||
@ -123,7 +163,8 @@ class ClusterFinder {
|
||||
NDArray<FRAME_TYPE, 2> rest({frame.shape(0), frame.shape(1)});
|
||||
NDArray<int, 2> nph({frame.shape(0), frame.shape(1)});
|
||||
// convert to n photons
|
||||
// nph = (frame-pedestal.mean()+0.5*m_threshold)/m_threshold; // can be optimized with expression templates?
|
||||
// nph = (frame-pedestal.mean()+0.5*m_threshold)/m_threshold; // can be
|
||||
// optimized with expression templates?
|
||||
for (int iy = 0; iy < frame.shape(0); iy++) {
|
||||
for (int ix = 0; ix < frame.shape(1); ix++) {
|
||||
auto val = frame(iy, ix) - pedestal.mean(iy, ix);
|
||||
@ -145,10 +186,14 @@ class ClusterFinder {
|
||||
}
|
||||
eventMask[iy][ix] = NEIGHBOUR;
|
||||
// iterate over cluster pixels around the current pixel (ix,iy)
|
||||
for (short ir = -(m_cluster_sizeY / 2); ir < (m_cluster_sizeY / 2) + 1; ir++) {
|
||||
for (short ic = -(m_cluster_sizeX / 2); ic < (m_cluster_sizeX / 2) + 1; ic++) {
|
||||
if (ix + ic >= 0 && ix + ic < frame.shape(1) && iy + ir >= 0 && iy + ir < frame.shape(0)) {
|
||||
auto val = frame(iy + ir, ix + ic) - pedestal.mean(iy + ir, ix + ic);
|
||||
for (short ir = -(m_cluster_sizeY / 2);
|
||||
ir < (m_cluster_sizeY / 2) + 1; ir++) {
|
||||
for (short ic = -(m_cluster_sizeX / 2);
|
||||
ic < (m_cluster_sizeX / 2) + 1; ic++) {
|
||||
if (ix + ic >= 0 && ix + ic < frame.shape(1) &&
|
||||
iy + ir >= 0 && iy + ir < frame.shape(0)) {
|
||||
auto val = frame(iy + ir, ix + ic) -
|
||||
pedestal.mean(iy + ir, ix + ic);
|
||||
total += val;
|
||||
if (val > max) {
|
||||
max = val;
|
||||
@ -157,7 +202,7 @@ class ClusterFinder {
|
||||
}
|
||||
}
|
||||
|
||||
auto rms = pedestal.standard_deviation(iy, ix);
|
||||
auto rms = pedestal.std(iy, ix);
|
||||
if (m_nSigma == 0) {
|
||||
tthr = m_threshold;
|
||||
tthr1 = m_threshold;
|
||||
@ -182,16 +227,22 @@ class ClusterFinder {
|
||||
pedestal.push(iy, ix, frame(iy, ix));
|
||||
continue;
|
||||
}
|
||||
if (eventMask[iy][ix] == PHOTON && frame(iy, ix) - pedestal.mean(iy, ix) >= max) {
|
||||
if (eventMask[iy][ix] == PHOTON &&
|
||||
frame(iy, ix) - pedestal.mean(iy, ix) >= max) {
|
||||
eventMask[iy][ix] = PHOTON_MAX;
|
||||
Cluster cluster(m_cluster_sizeX, m_cluster_sizeY, Dtype(typeid(FRAME_TYPE)));
|
||||
Cluster cluster(m_cluster_sizeX, m_cluster_sizeY,
|
||||
Dtype(typeid(FRAME_TYPE)));
|
||||
cluster.x = ix;
|
||||
cluster.y = iy;
|
||||
short i = 0;
|
||||
for (short ir = -(m_cluster_sizeY / 2); ir < (m_cluster_sizeY / 2) + 1; ir++) {
|
||||
for (short ic = -(m_cluster_sizeX / 2); ic < (m_cluster_sizeX / 2) + 1; ic++) {
|
||||
if (ix + ic >= 0 && ix + ic < frame.shape(1) && iy + ir >= 0 && iy + ir < frame.shape(0)) {
|
||||
auto tmp = frame(iy + ir, ix + ic) - pedestal.mean(iy + ir, ix + ic);
|
||||
for (short ir = -(m_cluster_sizeY / 2);
|
||||
ir < (m_cluster_sizeY / 2) + 1; ir++) {
|
||||
for (short ic = -(m_cluster_sizeX / 2);
|
||||
ic < (m_cluster_sizeX / 2) + 1; ic++) {
|
||||
if (ix + ic >= 0 && ix + ic < frame.shape(1) &&
|
||||
iy + ir >= 0 && iy + ir < frame.shape(0)) {
|
||||
auto tmp = frame(iy + ir, ix + ic) -
|
||||
pedestal.mean(iy + ir, ix + ic);
|
||||
cluster.set<FRAME_TYPE>(i, tmp);
|
||||
i++;
|
||||
}
|
||||
@ -203,14 +254,6 @@ class ClusterFinder {
|
||||
}
|
||||
return clusters;
|
||||
}
|
||||
|
||||
protected:
|
||||
int m_cluster_sizeX;
|
||||
int m_cluster_sizeY;
|
||||
double m_threshold;
|
||||
double m_nSigma;
|
||||
double c2;
|
||||
double c3;
|
||||
};
|
||||
|
||||
} // namespace aare
|
@ -6,11 +6,27 @@
|
||||
|
||||
namespace aare {
|
||||
|
||||
/**
|
||||
* @brief Calculate the pedestal of a series of frames. Can be used as
|
||||
* standalone but mostly used in the ClusterFinder.
|
||||
*
|
||||
* @tparam SUM_TYPE type of the sum
|
||||
*/
|
||||
template <typename SUM_TYPE = double> class Pedestal {
|
||||
uint32_t m_rows;
|
||||
uint32_t m_cols;
|
||||
|
||||
uint32_t m_samples;
|
||||
NDArray<uint32_t, 2> m_cur_samples;
|
||||
NDArray<SUM_TYPE, 2> m_sum;
|
||||
NDArray<SUM_TYPE, 2> m_sum2;
|
||||
|
||||
public:
|
||||
Pedestal(uint32_t rows, uint32_t cols, uint32_t n_samples = 1000)
|
||||
: m_rows(rows), m_cols(cols), m_freeze(false), m_samples(n_samples), m_cur_samples(NDArray<uint32_t, 2>({rows, cols}, 0)),m_sum(NDArray<SUM_TYPE, 2>({rows, cols})),
|
||||
m_sum2(NDArray<SUM_TYPE, 2>({rows, cols})) {
|
||||
: m_rows(rows), m_cols(cols), m_samples(n_samples),
|
||||
m_cur_samples(NDArray<uint32_t, 2>({rows, cols}, 0)),
|
||||
m_sum(NDArray<SUM_TYPE, 2>({rows, cols})),
|
||||
m_sum2(NDArray<SUM_TYPE, 2>({rows, cols})) {
|
||||
assert(rows > 0 && cols > 0 && n_samples > 0);
|
||||
m_sum = 0;
|
||||
m_sum2 = 0;
|
||||
@ -25,44 +41,51 @@ template <typename SUM_TYPE = double> class Pedestal {
|
||||
return mean_array;
|
||||
}
|
||||
|
||||
NDArray<SUM_TYPE, 2> variance() {
|
||||
NDArray<SUM_TYPE, 2> variance_array({m_rows, m_cols});
|
||||
for (uint32_t i = 0; i < m_rows * m_cols; i++) {
|
||||
variance_array(i / m_cols, i % m_cols) = variance(i / m_cols, i % m_cols);
|
||||
}
|
||||
return variance_array;
|
||||
}
|
||||
|
||||
NDArray<SUM_TYPE, 2> standard_deviation() {
|
||||
NDArray<SUM_TYPE, 2> standard_deviation_array({m_rows, m_cols});
|
||||
for (uint32_t i = 0; i < m_rows * m_cols; i++) {
|
||||
standard_deviation_array(i / m_cols, i % m_cols) = standard_deviation(i / m_cols, i % m_cols);
|
||||
}
|
||||
|
||||
return standard_deviation_array;
|
||||
}
|
||||
void clear() {
|
||||
for (uint32_t i = 0; i < m_rows * m_cols; i++) {
|
||||
clear(i / m_cols, i % m_cols);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* index level operations
|
||||
*/
|
||||
SUM_TYPE mean(const uint32_t row, const uint32_t col) const {
|
||||
if (m_cur_samples(row, col) == 0) {
|
||||
return 0.0;
|
||||
}
|
||||
return m_sum(row, col) / m_cur_samples(row, col);
|
||||
}
|
||||
|
||||
NDArray<SUM_TYPE, 2> variance() {
|
||||
NDArray<SUM_TYPE, 2> variance_array({m_rows, m_cols});
|
||||
for (uint32_t i = 0; i < m_rows * m_cols; i++) {
|
||||
variance_array(i / m_cols, i % m_cols) =
|
||||
variance(i / m_cols, i % m_cols);
|
||||
}
|
||||
return variance_array;
|
||||
}
|
||||
|
||||
SUM_TYPE variance(const uint32_t row, const uint32_t col) const {
|
||||
if (m_cur_samples(row, col) == 0) {
|
||||
return 0.0;
|
||||
}
|
||||
return m_sum2(row, col) / m_cur_samples(row, col) - mean(row, col) * mean(row, col);
|
||||
return m_sum2(row, col) / m_cur_samples(row, col) -
|
||||
mean(row, col) * mean(row, col);
|
||||
}
|
||||
SUM_TYPE standard_deviation(const uint32_t row, const uint32_t col) const { return std::sqrt(variance(row, col)); }
|
||||
|
||||
NDArray<SUM_TYPE, 2> std() {
|
||||
NDArray<SUM_TYPE, 2> standard_deviation_array({m_rows, m_cols});
|
||||
for (uint32_t i = 0; i < m_rows * m_cols; i++) {
|
||||
standard_deviation_array(i / m_cols, i % m_cols) =
|
||||
std(i / m_cols, i % m_cols);
|
||||
}
|
||||
|
||||
return standard_deviation_array;
|
||||
}
|
||||
|
||||
SUM_TYPE std(const uint32_t row, const uint32_t col) const {
|
||||
return std::sqrt(variance(row, col));
|
||||
}
|
||||
|
||||
void clear() {
|
||||
for (uint32_t i = 0; i < m_rows * m_cols; i++) {
|
||||
clear(i / m_cols, i % m_cols);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void clear(const uint32_t row, const uint32_t col) {
|
||||
m_sum(row, col) = 0;
|
||||
@ -72,29 +95,42 @@ template <typename SUM_TYPE = double> class Pedestal {
|
||||
// frame level operations
|
||||
template <typename T> void push(NDView<T, 2> frame) {
|
||||
assert(frame.size() == m_rows * m_cols);
|
||||
// TODO: test the effect of #pragma omp parallel for
|
||||
for (uint32_t index = 0; index < m_rows * m_cols; index++) {
|
||||
push<T>(index / m_cols, index % m_cols, frame(index));
|
||||
|
||||
// TODO! move away from m_rows, m_cols
|
||||
if (frame.shape() != std::array<int64_t, 2>{m_rows, m_cols}) {
|
||||
throw std::runtime_error(
|
||||
"Frame shape does not match pedestal shape");
|
||||
}
|
||||
|
||||
for (uint32_t row = 0; row < m_rows; row++) {
|
||||
for (uint32_t col = 0; col < m_cols; col++) {
|
||||
push<T>(row, col, frame(row, col));
|
||||
}
|
||||
}
|
||||
|
||||
// // TODO: test the effect of #pragma omp parallel for
|
||||
// for (uint32_t index = 0; index < m_rows * m_cols; index++) {
|
||||
// push<T>(index / m_cols, index % m_cols, frame(index));
|
||||
// }
|
||||
}
|
||||
template <typename T> void push(Frame &frame) {
|
||||
assert(frame.rows() == static_cast<size_t>(m_rows) && frame.cols() == static_cast<size_t>(m_cols));
|
||||
assert(frame.rows() == static_cast<size_t>(m_rows) &&
|
||||
frame.cols() == static_cast<size_t>(m_cols));
|
||||
push<T>(frame.view<T>());
|
||||
}
|
||||
|
||||
// getter functions
|
||||
inline uint32_t rows() const { return m_rows; }
|
||||
inline uint32_t cols() const { return m_cols; }
|
||||
inline uint32_t n_samples() const { return m_samples; }
|
||||
inline NDArray<uint32_t, 2> cur_samples() const { return m_cur_samples; }
|
||||
inline NDArray<SUM_TYPE, 2> get_sum() const { return m_sum; }
|
||||
inline NDArray<SUM_TYPE, 2> get_sum2() const { return m_sum2; }
|
||||
uint32_t rows() const { return m_rows; }
|
||||
uint32_t cols() const { return m_cols; }
|
||||
uint32_t n_samples() const { return m_samples; }
|
||||
NDArray<uint32_t, 2> cur_samples() const { return m_cur_samples; }
|
||||
NDArray<SUM_TYPE, 2> get_sum() const { return m_sum; }
|
||||
NDArray<SUM_TYPE, 2> get_sum2() const { return m_sum2; }
|
||||
|
||||
// pixel level operations (should be refactored to allow users to implement their own pixel level operations)
|
||||
template <typename T> inline void push(const uint32_t row, const uint32_t col, const T val_) {
|
||||
if (m_freeze) {
|
||||
return;
|
||||
}
|
||||
// pixel level operations (should be refactored to allow users to implement
|
||||
// their own pixel level operations)
|
||||
template <typename T>
|
||||
void push(const uint32_t row, const uint32_t col, const T val_) {
|
||||
SUM_TYPE val = static_cast<SUM_TYPE>(val_);
|
||||
const uint32_t idx = index(row, col);
|
||||
if (m_cur_samples(idx) < m_samples) {
|
||||
@ -106,16 +142,8 @@ template <typename SUM_TYPE = double> class Pedestal {
|
||||
m_sum2(idx) += val * val - m_sum2(idx) / m_cur_samples(idx);
|
||||
}
|
||||
}
|
||||
inline uint32_t index(const uint32_t row, const uint32_t col) const { return row * m_cols + col; };
|
||||
void set_freeze(bool freeze) { m_freeze = freeze; }
|
||||
|
||||
private:
|
||||
uint32_t m_rows;
|
||||
uint32_t m_cols;
|
||||
bool m_freeze;
|
||||
uint32_t m_samples;
|
||||
NDArray<uint32_t, 2> m_cur_samples;
|
||||
NDArray<SUM_TYPE, 2> m_sum;
|
||||
NDArray<SUM_TYPE, 2> m_sum2;
|
||||
uint32_t index(const uint32_t row, const uint32_t col) const {
|
||||
return row * m_cols + col;
|
||||
};
|
||||
};
|
||||
} // namespace aare
|
@ -2,4 +2,5 @@
|
||||
from . import _aare
|
||||
|
||||
from ._aare import VarClusterFinder, File, RawMasterFile
|
||||
from ._aare import Pedestal, ClusterFinder
|
||||
from .CtbRawFile import CtbRawFile
|
@ -27,5 +27,18 @@ fpath = Path('/Users/erik/data/Moench03old/test_034_irradiated_noise_g4_hg_expti
|
||||
# for header, image in f:
|
||||
# print(f'Frame number: {header["frameNumber"]}')
|
||||
|
||||
m = aare.RawMasterFile(fpath)
|
||||
# m = aare.RawMasterFile(fpath)
|
||||
f = aare.File(fpath)
|
||||
|
||||
|
||||
|
||||
cf = aare.ClusterFinder((400,400),(3,3))
|
||||
|
||||
for i in range(100):
|
||||
cf.push_pedestal_frame(f.read_frame())
|
||||
|
||||
|
||||
f.seek(0)
|
||||
pd = f.read_n(100).mean(axis=0)
|
||||
|
||||
clusters = cf.find_clusters_without_threshold(f.read_frame())
|
52
python/src/cluster.hpp
Normal file
52
python/src/cluster.hpp
Normal file
@ -0,0 +1,52 @@
|
||||
#include "aare/ClusterFinder.hpp"
|
||||
#include "aare/NDView.hpp"
|
||||
#include "aare/Pedestal.hpp"
|
||||
#include "np_helper.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <filesystem>
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h>
|
||||
|
||||
namespace py = pybind11;
|
||||
|
||||
void define_cluster_finder_bindings(py::module &m) {
|
||||
py::class_<ClusterFinder<uint16_t, double>>(m, "ClusterFinder")
|
||||
.def(py::init<Shape<2>, Shape<2>>())
|
||||
.def("push_pedestal_frame",
|
||||
[](ClusterFinder<uint16_t, double> &self,
|
||||
py::array_t<uint16_t> frame) {
|
||||
auto view = make_view_2d(frame);
|
||||
self.push_pedestal_frame(view);
|
||||
})
|
||||
.def("pedestal",
|
||||
[](ClusterFinder<uint16_t, double> &self) {
|
||||
auto m = new NDArray<double, 2>{};
|
||||
*m = self.pedestal();
|
||||
return return_image_data(m);
|
||||
})
|
||||
.def("find_clusters_without_threshold",
|
||||
[](ClusterFinder<uint16_t, double> &self,
|
||||
py::array_t<uint16_t> frame) {
|
||||
auto view = make_view_2d(frame);
|
||||
auto clusters = self.find_clusters_without_threshold(view);
|
||||
return clusters;
|
||||
});
|
||||
|
||||
py::class_<Cluster>(m, "Cluster", py::buffer_protocol())
|
||||
.def(py::init<int, int, Dtype>())
|
||||
.def("size", &Cluster::size)
|
||||
.def("begin", &Cluster::begin)
|
||||
.def("end", &Cluster::end)
|
||||
.def_readwrite("x", &Cluster::x)
|
||||
.def_readwrite("y", &Cluster::y)
|
||||
.def_buffer([](Cluster &c) -> py::buffer_info {
|
||||
return py::buffer_info(c.data(), c.dt.bytes(), c.dt.format_descr(),
|
||||
1, {c.size()}, {c.dt.bytes()});
|
||||
})
|
||||
|
||||
.def("__repr__", [](const Cluster &a) {
|
||||
return "<Cluster: x: " + std::to_string(a.x) +
|
||||
", y: " + std::to_string(a.y) + ">";
|
||||
});
|
||||
}
|
@ -2,6 +2,8 @@
|
||||
#include "file.hpp"
|
||||
#include "var_cluster.hpp"
|
||||
#include "pixel_map.hpp"
|
||||
#include "pedestal.hpp"
|
||||
#include "cluster.hpp"
|
||||
|
||||
//Pybind stuff
|
||||
#include <pybind11/pybind11.h>
|
||||
@ -13,4 +15,7 @@ PYBIND11_MODULE(_aare, m) {
|
||||
define_file_io_bindings(m);
|
||||
define_var_cluster_finder_bindings(m);
|
||||
define_pixel_map_bindings(m);
|
||||
define_pedestal_bindings<double>(m, "Pedestal");
|
||||
define_pedestal_bindings<float>(m, "Pedestal_float32");
|
||||
define_cluster_finder_bindings(m);
|
||||
}
|
47
python/src/pedestal.hpp
Normal file
47
python/src/pedestal.hpp
Normal file
@ -0,0 +1,47 @@
|
||||
|
||||
#include "aare/Pedestal.hpp"
|
||||
#include "np_helper.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <filesystem>
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h>
|
||||
|
||||
namespace py = pybind11;
|
||||
|
||||
template <typename SUM_TYPE> void define_pedestal_bindings(py::module &m, const std::string &name) {
|
||||
py::class_<Pedestal<SUM_TYPE>>(m, name.c_str())
|
||||
.def(py::init<int, int, int>())
|
||||
.def(py::init<int, int>())
|
||||
.def("mean",
|
||||
[](Pedestal<SUM_TYPE> &self) {
|
||||
auto m = new NDArray<SUM_TYPE, 2>{};
|
||||
*m = self.mean();
|
||||
return return_image_data(m);
|
||||
})
|
||||
.def("variance", [](Pedestal<SUM_TYPE> &self) {
|
||||
auto m = new NDArray<SUM_TYPE, 2>{};
|
||||
*m = self.variance();
|
||||
return return_image_data(m);
|
||||
})
|
||||
.def("std", [](Pedestal<SUM_TYPE> &self) {
|
||||
auto m = new NDArray<SUM_TYPE, 2>{};
|
||||
*m = self.std();
|
||||
return return_image_data(m);
|
||||
})
|
||||
.def("clear", py::overload_cast<>(&Pedestal<SUM_TYPE>::clear))
|
||||
.def_property_readonly("rows", &Pedestal<SUM_TYPE>::rows)
|
||||
.def_property_readonly("cols", &Pedestal<SUM_TYPE>::cols)
|
||||
.def_property_readonly("n_samples", &Pedestal<SUM_TYPE>::n_samples)
|
||||
.def_property_readonly("sum", &Pedestal<SUM_TYPE>::get_sum)
|
||||
.def_property_readonly("sum2", &Pedestal<SUM_TYPE>::get_sum2)
|
||||
.def("clone",
|
||||
[&](Pedestal<SUM_TYPE> &pedestal) {
|
||||
return Pedestal<SUM_TYPE>(pedestal);
|
||||
})
|
||||
//TODO! add push for other data types
|
||||
.def("push", [](Pedestal<SUM_TYPE> &pedestal, py::array_t<uint16_t> &f) {
|
||||
auto v = make_view_2d(f);
|
||||
pedestal.push(v);
|
||||
});
|
||||
}
|
@ -7,53 +7,65 @@
|
||||
|
||||
using namespace aare;
|
||||
|
||||
class ClusterFinderUnitTest : public ClusterFinder {
|
||||
public:
|
||||
ClusterFinderUnitTest(int cluster_sizeX, int cluster_sizeY, double nSigma = 5.0, double threshold = 0.0)
|
||||
: ClusterFinder(cluster_sizeX, cluster_sizeY, nSigma, threshold) {}
|
||||
double get_c2() { return c2; }
|
||||
double get_c3() { return c3; }
|
||||
auto get_threshold() { return m_threshold; }
|
||||
auto get_nSigma() { return m_nSigma; }
|
||||
auto get_cluster_sizeX() { return m_cluster_sizeX; }
|
||||
auto get_cluster_sizeY() { return m_cluster_sizeY; }
|
||||
};
|
||||
//TODO! Find a way to test the cluster finder
|
||||
|
||||
TEST_CASE("test ClusterFinder constructor") {
|
||||
ClusterFinderUnitTest cf(55, 100);
|
||||
REQUIRE(cf.get_cluster_sizeX() == 55);
|
||||
REQUIRE(cf.get_cluster_sizeY() == 100);
|
||||
REQUIRE(cf.get_threshold() == 0.0);
|
||||
REQUIRE(cf.get_nSigma() == 5.0);
|
||||
double c2 = sqrt((100 + 1) / 2 * (55 + 1) / 2);
|
||||
double c3 = sqrt(55 * 100);
|
||||
// REQUIRE(compare_floats<double>(cf.get_c2(), c2));
|
||||
// REQUIRE(compare_floats<double>(cf.get_c3(), c3));
|
||||
REQUIRE_THAT(cf.get_c2(), Catch::Matchers::WithinRel(c2, 1e-9));
|
||||
REQUIRE_THAT(cf.get_c3(), Catch::Matchers::WithinRel(c3, 1e-9));
|
||||
|
||||
|
||||
// class ClusterFinderUnitTest : public ClusterFinder {
|
||||
// public:
|
||||
// ClusterFinderUnitTest(int cluster_sizeX, int cluster_sizeY, double nSigma = 5.0, double threshold = 0.0)
|
||||
// : ClusterFinder(cluster_sizeX, cluster_sizeY, nSigma, threshold) {}
|
||||
// double get_c2() { return c2; }
|
||||
// double get_c3() { return c3; }
|
||||
// auto get_threshold() { return m_threshold; }
|
||||
// auto get_nSigma() { return m_nSigma; }
|
||||
// auto get_cluster_sizeX() { return m_cluster_sizeX; }
|
||||
// auto get_cluster_sizeY() { return m_cluster_sizeY; }
|
||||
// };
|
||||
|
||||
// TEST_CASE("test ClusterFinder constructor") {
|
||||
// ClusterFinderUnitTest cf(55, 100);
|
||||
// REQUIRE(cf.get_cluster_sizeX() == 55);
|
||||
// REQUIRE(cf.get_cluster_sizeY() == 100);
|
||||
// REQUIRE(cf.get_threshold() == 0.0);
|
||||
// REQUIRE(cf.get_nSigma() == 5.0);
|
||||
// double c2 = sqrt((100 + 1) / 2 * (55 + 1) / 2);
|
||||
// double c3 = sqrt(55 * 100);
|
||||
// // REQUIRE(compare_floats<double>(cf.get_c2(), c2));
|
||||
// // REQUIRE(compare_floats<double>(cf.get_c3(), c3));
|
||||
// REQUIRE_THAT(cf.get_c2(), Catch::Matchers::WithinRel(c2, 1e-9));
|
||||
// REQUIRE_THAT(cf.get_c3(), Catch::Matchers::WithinRel(c3, 1e-9));
|
||||
// }
|
||||
|
||||
TEST_CASE("Construct a cluster finder"){
|
||||
ClusterFinder clusterFinder({400,400}, {3,3});
|
||||
// REQUIRE(clusterFinder.get_cluster_sizeX() == 3);
|
||||
// REQUIRE(clusterFinder.get_cluster_sizeY() == 3);
|
||||
// REQUIRE(clusterFinder.get_threshold() == 1);
|
||||
// REQUIRE(clusterFinder.get_nSigma() == 1);
|
||||
}
|
||||
|
||||
TEST_CASE("test cluster finder") {
|
||||
aare::Pedestal pedestal(10, 10, 5);
|
||||
NDArray<double, 2> frame({10, 10});
|
||||
frame = 0;
|
||||
ClusterFinder clusterFinder(3, 3, 1, 1); // 3x3 cluster, 1 nSigma, 1 threshold
|
||||
// TEST_CASE("test cluster finder") {
|
||||
// aare::Pedestal pedestal(10, 10, 5);
|
||||
// NDArray<double, 2> frame({10, 10});
|
||||
// frame = 0;
|
||||
// ClusterFinder clusterFinder(3, 3, 1, 1); // 3x3 cluster, 1 nSigma, 1 threshold
|
||||
|
||||
auto clusters = clusterFinder.find_clusters_without_threshold(frame.span(), pedestal);
|
||||
// auto clusters = clusterFinder.find_clusters_without_threshold(frame.span(), pedestal);
|
||||
|
||||
REQUIRE(clusters.size() == 0);
|
||||
// REQUIRE(clusters.size() == 0);
|
||||
|
||||
frame(5, 5) = 10;
|
||||
clusters = clusterFinder.find_clusters_without_threshold(frame.span(), pedestal);
|
||||
REQUIRE(clusters.size() == 1);
|
||||
REQUIRE(clusters[0].x == 5);
|
||||
REQUIRE(clusters[0].y == 5);
|
||||
for (int i = 0; i < 3; i++) {
|
||||
for (int j = 0; j < 3; j++) {
|
||||
if (i == 1 && j == 1)
|
||||
REQUIRE(clusters[0].get<double>(i * 3 + j) == 10);
|
||||
else
|
||||
REQUIRE(clusters[0].get<double>(i * 3 + j) == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
// frame(5, 5) = 10;
|
||||
// clusters = clusterFinder.find_clusters_without_threshold(frame.span(), pedestal);
|
||||
// REQUIRE(clusters.size() == 1);
|
||||
// REQUIRE(clusters[0].x == 5);
|
||||
// REQUIRE(clusters[0].y == 5);
|
||||
// for (int i = 0; i < 3; i++) {
|
||||
// for (int j = 0; j < 3; j++) {
|
||||
// if (i == 1 && j == 1)
|
||||
// REQUIRE(clusters[0].get<double>(i * 3 + j) == 10);
|
||||
// else
|
||||
// REQUIRE(clusters[0].get<double>(i * 3 + j) == 0);
|
||||
// }
|
||||
// }
|
||||
// }
|
@ -66,7 +66,7 @@ TEST_CASE("test pedestal push") {
|
||||
}
|
||||
REQUIRE(pedestal.mean(i, j) == (i + j));
|
||||
REQUIRE(pedestal.variance(i, j) == 0);
|
||||
REQUIRE(pedestal.standard_deviation(i, j) == 0);
|
||||
REQUIRE(pedestal.std(i, j) == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -91,7 +91,7 @@ TEST_CASE("test pedestal with normal distribution") {
|
||||
}
|
||||
auto mean = pedestal.mean();
|
||||
auto variance = pedestal.variance();
|
||||
auto standard_deviation = pedestal.standard_deviation();
|
||||
auto standard_deviation = pedestal.std();
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
for (int j = 0; j < 5; j++) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user