Skip to content

Commit 3b497fa

Browse files
authored
CLUE clustering improvements, fixing multilayer option (#1835)
1 parent 4afc45d commit 3b497fa

File tree

13 files changed

+525
-401
lines changed

13 files changed

+525
-401
lines changed

ComparePlots/ecal.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,9 @@ def clue_cluster(d : Differ, out_dir = None) :
121121
"""
122122

123123
features = [
124-
('EcalClusterAnalyzer/EcalClusterAnalyzer_number_of_clusters', 'Number of CLUE clusters'),
124+
('EcalClusterAnalyzer/EcalClusterAnalyzer_number_of_clusters_first_layer', 'Number of CLUE clusters on the first layer'),
125+
('EcalClusterAnalyzer/EcalClusterAnalyzer_number_of_clusters_per_layer', 'Number of CLUE clusters per layer'),
126+
('EcalClusterAnalyzer/EcalClusterAnalyzer_number_of_clusters', 'Total number of CLUE clusters'),
125127
('EcalClusterAnalyzer/EcalClusterAnalyzer_energy_percentage', 'Percentage of energy in cluster'),
126128
('EcalClusterAnalyzer/EcalClusterAnalyzer_clusterless_hits_percentage', 'Percentage of hits not in a cluster'),
127129
('EcalClusterAnalyzer/EcalClusterAnalyzer_sp_clue_distance', 'CLUE centroid to SP ele distance in xy-plane [mm]'),

DQM/python/dqm.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1063,7 +1063,9 @@ def __init__(self,name='EcalClusterAnalyzer') :
10631063
self.ecal_sp_hits_passname = ''
10641064

10651065

1066-
self.build1DHistogram("number_of_clusters", "Number of CLUE clusters", 5, -0.5, 4.5)
1066+
self.build1DHistogram("number_of_clusters_first_layer", "Number of CLUE clusters on the first layer", 5, -0.5, 4.5)
1067+
self.build1DHistogram("number_of_clusters_per_layer", "Number of CLUE clusters per layer", 5, -0.5, 4.5)
1068+
self.build1DHistogram("number_of_clusters", "Total number of CLUE clusters", 51, -0.5, 50.5)
10671069
self.build1DHistogram("correctly_predicted_events", "Correct Cluster Count", 3, 0., 3.)
10681070

10691071
# Need to mod for more than two electrons
@@ -1080,7 +1082,8 @@ def __init__(self,name='EcalClusterAnalyzer') :
10801082
self.build2DHistogram("total_energy_vs_hits", "Total energy (edep) [MeV]", 30, 0, 150, "Hits in cluster", 20, 0, 200)
10811083
self.build2DHistogram("total_energy_vs_purity", "Total energy (edep) [MeV]", 30, 0, 150, "Energy purity %", 21, 0, 105)
10821084
self.build2DHistogram("sp_ele_distance_vs_purity", "SP ele distance in xy-plane [mm]", 50, 0, 250, "Energy purity %", 21, 0, 105)
1083-
1085+
self.build2DHistogram("sp_clue_distance_vs_layer", "CLUE centroid to SP ele distance in xy-plane [mm]", 125, 0., 250., "Layer", 33, -0.5, 32.5)
1086+
10841087
self.build1DHistogram("sp_clue_distance", "CLUE centroid to SP ele distance in xy-plane [mm]", 125, 0., 250.)
10851088
self.build1DHistogram("sp_clue_x_residual", "CLUE centroid X - SP ele X [mm]", 250, -250., 250.)
10861089
self.build1DHistogram("sp_clue_y_residual", "CLUE centroid Y - SP ele Y [mm]", 250, -250., 250.)

DQM/src/DQM/EcalClusterAnalyzer.cxx

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,26 @@ void EcalClusterAnalyzer::analyze(const framework::Event& event) {
3636
nbr_of_electrons = nbr_of_electrons_;
3737
}
3838

39-
int n_ecal_clusters = ecal_clusters.size();
39+
std::map<int, int> layer_cluster_count;
40+
for (const auto& cluster : ecal_clusters) {
41+
auto layer = cluster.getLayer();
42+
layer_cluster_count[layer]++;
43+
}
44+
45+
int total_clusters = 0;
46+
for (const auto& [layer, count] : layer_cluster_count) {
47+
total_clusters += count;
48+
}
49+
50+
int n_ecal_clusters = static_cast<int>(std::round(
51+
static_cast<double>(total_clusters) / layer_cluster_count.size()));
52+
53+
ldmx_log(info) << "Avg number of clusters per layer: " << n_ecal_clusters;
4054
// Fill histograms with the number of clusters
41-
histograms_.fill("number_of_clusters", n_ecal_clusters);
55+
histograms_.fill("number_of_clusters", total_clusters);
56+
histograms_.fill("number_of_clusters_per_layer", n_ecal_clusters);
57+
histograms_.fill("number_of_clusters_first_layer", layer_cluster_count[0]);
58+
4259
// Fill simplied 3-bin histogram to check the prediction
4360
if (n_ecal_clusters == nbr_of_electrons) {
4461
// correct
@@ -150,8 +167,14 @@ void EcalClusterAnalyzer::analyze(const framework::Event& event) {
150167
int clustered_hits = 0;
151168
ldmx_log(trace) << "Loop over the clusters, N = " << n_ecal_clusters;
152169
for (const auto& cl : ecal_clusters) {
153-
auto cluster_centroid_x = cl.getFirstLayerCentroidX();
154-
auto cluster_centroid_y = cl.getFirstLayerCentroidY();
170+
auto layer = cl.getLayer();
171+
ldmx_log(trace) << "Cluster in layer " << layer
172+
<< ", energy: " << cl.getEnergy()
173+
<< ", number of hits: " << cl.getHitIDs().size();
174+
auto cluster_centroid_x = cl.getCentroidX();
175+
auto cluster_centroid_y = cl.getCentroidY();
176+
auto cluster_rms_x = cl.getRMSX();
177+
auto cluster_rms_y = cl.getRMSY();
155178

156179
// Find the closest sp_electron_positions to the cluster centroid
157180
double min_distance = 9999.;
@@ -168,13 +191,17 @@ void EcalClusterAnalyzer::analyze(const framework::Event& event) {
168191
}
169192
} // end loop on the scoring plane electron positions
170193
// Fill histogram with the distance to the closest scoring plane electron
171-
ldmx_log(trace) << "\tCluster centroid: (" << cluster_centroid_x << ", "
172-
<< cluster_centroid_y
173-
<< ") mm, min distance to SP electron: " << min_distance
194+
ldmx_log(trace) << "\tCluster centroid: (" << cluster_centroid_x << " +/- "
195+
<< cluster_rms_x << ", " << cluster_centroid_y << " +/- "
196+
<< cluster_rms_y
197+
<< " mm; min distance to SP electron: " << min_distance
174198
<< " mm";
175-
histograms_.fill("sp_clue_distance", min_distance);
176-
histograms_.fill("sp_clue_x_residual", sp_clue_x_residuals);
177-
histograms_.fill("sp_clue_y_residual", sp_clue_y_residuals);
199+
if (layer == 0) {
200+
histograms_.fill("sp_clue_distance", min_distance);
201+
histograms_.fill("sp_clue_x_residual", sp_clue_x_residuals);
202+
histograms_.fill("sp_clue_y_residual", sp_clue_y_residuals);
203+
}
204+
histograms_.fill("sp_clue_distance_vs_layer", layer, min_distance);
178205

179206
// for each cluster
180207
// total number of hits coming from electron, index = electron ID

Ecal/include/Ecal/CLUE.h

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -29,23 +29,24 @@ class CLUE {
2929

3030
public:
3131
struct Density {
32-
float x_;
33-
float y_;
34-
float z_;
32+
double x_;
33+
double y_;
34+
double z_;
3535
double total_energy_;
3636
int index_;
3737

3838
// index of density this density is follower of
3939
// set to index of spatially closest density with higher energy; -1 if seed
4040
int follower_of_;
41-
// separation distance to density that this is follower of
42-
float delta_;
43-
float z_delta_;
44-
45-
int cluster_id_; // 2D cluster ID
46-
41+
// 2D separation distance to density that this is follower of
42+
double delta_;
43+
// separation in z to density that this is follower of
44+
double z_delta_;
45+
// 2D cluster ID
46+
int cluster_id_;
47+
// layer of density
4748
int layer_;
48-
49+
// hits in this density
4950
std::vector<const ldmx::EcalHit*> hits_;
5051

5152
Density() {}
@@ -63,9 +64,15 @@ class CLUE {
6364
}
6465
};
6566

66-
float dist(double x1, double y1, double x2, double y2);
67-
float floatDist(float x1, float y1, float x2, float y2);
68-
float floatDist(float x1, float y1, float z1, float x2, float y2, float z2);
67+
/**
68+
* Euclidean distance between two points
69+
* @tparam T floating point type
70+
*/
71+
template <typename T>
72+
T dist(T x1, T y1, T x2, T y2);
73+
// 3D version
74+
template <typename T>
75+
T dist(T x1, T y1, T z1, T x2, T y2, T z2);
6976
std::vector<std::vector<const ldmx::EcalHit*>> createLayers(
7077
const std::vector<const ldmx::EcalHit*>& hits);
7178
float roundToDecimal(float x, int num_decimal_precision_digits);
@@ -79,7 +86,7 @@ class CLUE {
7986
std::vector<std::shared_ptr<Density>>& densities, bool connectingLayers,
8087
int layerTag = 0);
8188

82-
std::vector<std::shared_ptr<Density>> layerSetup();
89+
std::vector<std::shared_ptr<Density>> setupForClue3D();
8390

8491
void convertToIntermediateClusters(
8592
std::vector<std::vector<const ldmx::EcalHit*>>& clusters);
@@ -117,15 +124,10 @@ class CLUE {
117124
double deltao_;
118125
double dm_;
119126

120-
// layers in Ecal; a bit unsure if this is the correct number
121-
int max_layers_{17};
127+
// layers in Ecal
128+
int max_layers_{32};
122129
int nbr_of_layers_;
123-
// air between layers (a guess, but it seems to work)
124-
double air_{10.};
125-
// thickness of ECal layers
126-
std::vector<double> layer_thickness_ = {2., 3.5, 5.3, 5.3, 5.3, 5.3,
127-
5.3, 5.3, 5.3, 5.3, 5.3, 10.5,
128-
10.5, 10.5, 10.5, 10.5};
130+
129131
std::vector<double> layer_rho_c_;
130132
std::vector<double> layer_delta_c_;
131133
// containment radius for the different layers of the ECal
@@ -144,7 +146,6 @@ class CLUE {
144146
std::vector<double> centroid_distances_;
145147
IntermediateCluster event_centroid_;
146148

147-
float first_layer_max_z_;
148149
std::vector<IntermediateCluster> first_layer_centroids_;
149150

150151
int seed_index_{0};

Ecal/include/Ecal/Event/EcalCluster.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,6 @@ class EcalCluster : public ldmx::CaloCluster {
5757
}
5858

5959
private:
60-
// Could add further ECal-specific info here...
61-
6260
std::vector<unsigned int> first_layer_hit_ids_;
6361

6462
double first_layer_centroid_x_{0};

Ecal/include/Ecal/IntermediateCluster.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ class IntermediateCluster {
2525
std::vector<const ldmx::EcalHit*> getHits() const { return hits_; }
2626
bool empty() const { return hits_.empty(); }
2727
void clear() { hits_.clear(); }
28-
int getLayer() const { return layer_; }
28+
int getLayer() const;
29+
void setLayer(int layer);
2930

3031
private:
3132
int layer_;

Ecal/include/Ecal/MyClusterWeight.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@ namespace ecal {
1010

1111
class MyClusterWeight {
1212
public:
13+
// returns weighting function, where smallest, weights will be combined first
1314
double operator()(const IntermediateCluster& a,
14-
const IntermediateCluster&
15-
b) { // returns weighting function, where smallest
16-
// weights will be combined first
17-
18-
double rmol = 10.00; // Moliere radius_ of detector, roughly. In mm
19-
double dzchar = 100.0; // Characteristic cluster longitudinal variable TO
20-
// BE DETERMINED! in mm
15+
const IntermediateCluster& b) {
16+
// Moliere radius_ of detector, roughly. In mm
17+
double rmol = 10.00;
18+
// Characteristic cluster longitudinal variable TO
19+
// BE DETERMINED! in mm
20+
double dzchar = 100.0;
2121

2222
double a_e = a.centroid().E();
2323
double a_x = a.centroid().Px();

Ecal/python/ecalClusters.py

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,19 +39,13 @@ def __init__(self,name='ecalClusters') :
3939
# Currently only used when nbrOfLayers > 1
4040
self.dc = 5.
4141
# Minimum seed energy/maximum outlier energy
42+
# Not used when nbrOfLayers > 1
4243
self.rhoc = 550.
4344
# Minimum seed separation
45+
# Not used when nbrOfLayers > 1
4446
self.deltac = 10.
4547
# Minimum outlier separation
4648
self.deltao = 40.
4749
# Recluster merged clusters or not
4850
# No reclustering leads to more undercounting, reclustering leads to more overcounting
49-
self.reclustering = False
50-
51-
self.build1DHistogram("nLoops", "Number of loops for clustering", 50, 0, 400) # not applicable for CLUE
52-
self.build1DHistogram("nClusters", "Number of clusters", 20, 0, 20)
53-
self.build1DHistogram("nHits", "Hits per cluster", 20, 0, 300)
54-
self.build1DHistogram("cluster_energy", "Energy [MeV] per cluster", 100, 0, 20000)
55-
self.build2DHistogram("seed_weights", "Number of seeds", 20, 0, 100, "Minimum weight", 20, 0, 10) # not applicable for CLUE
56-
self.build2DHistogram("recluster", "Initial number of clusters", 20, 0, 20, "Number of clusters after reclustering", 20, 0, 20) # not applicable for existing algo
57-
51+
self.reclustering = False

0 commit comments

Comments
 (0)