Process the event and put new data products into it.
33 {
34 auto start = std::chrono::high_resolution_clock::now();
35 nevents_++;
36
37 if (!event.
exists(hit_coll_name_, hit_coll_passname_))
return;
38
39 const auto calo_hits = event.getObject<std::vector<TrigCaloHit>>(
40 hit_coll_name_, hit_coll_passname_);
41
42 if (calorimeter_type_is_hcal_) {
43 std::vector<TrigCaloHit> sorted_hits;
44 int even_matrix[24][5] = {};
45 int even_start[5] = {99, 99, 99, 99, 99};
46 int even_end[5] = {};
47 int even_counts[5] = {};
48 int odd_matrix[24][5] = {};
49 int odd_start[5] = {99, 99, 99, 99, 99};
50 int odd_end[5] = {};
51 int odd_counts[5] = {};
52
53 constexpr int layer_start = 80;
54
55 for (const auto& tp : calo_hits) {
56 if (tp.section() > 0 || tp.energy() < hcal_min_energy_ ||
57 tp.layer() > 47) {
58 continue;
59 }
60
61 sorted_hits.push_back(tp);
62 const int layer_index = tp.layer() / 2;
63 const int strip = tp.strip();
64 if (tp.layer() % 2) {
65 odd_matrix[layer_index][strip] = 1;
66 odd_start[strip] = std::min(odd_start[strip], tp.layer());
67 odd_end[strip] = std::max(odd_end[strip], tp.layer());
68 } else {
69 even_matrix[layer_index][strip] = 1;
70 even_start[strip] = std::min(even_start[strip], tp.layer());
71 even_end[strip] = std::max(even_end[strip], tp.layer());
72 }
73 }
74
75 for (int i = 0; i < 24; i++) {
76 for (int j = 0; j < 5; j++) {
77 if (even_matrix[i][j]) {
78 even_counts[j]++;
79 }
80 if (odd_matrix[i][j]) {
81 odd_counts[j]++;
82 }
83 }
84 }
85
86
87 std::vector<TrigMip> mips;
88
89 for (int i = 0; i < 5; i++) {
90 if (odd_start[i] < layer_start) {
91 TrigMip m;
92 m.setStartLayer(odd_start[i]);
93 m.setEndLayer(odd_end[i]);
94 m.setNHits(odd_counts[i]);
95 m.setLength(odd_end[i] - odd_start[i] + 1);
96 int holes = m.length() / 2 - m.nHits();
97 if (holes < 0) {
98 holes = 0;
99 }
100 m.setNHoles(holes);
101 mips.push_back(m);
102 }
103 if (even_start[i] < layer_start) {
104 TrigMip m;
105 m.setStartLayer(even_start[i]);
106 m.setEndLayer(even_end[i]);
107 m.setNHits(even_counts[i]);
108 m.setLength(even_end[i] - even_start[i] + 1);
109 int holes = m.length() / 2 - m.nHits();
110 if (holes < 0) {
111 holes = 0;
112 }
113 m.setNHoles(holes);
114 mips.push_back(m);
115 }
116 }
117
118 std::sort(mips.begin(), mips.end());
119 event.add(pass_coll_name_, mips);
120
121 auto end = std::chrono::high_resolution_clock::now();
122 auto time_diff = end - start;
123 processing_time_ +=
124 std::chrono::duration<double, std::milli>(time_diff).count();
125
126 return;
127
128 } else {
129 const float radius_cut_2 = search_radius_ * search_radius_;
130 std::map<int, std::vector<TrigCaloHit>> layer_hits;
131 std::set<const TrigCaloHit*> used_hits;
132 std::vector<std::vector<const TrigCaloHit*>> candidate_tracks;
133 std::map<const TrigCaloHit*, size_t> hit_to_best_track;
134
135
136 for (const auto& hit : calo_hits) {
137 if (hit.section() > 0 || hit.layer() > max_layer_) continue;
138 layer_hits[hit.layer()].push_back(hit);
139 }
140
141
142 for (const auto& [seed_layer, seeds] : layer_hits) {
143 for (const auto& seed : seeds) {
144
145 if (used_hits.count(&seed) || seed.energy() < ecal_min_energy_ ||
146 seed.energy() > ecal_max_energy_) {
147 continue;
148 }
149
150 std::vector<const TrigCaloHit*> track{&seed};
151
152 const TrigCaloHit* last = &seed;
153 int holes = 0;
154 float growth_factor = 1.0f;
155
156
157 for (int l = seed.layer() + 1; l <= max_layer_; ++l) {
158 const TrigCaloHit* best_hit = nullptr;
159
160 float best_d_r_2 = radius_cut_2 * growth_factor * growth_factor;
161
162 for (const auto& cand : layer_hits[l]) {
163 if (used_hits.count(&cand) || cand.energy() < ecal_min_energy_ ||
164 cand.energy() > ecal_max_energy_) {
165 continue;
166 }
167
168
169 const float layer_shift_last =
170 (last->layer() % 2 == 0) ? 0.0f : 4.82f;
171 const float layer_shift_cand =
172 (cand.layer() % 2 == 0) ? 0.0f : 4.82f;
173 const float dx = (cand.positionX() - layer_shift_cand) -
174 (last->positionX() - layer_shift_last);
175 const float dy = cand.positionY() - last->positionY();
176 const float d_r_2 = dx * dx + dy * dy;
177
178 if (d_r_2 < best_d_r_2) {
179 best_d_r_2 = d_r_2;
180
181 best_hit = &cand;
182 }
183 }
184
185 if (best_hit) {
186
187 track.push_back(best_hit);
188 last = best_hit;
189 holes = 0;
190
191 growth_factor = 1.0f;
192 } else {
193 holes++;
194
195 growth_factor = static_cast<float>(holes + 1);
196 }
197 }
198
199 bool is_isolated = true;
200 if (track.size() >= min_track_length_) {
201
202 for (const auto* hit : track) {
203 const int layer = hit->layer();
204 const float hit_x = hit->positionX();
205 const float hit_y = hit->positionY();
206 float sum_e = 0.0f;
207
208 for (const auto& cand : layer_hits[layer]) {
209
210 if (&cand == hit) continue;
211
212 const float dx = cand.positionX() - hit_x;
213 const float dy = cand.positionY() - hit_y;
214 const float d_r_2 = dx * dx + dy * dy;
215
216 if (d_r_2 < radius_cut_2) {
217 sum_e += cand.energy();
218 }
219 }
220
221 if (sum_e >= isolation_e_cut_) {
222 is_isolated = false;
223
224 used_hits.insert(hit);
225 break;
226 }
227 }
228
229 if (!is_isolated) {
230
231 continue;
232 }
233
234 const size_t i = candidate_tracks.size();
235 candidate_tracks.push_back(track);
236
237 for (const auto* hit : track) {
238 if (!hit_to_best_track.count(hit) ||
239 candidate_tracks[i].size() >
240 candidate_tracks[hit_to_best_track[hit]].size()) {
241 hit_to_best_track[hit] = i;
242
243 used_hits.insert(hit);
244 }
245 }
246 }
247 }
248 }
249
250 std::set<size_t> valid_track_i_ds;
251 for (const auto& [hit, idx] : hit_to_best_track) {
252 valid_track_i_ds.insert(idx);
253 }
254
255 std::vector<TrigMip> mips;
256 for (const size_t idx : valid_track_i_ds) {
257 const auto& track = candidate_tracks[idx];
258 TrigMip mip;
259 mip.setStartLayer(track.front()->layer());
260 mip.setEndLayer(track.back()->layer());
261 mip.setNHits(track.size());
262 mip.setLength(track.back()->layer() - track.front()->layer());
263 int holes = mip.length() - mip.nHits();
264 if (holes < 0) {
265 holes = 0;
266 }
267 mip.setNHoles(holes);
268
269 const float hole_fraction =
270 static_cast<float>(mip.nHoles()) / mip.length();
271
272 if (hole_fraction >= hole_fraction_max_) continue;
273
274 float total_isolation_e_sum = 0.0f;
275 for (const auto* hit : track) {
276 const int layer = hit->layer();
277 const float hit_x = hit->positionX();
278 const float hit_y = hit->positionY();
279 for (const auto& cand : layer_hits[layer]) {
280 if (&cand == hit) continue;
281 const float dx = cand.positionX() - hit_x;
282 const float dy = cand.positionY() - hit_y;
283 const float d_r_2 = dx * dx + dy * dy;
284 if (d_r_2 < radius_cut_2) {
285 total_isolation_e_sum += cand.energy();
286 }
287 }
288 }
289 mip.setSumEinIsolationRegion(total_isolation_e_sum);
290 mips.push_back(mip);
291 }
292
293 std::sort(mips.begin(), mips.end());
294 event.add(pass_coll_name_, mips);
295 }
296
297 auto end = std::chrono::high_resolution_clock::now();
298 auto time_diff = end - start;
299 processing_time_ +=
300 std::chrono::duration<double, std::milli>(time_diff).count();
301}
bool exists(const std::string &name, const std::string &passName, bool unique=true) const
Check for the existence of an object or collection with the given name and pass name in the event.