Process the event and put new data products into it.
172 {
173
175 ldmx::EcalGeometry::CONDITIONS_OBJECT_NAME);
176
178
179 clearProcessor();
180
181
182
183
184 std::vector<double> recoilP;
185 std::vector<float> recoilPos;
186 std::vector<double> recoilPAtTarget;
187 std::vector<float> recoilPosAtTarget;
188
189 if (verbose_) {
190 ldmx_log(debug) << " Loop through all of the sim particles and find the "
191 "recoil electron";
192 }
193
194 if (event.
exists(
"EcalScoringPlaneHits")) {
195
196
197
198
199
201
202
204
205
206 auto ecalSpHits{
208 float pmax = 0;
211 if (hit_id.plane() != 31 || spHit.getMomentum()[2] <= 0) continue;
212
213 if (spHit.getTrackID() == recoilTrackID) {
214 if (sqrt(pow(spHit.getMomentum()[0], 2) +
215 pow(spHit.getMomentum()[1], 2) +
216 pow(spHit.getMomentum()[2], 2)) > pmax) {
217 recoilP = spHit.getMomentum();
218 recoilPos = spHit.getPosition();
219 pmax = sqrt(pow(recoilP[0], 2) + pow(recoilP[1], 2) +
220 pow(recoilP[2], 2));
221 }
222 }
223 }
224
225
226 if (event.
exists(
"TargetScoringPlaneHits")) {
227 std::vector<ldmx::SimTrackerHit> targetSpHits =
229 pmax = 0;
232 if (hit_id.plane() != 1 || spHit.getMomentum()[2] <= 0) continue;
233
234 if (spHit.getTrackID() == recoilTrackID) {
235 if (sqrt(pow(spHit.getMomentum()[0], 2) +
236 pow(spHit.getMomentum()[1], 2) +
237 pow(spHit.getMomentum()[2], 2)) > pmax) {
238 recoilPAtTarget = spHit.getMomentum();
239 recoilPosAtTarget = spHit.getPosition();
240 pmax =
241 sqrt(pow(recoilPAtTarget[0], 2) + pow(recoilPAtTarget[1], 2) +
242 pow(recoilPAtTarget[2], 2));
243 }
244 }
245 }
246 }
247 }
248
249 if (recoil_from_tracking_) {
250 std::vector<float> recoil_track_states;
251 if (verbose_) {
252 ldmx_log(debug) << " Propagate recoil tracks to ECAL face";
253 }
254
255 auto recoil_tracks{
event.getCollection<
ldmx::Track>(track_collection_)};
256
257 ldmx::TrackStateType ts_type = ldmx::TrackStateType::AtECAL;
258 recoil_track_states =
trackProp(recoil_tracks, ts_type,
"ecal");
259
260
261 recoilPos = recoil_track_states;
262 }
263
264 if (verbose_) {
265 ldmx_log(debug) << " Get projected trajectories for electron and photon";
266 }
267
268 std::vector<XYCoords> ele_trajectory, photon_trajectory;
269 if (!recoilP.empty() && !recoilPos.empty()) {
270 ele_trajectory = getTrajectory(recoilP, recoilPos);
271 std::vector<double> pvec = recoilPAtTarget.size()
272 ? recoilPAtTarget
273 : std::vector<double>{0.0, 0.0, 0.0};
274 std::vector<float> posvec = recoilPosAtTarget.size()
275 ? recoilPosAtTarget
276 : std::vector<float>{0.0, 0.0, 0.0};
277 photon_trajectory =
278 getTrajectory({-pvec[0], -pvec[1], beamEnergyMeV_ - pvec[2]}, posvec);
279 }
280
281 float recoilPMag =
282 recoilP.size()
283 ? sqrt(pow(recoilP[0], 2) + pow(recoilP[1], 2) + pow(recoilP[2], 2))
284 : -1.0;
285 float recoilTheta =
286 recoilPMag > 0 ? acos(recoilP[2] / recoilPMag) * 180.0 / M_PI : -1.0;
287
288 if (verbose_) {
289 ldmx_log(debug) << " Build Radii of containment (ROC)";
290 }
291
292 std::vector<double> roc_values_bin0(roc_range_values_[0].begin() + 4,
293 roc_range_values_[0].end());
294 std::vector<double> ele_radii = roc_values_bin0;
295 double theta_min, theta_max, p_min, p_max;
296 bool inrange;
297
298 for (int i = 0; i < roc_range_values_.size(); i++) {
299 theta_min = roc_range_values_[i][0];
300 theta_max = roc_range_values_[i][1];
301 p_min = roc_range_values_[i][2];
302 p_max = roc_range_values_[i][3];
303 inrange = true;
304
305 if (theta_min != -1.0) {
306 inrange = inrange && (recoilTheta >= theta_min);
307 }
308 if (theta_max != -1.0) {
309 inrange = inrange && (recoilTheta < theta_max);
310 }
311 if (p_min != -1.0) {
312 inrange = inrange && (recoilPMag >= p_min);
313 }
314 if (p_max != -1.0) {
315 inrange = inrange && (recoilPMag < p_max);
316 }
317 if (inrange) {
318 std::vector<double> roc_values_bini(roc_range_values_[i].begin() + 4,
319 roc_range_values_[i].end());
320 ele_radii = roc_values_bini;
321 }
322 }
323
324 std::vector<double> photon_radii = roc_values_bin0;
325
326
327 const std::vector<ldmx::EcalHit> ecalRecHits =
328 event.getCollection<
ldmx::EcalHit>(rec_coll_name_, rec_pass_name_);
329
331 GetShowerCentroidIDAndRMS(ecalRecHits, showerRMS_);
332
334 bool doTight = true;
335
336 fillIsolatedHitMap(ecalRecHits, globalCentroid, cellMap_, cellMapTightIso_,
337 doTight);
338
339
340
341
342 float wavgLayerHit = 0;
343 float xMean = 0;
344 float yMean = 0;
345
346
347 unsigned int nregions = 5;
348 std::vector<float> electronContainmentEnergy(nregions, 0.0);
349 std::vector<float> photonContainmentEnergy(nregions, 0.0);
350 std::vector<float> outsideContainmentEnergy(nregions, 0.0);
351 std::vector<int> outsideContainmentNHits(nregions, 0);
352 std::vector<float> outsideContainmentXmean(nregions, 0.0);
353 std::vector<float> outsideContainmentYmean(nregions, 0.0);
354 std::vector<float> outsideContainmentXstd(nregions, 0.0);
355 std::vector<float> outsideContainmentYstd(nregions, 0.0);
356
357 std::vector<int> segLayers = {0, 6, 17, 34};
358 unsigned int nsegments = segLayers.size() - 1;
359 std::vector<float> energySeg(nsegments, 0.0);
360 std::vector<float> xMeanSeg(nsegments, 0.0);
361 std::vector<float> xStdSeg(nsegments, 0.0);
362 std::vector<float> yMeanSeg(nsegments, 0.0);
363 std::vector<float> yStdSeg(nsegments, 0.0);
364 std::vector<float> layerMeanSeg(nsegments, 0.0);
365 std::vector<float> layerStdSeg(nsegments, 0.0);
366 std::vector<std::vector<float>> eContEnergy(
367 nregions, std::vector<float>(nsegments, 0.0));
368 std::vector<std::vector<float>> eContXMean(
369 nregions, std::vector<float>(nsegments, 0.0));
370 std::vector<std::vector<float>> eContYMean(
371 nregions, std::vector<float>(nsegments, 0.0));
372 std::vector<std::vector<float>> gContEnergy(
373 nregions, std::vector<float>(nsegments, 0.0));
374 std::vector<std::vector<int>> gContNHits(nregions,
375 std::vector<int>(nsegments, 0));
376 std::vector<std::vector<float>> gContXMean(
377 nregions, std::vector<float>(nsegments, 0.0));
378 std::vector<std::vector<float>> gContYMean(
379 nregions, std::vector<float>(nsegments, 0.0));
380 std::vector<std::vector<float>> oContEnergy(
381 nregions, std::vector<float>(nsegments, 0.0));
382 std::vector<std::vector<int>> oContNHits(nregions,
383 std::vector<int>(nsegments, 0));
384 std::vector<std::vector<float>> oContXMean(
385 nregions, std::vector<float>(nsegments, 0.0));
386 std::vector<std::vector<float>> oContYMean(
387 nregions, std::vector<float>(nsegments, 0.0));
388 std::vector<std::vector<float>> oContXStd(nregions,
389 std::vector<float>(nsegments, 0.0));
390 std::vector<std::vector<float>> oContYStd(nregions,
391 std::vector<float>(nsegments, 0.0));
392 std::vector<std::vector<float>> oContLayerMean(
393 nregions, std::vector<float>(nsegments, 0.0));
394 std::vector<std::vector<float>> oContLayerStd(
395 nregions, std::vector<float>(nsegments, 0.0));
396
397
398
399
400 std::vector<HitData> trackingHitList;
401
402 if (verbose_) {
403 ldmx_log(debug)
404 << " Loop over the hits from the event to calculate the BDT features";
405 }
406
408
410 ecalLayerEdepRaw_[id.layer()] =
411 ecalLayerEdepRaw_[id.layer()] + hit.getEnergy();
412 if (id.layer() >= 20) ecalBackEnergy_ += hit.getEnergy();
413 if (maxCellDep_ < hit.getEnergy()) maxCellDep_ = hit.getEnergy();
414 if (hit.getEnergy() <= 0) {
415 ldmx_log(fatal)
416 << "ECal hit has negative or zero energy, this should never happen, "
417 "check the threshold settings in HgcrocEmulator";
418 continue;
419 }
420 nReadoutHits_++;
421 ecalLayerEdepReadout_[id.layer()] += hit.getEnergy();
422 ecalLayerTime_[id.layer()] += (hit.getEnergy()) * hit.getTime();
424 xMean += x * hit.getEnergy();
425 yMean += y * hit.getEnergy();
426 avgLayerHit_ += id.layer();
427 wavgLayerHit += id.layer() * hit.getEnergy();
428 if (deepestLayerHit_ < id.layer()) {
429 deepestLayerHit_ = id.layer();
430 }
431 XYCoords xy_pair = std::make_pair(x, y);
432 float distance_ele_trajectory =
433 ele_trajectory.size()
434 ? sqrt(pow((xy_pair.first - ele_trajectory[id.layer()].first), 2) +
435 pow((xy_pair.second - ele_trajectory[id.layer()].second), 2))
436 : -1.0;
437 float distance_photon_trajectory =
438 photon_trajectory.size()
439 ? sqrt(pow((xy_pair.first - photon_trajectory[id.layer()].first),
440 2) +
441 pow((xy_pair.second - photon_trajectory[id.layer()].second),
442 2))
443 : -1.0;
444
445
446 for (unsigned int iseg = 0; iseg < nsegments; iseg++) {
447 if (id.layer() >= segLayers[iseg] &&
448 id.layer() <= segLayers[iseg + 1] - 1) {
449 energySeg[iseg] += hit.getEnergy();
450 xMeanSeg[iseg] += xy_pair.first * hit.getEnergy();
451 yMeanSeg[iseg] += xy_pair.second * hit.getEnergy();
452 layerMeanSeg[iseg] += id.layer() * hit.getEnergy();
453
454
455 for (unsigned int ireg = 0; ireg < nregions; ireg++) {
456 if (distance_ele_trajectory >= ireg * ele_radii[id.layer()] &&
457 distance_ele_trajectory < (ireg + 1) * ele_radii[id.layer()]) {
458 eContEnergy[ireg][iseg] += hit.getEnergy();
459 eContXMean[ireg][iseg] += xy_pair.first * hit.getEnergy();
460 eContYMean[ireg][iseg] += xy_pair.second * hit.getEnergy();
461 }
462 if (distance_photon_trajectory >= ireg * photon_radii[id.layer()] &&
463 distance_photon_trajectory <
464 (ireg + 1) * photon_radii[id.layer()]) {
465 gContEnergy[ireg][iseg] += hit.getEnergy();
466 gContNHits[ireg][iseg] += 1;
467 gContXMean[ireg][iseg] += xy_pair.first * hit.getEnergy();
468 gContYMean[ireg][iseg] += xy_pair.second * hit.getEnergy();
469 }
470 if (distance_ele_trajectory > (ireg + 1) * ele_radii[id.layer()] &&
471 distance_photon_trajectory >
472 (ireg + 1) * photon_radii[id.layer()]) {
473 oContEnergy[ireg][iseg] += hit.getEnergy();
474 oContNHits[ireg][iseg] += 1;
475 oContXMean[ireg][iseg] += xy_pair.first * hit.getEnergy();
476 oContYMean[ireg][iseg] += xy_pair.second * hit.getEnergy();
477 oContLayerMean[ireg][iseg] += id.layer() * hit.getEnergy();
478 }
479 }
480 }
481 }
482
483
484 for (unsigned int ireg = 0; ireg < nregions; ireg++) {
485 if (distance_ele_trajectory >= ireg * ele_radii[id.layer()] &&
486 distance_ele_trajectory < (ireg + 1) * ele_radii[id.layer()])
487 electronContainmentEnergy[ireg] += hit.getEnergy();
488 if (distance_photon_trajectory >= ireg * photon_radii[id.layer()] &&
489 distance_photon_trajectory < (ireg + 1) * photon_radii[id.layer()])
490 photonContainmentEnergy[ireg] += hit.getEnergy();
491 if (distance_ele_trajectory > (ireg + 1) * ele_radii[id.layer()] &&
492 distance_photon_trajectory > (ireg + 1) * photon_radii[id.layer()]) {
493 outsideContainmentEnergy[ireg] += hit.getEnergy();
494 outsideContainmentNHits[ireg] += 1;
495 outsideContainmentXmean[ireg] += xy_pair.first * hit.getEnergy();
496 outsideContainmentYmean[ireg] += xy_pair.second * hit.getEnergy();
497 }
498 }
499
500
501
502 if (distance_ele_trajectory >= ele_radii[id.layer()] ||
503 distance_ele_trajectory == -1.0) {
504 HitData hd;
505 hd.pos = TVector3(xy_pair.first, xy_pair.second,
507 hd.layer = id.layer();
508 trackingHitList.push_back(hd);
509 }
510 }
511
512 for (const auto &[id, energy] : cellMapTightIso_) {
513 if (energy > 0) summedTightIso_ += energy;
514 }
515
516 for (int iLayer = 0; iLayer < ecalLayerEdepReadout_.size(); iLayer++) {
517 ecalLayerTime_[iLayer] =
518 ecalLayerTime_[iLayer] / ecalLayerEdepReadout_[iLayer];
519 summedDet_ += ecalLayerEdepReadout_[iLayer];
520 }
521
522 if (nReadoutHits_ > 0) {
523 avgLayerHit_ /= nReadoutHits_;
524 wavgLayerHit /= summedDet_;
525 xMean /= summedDet_;
526 yMean /= summedDet_;
527 } else {
528 wavgLayerHit = 0;
529 avgLayerHit_ = 0;
530 xMean = 0;
531 yMean = 0;
532 }
533
534
535 for (unsigned int iseg = 0; iseg < nsegments; iseg++) {
536 if (energySeg[iseg] > 0) {
537 xMeanSeg[iseg] /= energySeg[iseg];
538 yMeanSeg[iseg] /= energySeg[iseg];
539 layerMeanSeg[iseg] /= energySeg[iseg];
540 }
541 for (unsigned int ireg = 0; ireg < nregions; ireg++) {
542 if (eContEnergy[ireg][iseg] > 0) {
543 eContXMean[ireg][iseg] /= eContEnergy[ireg][iseg];
544 eContYMean[ireg][iseg] /= eContEnergy[ireg][iseg];
545 }
546 if (gContEnergy[ireg][iseg] > 0) {
547 gContXMean[ireg][iseg] /= gContEnergy[ireg][iseg];
548 gContYMean[ireg][iseg] /= gContEnergy[ireg][iseg];
549 }
550 if (oContEnergy[ireg][iseg] > 0) {
551 oContXMean[ireg][iseg] /= oContEnergy[ireg][iseg];
552 oContYMean[ireg][iseg] /= oContEnergy[ireg][iseg];
553 oContLayerMean[ireg][iseg] /= oContEnergy[ireg][iseg];
554 }
555 }
556 }
557
558 for (unsigned int ireg = 0; ireg < nregions; ireg++) {
559 if (outsideContainmentEnergy[ireg] > 0) {
560 outsideContainmentXmean[ireg] /= outsideContainmentEnergy[ireg];
561 outsideContainmentYmean[ireg] /= outsideContainmentEnergy[ireg];
562 }
563 }
564
565
569 if (hit.getEnergy() > 0) {
570 xStd_ += pow((x - xMean), 2) * hit.getEnergy();
571 yStd_ += pow((y - yMean), 2) * hit.getEnergy();
572 stdLayerHit_ += pow((id.layer() - wavgLayerHit), 2) * hit.getEnergy();
573 }
574 XYCoords xy_pair = std::make_pair(x, y);
575 float distance_ele_trajectory =
576 ele_trajectory.size()
577 ? sqrt(pow((xy_pair.first - ele_trajectory[id.layer()].first), 2) +
578 pow((xy_pair.second - ele_trajectory[id.layer()].second), 2))
579 : -1.0;
580 float distance_photon_trajectory =
581 photon_trajectory.size()
582 ? sqrt(pow((xy_pair.first - photon_trajectory[id.layer()].first),
583 2) +
584 pow((xy_pair.second - photon_trajectory[id.layer()].second),
585 2))
586 : -1.0;
587
588 for (unsigned int iseg = 0; iseg < nsegments; iseg++) {
589 if (id.layer() >= segLayers[iseg] &&
590 id.layer() <= segLayers[iseg + 1] - 1) {
591 xStdSeg[iseg] +=
592 pow((xy_pair.first - xMeanSeg[iseg]), 2) * hit.getEnergy();
593 yStdSeg[iseg] +=
594 pow((xy_pair.second - yMeanSeg[iseg]), 2) * hit.getEnergy();
595 layerStdSeg[iseg] +=
596 pow((id.layer() - layerMeanSeg[iseg]), 2) * hit.getEnergy();
597
598 for (unsigned int ireg = 0; ireg < nregions; ireg++) {
599 if (distance_ele_trajectory > (ireg + 1) * ele_radii[id.layer()] &&
600 distance_photon_trajectory >
601 (ireg + 1) * photon_radii[id.layer()]) {
602 oContXStd[ireg][iseg] +=
603 pow((xy_pair.first - oContXMean[ireg][iseg]), 2) *
604 hit.getEnergy();
605 oContYStd[ireg][iseg] +=
606 pow((xy_pair.second - oContYMean[ireg][iseg]), 2) *
607 hit.getEnergy();
608 oContLayerStd[ireg][iseg] +=
609 pow((id.layer() - oContLayerMean[ireg][iseg]), 2) *
610 hit.getEnergy();
611 }
612 }
613 }
614 }
615
616 for (unsigned int ireg = 0; ireg < nregions; ireg++) {
617 if (distance_ele_trajectory > (ireg + 1) * ele_radii[id.layer()] &&
618 distance_photon_trajectory > (ireg + 1) * photon_radii[id.layer()]) {
619 outsideContainmentXstd[ireg] +=
620 pow((xy_pair.first - outsideContainmentXmean[ireg]), 2) *
621 hit.getEnergy();
622 outsideContainmentYstd[ireg] +=
623 pow((xy_pair.second - outsideContainmentYmean[ireg]), 2) *
624 hit.getEnergy();
625 }
626 }
627 }
628
629 if (nReadoutHits_ > 0) {
630 xStd_ = sqrt(xStd_ / summedDet_);
631 yStd_ = sqrt(yStd_ / summedDet_);
632 stdLayerHit_ = sqrt(stdLayerHit_ / summedDet_);
633 } else {
634 xStd_ = 0;
635 yStd_ = 0;
636 stdLayerHit_ = 0;
637 }
638
639
640
641 for (unsigned int iseg = 0; iseg < nsegments; iseg++) {
642 if (energySeg[iseg] > 0) {
643 xStdSeg[iseg] = sqrt(xStdSeg[iseg] / energySeg[iseg]);
644 yStdSeg[iseg] = sqrt(yStdSeg[iseg] / energySeg[iseg]);
645 layerStdSeg[iseg] = sqrt(layerStdSeg[iseg] / energySeg[iseg]);
646 }
647 for (unsigned int ireg = 0; ireg < nregions; ireg++) {
648 if (oContEnergy[ireg][iseg] > 0) {
649 oContXStd[ireg][iseg] =
650 sqrt(oContXStd[ireg][iseg] / oContEnergy[ireg][iseg]);
651 oContYStd[ireg][iseg] =
652 sqrt(oContYStd[ireg][iseg] / oContEnergy[ireg][iseg]);
653 oContLayerStd[ireg][iseg] =
654 sqrt(oContLayerStd[ireg][iseg] / oContEnergy[ireg][iseg]);
655 }
656 }
657 }
658
659 for (unsigned int ireg = 0; ireg < nregions; ireg++) {
660 if (outsideContainmentEnergy[ireg] > 0) {
661 outsideContainmentXstd[ireg] =
662 sqrt(outsideContainmentXstd[ireg] / outsideContainmentEnergy[ireg]);
663 outsideContainmentYstd[ireg] =
664 sqrt(outsideContainmentYstd[ireg] / outsideContainmentEnergy[ireg]);
665 }
666 }
667
668 if (verbose_) {
669 ldmx_log(debug) << " Find out if the recoil electron is fiducial";
670 }
671
672
673
674
675 const float dz_from_face{7.932};
676 float drifted_recoil_x{-9999.};
677 float drifted_recoil_y{-9999.};
678 if (!recoilP.empty()) {
679 drifted_recoil_x =
680 (dz_from_face * (recoilP[0] / recoilP[2])) + recoilPos[0];
681 drifted_recoil_y =
682 (dz_from_face * (recoilP[1] / recoilP[2])) + recoilPos[1];
683 }
684 const int recoil_layer_index = 0;
685
686
687 bool inside{false};
688
689 const auto ecalID =
geometry_->
getID(drifted_recoil_x, drifted_recoil_y,
690 recoil_layer_index, true);
691 if (!ecalID.null()) {
692
693 const auto cellID =
694 geometry_->
getID(drifted_recoil_x, drifted_recoil_y, recoil_layer_index,
695 ecalID.getModuleID(), true);
696 if (!cellID.null()) {
697 inside = true;
698 }
699 }
700
701 if (!inside) {
702 ldmx_log(info) << "This event is non-fiducial in ECAL";
703 }
704
705
706
707
708
709
710
711
712
713
714 TVector3 e_traj_start;
715 TVector3 e_traj_end;
716 TVector3 p_traj_start;
717 TVector3 p_traj_end;
718 if (!ele_trajectory.empty() && !photon_trajectory.empty()) {
719
720
721 e_traj_start.SetXYZ(ele_trajectory[0].first, ele_trajectory[0].second,
723 e_traj_end.SetXYZ(ele_trajectory[(nEcalLayers_ - 1)].first,
724 ele_trajectory[(nEcalLayers_ - 1)].second,
726 p_traj_start.SetXYZ(photon_trajectory[0].first, photon_trajectory[0].second,
728 p_traj_end.SetXYZ(photon_trajectory[(nEcalLayers_ - 1)].first,
729 photon_trajectory[(nEcalLayers_ - 1)].second,
731
732 TVector3 evec = e_traj_end - e_traj_start;
733 TVector3 e_norm = evec.Unit();
734 TVector3 pvec = p_traj_end - p_traj_start;
735 TVector3 p_norm = pvec.Unit();
736 epDot_ = e_norm.Dot(p_norm);
738 epSep_ = sqrt(pow(e_traj_start.X() - p_traj_start.X(), 2) +
739 pow(e_traj_start.Y() - p_traj_start.Y(), 2));
740 } else {
741
742
743
745 e_traj_end = TVector3(
748 p_traj_end = TVector3(
750
754 }
755
756
757
758
759
761
762
763 if (!photon_trajectory.empty()) {
764 for (std::vector<HitData>::iterator it = trackingHitList.begin();
765 it != trackingHitList.end(); ++it) {
766 float ehDist =
767 sqrt(pow((*it).pos.X() - photon_trajectory[(*it).layer].first, 2) +
768 pow((*it).pos.Y() - photon_trajectory[(*it).layer].second, 2));
769 if (ehDist < 8.7) {
773 }
774 }
775 }
776 }
777
778
779 TVector3 gToe = (e_traj_start - p_traj_start).Unit();
780 TVector3 origin = p_traj_start + 0.5 * 8.7 * gToe;
781 if (!ele_trajectory.empty()) {
782 for (auto &hitData : trackingHitList) {
783 TVector3 hitPos = hitData.pos;
784 TVector3 hitPrime = hitPos - origin;
785 if (hitPrime.Dot(gToe) <= 0) {
787 }
788 }
789 } else {
791 }
792
793
794
795
796 std::sort(trackingHitList.begin(), trackingHitList.end(),
797 [](HitData ha, HitData hb) { return ha.layer > hb.layer; });
798
799
800
801
802 std::vector<std::vector<HitData>> track_list;
803
804
805 if (verbose_) {
806 ldmx_log(debug) << "====== Tracking hit list (original) length "
807 << trackingHitList.size() << " ======";
808 for (int i = 0; i < trackingHitList.size(); i++) {
809 std::cout << "[" << trackingHitList[i].pos.X() << ", "
810 << trackingHitList[i].pos.Y() << ", "
811 << trackingHitList[i].layer << "], ";
812 }
813 std::cout << std::endl;
814 ldmx_log(debug) << "====== END OF Tracking hit list ======";
815 }
816
817
818
820 for (int iHit = 0; iHit < trackingHitList.size(); iHit++) {
821
822 int track[34];
823 int currenthit{iHit};
824 int trackLen{1};
825
826 track[0] = iHit;
827
828
829
830
831
832 int jHit = iHit;
833 while (jHit < trackingHitList.size()) {
834 if ((trackingHitList[jHit].layer ==
835 trackingHitList[currenthit].layer - 1 ||
836 trackingHitList[jHit].layer ==
837 trackingHitList[currenthit].layer - 2) &&
838 abs(trackingHitList[jHit].pos.X() -
839 trackingHitList[currenthit].pos.X()) <= 0.5 * cellWidth &&
840 abs(trackingHitList[jHit].pos.Y() -
841 trackingHitList[currenthit].pos.Y()) <= 0.5 * cellWidth) {
842 track[trackLen] = jHit;
843 trackLen++;
844 currenthit = jHit;
845 }
846 jHit++;
847 }
848
849
850 if (trackLen < 2) continue;
851 float closest_e =
distTwoLines(trackingHitList[track[0]].pos,
852 trackingHitList[track[trackLen - 1]].pos,
853 e_traj_start, e_traj_end);
854 float closest_p =
distTwoLines(trackingHitList[track[0]].pos,
855 trackingHitList[track[trackLen - 1]].pos,
856 p_traj_start, p_traj_end);
857
858
859 if (closest_p > cellWidth and closest_e < 2 * cellWidth) continue;
860 if (trackLen < 4 and closest_e > closest_p) continue;
861 if (verbose_) {
862 ldmx_log(debug) << "====== After rejection for MIP tracking ======";
863 ldmx_log(debug) << "current hit: [" << trackingHitList[iHit].pos.X()
864 << ", " << trackingHitList[iHit].pos.Y() << ", "
865 << trackingHitList[iHit].layer << "]";
866
867 for (int k = 0; k < trackLen; k++) {
868 ldmx_log(debug) << "track[" << k << "] position = ["
869 << trackingHitList[track[k]].pos.X() << ", "
870 << trackingHitList[track[k]].pos.Y() << ", "
871 << trackingHitList[track[k]].layer << "]";
872 }
873 }
874
875
876
877 if (trackLen >= 2) {
878 std::vector<HitData> temp_track_list;
879 int n_remove = 0;
880 for (int kHit = 0; kHit < trackLen; kHit++) {
881 temp_track_list.push_back(trackingHitList[track[kHit] - n_remove]);
882 trackingHitList.erase(trackingHitList.begin() + track[kHit] - n_remove);
883 n_remove++;
884 }
885
886 if (verbose_) {
887 ldmx_log(debug) << "====== Tracking hit list (after erase) length "
888 << trackingHitList.size() << " ======";
889 for (int i = 0; i < trackingHitList.size(); i++) {
890 std::cout << "[" << trackingHitList[i].pos.X() << ", "
891 << trackingHitList[i].pos.Y() << ", "
892 << trackingHitList[i].layer << "] ";
893 }
894 std::cout << std::endl;
895 ldmx_log(debug) << "====== END OF Tracking hit list ======";
896 }
897
898 track_list.push_back(temp_track_list);
899
900
901 iHit--;
902 }
903 }
904
905 ldmx_log(debug) << "Straight tracks found (before merge): "
906 << track_list.size();
907 if (verbose_) {
908 for (int iTrack = 0; iTrack < track_list.size(); iTrack++) {
909 ldmx_log(debug) << "Track " << iTrack << ":";
910 for (int iHit = 0; iHit < track_list[iTrack].size(); iHit++) {
911 std::cout << " Hit " << iHit << ": ["
912 << track_list[iTrack][iHit].pos.X() << ", "
913 << track_list[iTrack][iHit].pos.Y() << ", "
914 << track_list[iTrack][iHit].layer << "]" << std::endl;
915 }
916 std::cout << std::endl;
917 }
918 }
919
920
921
922
923 ldmx_log(debug) << "Beginning track merging using " << track_list.size()
924 << " tracks";
925
926 for (int track_i = 0; track_i < track_list.size(); track_i++) {
927
928
929 std::vector<HitData> base_track = track_list[track_i];
930 HitData tail_hitdata = base_track.back();
931 if (verbose_) ldmx_log(debug) << " Considering track " << track_i;
932 for (int track_j = track_i + 1; track_j < track_list.size(); track_j++) {
933 std::vector<HitData> checking_track = track_list[track_j];
934 HitData head_hitdata = checking_track.front();
935
936 if ((head_hitdata.layer == tail_hitdata.layer + 1 ||
937 head_hitdata.layer == tail_hitdata.layer + 2) &&
938 pow(pow(head_hitdata.pos.X() - tail_hitdata.pos.X(), 2) +
939 pow(head_hitdata.pos.Y() - tail_hitdata.pos.Y(), 2),
940 0.5) <= cellWidth) {
941
942
943
944 if (verbose_) {
945 ldmx_log(debug) << " ** Compatible track found at index "
946 << track_j;
947 ldmx_log(debug) << " Tail xylayer: " << head_hitdata.pos.X()
948 << "," << head_hitdata.pos.Y() << ","
949 << head_hitdata.layer;
950 ldmx_log(debug) << " Head xylayer: " << tail_hitdata.pos.X()
951 << "," << tail_hitdata.pos.Y() << ","
952 << tail_hitdata.layer;
953 }
954 for (int hit_k = 0; hit_k < checking_track.size(); hit_k++) {
955 base_track.push_back(track_list[track_j][hit_k]);
956 }
957 track_list[track_i] = base_track;
958 track_list.erase(track_list.begin() + track_j);
959 break;
960 }
961 }
962 }
964
965 ldmx_log(debug) << "Straight tracks found (after merge): "
967 for (int track_i = 0; track_i < track_list.size(); track_i++) {
968 ldmx_log(debug) << "Track " << track_i << ":";
969 for (int hit_i = 0; hit_i < track_list[track_i].size(); hit_i++) {
970 ldmx_log(debug) << " Hit " << hit_i << ": ["
971 << track_list[track_i][hit_i].pos.X() << ", "
972 << track_list[track_i][hit_i].pos.Y() << ", "
973 << track_list[track_i][hit_i].layer << "]";
974 }
975 }
976
977
978
979 ldmx_log(info) << "Finding linreg tracks from a total of "
980 << trackingHitList.size() << " hits using a radius of "
981 << linreg_radius_ << " mm";
982
983 for (int iHit = 0; iHit < trackingHitList.size(); iHit++) {
984
985 std::vector<int> hitsInRegion;
986 TMatrixD Vm(3, 3);
987 TMatrixD hdt(3, 3);
988 TVector3 slopeVec;
989 TVector3 hmean;
990 TVector3 hpoint;
991 float r_corr_best{0.0};
992
993 int hitNums[3];
994
995 int bestHitNums[3];
996
997 hitsInRegion.push_back(iHit);
998
999 for (int jHit = 0; jHit < trackingHitList.size(); jHit++) {
1000
1001 if (trackingHitList[iHit].pos(2) == trackingHitList[jHit].pos(2)) {
1002 continue;
1003 }
1004 float dstToHit =
1005 (trackingHitList[iHit].pos - trackingHitList[jHit].pos).Mag();
1006
1007
1008
1009 if (dstToHit <= 2 * linreg_radius_) {
1010 hitsInRegion.push_back(jHit);
1011 }
1012 }
1013
1014 bool bestLinRegFound{false};
1015 if (verbose_) {
1016 ldmx_log(debug) << "There are " << hitsInRegion.size()
1017 << " hits within a radius of " << linreg_radius_ << " mm";
1018 }
1019
1020
1021 hitNums[0] = iHit;
1022 for (int jHitInReg = 1; jHitInReg < hitsInRegion.size() - 1; jHitInReg++) {
1023
1024 if (hitsInRegion.size() < 3) break;
1025 hitNums[1] = hitsInRegion[jHitInReg];
1026 for (int kHitReg = jHitInReg + 1; kHitReg < hitsInRegion.size();
1027 kHitReg++) {
1028 hitNums[2] = hitsInRegion[kHitReg];
1029 for (int hInd = 0; hInd < 3; hInd++) {
1030
1031
1032 hmean(hInd) = (trackingHitList[hitNums[0]].pos(hInd) +
1033 trackingHitList[hitNums[1]].pos(hInd) +
1034 trackingHitList[hitNums[2]].pos(hInd)) /
1035 3.0;
1036 }
1037 for (int hInd = 0; hInd < 3; hInd++) {
1038 for (int lInd = 0; lInd < 3; lInd++) {
1039 hdt(hInd, lInd) =
1040 trackingHitList[hitNums[hInd]].pos(lInd) - hmean(lInd);
1041 }
1042 }
1043
1044
1045
1046 double determinant =
1047 hdt(0, 0) * (hdt(1, 1) * hdt(2, 2) - hdt(1, 2) * hdt(2, 1)) -
1048 hdt(0, 1) * (hdt(1, 0) * hdt(2, 2) - hdt(1, 2) * hdt(2, 0)) +
1049 hdt(0, 2) * (hdt(1, 0) * hdt(2, 1) - hdt(1, 1) * hdt(2, 0));
1050
1051 if (determinant == 0) continue;
1052
1053 TDecompSVD svdObj(hdt);
1054 bool decomposed = svdObj.Decompose();
1055 if (!decomposed) continue;
1056
1057
1058 Vm = svdObj.GetV();
1059 for (int hInd = 0; hInd < 3; hInd++) {
1060 slopeVec(hInd) = Vm[0][hInd];
1061 }
1062
1063 hpoint = slopeVec + hmean;
1064
1065
1066
1067 float closest_e =
distTwoLines(hmean, hpoint, e_traj_start, e_traj_end);
1068 float closest_p =
distTwoLines(hmean, hpoint, p_traj_start, p_traj_end);
1069
1070
1071 if (closest_p > cellWidth or closest_e < 1.5 * cellWidth) continue;
1072
1073
1074 float vrnc = (trackingHitList[hitNums[0]].pos - hmean).Mag() +
1075 (trackingHitList[hitNums[1]].pos - hmean).Mag() +
1076 (trackingHitList[hitNums[2]].pos - hmean).Mag();
1077
1078 float sumerr =
1079 distPtToLine(trackingHitList[hitNums[0]].pos, hmean, hpoint) +
1080 distPtToLine(trackingHitList[hitNums[1]].pos, hmean, hpoint) +
1081 distPtToLine(trackingHitList[hitNums[2]].pos, hmean, hpoint);
1082 float r_corr = 1 - sumerr / vrnc;
1083
1084
1085
1086 if (r_corr > r_corr_best and r_corr > .6) {
1087 r_corr_best = r_corr;
1088
1089 bestLinRegFound = true;
1090 for (int k = 0; k < 3; k++) {
1091 bestHitNums[k] = hitNums[k];
1092 }
1093 }
1094 }
1095 }
1096
1097
1098 if (!bestLinRegFound) continue;
1099
1102 for (int finalHitIndx = 0; finalHitIndx < 3; finalHitIndx++) {
1103 ldmx_log(debug) << " Hit " << finalHitIndx << " ["
1104 << trackingHitList[bestHitNums[finalHitIndx]].pos(0)
1105 << ", "
1106 << trackingHitList[bestHitNums[finalHitIndx]].pos(1)
1107 << ", "
1108 << trackingHitList[bestHitNums[finalHitIndx]].pos(2)
1109 << "] ";
1110 }
1111
1112
1113 for (int lHit = 0; lHit < 3; lHit++) {
1114 trackingHitList.erase(trackingHitList.begin() + bestHitNums[lHit]);
1115 }
1116 iHit--;
1117 }
1118
1121 << " lin-reg tracks";
1122
1124 nReadoutHits_, deepestLayerHit_, summedDet_, summedTightIso_, maxCellDep_,
1125 showerRMS_, xStd_, yStd_, avgLayerHit_, stdLayerHit_, ecalBackEnergy_,
1128 photonContainmentEnergy, outsideContainmentEnergy,
1129 outsideContainmentNHits, outsideContainmentXstd, outsideContainmentYstd,
1130 energySeg, xMeanSeg, yMeanSeg, xStdSeg, yStdSeg, layerMeanSeg,
1131 layerStdSeg, eContEnergy, eContXMean, eContYMean, gContEnergy, gContNHits,
1132 gContXMean, gContYMean, oContEnergy, oContNHits, oContXMean, oContYMean,
1133 oContXStd, oContYStd, oContLayerMean, oContLayerStd,
1134 ecalLayerEdepReadout_, recoilP, recoilPos);
1135
1137 ldmx::Ort::FloatArrays inputs({bdtFeatures_});
1138 float pred = rt_->run({featureListName_}, inputs, {"probabilities"})[0].at(1);
1139 ldmx_log(info) << " BDT was ran, score is " << pred;
1140
1141
1142
1144 result.setVetoResult(pred > bdtCutVal_ && passesTrackingVeto);
1145 result.setDiscValue(pred);
1146 ldmx_log(info) << " The pred > bdtCutVal = " << (pred > bdtCutVal_)
1147 << " and MIP tracking passed = " << passesTrackingVeto;
1148
1149
1150 result.setFiducial(inside);
1151
1152
1153
1154 if (!inverse_skim_) {
1157 } else {
1159 }
1160 } else {
1161
1164 } else {
1166 }
1167 }
1168
1170}
std::tuple< int, const ldmx::SimParticle * > getRecoil(const std::map< int, ldmx::SimParticle > &particleMap)
Find and return the sim particle associated with the recoil electron.
std::vector< float > trackProp(const ldmx::Tracks &tracks, ldmx::TrackStateType ts_type, const std::string &ts_title)
Return a vector of parameters for a propagated recoil track.
float distTwoLines(TVector3 v1, TVector3 v2, TVector3 w1, TVector3 w2)
Returns the distance between the lines v and w, with v defined to pass through the points (v1,...
void buildBDTFeatureVector(const ldmx::EcalVetoResult &result)
float distPtToLine(TVector3 h1, TVector3 p1, TVector3 p2)
Return the minimum distance between the point h1 and the line passing through points p1 and p2.
void fillHitMap(const std::vector< ldmx::EcalHit > &ecalRecHits, std::map< ldmx::EcalID, float > &cellMap_)
Function to load up empty vector of hit maps.
const T & getCondition(const std::string &condition_name)
Access a conditions object for the current event.
void setStorageHint(framework::StorageControl::Hint hint)
Mark the current event as having the given storage control hint from this module.
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.
EcalID getID(double x, double y, double z, bool fallible=false) const
Get a cell's ID number from its position.
double getCellMaxR() const
Get the center-to-corner radius of the cell hexagons.
void setVariables(int nReadoutHits, int deepestLayerHit, float summedDet, float summedTightIso, float maxCellDep, float showerRMS, float xStd, float yStd, float avgLayerHit, float stdLayerHit, float ecalBackEnergy, int nStraightTracks, int nLinregTracks, int firstNearPhLayer, int nNearPhHits, int photonTerritoryHits, float epAng, float epSep, float epDot, std::vector< float > electronContainmentEnergy, std::vector< float > photonContainmentEnergy, std::vector< float > outsideContainmentEnergy, std::vector< int > outsideContainmentNHits, std::vector< float > outsideContainmentXStd, std::vector< float > outsideContainmentYStd, std::vector< float > energySeg, std::vector< float > xMeanSeg, std::vector< float > yMeanSeg, std::vector< float > xStdSeg, std::vector< float > yStdSeg, std::vector< float > layerMeanSeg, std::vector< float > layerStdSeg, std::vector< std::vector< float > > eContEnergy, std::vector< std::vector< float > > eContXMean, std::vector< std::vector< float > > eContYMean, std::vector< std::vector< float > > gContEnergy, std::vector< std::vector< int > > gContNHits, std::vector< std::vector< float > > gContXMean, std::vector< std::vector< float > > gContYMean, std::vector< std::vector< float > > oContEnergy, std::vector< std::vector< int > > oContNHits, std::vector< std::vector< float > > oContXMean, std::vector< std::vector< float > > oContYMean, std::vector< std::vector< float > > oContXStd, std::vector< std::vector< float > > oContYStd, std::vector< std::vector< float > > oContLayerMean, std::vector< std::vector< float > > oContLayerStd, std::vector< float > EcalLayerEdepReadout, std::vector< double > recoilP, std::vector< float > recoilPos)
Set the sim particle and 'is findable' flag.
bool passesVeto() const
Checks if the event passes the Ecal veto.
Class representing a simulated particle.
Implements detector ids for special simulation-derived hits like scoring planes.
Represents a simulated tracker hit in the simulation.
Implementation of a track object.
constexpr StorageControl::Hint hint_shouldKeep
storage control hint alias for backwards compatibility
constexpr StorageControl::Hint hint_shouldDrop
storage control hint alias for backwards compatibility