cpp Cluster and ClusterVector and ClusterFile are templated now, they support generic cluster types

This commit is contained in:
2025-03-25 21:42:50 +01:00
parent 6e7e81b36b
commit 0876b6891a
6 changed files with 619 additions and 89 deletions

View File

@ -4,8 +4,11 @@
namespace aare {
ClusterFile::ClusterFile(const std::filesystem::path &fname, size_t chunk_size,
const std::string &mode)
template <typename ClusterType,
typename = std::enable_if_t<is_cluster_v<ClusterType>>>
ClusterFile<ClusterType>::ClusterFile(const std::filesystem::path &fname,
size_t chunk_size,
const std::string &mode)
: m_chunk_size(chunk_size), m_mode(mode) {
if (mode == "r") {
@ -31,16 +34,21 @@ ClusterFile::ClusterFile(const std::filesystem::path &fname, size_t chunk_size,
}
}
ClusterFile::~ClusterFile() { close(); }
template <typename ClusterType> ClusterFile<ClusterType>::~ClusterFile() {
close();
}
void ClusterFile::close() {
template <typename ClusterType> void ClusterFile<ClusterType>::close() {
if (fp) {
fclose(fp);
fp = nullptr;
}
}
void ClusterFile::write_frame(const ClusterVector<int32_t> &clusters) {
// TODO generally supported for all clsuter types
template <typename ClusterType>
void ClusterFile<ClusterType>::write_frame(
const ClusterVector<ClusterType> &clusters) {
if (m_mode != "w" && m_mode != "a") {
throw std::runtime_error("File not opened for writing");
}
@ -55,12 +63,14 @@ void ClusterFile::write_frame(const ClusterVector<int32_t> &clusters) {
fwrite(clusters.data(), clusters.item_size(), clusters.size(), fp);
}
ClusterVector<int32_t> ClusterFile::read_clusters(size_t n_clusters) {
template <typename ClusterType>
ClusterVector<ClusterType>
ClusterFile<ClusterType>::read_clusters(size_t n_clusters) {
if (m_mode != "r") {
throw std::runtime_error("File not opened for reading");
}
ClusterVector<int32_t> clusters(3, 3, n_clusters);
ClusterVector<ClusterType> clusters(n_clusters);
int32_t iframe = 0; // frame number needs to be 4 bytes!
size_t nph_read = 0;
@ -108,12 +118,14 @@ ClusterVector<int32_t> ClusterFile::read_clusters(size_t n_clusters) {
return clusters;
}
ClusterVector<int32_t> ClusterFile::read_clusters(size_t n_clusters, ROI roi) {
template <typename ClusterType>
ClusterVector<ClusterType>
ClusterFile<ClusterType>::read_clusters(size_t n_clusters, ROI roi) {
if (m_mode != "r") {
throw std::runtime_error("File not opened for reading");
}
ClusterVector<int32_t> clusters(3, 3);
ClusterVector<ClusterType> clusters;
clusters.reserve(n_clusters);
int32_t iframe = 0; // frame number needs to be 4 bytes!
@ -124,7 +136,7 @@ ClusterVector<int32_t> ClusterFile::read_clusters(size_t n_clusters, ROI roi) {
// auto buf = reinterpret_cast<Cluster3x3 *>(clusters.data());
// auto buf = clusters.data();
Cluster3x3 tmp; // this would break if the cluster size changes
ClusterType tmp; // this would break if the cluster size changes
// if there are photons left from previous frame read them first
if (nph) {
@ -186,7 +198,8 @@ ClusterVector<int32_t> ClusterFile::read_clusters(size_t n_clusters, ROI roi) {
return clusters;
}
ClusterVector<int32_t> ClusterFile::read_frame() {
template <typename ClusterType>
ClusterVector<ClusterType> ClusterFile<ClusterType>::read_frame() {
if (m_mode != "r") {
throw std::runtime_error("File not opened for reading");
}
@ -204,7 +217,7 @@ ClusterVector<int32_t> ClusterFile::read_frame() {
throw std::runtime_error("Could not read number of clusters");
}
// std::vector<Cluster3x3> clusters(n_clusters);
ClusterVector<int32_t> clusters(3, 3, n_clusters);
ClusterVector<ClusterType> clusters(n_clusters);
clusters.set_frame_number(frame_number);
if (fread(clusters.data(), clusters.item_size(), n_clusters, fp) !=
@ -372,8 +385,9 @@ Eta2 calculate_eta2(Cluster<T, ClusterSizeX, ClusterSizeY, CoordType> &cl) {
Eta2 eta{};
// TODO loads of overhead for a 2x2 clsuter maybe keep 2x2 calculation
size_t num_2x2_subclusters = (ClusterSizeX - 1) * (ClusterSizeY - 1);
std::array<int32_t, num_2x2_subclusters> sum_2x2_subcluster;
constexpr size_t num_2x2_subclusters =
(ClusterSizeX - 1) * (ClusterSizeY - 1);
std::array<T, num_2x2_subclusters> sum_2x2_subcluster;
for (size_t i = 0; i < ClusterSizeY - 1; ++i) {
for (size_t j = 0; j < ClusterSizeX - 1; ++j)
sum_2x2_subcluster[i * (ClusterSizeX - 1) + j] =
@ -383,9 +397,9 @@ Eta2 calculate_eta2(Cluster<T, ClusterSizeX, ClusterSizeY, CoordType> &cl) {
cl.data[(i + 1) * ClusterSizeX + j + 1];
}
auto c = std::max_element(sum_2x2_subclusters.begin(),
sum_2x2_subcluster.end()) -
sum_2x2_subcluster.begin();
auto c =
std::max_element(sum_2x2_subcluster.begin(), sum_2x2_subcluster.end()) -
sum_2x2_subcluster.begin();
eta.sum = sum_2x2_subcluster[c];
@ -458,7 +472,6 @@ template <typename T> Eta2 calculate_eta2(Cluster<T, 3, 3> &cl) {
eta.y = static_cast<double>(cl.data[7]) / (cl.data[7] + cl.data[4]);
eta.c = cTopRight;
break;
// no default to allow compiler to warn about missing cases
}
return eta;
}
@ -473,8 +486,9 @@ template <typename T> Eta2 calculate_eta2(Cluster<T, 2, 2> &cl) {
return eta;
}
int analyze_cluster(Cluster3x3 &cl, int32_t *t2, int32_t *t3, char *quad,
double *eta2x, double *eta2y, double *eta3x,
// TODO complicated API simplify?
int analyze_cluster(Cluster<int32_t, 3, 3> &cl, int32_t *t2, int32_t *t3,
char *quad, double *eta2x, double *eta2y, double *eta3x,
double *eta3y) {
return analyze_data(cl.data, t2, t3, quad, eta2x, eta2y, eta3x, eta3y);

View File

@ -5,7 +5,8 @@ namespace aare {
Interpolator::Interpolator(NDView<double, 3> etacube, NDView<double, 1> xbins,
NDView<double, 1> ybins, NDView<double, 1> ebins)
: m_ietax(etacube), m_ietay(etacube), m_etabinsx(xbins), m_etabinsy(ybins), m_energy_bins(ebins) {
: m_ietax(etacube), m_ietay(etacube), m_etabinsx(xbins), m_etabinsy(ybins),
m_energy_bins(ebins) {
if (etacube.shape(0) != xbins.size() || etacube.shape(1) != ybins.size() ||
etacube.shape(2) != ebins.size()) {
throw std::invalid_argument(
@ -51,35 +52,37 @@ Interpolator::Interpolator(NDView<double, 3> etacube, NDView<double, 1> xbins,
}
}
}
}
std::vector<Photon> Interpolator::interpolate(const ClusterVector<int32_t>& clusters) {
template <typename ClusterType,
typename = std::enable_if_t<is_cluster_v<ClusterType>>>
std::vector<Photon>
Interpolator::interpolate(const ClusterVector<ClusterType> &clusters) {
std::vector<Photon> photons;
photons.reserve(clusters.size());
if (clusters.cluster_size_x() == 3 || clusters.cluster_size_y() == 3) {
for (size_t i = 0; i<clusters.size(); i++){
for (size_t i = 0; i < clusters.size(); i++) {
auto cluster = clusters.at(i);
Eta2 eta = calculate_eta2(cluster);
auto cluster = clusters.at<Cluster3x3>(i);
Eta2 eta= calculate_eta2(cluster);
Photon photon;
photon.x = cluster.x;
photon.y = cluster.y;
photon.energy = eta.sum;
// auto ie = nearest_index(m_energy_bins, photon.energy)-1;
// auto ix = nearest_index(m_etabinsx, eta.x)-1;
// auto iy = nearest_index(m_etabinsy, eta.y)-1;
//Finding the index of the last element that is smaller
//should work fine as long as we have many bins
// auto iy = nearest_index(m_etabinsy, eta.y)-1;
// Finding the index of the last element that is smaller
// should work fine as long as we have many bins
auto ie = last_smaller(m_energy_bins, photon.energy);
auto ix = last_smaller(m_etabinsx, eta.x);
auto iy = last_smaller(m_etabinsy, eta.y);
auto iy = last_smaller(m_etabinsy, eta.y);
// fmt::print("ex: {}, ix: {}, iy: {}\n", ie, ix, iy);
double dX, dY;
int ex, ey;
// cBottomLeft = 0,
@ -100,44 +103,47 @@ std::vector<Photon> Interpolator::interpolate(const ClusterVector<int32_t>& clus
dY = -1.;
break;
case cBottomRight:
dX = 0.;
dX = 0.;
dY = -1.;
break;
}
photon.x += m_ietax(ix, iy, 0)*2 + dX;
photon.y += m_ietay(ix, iy, 0)*2 + dY;
photon.x += m_ietax(ix, iy, 0) * 2 + dX;
photon.y += m_ietay(ix, iy, 0) * 2 + dY;
photons.push_back(photon);
}
}else if(clusters.cluster_size_x() == 2 || clusters.cluster_size_y() == 2){
for (size_t i = 0; i<clusters.size(); i++){
auto cluster = clusters.at<Cluster2x2>(i);
Eta2 eta= calculate_eta2(cluster);
} else if (clusters.cluster_size_x() == 2 ||
clusters.cluster_size_y() == 2) {
for (size_t i = 0; i < clusters.size(); i++) {
auto cluster = clusters.at(i);
Eta2 eta = calculate_eta2(cluster);
Photon photon;
photon.x = cluster.x;
photon.y = cluster.y;
photon.energy = eta.sum;
//Now do some actual interpolation.
//Find which energy bin the cluster is in
// auto ie = nearest_index(m_energy_bins, photon.energy)-1;
// auto ix = nearest_index(m_etabinsx, eta.x)-1;
// auto iy = nearest_index(m_etabinsy, eta.y)-1;
//Finding the index of the last element that is smaller
//should work fine as long as we have many bins
// Now do some actual interpolation.
// Find which energy bin the cluster is in
// auto ie = nearest_index(m_energy_bins, photon.energy)-1;
// auto ix = nearest_index(m_etabinsx, eta.x)-1;
// auto iy = nearest_index(m_etabinsy, eta.y)-1;
// Finding the index of the last element that is smaller
// should work fine as long as we have many bins
auto ie = last_smaller(m_energy_bins, photon.energy);
auto ix = last_smaller(m_etabinsx, eta.x);
auto iy = last_smaller(m_etabinsy, eta.y);
auto iy = last_smaller(m_etabinsy, eta.y);
photon.x += m_ietax(ix, iy, 0)*2; //eta goes between 0 and 1 but we could move the hit anywhere in the 2x2
photon.y += m_ietay(ix, iy, 0)*2;
photon.x +=
m_ietax(ix, iy, 0) * 2; // eta goes between 0 and 1 but we could
// move the hit anywhere in the 2x2
photon.y += m_ietay(ix, iy, 0) * 2;
photons.push_back(photon);
}
}else{
throw std::runtime_error("Only 3x3 and 2x2 clusters are supported for interpolation");
} else {
throw std::runtime_error(
"Only 3x3 and 2x2 clusters are supported for interpolation");
}
return photons;
}