LDMX Software
TemplatedClusterFinder.h
Go to the documentation of this file.
1
5#ifndef RECON_TEMPLATEDCLUSTERFINDER_H_
6#define RECON_TEMPLATEDCLUSTERFINDER_H_
7
8#include <algorithm>
9#include <map>
10#include <vector>
11
13
14namespace recon {
15
36template <class HitType, class WeightClass>
38 public:
40
46 void add(const HitType& hit) { clusters_.push_back(ClusterType(hit)); }
47
53 void add(const HitType* hit) {
54 if (hit) {
55 clusters_.push_back(ClusterType(hit));
56 }
57 }
58
67 void add(const HitType* hit, double x, double y, double z) {
68 if (hit) {
70 cluster.add(hit, x, y, z);
71 clusters_.push_back(cluster);
72 }
73 }
74
78 static bool compClusters(const ClusterType& a, const ClusterType& b) {
79 return a.energy() > b.energy();
80 }
81
88 void cluster(double seed_threshold, double cutoff) {
89 int ncluster = clusters_.size();
90 double minwgt = cutoff;
91
92 // Sort by energy (highest first)
93 std::sort(clusters_.begin(), clusters_.end(), compClusters);
94
95 loops_ = 0;
96 do {
97 bool any = false;
98 size_t mi(0), mj(0);
99 int nseeds = 0;
100
101 for (size_t i = 0; i < clusters_.size(); i++) {
102 if (clusters_[i].empty()) continue;
103
104 bool iseed = (clusters_[i].energy() >= seed_threshold);
105 if (iseed) {
106 nseeds++;
107 } else {
108 // Since we sorted initially, if we find a hit below seed threshold
109 // there will be no seeds after.
110 break;
111 }
112
113 for (size_t j = i + 1; j < clusters_.size(); j++) {
114 if (clusters_[j].empty() ||
115 (!iseed && clusters_[j].energy() < seed_threshold))
116 continue;
117
118 double wgt = wgt_(clusters_[i], clusters_[j]);
119 if (!any || wgt < minwgt) {
120 any = true;
121 minwgt = wgt;
122 mi = i;
123 mj = j;
124 }
125 }
126 }
127
128 nseeds_ = nseeds;
129 transition_weights_.insert(std::pair<int, double>(ncluster, minwgt));
130
131 if (any && minwgt < cutoff) {
132 // Put the bigger one in mi
133 if (clusters_[mi].energy() < clusters_[mj].energy()) {
134 std::swap(mi, mj);
135 }
136 // Merge the smaller into the bigger
137 clusters_[mi].add(clusters_[mj]);
138 clusters_[mj].clear();
139 // Decrement cluster count
140 ncluster--;
141 }
142 loops_++;
143 } while (minwgt < cutoff && ncluster > 1);
144
145 finalwgt_ = minwgt;
146
147 // Collect final clusters that pass the seed threshold
148 for (const auto& cl : clusters_) {
149 if (!cl.empty() && cl.energy() >= seed_threshold) {
150 final_clusters_.push_back(cl);
151 } else if (cl.energy() < seed_threshold) {
152 break; // Clusters are sorted, so safe to break
153 }
154 }
155 }
156
160 double getYMax() const { return finalwgt_; }
161
165 int getNSeeds() const { return nseeds_; }
166
170 int getNLoops() const { return loops_; }
171
175 std::map<int, double> getWeights() const { return transition_weights_; }
176
180 std::vector<ClusterType> getClusters() const { return final_clusters_; }
181
185 std::vector<ClusterType> getAllClusters() const { return clusters_; }
186
187 private:
188 WeightClass wgt_;
189 double finalwgt_{0};
190 int nseeds_{0};
191 int loops_{0};
192 std::map<int, double> transition_weights_;
193 std::vector<ClusterType> clusters_;
194 std::vector<ClusterType> final_clusters_;
195};
196
197} // namespace recon
198
199#endif // RECON_TEMPLATEDCLUSTERFINDER_H_
In-memory tool for working on clusters during reconstruction.
A templated agglomerative clustering algorithm.
void cluster(double seed_threshold, double cutoff)
Run the clustering algorithm.
int getNLoops() const
Get the number of iterations performed.
std::vector< ClusterType > getClusters() const
Get the final clusters after filtering by seed threshold.
void add(const HitType *hit)
Add a hit to be clustered using its stored position.
double getYMax() const
Get the final weight (minimum distance between remaining clusters).
std::map< int, double > getWeights() const
Get the transition weights (cluster count -> minimum weight at that step).
std::vector< ClusterType > getAllClusters() const
Get all clusters including empty ones (for debugging).
int getNSeeds() const
Get the number of seed clusters found.
void add(const HitType &hit)
Add a hit to be clustered using its stored position.
static bool compClusters(const ClusterType &a, const ClusterType &b)
Compare clusters by energy (descending order).
void add(const HitType *hit, double x, double y, double z)
Add a hit with explicit position (e.g., from geometry).
An in-memory representation of a cluster being built during reconstruction.
double energy() const
Get the total energy of the cluster.
void add(const HitType *hit)
Add a hit to the cluster using its stored position.