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