mirror of
https://github.com/slsdetectorgroup/aare.git
synced 2025-12-21 12:31:25 +01:00
Compare commits
10 Commits
dev/py314
...
dev/highz/
| Author | SHA1 | Date | |
|---|---|---|---|
| 1b8657c524 | |||
| de1fd62e66 | |||
| 6b894a5083 | |||
| faaa831238 | |||
| 12498dacaa | |||
| 7ea20c6b9d | |||
| 29a2374446 | |||
| efb16ea8c1 | |||
| 7aa3fcfcd0 | |||
| 836dddbc26 |
152
include/aare/ChunkedPedestal.hpp
Normal file
152
include/aare/ChunkedPedestal.hpp
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "aare/Frame.hpp"
|
||||||
|
#include "aare/NDArray.hpp"
|
||||||
|
#include "aare/NDView.hpp"
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
//JMulvey
|
||||||
|
//This is a new way to do pedestals (inspired by Dominic's cluster finder)
|
||||||
|
//Instead of pedestal tracking, we split the data (photon data) up into chunks (say 50K frames)
|
||||||
|
//For each chunk, we look at the spectra and fit to the noise peak. When we run the cluster finder, we then use this chunked pedestal data
|
||||||
|
//The smaller the chunk size, the more accurate, but also the longer it takes to process.
|
||||||
|
//It is essentially a pre-processing step.
|
||||||
|
//Ideally this new class will do that processing.
|
||||||
|
//But for now we will just implement a method to pass in the chunked pedestal values directly (I have my own script which does it for now)
|
||||||
|
//I've cut this down a lot, knowing full well it'll need changing if we want to merge it with main (happy to do that once I get it work for what I need)
|
||||||
|
|
||||||
|
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 ChunkedPedestal {
|
||||||
|
uint32_t m_rows;
|
||||||
|
uint32_t m_cols;
|
||||||
|
uint32_t m_n_chunks;
|
||||||
|
uint64_t m_current_frame_number;
|
||||||
|
uint64_t m_current_chunk_number;
|
||||||
|
|
||||||
|
NDArray<SUM_TYPE, 3> m_mean;
|
||||||
|
NDArray<SUM_TYPE, 3> m_std;
|
||||||
|
uint32_t m_chunk_size;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ChunkedPedestal(uint32_t rows, uint32_t cols, uint32_t chunk_size = 50000, uint32_t n_chunks = 10)
|
||||||
|
: m_rows(rows), m_cols(cols), m_chunk_size(chunk_size), m_n_chunks(n_chunks),
|
||||||
|
m_mean(NDArray<SUM_TYPE, 3>({n_chunks, rows, cols})), m_std(NDArray<SUM_TYPE, 3>({n_chunks, rows, cols})) {
|
||||||
|
assert(rows > 0 && cols > 0 && chunk_size > 0);
|
||||||
|
m_mean = 0;
|
||||||
|
m_std = 0;
|
||||||
|
m_current_frame_number = 0;
|
||||||
|
m_current_chunk_number = 0;
|
||||||
|
}
|
||||||
|
~ChunkedPedestal() = default;
|
||||||
|
|
||||||
|
NDArray<SUM_TYPE, 3> mean() { return m_mean; }
|
||||||
|
NDArray<SUM_TYPE, 3> std() { return m_std; }
|
||||||
|
|
||||||
|
void set_frame_number (uint64_t frame_number) {
|
||||||
|
m_current_frame_number = frame_number;
|
||||||
|
m_current_chunk_number = std::floor(frame_number / m_chunk_size);
|
||||||
|
|
||||||
|
//Debug
|
||||||
|
// if (frame_number % 10000 == 0)
|
||||||
|
// {
|
||||||
|
// std::cout << "frame_number: " << frame_number << " -> chunk_number: " << m_current_chunk_number << " pedestal at (100, 100): " << m_mean(m_current_chunk_number, 100, 100) << std::endl;
|
||||||
|
// }
|
||||||
|
|
||||||
|
if (m_current_chunk_number >= m_n_chunks)
|
||||||
|
{
|
||||||
|
m_current_chunk_number = 0;
|
||||||
|
throw std::runtime_error(
|
||||||
|
"Chunk number exceeds the number of chunks");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SUM_TYPE mean(const uint32_t row, const uint32_t col) const {
|
||||||
|
return m_mean(m_current_chunk_number, row, col);
|
||||||
|
}
|
||||||
|
|
||||||
|
SUM_TYPE std(const uint32_t row, const uint32_t col) const {
|
||||||
|
return m_std(m_current_chunk_number, row, col);
|
||||||
|
}
|
||||||
|
|
||||||
|
SUM_TYPE* get_mean_chunk_ptr() {
|
||||||
|
return &m_mean(m_current_chunk_number, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
SUM_TYPE* get_std_chunk_ptr() {
|
||||||
|
return &m_std(m_current_chunk_number, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear() {
|
||||||
|
m_mean = 0;
|
||||||
|
m_std = 0;
|
||||||
|
m_n_chunks = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Probably don't need to do this one at a time, but let's keep it simple for now
|
||||||
|
template <typename T> void push_mean(NDView<T, 2> frame, uint32_t chunk_number) {
|
||||||
|
assert(frame.size() == m_rows * m_cols);
|
||||||
|
|
||||||
|
if (chunk_number >= m_n_chunks)
|
||||||
|
throw std::runtime_error(
|
||||||
|
"Chunk number is larger than the number of chunks");
|
||||||
|
|
||||||
|
// TODO! move away from m_rows, m_cols
|
||||||
|
if (frame.shape() != std::array<ssize_t, 2>{m_rows, m_cols}) {
|
||||||
|
throw std::runtime_error(
|
||||||
|
"Frame shape does not match pedestal shape");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t row = 0; row < m_rows; row++) {
|
||||||
|
for (size_t col = 0; col < m_cols; col++) {
|
||||||
|
push_mean<T>(row, col, chunk_number, frame(row, col));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> void push_std(NDView<T, 2> frame, uint32_t chunk_number) {
|
||||||
|
assert(frame.size() == m_rows * m_cols);
|
||||||
|
|
||||||
|
if (chunk_number >= m_n_chunks)
|
||||||
|
throw std::runtime_error(
|
||||||
|
"Chunk number is larger than the number of chunks");
|
||||||
|
|
||||||
|
// TODO! move away from m_rows, m_cols
|
||||||
|
if (frame.shape() != std::array<ssize_t, 2>{m_rows, m_cols}) {
|
||||||
|
throw std::runtime_error(
|
||||||
|
"Frame shape does not match pedestal shape");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t row = 0; row < m_rows; row++) {
|
||||||
|
for (size_t col = 0; col < m_cols; col++) {
|
||||||
|
push_std<T>(row, col, chunk_number, frame(row, col));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// pixel level operations (should be refactored to allow users to implement
|
||||||
|
// their own pixel level operations)
|
||||||
|
template <typename T>
|
||||||
|
void push_mean(const uint32_t row, const uint32_t col, const uint32_t chunk_number, const T val_) {
|
||||||
|
m_mean(chunk_number, row, col) = val_;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void push_std(const uint32_t row, const uint32_t col, const uint32_t chunk_number, const T val_) {
|
||||||
|
m_std(chunk_number, row, col) = val_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// getter functions
|
||||||
|
uint32_t rows() const { return m_rows; }
|
||||||
|
uint32_t cols() const { return m_cols; }
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace aare
|
||||||
@@ -4,9 +4,11 @@
|
|||||||
#include "aare/Dtype.hpp"
|
#include "aare/Dtype.hpp"
|
||||||
#include "aare/NDArray.hpp"
|
#include "aare/NDArray.hpp"
|
||||||
#include "aare/NDView.hpp"
|
#include "aare/NDView.hpp"
|
||||||
#include "aare/Pedestal.hpp"
|
// #include "aare/Pedestal.hpp"
|
||||||
|
#include "aare/ChunkedPedestal.hpp"
|
||||||
#include "aare/defs.hpp"
|
#include "aare/defs.hpp"
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
namespace aare {
|
namespace aare {
|
||||||
|
|
||||||
@@ -17,11 +19,13 @@ class ClusterFinder {
|
|||||||
const PEDESTAL_TYPE m_nSigma;
|
const PEDESTAL_TYPE m_nSigma;
|
||||||
const PEDESTAL_TYPE c2;
|
const PEDESTAL_TYPE c2;
|
||||||
const PEDESTAL_TYPE c3;
|
const PEDESTAL_TYPE c3;
|
||||||
Pedestal<PEDESTAL_TYPE> m_pedestal;
|
ChunkedPedestal<PEDESTAL_TYPE> m_pedestal;
|
||||||
ClusterVector<ClusterType> m_clusters;
|
ClusterVector<ClusterType> m_clusters;
|
||||||
|
const uint32_t ClusterSizeX;
|
||||||
|
const uint32_t ClusterSizeY;
|
||||||
|
|
||||||
static const uint8_t ClusterSizeX = ClusterType::cluster_size_x;
|
static const uint8_t SavedClusterSizeX = ClusterType::cluster_size_x;
|
||||||
static const uint8_t ClusterSizeY = ClusterType::cluster_size_y;
|
static const uint8_t SavedClusterSizeY = ClusterType::cluster_size_y;
|
||||||
using CT = typename ClusterType::value_type;
|
using CT = typename ClusterType::value_type;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -34,19 +38,30 @@ class ClusterFinder {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
ClusterFinder(Shape<2> image_size, PEDESTAL_TYPE nSigma = 5.0,
|
ClusterFinder(Shape<2> image_size, PEDESTAL_TYPE nSigma = 5.0,
|
||||||
size_t capacity = 1000000)
|
size_t capacity = 1000000,
|
||||||
|
uint32_t chunk_size = 50000, uint32_t n_chunks = 10,
|
||||||
|
uint32_t cluster_size_x = 3, uint32_t cluster_size_y = 3)
|
||||||
: m_image_size(image_size), m_nSigma(nSigma),
|
: m_image_size(image_size), m_nSigma(nSigma),
|
||||||
c2(sqrt((ClusterSizeY + 1) / 2 * (ClusterSizeX + 1) / 2)),
|
c2(sqrt((cluster_size_y + 1) / 2 * (cluster_size_x + 1) / 2)),
|
||||||
c3(sqrt(ClusterSizeX * ClusterSizeY)),
|
c3(sqrt(cluster_size_x * cluster_size_y)),
|
||||||
m_pedestal(image_size[0], image_size[1]), m_clusters(capacity) {
|
ClusterSizeX(cluster_size_x), ClusterSizeY(cluster_size_y),
|
||||||
|
m_pedestal(image_size[0], image_size[1], chunk_size, n_chunks), m_clusters(capacity) {
|
||||||
LOG(logDEBUG) << "ClusterFinder: "
|
LOG(logDEBUG) << "ClusterFinder: "
|
||||||
<< "image_size: " << image_size[0] << "x" << image_size[1]
|
<< "image_size: " << image_size[0] << "x" << image_size[1]
|
||||||
<< ", nSigma: " << nSigma << ", capacity: " << capacity;
|
<< ", nSigma: " << nSigma << ", capacity: " << capacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
void push_pedestal_frame(NDView<FRAME_TYPE, 2> frame) {
|
// void push_pedestal_frame(NDView<FRAME_TYPE, 2> frame) {
|
||||||
m_pedestal.push(frame);
|
// m_pedestal.push(frame);
|
||||||
|
// }
|
||||||
|
void push_pedestal_mean(NDView<PEDESTAL_TYPE, 2> frame, uint32_t chunk_number) {
|
||||||
|
m_pedestal.push_mean(frame, chunk_number);
|
||||||
}
|
}
|
||||||
|
void push_pedestal_std(NDView<PEDESTAL_TYPE, 2> frame, uint32_t chunk_number) {
|
||||||
|
m_pedestal.push_std(frame, chunk_number);
|
||||||
|
}
|
||||||
|
//This is here purely to keep the compiler happy for now
|
||||||
|
void push_pedestal_frame(NDView<FRAME_TYPE, 2> frame) {}
|
||||||
|
|
||||||
NDArray<PEDESTAL_TYPE, 2> pedestal() { return m_pedestal.mean(); }
|
NDArray<PEDESTAL_TYPE, 2> pedestal() { return m_pedestal.mean(); }
|
||||||
NDArray<PEDESTAL_TYPE, 2> noise() { return m_pedestal.std(); }
|
NDArray<PEDESTAL_TYPE, 2> noise() { return m_pedestal.std(); }
|
||||||
@@ -69,11 +84,13 @@ class ClusterFinder {
|
|||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
void find_clusters(NDView<FRAME_TYPE, 2> frame, uint64_t frame_number = 0) {
|
void find_clusters(NDView<FRAME_TYPE, 2> frame, uint64_t frame_number = 0) {
|
||||||
// // TODO! deal with even size clusters
|
|
||||||
// // currently 3,3 -> +/- 1
|
// // currently 3,3 -> +/- 1
|
||||||
// // 4,4 -> +/- 2
|
// // 4,4 -> +/- 2
|
||||||
int dy = ClusterSizeY / 2;
|
int dy = ClusterSizeY / 2;
|
||||||
int dx = ClusterSizeX / 2;
|
int dx = ClusterSizeX / 2;
|
||||||
|
int dy2 = SavedClusterSizeY / 2;
|
||||||
|
int dx2 = SavedClusterSizeX / 2;
|
||||||
|
|
||||||
int has_center_pixel_x =
|
int has_center_pixel_x =
|
||||||
ClusterSizeX %
|
ClusterSizeX %
|
||||||
2; // for even sized clusters there is no proper cluster center and
|
2; // for even sized clusters there is no proper cluster center and
|
||||||
@@ -81,27 +98,39 @@ class ClusterFinder {
|
|||||||
int has_center_pixel_y = ClusterSizeY % 2;
|
int has_center_pixel_y = ClusterSizeY % 2;
|
||||||
|
|
||||||
m_clusters.set_frame_number(frame_number);
|
m_clusters.set_frame_number(frame_number);
|
||||||
|
m_pedestal.set_frame_number(frame_number);
|
||||||
|
auto mean_ptr = m_pedestal.get_mean_chunk_ptr();
|
||||||
|
auto std_ptr = m_pedestal.get_std_chunk_ptr();
|
||||||
|
|
||||||
for (int iy = 0; iy < frame.shape(0); iy++) {
|
for (int iy = 0; iy < frame.shape(0); iy++) {
|
||||||
|
size_t row_offset = iy * frame.shape(1);
|
||||||
for (int ix = 0; ix < frame.shape(1); ix++) {
|
for (int ix = 0; ix < frame.shape(1); ix++) {
|
||||||
|
|
||||||
|
// PEDESTAL_TYPE rms = m_pedestal.std(iy, ix);
|
||||||
|
PEDESTAL_TYPE rms = std_ptr[row_offset + ix];
|
||||||
|
if (rms == 0) continue;
|
||||||
|
|
||||||
PEDESTAL_TYPE max = std::numeric_limits<FRAME_TYPE>::min();
|
PEDESTAL_TYPE max = std::numeric_limits<FRAME_TYPE>::min();
|
||||||
PEDESTAL_TYPE total = 0;
|
PEDESTAL_TYPE total = 0;
|
||||||
|
|
||||||
// What can we short circuit here?
|
// What can we short circuit here?
|
||||||
PEDESTAL_TYPE rms = m_pedestal.std(iy, ix);
|
// PEDESTAL_TYPE value = (frame(iy, ix) - m_pedestal.mean(iy, ix));
|
||||||
PEDESTAL_TYPE value = (frame(iy, ix) - m_pedestal.mean(iy, ix));
|
PEDESTAL_TYPE value = (frame(iy, ix) - mean_ptr[row_offset + ix]);
|
||||||
|
|
||||||
if (value < -m_nSigma * rms)
|
if (value < -m_nSigma * rms)
|
||||||
continue; // NEGATIVE_PEDESTAL go to next pixel
|
continue; // NEGATIVE_PEDESTAL go to next pixel
|
||||||
// TODO! No pedestal update???
|
// TODO! No pedestal update???
|
||||||
|
|
||||||
for (int ir = -dy; ir < dy + has_center_pixel_y; ir++) {
|
for (int ir = -dy; ir < dy + has_center_pixel_y; ir++) {
|
||||||
|
size_t inner_row_offset = row_offset + (ir * frame.shape(1));
|
||||||
for (int ic = -dx; ic < dx + has_center_pixel_x; ic++) {
|
for (int ic = -dx; ic < dx + has_center_pixel_x; ic++) {
|
||||||
if (ix + ic >= 0 && ix + ic < frame.shape(1) &&
|
if (ix + ic >= 0 && ix + ic < frame.shape(1) &&
|
||||||
iy + ir >= 0 && iy + ir < frame.shape(0)) {
|
iy + ir >= 0 && iy + ir < frame.shape(0)) {
|
||||||
PEDESTAL_TYPE val =
|
// if (m_pedestal.std(iy + ir, ix + ic) == 0) continue;
|
||||||
frame(iy + ir, ix + ic) -
|
if (std_ptr[inner_row_offset + ix + ic] == 0) continue;
|
||||||
m_pedestal.mean(iy + ir, ix + ic);
|
|
||||||
|
// PEDESTAL_TYPE val = frame(iy + ir, ix + ic) - m_pedestal.mean(iy + ir, ix + ic);
|
||||||
|
PEDESTAL_TYPE val = frame(iy + ir, ix + ic) - mean_ptr[inner_row_offset + ix + ic];
|
||||||
|
|
||||||
total += val;
|
total += val;
|
||||||
max = std::max(max, val);
|
max = std::max(max, val);
|
||||||
@@ -109,24 +138,64 @@ class ClusterFinder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((max > m_nSigma * rms)) {
|
// if (frame_number < 1)
|
||||||
if (value < max)
|
// if ( (ix == 115 && iy == 122) )
|
||||||
continue; // Not max go to the next pixel
|
// if ( (ix == 175 && iy == 175) )
|
||||||
// but also no pedestal update
|
// {
|
||||||
} else if (total > c3 * m_nSigma * rms) {
|
// // std::cout << std::endl;
|
||||||
|
// // std::cout << std::endl;
|
||||||
|
// // std::cout << "frame_number: " << frame_number << std::endl;
|
||||||
|
// // std::cout << "(" << ix << ", " << iy << "): " << std::endl;
|
||||||
|
// // std::cout << "frame.shape: (" << frame.shape(0) << ", " << frame.shape(1) << "): " << std::endl;
|
||||||
|
// // std::cout << "frame(175, 175): " << frame(175, 175) << std::endl;
|
||||||
|
// // std::cout << "frame(77, 98): " << frame(77, 98) << std::endl;
|
||||||
|
// // std::cout << "frame(82, 100): " << frame(82, 100) << std::endl;
|
||||||
|
// // std::cout << "frame(iy, ix): " << frame(iy, ix) << std::endl;
|
||||||
|
// // std::cout << "mean_ptr[row_offset + ix]: " << mean_ptr[row_offset + ix] << std::endl;
|
||||||
|
// // std::cout << "total: " << total << std::endl;
|
||||||
|
|
||||||
|
// std::cout << "(" << ix << ", " << iy << "): " << frame(iy, ix) << std::endl;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if ((max > m_nSigma * rms)) {
|
||||||
|
// if (value < max)
|
||||||
|
// continue; // Not max go to the next pixel
|
||||||
|
// // but also no pedestal update
|
||||||
|
// } else
|
||||||
|
if (total > c3 * m_nSigma * rms) {
|
||||||
// pass
|
// pass
|
||||||
} else {
|
} else {
|
||||||
// m_pedestal.push(iy, ix, frame(iy, ix)); // Safe option
|
// m_pedestal.push(iy, ix, frame(iy, ix)); // Safe option
|
||||||
m_pedestal.push_fast(
|
|
||||||
iy, ix,
|
//Not needed for chunked pedestal
|
||||||
frame(iy,
|
// m_pedestal.push_fast(
|
||||||
ix)); // Assume we have reached n_samples in the
|
// iy, ix,
|
||||||
// pedestal, slight performance improvement
|
// frame(iy,
|
||||||
|
// ix)); // Assume we have reached n_samples in the
|
||||||
|
// // pedestal, slight performance improvement
|
||||||
continue; // It was a pedestal value nothing to store
|
continue; // It was a pedestal value nothing to store
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store cluster
|
// Store cluster
|
||||||
if (value == max) {
|
if (value == max) {
|
||||||
|
|
||||||
|
// if (total < 0)
|
||||||
|
// {
|
||||||
|
// std::cout << "" << std::endl;
|
||||||
|
// std::cout << "frame_number: " << frame_number << std::endl;
|
||||||
|
// std::cout << "ix: " << ix << std::endl;
|
||||||
|
// std::cout << "iy: " << iy << std::endl;
|
||||||
|
// std::cout << "frame(iy, ix): " << frame(iy, ix) << std::endl;
|
||||||
|
// std::cout << "m_pedestal.mean(iy, ix): " << m_pedestal.mean(iy, ix) << std::endl;
|
||||||
|
// std::cout << "m_pedestal.std(iy, ix): " << m_pedestal.std(iy, ix) << std::endl;
|
||||||
|
// std::cout << "max: " << max << std::endl;
|
||||||
|
// std::cout << "value: " << value << std::endl;
|
||||||
|
// std::cout << "m_nSigma * rms: " << (m_nSigma * rms) << std::endl;
|
||||||
|
// std::cout << "total: " << total << std::endl;
|
||||||
|
// std::cout << "c3 * m_nSigma * rms: " << (c3 * m_nSigma * rms) << std::endl;
|
||||||
|
// }
|
||||||
|
|
||||||
ClusterType cluster{};
|
ClusterType cluster{};
|
||||||
cluster.x = ix;
|
cluster.x = ix;
|
||||||
cluster.y = iy;
|
cluster.y = iy;
|
||||||
@@ -135,19 +204,25 @@ class ClusterFinder {
|
|||||||
// It's worth redoing the look since most of the time we
|
// It's worth redoing the look since most of the time we
|
||||||
// don't have a photon
|
// don't have a photon
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (int ir = -dy; ir < dy + has_center_pixel_y; ir++) {
|
for (int ir = -dy2; ir < dy2 + has_center_pixel_y; ir++) {
|
||||||
for (int ic = -dx; ic < dx + has_center_pixel_y; ic++) {
|
size_t inner_row_offset = row_offset + (ir * frame.shape(1));
|
||||||
|
for (int ic = -dx2; ic < dx2 + has_center_pixel_y; ic++) {
|
||||||
if (ix + ic >= 0 && ix + ic < frame.shape(1) &&
|
if (ix + ic >= 0 && ix + ic < frame.shape(1) &&
|
||||||
iy + ir >= 0 && iy + ir < frame.shape(0)) {
|
iy + ir >= 0 && iy + ir < frame.shape(0)) {
|
||||||
CT tmp =
|
// if (m_pedestal.std(iy + ir, ix + ic) == 0) continue;
|
||||||
static_cast<CT>(frame(iy + ir, ix + ic)) -
|
// if (std_ptr[inner_row_offset + ix + ic] == 0) continue;
|
||||||
static_cast<CT>(
|
|
||||||
m_pedestal.mean(iy + ir, ix + ic));
|
// CT tmp = static_cast<CT>(frame(iy + ir, ix + ic)) - static_cast<CT>(m_pedestal.mean(iy + ir, ix + ic));
|
||||||
cluster.data[i] =
|
|
||||||
tmp; // Watch for out of bounds access
|
// CT tmp = 0;
|
||||||
i++;
|
if (std_ptr[inner_row_offset + ix + ic] != 0)
|
||||||
|
{
|
||||||
|
CT tmp = static_cast<CT>(frame(iy + ir, ix + ic)) - static_cast<CT>(mean_ptr[inner_row_offset + ix + ic]);
|
||||||
|
cluster.data[i] = tmp; // Watch for out of bounds access
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the cluster to the output ClusterVector
|
// Add the cluster to the output ClusterVector
|
||||||
|
|||||||
@@ -20,9 +20,15 @@ enum class FrameType {
|
|||||||
struct FrameWrapper {
|
struct FrameWrapper {
|
||||||
FrameType type;
|
FrameType type;
|
||||||
uint64_t frame_number;
|
uint64_t frame_number;
|
||||||
|
// NDArray<T, 2> data;
|
||||||
NDArray<uint16_t, 2> data;
|
NDArray<uint16_t, 2> data;
|
||||||
|
// NDArray<double, 2> data;
|
||||||
|
// void* data_ptr;
|
||||||
|
// std::type_index data_type;
|
||||||
|
uint32_t chunk_number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief ClusterFinderMT is a multi-threaded version of ClusterFinder. It uses
|
* @brief ClusterFinderMT is a multi-threaded version of ClusterFinder. It uses
|
||||||
* a producer-consumer queue to distribute the frames to the threads. The
|
* a producer-consumer queue to distribute the frames to the threads. The
|
||||||
@@ -68,6 +74,7 @@ class ClusterFinderMT {
|
|||||||
while (!m_stop_requested || !q->isEmpty()) {
|
while (!m_stop_requested || !q->isEmpty()) {
|
||||||
if (FrameWrapper *frame = q->frontPtr(); frame != nullptr) {
|
if (FrameWrapper *frame = q->frontPtr(); frame != nullptr) {
|
||||||
|
|
||||||
|
|
||||||
switch (frame->type) {
|
switch (frame->type) {
|
||||||
case FrameType::DATA:
|
case FrameType::DATA:
|
||||||
cf->find_clusters(frame->data.view(), frame->frame_number);
|
cf->find_clusters(frame->data.view(), frame->frame_number);
|
||||||
@@ -121,7 +128,9 @@ class ClusterFinderMT {
|
|||||||
* @param n_threads number of threads to use
|
* @param n_threads number of threads to use
|
||||||
*/
|
*/
|
||||||
ClusterFinderMT(Shape<2> image_size, PEDESTAL_TYPE nSigma = 5.0,
|
ClusterFinderMT(Shape<2> image_size, PEDESTAL_TYPE nSigma = 5.0,
|
||||||
size_t capacity = 2000, size_t n_threads = 3)
|
size_t capacity = 2000, size_t n_threads = 3,
|
||||||
|
uint32_t chunk_size = 50000, uint32_t n_chunks = 10,
|
||||||
|
uint32_t cluster_size_x = 3, uint32_t cluster_size_y = 3)
|
||||||
: m_n_threads(n_threads) {
|
: m_n_threads(n_threads) {
|
||||||
|
|
||||||
LOG(logDEBUG1) << "ClusterFinderMT: "
|
LOG(logDEBUG1) << "ClusterFinderMT: "
|
||||||
@@ -134,7 +143,7 @@ class ClusterFinderMT {
|
|||||||
m_cluster_finders.push_back(
|
m_cluster_finders.push_back(
|
||||||
std::make_unique<
|
std::make_unique<
|
||||||
ClusterFinder<ClusterType, FRAME_TYPE, PEDESTAL_TYPE>>(
|
ClusterFinder<ClusterType, FRAME_TYPE, PEDESTAL_TYPE>>(
|
||||||
image_size, nSigma, capacity));
|
image_size, nSigma, capacity, chunk_size, n_chunks, cluster_size_x, cluster_size_y));
|
||||||
}
|
}
|
||||||
for (size_t i = 0; i < n_threads; i++) {
|
for (size_t i = 0; i < n_threads; i++) {
|
||||||
m_input_queues.emplace_back(std::make_unique<InputQueue>(200));
|
m_input_queues.emplace_back(std::make_unique<InputQueue>(200));
|
||||||
@@ -208,7 +217,7 @@ class ClusterFinderMT {
|
|||||||
*/
|
*/
|
||||||
void push_pedestal_frame(NDView<FRAME_TYPE, 2> frame) {
|
void push_pedestal_frame(NDView<FRAME_TYPE, 2> frame) {
|
||||||
FrameWrapper fw{FrameType::PEDESTAL, 0,
|
FrameWrapper fw{FrameType::PEDESTAL, 0,
|
||||||
NDArray(frame)}; // TODO! copies the data!
|
NDArray(frame), 0}; // TODO! copies the data!
|
||||||
|
|
||||||
for (auto &queue : m_input_queues) {
|
for (auto &queue : m_input_queues) {
|
||||||
while (!queue->write(fw)) {
|
while (!queue->write(fw)) {
|
||||||
@@ -217,6 +226,23 @@ class ClusterFinderMT {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void push_pedestal_mean(NDView<PEDESTAL_TYPE, 2> frame, uint32_t chunk_number) {
|
||||||
|
if (!m_processing_threads_stopped) {
|
||||||
|
throw std::runtime_error("ClusterFinderMT is still running");
|
||||||
|
}
|
||||||
|
for (auto &cf : m_cluster_finders) {
|
||||||
|
cf->push_pedestal_mean(frame, chunk_number);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void push_pedestal_std(NDView<PEDESTAL_TYPE, 2> frame, uint32_t chunk_number) {
|
||||||
|
if (!m_processing_threads_stopped) {
|
||||||
|
throw std::runtime_error("ClusterFinderMT is still running");
|
||||||
|
}
|
||||||
|
for (auto &cf : m_cluster_finders) {
|
||||||
|
cf->push_pedestal_std(frame, chunk_number);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Push the frame to the queue of the next available thread. Function
|
* @brief Push the frame to the queue of the next available thread. Function
|
||||||
* returns once the frame is in a queue.
|
* returns once the frame is in a queue.
|
||||||
@@ -224,7 +250,10 @@ class ClusterFinderMT {
|
|||||||
*/
|
*/
|
||||||
void find_clusters(NDView<FRAME_TYPE, 2> frame, uint64_t frame_number = 0) {
|
void find_clusters(NDView<FRAME_TYPE, 2> frame, uint64_t frame_number = 0) {
|
||||||
FrameWrapper fw{FrameType::DATA, frame_number,
|
FrameWrapper fw{FrameType::DATA, frame_number,
|
||||||
NDArray(frame)}; // TODO! copies the data!
|
NDArray(frame), 0}; // TODO! copies the data!
|
||||||
|
|
||||||
|
// std::cout << "frame(122, 115): " << frame(122, 115) << std::endl;
|
||||||
|
|
||||||
while (!m_input_queues[m_current_thread % m_n_threads]->write(fw)) {
|
while (!m_input_queues[m_current_thread % m_n_threads]->write(fw)) {
|
||||||
std::this_thread::sleep_for(m_default_wait);
|
std::this_thread::sleep_for(m_default_wait);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,24 +26,24 @@ def _get_class(name, cluster_size, dtype):
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
def ClusterFinder(image_size, cluster_size, n_sigma=5, dtype = np.int32, capacity = 1024):
|
def ClusterFinder(image_size, saved_cluster_size, checked_cluster_size, n_sigma=5, dtype = np.int32, capacity = 1024, chunk_size=50000, n_chunks = 10):
|
||||||
"""
|
"""
|
||||||
Factory function to create a ClusterFinder object. Provides a cleaner syntax for
|
Factory function to create a ClusterFinder object. Provides a cleaner syntax for
|
||||||
the templated ClusterFinder in C++.
|
the templated ClusterFinder in C++.
|
||||||
"""
|
"""
|
||||||
cls = _get_class("ClusterFinder", cluster_size, dtype)
|
cls = _get_class("ClusterFinder", saved_cluster_size, dtype)
|
||||||
return cls(image_size, n_sigma=n_sigma, capacity=capacity)
|
return cls(image_size, n_sigma=n_sigma, capacity=capacity, chunk_size=chunk_size, n_chunks=n_chunks, cluster_size_x=checked_cluster_size[0], cluster_size_y=checked_cluster_size[1])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def ClusterFinderMT(image_size, cluster_size = (3,3), dtype=np.int32, n_sigma=5, capacity = 1024, n_threads = 3):
|
def ClusterFinderMT(image_size, saved_cluster_size = (3,3), checked_cluster_size = (3,3), dtype=np.int32, n_sigma=5, capacity = 1024, n_threads = 3, chunk_size=50000, n_chunks = 10):
|
||||||
"""
|
"""
|
||||||
Factory function to create a ClusterFinderMT object. Provides a cleaner syntax for
|
Factory function to create a ClusterFinderMT object. Provides a cleaner syntax for
|
||||||
the templated ClusterFinderMT in C++.
|
the templated ClusterFinderMT in C++.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
cls = _get_class("ClusterFinderMT", cluster_size, dtype)
|
cls = _get_class("ClusterFinderMT", saved_cluster_size, dtype)
|
||||||
return cls(image_size, n_sigma=n_sigma, capacity=capacity, n_threads=n_threads)
|
return cls(image_size, n_sigma=n_sigma, capacity=capacity, n_threads=n_threads, chunk_size=chunk_size, n_chunks=n_chunks, cluster_size_x=checked_cluster_size[0], cluster_size_y=checked_cluster_size[1])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -30,14 +30,30 @@ void define_ClusterFinder(py::module &m, const std::string &typestr) {
|
|||||||
|
|
||||||
py::class_<ClusterFinder<ClusterType, uint16_t, pd_type>>(
|
py::class_<ClusterFinder<ClusterType, uint16_t, pd_type>>(
|
||||||
m, class_name.c_str())
|
m, class_name.c_str())
|
||||||
.def(py::init<Shape<2>, pd_type, size_t>(), py::arg("image_size"),
|
.def(py::init<Shape<2>, pd_type, size_t, uint32_t, uint32_t, uint32_t, uint32_t>(),
|
||||||
py::arg("n_sigma") = 5.0, py::arg("capacity") = 1'000'000)
|
py::arg("image_size"), py::arg("n_sigma") = 5.0, py::arg("capacity") = 1'000'000,
|
||||||
|
py::arg("chunk_size") = 50'000, py::arg("n_chunks") = 10,
|
||||||
|
py::arg("cluster_size_x") = 3, py::arg("cluster_size_y") = 3)
|
||||||
.def("push_pedestal_frame",
|
.def("push_pedestal_frame",
|
||||||
[](ClusterFinder<ClusterType, uint16_t, pd_type> &self,
|
[](ClusterFinder<ClusterType, uint16_t, pd_type> &self,
|
||||||
py::array_t<uint16_t> frame) {
|
py::array_t<uint16_t> frame) {
|
||||||
auto view = make_view_2d(frame);
|
auto view = make_view_2d(frame);
|
||||||
self.push_pedestal_frame(view);
|
self.push_pedestal_frame(view);
|
||||||
})
|
})
|
||||||
|
|
||||||
|
.def("push_pedestal_mean",
|
||||||
|
[](ClusterFinder<ClusterType, uint16_t, pd_type> &self,
|
||||||
|
py::array_t<double> frame, uint32_t chunk_number) {
|
||||||
|
auto view = make_view_2d(frame);
|
||||||
|
self.push_pedestal_mean(view, chunk_number);
|
||||||
|
})
|
||||||
|
.def("push_pedestal_std",
|
||||||
|
[](ClusterFinder<ClusterType, uint16_t, pd_type> &self,
|
||||||
|
py::array_t<double> frame, uint32_t chunk_number) {
|
||||||
|
auto view = make_view_2d(frame);
|
||||||
|
self.push_pedestal_std(view, chunk_number);
|
||||||
|
})
|
||||||
|
|
||||||
.def("clear_pedestal",
|
.def("clear_pedestal",
|
||||||
&ClusterFinder<ClusterType, uint16_t, pd_type>::clear_pedestal)
|
&ClusterFinder<ClusterType, uint16_t, pd_type>::clear_pedestal)
|
||||||
.def_property_readonly(
|
.def_property_readonly(
|
||||||
|
|||||||
@@ -30,15 +30,31 @@ void define_ClusterFinderMT(py::module &m, const std::string &typestr) {
|
|||||||
|
|
||||||
py::class_<ClusterFinderMT<ClusterType, uint16_t, pd_type>>(
|
py::class_<ClusterFinderMT<ClusterType, uint16_t, pd_type>>(
|
||||||
m, class_name.c_str())
|
m, class_name.c_str())
|
||||||
.def(py::init<Shape<2>, pd_type, size_t, size_t>(),
|
.def(py::init<Shape<2>, pd_type, size_t, size_t, uint32_t, uint32_t, uint32_t, uint32_t>(),
|
||||||
py::arg("image_size"), py::arg("n_sigma") = 5.0,
|
py::arg("image_size"), py::arg("n_sigma") = 5.0,
|
||||||
py::arg("capacity") = 2048, py::arg("n_threads") = 3)
|
py::arg("capacity") = 2048, py::arg("n_threads") = 3,
|
||||||
|
py::arg("chunk_size") = 50'000, py::arg("n_chunks") = 10,
|
||||||
|
py::arg("cluster_size_x") = 3, py::arg("cluster_size_y") = 3)
|
||||||
.def("push_pedestal_frame",
|
.def("push_pedestal_frame",
|
||||||
[](ClusterFinderMT<ClusterType, uint16_t, pd_type> &self,
|
[](ClusterFinderMT<ClusterType, uint16_t, pd_type> &self,
|
||||||
py::array_t<uint16_t> frame) {
|
py::array_t<uint16_t> frame) {
|
||||||
auto view = make_view_2d(frame);
|
auto view = make_view_2d(frame);
|
||||||
self.push_pedestal_frame(view);
|
self.push_pedestal_frame(view);
|
||||||
})
|
})
|
||||||
|
|
||||||
|
.def("push_pedestal_mean",
|
||||||
|
[](ClusterFinderMT<ClusterType, uint16_t, pd_type> &self,
|
||||||
|
py::array_t<double> frame, uint32_t chunk_number) {
|
||||||
|
auto view = make_view_2d(frame);
|
||||||
|
self.push_pedestal_mean(view, chunk_number);
|
||||||
|
})
|
||||||
|
.def("push_pedestal_std",
|
||||||
|
[](ClusterFinderMT<ClusterType, uint16_t, pd_type> &self,
|
||||||
|
py::array_t<double> frame, uint32_t chunk_number) {
|
||||||
|
auto view = make_view_2d(frame);
|
||||||
|
self.push_pedestal_std(view, chunk_number);
|
||||||
|
})
|
||||||
|
|
||||||
.def(
|
.def(
|
||||||
"find_clusters",
|
"find_clusters",
|
||||||
[](ClusterFinderMT<ClusterType, uint16_t, pd_type> &self,
|
[](ClusterFinderMT<ClusterType, uint16_t, pd_type> &self,
|
||||||
|
|||||||
Reference in New Issue
Block a user