81 auto start = std::chrono::high_resolution_clock::now();
93 ldmx::EcalGeometry::CONDITIONS_OBJECT_NAME);
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 =
103 std::vector<double> recoil_e_p, recoil_y_p;
104 std::vector<float> recoil_e_pos, recoil_y_pos;
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.;
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;
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));
147 float energy = hit.getEnergy();
148 float layer_num =
id.layer();
149 rec_hit_list.push_back({x_, y_, z_, layer_num, 0, energy});
152 if (event.
exists(
"TargetScoringPlaneHits", sp_pass_name_)) {
159 const std::vector<ldmx::SimTrackerHit> target_sp_hits =
162 float photon_p_zmax = 0, electron_p_zmax = 0;
165 if (hit_id.
plane() != 1 || sp_hit.getMomentum()[2] <= 0)
continue;
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];
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];
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])));
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])));
211 if (recoil_y_p.size() == 3 && recoil_y_p[2] != 0 &&
212 recoil_e_p.size() == 3 && recoil_e_p[2] != 0) {
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;
218 if (recoil_e_p[0] < 0 && recoil_e_p[1] > 0) {
219 true_phi_electron += 360;
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;
226 if (recoil_y_p[0] < 0 && recoil_y_p[1] > 0) {
227 true_phi_photon += 360;
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],
235 std::array<double, 2> phi_diff_photon_arr = {recoil_y_p[0],
237 std::array<double, 2> theta_diff_electron_arr = {recoil_e_p[2],
239 std::array<double, 2> theta_diff_photon_arr = {recoil_y_p[2],
242 true_theta_diff_electron_photon =
243 (180 / std::numbers::pi) *
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])) *
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) *
258 std::inner_product(phi_diff_electron_arr.begin(),
259 phi_diff_electron_arr.end(),
260 phi_diff_photon_arr.begin(), 0.0) /
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]))));
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;
277 std::vector<float> ele_roc = RADIUS_68_THETA_30_TO_90;
281 std::vector<double> track_vec = {track.getSlopeX(), track.getSlopeY(), 1};
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;
299 for (std::array<float, 6>& hit : rec_hit_list) {
301 (hit[0] - (track.getSlopeX() * hit[2] + track.getInterceptX())) *
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]]) {
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;
315 for (
const auto& hit : rec_hit_list) {
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]);
331 if (phot_hit_list.size() >= 3 && ele_hit_list.size() >= 3) {
336 std::vector<double> x_guess = {
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 = {
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);
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,
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,
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;
375 else if (ele_hit_list.size() >= 3) {
376 if (progress_num != 3) {
380 polyfitXYvsZ(ele_hit_list_x, ele_hit_list_y, ele_hit_list_z, 1);
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];
393 for (
const auto& hit : phot_hit_list) {
394 rec_photon_shower_energy += hit[5];
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)};
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));
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));
414 (180 / std::numbers::pi) * std::atan(ele_params[1] / ele_params[0]);
415 if (ele_params[1] < 0) {
416 rec_phi_electron += 180;
418 if (ele_params[0] < 0 && ele_params[1] > 0) {
419 rec_phi_electron += 360;
422 (180 / std::numbers::pi) * std::atan(phot_params[1] / phot_params[0]);
423 if (phot_params[1] < 0) {
424 rec_phi_photon += 180;
426 if (phot_params[0] < 0 && phot_params[1] > 0) {
427 rec_phi_photon += 360;
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]))));
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(),
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]))));
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];
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)};
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));
494 (180 / std::numbers::pi) * std::atan(ele_params[1] / ele_params[0]);
495 if (ele_params[1] < 0) {
496 rec_phi_electron += 180;
498 if (ele_params[0] < 0 && ele_params[1] > 0) {
499 rec_phi_electron += 360;
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]))));
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.;
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);
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();