69 auto start = std::chrono::high_resolution_clock::now();
81 ldmx::EcalGeometry::CONDITIONS_OBJECT_NAME);
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 =
91 std::vector<double> recoil_e_p, recoil_y_p;
92 std::vector<float> recoil_e_pos, recoil_y_pos;
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.;
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;
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));
135 float energy = hit.getEnergy();
136 float layer_num =
id.layer();
137 rec_hit_list.push_back({x, y, z, layer_num, 0, energy});
140 if (event.
exists(
"TargetScoringPlaneHits", sp_pass_name_)) {
147 const std::vector<ldmx::SimTrackerHit> target_sp_hits =
150 float photon_p_zmax = 0, electron_p_zmax = 0;
153 if (hit_id.
plane() != 1 || sp_hit.getMomentum()[2] <= 0)
continue;
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];
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];
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])));
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])));
199 if (recoil_y_p.size() == 3 && recoil_y_p[2] != 0 &&
200 recoil_e_p.size() == 3 && recoil_e_p[2] != 0) {
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;
206 if (recoil_e_p[0] < 0 && recoil_e_p[1] > 0) {
207 true_phi_electron += 360;
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;
214 if (recoil_y_p[0] < 0 && recoil_y_p[1] > 0) {
215 true_phi_photon += 360;
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],
223 std::array<double, 2> phi_diff_photon_arr = {recoil_y_p[0],
225 std::array<double, 2> theta_diff_electron_arr = {recoil_e_p[2],
227 std::array<double, 2> theta_diff_photon_arr = {recoil_y_p[2],
230 true_theta_diff_electron_photon =
231 (180 / std::numbers::pi) *
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])) *
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) *
246 std::inner_product(phi_diff_electron_arr.begin(),
247 phi_diff_electron_arr.end(),
248 phi_diff_photon_arr.begin(), 0.0) /
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]))));
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;
265 std::vector<float> ele_roc = radius_68_theta_30_to_90;
269 std::vector<double> track_vec = {track.getSlopeX(), track.getSlopeY(), 1};
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;
287 for (std::array<float, 6>& hit : rec_hit_list) {
289 (hit[0] - (track.getSlopeX() * hit[2] + track.getInterceptX())) *
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]]) {
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;
303 for (
const auto& hit : rec_hit_list) {
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]);
319 if (phot_hit_list.size() >= 3 && ele_hit_list.size() >= 3) {
324 std::vector<double> x_guess = {
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 = {
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);
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,
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,
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;
363 else if (ele_hit_list.size() >= 3) {
364 if (progress_num != 3) {
368 polyfitXYvsZ(ele_hit_list_x, ele_hit_list_y, ele_hit_list_z, 1);
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];
381 for (
const auto& hit : phot_hit_list) {
382 rec_photon_shower_energy += hit[5];
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)};
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));
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));
402 (180 / std::numbers::pi) * std::atan(ele_params[1] / ele_params[0]);
403 if (ele_params[1] < 0) {
404 rec_phi_electron += 180;
406 if (ele_params[0] < 0 && ele_params[1] > 0) {
407 rec_phi_electron += 360;
410 (180 / std::numbers::pi) * std::atan(phot_params[1] / phot_params[0]);
411 if (phot_params[1] < 0) {
412 rec_phi_photon += 180;
414 if (phot_params[0] < 0 && phot_params[1] > 0) {
415 rec_phi_photon += 360;
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]))));
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(),
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]))));
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];
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)};
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));
482 (180 / std::numbers::pi) * std::atan(ele_params[1] / ele_params[0]);
483 if (ele_params[1] < 0) {
484 rec_phi_electron += 180;
486 if (ele_params[0] < 0 && ele_params[1] > 0) {
487 rec_phi_electron += 360;
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]))));
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.;
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);
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();