Process the event and put new data products into it.
67 {
68
69 auto start = std::chrono::high_resolution_clock::now();
70 nevents_++;
71
72
73
74
75
76
77 int progress_num = 0;
78
79
81 ldmx::EcalGeometry::CONDITIONS_OBJECT_NAME);
82
83
84 const std::vector<ldmx::EcalHit> ecal_rec_hits =
85 event.getCollection<
ldmx::EcalHit>(rec_coll_name_, rec_pass_name_);
86 const std::vector<ldmx::StraightTrack> linear_tracks =
88 track_pass_name_);
89
90
91 std::vector<double> recoil_e_p, recoil_y_p;
92 std::vector<float> recoil_e_pos, recoil_y_pos;
93
94
96
97
98 const std::vector<float> z_hat = {0, 0, 1};
99 float true_theta_electron = -9.;
100 float true_theta_photon = -9.;
101 float true_phi_electron = -9.;
102 float true_phi_photon = -9.;
103 float rec_theta_electron = -9.;
104 float rec_theta_photon = -9.;
105 float rec_phi_electron = -9.;
106 float rec_phi_photon = -9.;
107 float true_theta_diff_electron_photon = -9.;
108 float true_phi_diff_electron_photon = -9.;
109 float rec_theta_diff_electron_photon = -9.;
110 float rec_phi_diff_electron_photon = -9.;
111 float true_rec_theta_diff_electron = -9.;
112 float true_rec_phi_diff_electron = -9.;
113 float true_rec_theta_diff_photon = -9.;
114 float true_rec_phi_diff_photon = -9.;
115 float true_electron_shower_energy = -999.;
116 float true_photon_shower_energy = -999.;
117 float rec_electron_shower_energy = -999.;
118 float rec_photon_shower_energy = -999.;
119
120
121 std::vector<std::array<float, 6>> rec_hit_list;
122 std::vector<std::array<float, 6>> ele_hit_list;
123 std::vector<std::array<float, 6>> phot_hit_list;
124
125
129 auto [x, y, z] = std::apply(
130 [](double a, double b, double c) {
131 return std::make_tuple(static_cast<float>(a), static_cast<float>(b),
132 static_cast<float>(c));
133 },
134 pos);
135 float energy = hit.getEnergy();
136 float layer_num = id.layer();
137 rec_hit_list.push_back({x, y, z, layer_num, 0, energy});
138 }
139
140 if (event.
exists(
"TargetScoringPlaneHits", sp_pass_name_)) {
141
142
143
144
145
146
147 const std::vector<ldmx::SimTrackerHit> target_sp_hits =
149 sp_pass_name_);
150 float photon_p_zmax = 0, electron_p_zmax = 0;
153 if (hit_id.plane() != 1 || sp_hit.getMomentum()[2] <= 0) continue;
154
155 if (sp_hit.getPdgID() == 11) {
156 if (sp_hit.getMomentum()[2] > electron_p_zmax) {
157 recoil_e_p = sp_hit.getMomentum();
158 true_electron_shower_energy = sp_hit.getEnergy();
159 recoil_e_pos = sp_hit.getPosition();
160 electron_p_zmax = recoil_e_p[2];
161 }
162 }
163 if (sp_hit.getPdgID() == 22) {
164 if (sp_hit.getMomentum()[2] > photon_p_zmax) {
165 recoil_y_p = sp_hit.getMomentum();
166 true_photon_shower_energy = sp_hit.getEnergy();
167 recoil_y_pos = sp_hit.getPosition();
168 photon_p_zmax = recoil_y_p[2];
169 }
170 }
171 }
172
173
174 if (recoil_y_p.size() == 3 &&
175 std::sqrt((recoil_y_p[0]) * (recoil_y_p[0]) +
176 (recoil_y_p[1]) * (recoil_y_p[1]) +
177 (recoil_y_p[2]) * (recoil_y_p[2])) != 0 &&
178 recoil_e_p.size() == 3 &&
179 std::sqrt((recoil_e_p[0]) * (recoil_e_p[0]) +
180 (recoil_e_p[1]) * (recoil_e_p[1]) +
181 (recoil_e_p[2]) * (recoil_e_p[2])) != 0) {
182 true_theta_electron =
183 (180 / std::numbers::pi) *
184 std::acos(std::inner_product(recoil_e_p.begin(), recoil_e_p.end(),
185 z_hat.begin(), 0.0) /
186 std::sqrt((recoil_e_p[0]) * (recoil_e_p[0]) +
187 (recoil_e_p[1]) * (recoil_e_p[1]) +
188 (recoil_e_p[2]) * (recoil_e_p[2])));
189 true_theta_photon =
190 (180 / std::numbers::pi) *
191 std::acos(std::inner_product(recoil_y_p.begin(), recoil_y_p.end(),
192 z_hat.begin(), 0.0) /
193 std::sqrt((recoil_y_p[0]) * (recoil_y_p[0]) +
194 (recoil_y_p[1]) * (recoil_y_p[1]) +
195 (recoil_y_p[2]) * (recoil_y_p[2])));
196 }
197
198
199 if (recoil_y_p.size() == 3 && recoil_y_p[2] != 0 &&
200 recoil_e_p.size() == 3 && recoil_e_p[2] != 0) {
201 true_phi_electron =
202 (180 / std::numbers::pi) * std::atan(recoil_e_p[1] / recoil_e_p[0]);
203 if (recoil_e_p[1] < 0) {
204 true_phi_electron += 180;
205 }
206 if (recoil_e_p[0] < 0 && recoil_e_p[1] > 0) {
207 true_phi_electron += 360;
208 }
209 true_phi_photon =
210 (180 / std::numbers::pi) * std::atan(recoil_y_p[1] / recoil_y_p[0]);
211 if (recoil_y_p[1] < 0) {
212 true_phi_photon += 180;
213 }
214 if (recoil_y_p[0] < 0 && recoil_y_p[1] > 0) {
215 true_phi_photon += 360;
216 }
217 }
218
219
220 if (recoil_y_p.size() == 3 && recoil_e_p.size() == 3) {
221 std::array<double, 2> phi_diff_electron_arr = {recoil_e_p[0],
222 recoil_e_p[1]};
223 std::array<double, 2> phi_diff_photon_arr = {recoil_y_p[0],
224 recoil_y_p[1]};
225 std::array<double, 2> theta_diff_electron_arr = {recoil_e_p[2],
226 recoil_e_p[0]};
227 std::array<double, 2> theta_diff_photon_arr = {recoil_y_p[2],
228 recoil_y_p[0]};
229
230 true_theta_diff_electron_photon =
231 (180 / std::numbers::pi) *
232 std::acos(
233 std::inner_product(theta_diff_electron_arr.begin(),
234 theta_diff_electron_arr.end(),
235 theta_diff_photon_arr.begin(), 0.0) /
236 (std::sqrt((theta_diff_electron_arr[0]) *
237 (theta_diff_electron_arr[0]) +
238 (theta_diff_electron_arr[1]) *
239 (theta_diff_electron_arr[1])) *
240 std::sqrt(
241 (theta_diff_photon_arr[0]) * (theta_diff_photon_arr[0]) +
242 (theta_diff_photon_arr[1]) * (theta_diff_photon_arr[1]))));
243 true_phi_diff_electron_photon =
244 (180 / std::numbers::pi) *
245 std::acos(
246 std::inner_product(phi_diff_electron_arr.begin(),
247 phi_diff_electron_arr.end(),
248 phi_diff_photon_arr.begin(), 0.0) /
249 (std::sqrt(
250 (phi_diff_electron_arr[0]) * (phi_diff_electron_arr[0]) +
251 (phi_diff_electron_arr[1]) * (phi_diff_electron_arr[1])) *
252 std::sqrt((phi_diff_photon_arr[0]) * (phi_diff_photon_arr[0]) +
253 (phi_diff_photon_arr[1]) * (phi_diff_photon_arr[1]))));
254 }
255 }
256
257
258 std::pair<Eigen::VectorXd, Eigen::VectorXd> linear_fit_coeffs;
259 std::tuple<Eigen::VectorXd, float, int, Eigen::MatrixXd, int> best_x_result;
260 std::tuple<Eigen::VectorXd, float, int, Eigen::MatrixXd, int> best_y_result;
261 std::get<1>(best_x_result) = 10e99;
262 std::get<1>(best_y_result) = 10e99;
263
264
265 std::vector<float> ele_roc = radius_68_theta_30_to_90;
267 progress_num = 1;
268
269 std::vector<double> track_vec = {track.getSlopeX(), track.getSlopeY(), 1};
270 float track_theta =
271 (180 / std::numbers::pi) *
272 std::acos(std::inner_product(track_vec.begin(), track_vec.end(),
273 z_hat.begin(), 0.0) /
274 std::sqrt((track_vec[0]) * (track_vec[0]) +
275 (track_vec[1]) * (track_vec[1]) + 1));
276 if (track_theta <= 10) {
277 ele_roc = radius_68_theta_0_to_10;
278 } else if (track_theta > 10 && track_theta <= 15) {
279 ele_roc = radius_68_theta_10_to_15;
280 } else if (track_theta > 15 && track_theta <= 20) {
281 ele_roc = radius_68_theta_15_to_20;
282 } else if (track_theta > 20 && track_theta <= 30) {
283 ele_roc = radius_68_theta_20_to_30;
284 }
285
286
287 for (std::array<float, 6>& hit : rec_hit_list) {
288 if (std::sqrt(
289 (hit[0] - (track.getSlopeX() * hit[2] + track.getInterceptX())) *
290 (hit[0] -
291 (track.getSlopeX() * hit[2] + track.getInterceptX())) +
292 (hit[1] - (track.getSlopeY() * hit[2] + track.getInterceptY())) *
293 (hit[1] - (track.getSlopeY() * hit[2] +
294 track.getInterceptY()))) < ele_roc[hit[3]]) {
295 hit[4] = 1;
296 }
297 }
298
299 std::vector<float> ele_hit_list_x, ele_hit_list_y, ele_hit_list_z;
300 std::vector<float> phot_hit_list_x, phot_hit_list_y, phot_hit_list_z;
301
302
303 for (const auto& hit : rec_hit_list) {
304 if (hit[4] == 1) {
305 ele_hit_list.push_back(hit);
306 ele_hit_list_x.push_back(hit[0]);
307 ele_hit_list_y.push_back(hit[1]);
308 ele_hit_list_z.push_back(hit[2]);
309 } else if (hit[4] == 0) {
310 phot_hit_list.push_back(hit);
311 phot_hit_list_x.push_back(hit[0]);
312 phot_hit_list_y.push_back(hit[1]);
313 phot_hit_list_z.push_back(hit[2]);
314 }
315 }
316
317
318
319 if (phot_hit_list.size() >= 3 && ele_hit_list.size() >= 3) {
320 progress_num =
321 3;
322
323
324 std::vector<double> x_guess = {
325 track.getSlopeX(),
326 (phot_hit_list.back()[0] - phot_hit_list[0][0]) /
327 (phot_hit_list.back()[2] - phot_hit_list[0][2]),
328 track.getInterceptX()};
329 std::vector<double> y_guess = {
330 track.getSlopeY(),
331 (phot_hit_list.back()[1] - phot_hit_list[0][1]) /
332 (phot_hit_list.back()[2] - phot_hit_list[0][2]),
333 track.getInterceptY()};
334 std::vector<float> phot_hit_error(phot_hit_list.size(),
335 0.456435464588 * 4.816);
336 std::vector<float> ele_hit_error(ele_hit_list.size(),
337 0.456435464588 * 4.816);
338
339 int max_iter = 200;
340
341 std::tuple<Eigen::VectorXd, float, int, Eigen::MatrixXd, int> x_result =
342 fit2DTracksConstrained(ele_hit_list_z, ele_hit_list_x, ele_hit_error,
343 phot_hit_list_z, phot_hit_list_x,
344 phot_hit_error, x_guess, max_iter, 0, 0.001,
345 10.0);
346
347 std::tuple<Eigen::VectorXd, float, int, Eigen::MatrixXd, int> y_result =
348 fit2DTracksConstrained(ele_hit_list_z, ele_hit_list_y, ele_hit_error,
349 phot_hit_list_z, phot_hit_list_y,
350 phot_hit_error, y_guess, max_iter, 0, 0.001,
351 40.0);
352
353
354 if ((std::get<1>(x_result) + std::get<1>(y_result)) / 2 <
355 (std::get<1>(best_x_result) + std::get<1>(best_y_result)) / 2) {
356 best_x_result = x_result;
357 best_y_result = y_result;
358 }
359 }
360
361
362
363 else if (ele_hit_list.size() >= 3) {
364 if (progress_num != 3) {
365 progress_num = 2;
366
367 linear_fit_coeffs =
368 polyfitXYvsZ(ele_hit_list_x, ele_hit_list_y, ele_hit_list_z, 1);
369 }
370 }
371 }
372
373
374
375 if (std::get<0>(best_x_result).size() != 0) {
376 rec_electron_shower_energy = 0;
377 rec_photon_shower_energy = 0;
378 for (const auto& hit : ele_hit_list) {
379 rec_electron_shower_energy += hit[5];
380 }
381 for (const auto& hit : phot_hit_list) {
382 rec_photon_shower_energy += hit[5];
383 }
384
385 std::vector<double> ele_params = {std::get<0>(best_x_result)(0),
386 std::get<0>(best_y_result)(0)};
387 std::vector<double> phot_params = {std::get<0>(best_x_result)(1),
388 std::get<0>(best_y_result)(1)};
389 std::vector<double> ele_params_x = {std::get<0>(best_x_result)(0)};
390 std::vector<double> phot_params_x = {std::get<0>(best_x_result)(1)};
391
392 rec_theta_electron =
393 (180 / std::numbers::pi) *
394 std::acos(1 / std::sqrt((ele_params[0]) * (ele_params[0]) +
395 (ele_params[1]) * (ele_params[1]) + 1));
396 rec_theta_photon =
397 (180 / std::numbers::pi) *
398 std::acos(1 / std::sqrt((phot_params[0]) * (phot_params[0]) +
399 (phot_params[1]) * (phot_params[1]) + 1));
400
401 rec_phi_electron =
402 (180 / std::numbers::pi) * std::atan(ele_params[1] / ele_params[0]);
403 if (ele_params[1] < 0) {
404 rec_phi_electron += 180;
405 }
406 if (ele_params[0] < 0 && ele_params[1] > 0) {
407 rec_phi_electron += 360;
408 }
409 rec_phi_photon =
410 (180 / std::numbers::pi) * std::atan(phot_params[1] / phot_params[0]);
411 if (phot_params[1] < 0) {
412 rec_phi_photon += 180;
413 }
414 if (phot_params[0] < 0 && phot_params[1] > 0) {
415 rec_phi_photon += 360;
416 }
417
418 rec_theta_diff_electron_photon =
419 (180 / std::numbers::pi) *
420 std::acos(std::inner_product(ele_params_x.begin(), ele_params_x.end(),
421 phot_params_x.begin(), 1.0) /
422 (std::sqrt((ele_params_x[0]) * (ele_params_x[0]) + (1)) *
423 std::sqrt((phot_params_x[0]) * (phot_params_x[0]) + 1)));
424 rec_phi_diff_electron_photon =
425 (180 / std::numbers::pi) *
426 std::acos(std::inner_product(ele_params.begin(), ele_params.end(),
427 phot_params.begin(), 0.0) /
428 (std::sqrt((ele_params[0]) * (ele_params[0]) +
429 (ele_params[1]) * (ele_params[1])) *
430 std::sqrt((phot_params[0]) * (phot_params[0]) +
431 (phot_params[1]) * (phot_params[1]))));
432
433 if (recoil_y_p.size() == 3 && recoil_y_p[2] != 0 &&
434 recoil_e_p.size() == 3 && recoil_e_p[2] != 0) {
435 true_rec_theta_diff_electron =
436 (180 / std::numbers::pi) *
437 std::acos(std::inner_product(ele_params_x.begin(), ele_params_x.end(),
438 recoil_e_p.begin(), recoil_e_p[2]) /
439 (std::sqrt((ele_params_x[0]) * (ele_params_x[0]) + 1) *
440 std::sqrt((recoil_e_p[0]) * (recoil_e_p[0]) +
441 (recoil_e_p[2]) * (recoil_e_p[2]))));
442 true_rec_theta_diff_photon =
443 (180 / std::numbers::pi) *
444 std::acos(std::inner_product(phot_params_x.begin(),
445 phot_params_x.end(), recoil_y_p.begin(),
446 recoil_y_p[2]) /
447 (std::sqrt((phot_params_x[0]) * (phot_params_x[0]) + 1) *
448 std::sqrt((recoil_y_p[0]) * (recoil_y_p[0]) +
449 (recoil_y_p[2]) * (recoil_y_p[2]))));
450 true_rec_phi_diff_electron =
451 (180 / std::numbers::pi) *
452 std::acos(std::inner_product(ele_params.begin(), ele_params.end(),
453 recoil_e_p.begin(), 0) /
454 (std::sqrt((ele_params[0]) * (ele_params[0]) +
455 (ele_params[1]) * (ele_params[1])) *
456 std::sqrt((recoil_e_p[0]) * (recoil_e_p[0]) +
457 (recoil_e_p[1]) * (recoil_e_p[1]))));
458 true_rec_phi_diff_photon =
459 (180 / std::numbers::pi) *
460 std::acos(std::inner_product(phot_params.begin(), phot_params.end(),
461 recoil_y_p.begin(), 0) /
462 (std::sqrt((phot_params[0]) * (phot_params[0]) +
463 (phot_params[1]) * (phot_params[1])) *
464 std::sqrt((recoil_y_p[0]) * (recoil_y_p[0]) +
465 (recoil_y_p[1]) * (recoil_y_p[1]))));
466 }
467 } else if (progress_num == 2) {
468 rec_electron_shower_energy = 0;
469 for (const auto& hit : ele_hit_list) {
470 rec_electron_shower_energy += hit[5];
471 }
472
473 std::vector<double> ele_params = {linear_fit_coeffs.first(1),
474 linear_fit_coeffs.second(1)};
475 std::vector<double> ele_params_x = {linear_fit_coeffs.first(1)};
476
477 rec_theta_electron =
478 (180 / std::numbers::pi) *
479 std::acos(1 / std::sqrt((ele_params[0]) * (ele_params[0]) +
480 (ele_params[1]) * (ele_params[1]) + 1));
481 rec_phi_electron =
482 (180 / std::numbers::pi) * std::atan(ele_params[1] / ele_params[0]);
483 if (ele_params[1] < 0) {
484 rec_phi_electron += 180;
485 }
486 if (ele_params[0] < 0 && ele_params[1] > 0) {
487 rec_phi_electron += 360;
488 }
489
490 if (recoil_y_p.size() == 3 && recoil_y_p[2] != 0 &&
491 recoil_e_p.size() == 3 && recoil_e_p[2] != 0) {
492 true_rec_theta_diff_electron =
493 (180 / std::numbers::pi) *
494 std::acos(std::inner_product(ele_params_x.begin(), ele_params_x.end(),
495 recoil_e_p.begin(), recoil_e_p[2]) /
496 (std::sqrt((ele_params_x[0]) * (ele_params_x[0]) + 1) *
497 std::sqrt((recoil_e_p[0]) * (recoil_e_p[0]) +
498 (recoil_e_p[2]) * (recoil_e_p[2]))));
499 true_rec_phi_diff_electron =
500 (180 / std::numbers::pi) *
501 std::acos(std::inner_product(ele_params.begin(), ele_params.end(),
502 recoil_e_p.begin(), 0) /
503 (std::sqrt((ele_params[0]) * (ele_params[0]) +
504 (ele_params[1]) * (ele_params[1])) *
505 std::sqrt((recoil_e_p[0]) * (recoil_e_p[0]) +
506 (recoil_e_p[1]) * (recoil_e_p[1]))));
507 }
508
509
510
511 rec_theta_photon = -5.;
512 rec_phi_photon = -5.;
513 rec_theta_diff_electron_photon = -5.;
514 rec_phi_diff_electron_photon = -5.;
515 true_rec_theta_diff_photon = -5.;
516 true_rec_phi_diff_photon = -5.;
517 }
518
519
520 result.setVariables(
521 true_theta_electron, true_theta_photon, true_phi_electron,
522 true_phi_photon, rec_theta_electron, rec_theta_photon, rec_phi_electron,
523 rec_phi_photon, true_theta_diff_electron_photon,
524 true_phi_diff_electron_photon, rec_theta_diff_electron_photon,
525 rec_phi_diff_electron_photon, true_rec_theta_diff_electron,
526 true_rec_phi_diff_electron, true_rec_theta_diff_photon,
527 true_rec_phi_diff_photon, true_electron_shower_energy,
528 true_photon_shower_energy, rec_electron_shower_energy,
529 rec_photon_shower_energy, progress_num);
530
532
533
534 auto end = std::chrono::high_resolution_clock::now();
535 auto diff = end - start;
536 processing_time_ += std::chrono::duration<float, std::milli>(diff).count();
537}
const T & getCondition(const std::string &condition_name)
Access a conditions object for the current event.
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.
Translation between real-space positions and cell IDs within the ECal.
std::tuple< double, double, double > getPosition(EcalID id) const
Get a cell's position from its ID number.
Stores reconstructed hit information from the ECAL.
Extension of DetectorID providing access to ECal layers and cell numbers in a hex grid.
Implements detector ids for special simulation-derived hits like scoring planes.
Represents a simulated tracker hit in the simulation.