54 def _reconstruct_clusters(self) -> None:
55 """Perform cluster reconstruction from digitized hits."""
56
57 noise_energy_threshold = 0.002
58 list_hits_above_threshold = []
59 hit_to_index = {}
60 for idx, hit in enumerate(self.det):
61 if hit.GetEnergy() > noise_energy_threshold:
62 hit.SetIsUsed(0)
63 list_hits_above_threshold.append(hit)
64 hit_to_index[id(hit)] = idx
65
66 if not list_hits_above_threshold:
67 return
68
69
70 self.step = 1
71 self.input_hits = list_hits_above_threshold
72 list_clusters_of_hits = self._clustering()
73
74
75 self.step = 2
76 list_final_clusters = {}
77 index_final_cluster = 0
78
79 for i in list_clusters_of_hits:
80 list_hits_x = []
81 list_hits_y = []
82 for hit in list_clusters_of_hits[i]:
83 hit.SetIsUsed(0)
84 if hit.IsX():
85 list_hits_x.append(hit)
86 if hit.IsY():
87 list_hits_y.append(hit)
88
89
90 self.input_hits = list_hits_x
91 list_subclusters_of_x_hits = self._clustering()
92 cluster_energy_x = self._get_cluster_energy(list_hits_x)
93
94 self.list_subclusters_of_hits = list_subclusters_of_x_hits
95 list_of_subclusters_x = self._get_subclusters_excluding_fragments()
96
97
98 weights_from_x_splitting = {}
99 for index_subcluster in list_of_subclusters_x:
100 subcluster_energy_x = self._get_cluster_energy(list_of_subclusters_x[index_subcluster])
101 weight = subcluster_energy_x / cluster_energy_x if cluster_energy_x > 0 else 0
102 weights_from_x_splitting[index_subcluster] = weight
103
104
105 self.input_hits = list_hits_y
106 list_subclusters_of_y_hits = self._clustering()
107 cluster_energy_y = self._get_cluster_energy(list_hits_y)
108
109 self.list_subclusters_of_hits = list_subclusters_of_y_hits
110 list_of_subclusters_y = self._get_subclusters_excluding_fragments()
111
112
113 weights_from_y_splitting = {}
114 for index_subcluster in list_of_subclusters_y:
115 subcluster_energy_y = self._get_cluster_energy(list_of_subclusters_y[index_subcluster])
116 weight = subcluster_energy_y / cluster_energy_y if cluster_energy_y > 0 else 0
117 weights_from_y_splitting[index_subcluster] = weight
118
119
120 if len(list_of_subclusters_x) == 1 and len(list_of_subclusters_y) == 1:
121 list_final_clusters[index_final_cluster] = [(hit, 1.0) for hit in list_clusters_of_hits[i]]
122 index_final_cluster += 1
123 else:
124 for ix in list_of_subclusters_x:
125 for iy in list_of_subclusters_y:
126
127 hit_weight_list = []
128 for hit in list_of_subclusters_y[iy]:
129 hit_weight_list.append((hit, weights_from_x_splitting[ix]))
130 for hit in list_of_subclusters_x[ix]:
131 hit_weight_list.append((hit, weights_from_y_splitting[iy]))
132
133 list_final_clusters[index_final_cluster] = hit_weight_list
134 index_final_cluster += 1
135
136
137 for i in list_final_clusters:
138
139 cluster = ROOT.splitcalCluster()
140
141
142 for hit, weight in list_final_clusters[i]:
143 hit_index = hit_to_index[id(hit)]
144 cluster.AddHit(hit_index, weight)
145
146 cluster.SetIndex(int(i))
147 cluster.ComputeEtaPhiE(self.det)
148 self.reco.push_back(cluster)
149