171 geometry_ = &getCondition<ldmx::EcalGeometry>(
172 ldmx::EcalGeometry::CONDITIONS_OBJECT_NAME);
181 std::vector<double> recoilP;
182 std::vector<float> recoilPos;
183 std::vector<double> recoilPAtTarget;
184 std::vector<float> recoilPosAtTarget;
187 ldmx_log(debug) <<
" Loop through all of the sim particles and find the "
191 if (event.
exists(
"EcalScoringPlaneHits")) {
200 auto [recoilTrackID, recoilElectron] = Analysis::getRecoil(particleMap);
208 if (hit_id.
plane() != 31 || spHit.getMomentum()[2] <= 0)
continue;
210 if (spHit.getTrackID() == recoilTrackID) {
211 if (sqrt(pow(spHit.getMomentum()[0], 2) +
212 pow(spHit.getMomentum()[1], 2) +
213 pow(spHit.getMomentum()[2], 2)) > pmax) {
214 recoilP = spHit.getMomentum();
215 recoilPos = spHit.getPosition();
216 pmax = sqrt(pow(recoilP[0], 2) + pow(recoilP[1], 2) +
223 if (event.
exists(
"TargetScoringPlaneHits")) {
224 std::vector<ldmx::SimTrackerHit> targetSpHits =
229 if (hit_id.
plane() != 1 || spHit.getMomentum()[2] <= 0)
continue;
231 if (spHit.getTrackID() == recoilTrackID) {
232 if (sqrt(pow(spHit.getMomentum()[0], 2) +
233 pow(spHit.getMomentum()[1], 2) +
234 pow(spHit.getMomentum()[2], 2)) > pmax) {
235 recoilPAtTarget = spHit.getMomentum();
236 recoilPosAtTarget = spHit.getPosition();
238 sqrt(pow(recoilPAtTarget[0], 2) + pow(recoilPAtTarget[1], 2) +
239 pow(recoilPAtTarget[2], 2));
247 ldmx_log(debug) <<
" Get projected trajectories for electron and photon";
250 std::vector<XYCoords> ele_trajectory, photon_trajectory;
251 if (recoilP.size() > 0) {
252 ele_trajectory = getTrajectory(recoilP, recoilPos);
253 std::vector<double> pvec = recoilPAtTarget.size()
255 : std::vector<double>{0.0, 0.0, 0.0};
256 std::vector<float> posvec = recoilPosAtTarget.size()
258 : std::vector<float>{0.0, 0.0, 0.0};
260 getTrajectory({-pvec[0], -pvec[1], beamEnergyMeV_ - pvec[2]}, posvec);
265 ? sqrt(pow(recoilP[0], 2) + pow(recoilP[1], 2) + pow(recoilP[2], 2))
268 recoilPMag > 0 ? acos(recoilP[2] / recoilPMag) * 180.0 / M_PI : -1.0;
271 ldmx_log(debug) <<
" Build Radii of containment (ROC)";
274 std::vector<double> roc_values_bin0(roc_range_values_[0].begin() + 4,
275 roc_range_values_[0].end());
276 std::vector<double> ele_radii = roc_values_bin0;
277 double theta_min, theta_max, p_min, p_max;
280 for (
int i = 0; i < roc_range_values_.size(); i++) {
281 theta_min = roc_range_values_[i][0];
282 theta_max = roc_range_values_[i][1];
283 p_min = roc_range_values_[i][2];
284 p_max = roc_range_values_[i][3];
287 if (theta_min != -1.0) {
288 inrange = inrange && (recoilTheta >= theta_min);
290 if (theta_max != -1.0) {
291 inrange = inrange && (recoilTheta < theta_max);
294 inrange = inrange && (recoilPMag >= p_min);
297 inrange = inrange && (recoilPMag < p_max);
300 std::vector<double> roc_values_bini(roc_range_values_[i].begin() + 4,
301 roc_range_values_[i].end());
302 ele_radii = roc_values_bini;
306 std::vector<double> photon_radii = roc_values_bin0;
309 const std::vector<ldmx::EcalHit> ecalRecHits =
310 event.getCollection<
ldmx::EcalHit>(rec_coll_name_, rec_pass_name_);
313 GetShowerCentroidIDAndRMS(ecalRecHits, showerRMS_);
318 fillIsolatedHitMap(ecalRecHits, globalCentroid, cellMap_, cellMapTightIso_,
324 float wavgLayerHit = 0;
329 unsigned int nregions = 5;
330 std::vector<float> electronContainmentEnergy(nregions, 0.0);
331 std::vector<float> photonContainmentEnergy(nregions, 0.0);
332 std::vector<float> outsideContainmentEnergy(nregions, 0.0);
333 std::vector<int> outsideContainmentNHits(nregions, 0);
334 std::vector<float> outsideContainmentXmean(nregions, 0.0);
335 std::vector<float> outsideContainmentYmean(nregions, 0.0);
336 std::vector<float> outsideContainmentXstd(nregions, 0.0);
337 std::vector<float> outsideContainmentYstd(nregions, 0.0);
339 std::vector<int> segLayers = {0, 6, 17, 34};
340 unsigned int nsegments = segLayers.size() - 1;
341 std::vector<float> energySeg(nsegments, 0.0);
342 std::vector<float> xMeanSeg(nsegments, 0.0);
343 std::vector<float> xStdSeg(nsegments, 0.0);
344 std::vector<float> yMeanSeg(nsegments, 0.0);
345 std::vector<float> yStdSeg(nsegments, 0.0);
346 std::vector<float> layerMeanSeg(nsegments, 0.0);
347 std::vector<float> layerStdSeg(nsegments, 0.0);
348 std::vector<std::vector<float>> eContEnergy(
349 nregions, std::vector<float>(nsegments, 0.0));
350 std::vector<std::vector<float>> eContXMean(
351 nregions, std::vector<float>(nsegments, 0.0));
352 std::vector<std::vector<float>> eContYMean(
353 nregions, std::vector<float>(nsegments, 0.0));
354 std::vector<std::vector<float>> gContEnergy(
355 nregions, std::vector<float>(nsegments, 0.0));
356 std::vector<std::vector<int>> gContNHits(nregions,
357 std::vector<int>(nsegments, 0));
358 std::vector<std::vector<float>> gContXMean(
359 nregions, std::vector<float>(nsegments, 0.0));
360 std::vector<std::vector<float>> gContYMean(
361 nregions, std::vector<float>(nsegments, 0.0));
362 std::vector<std::vector<float>> oContEnergy(
363 nregions, std::vector<float>(nsegments, 0.0));
364 std::vector<std::vector<int>> oContNHits(nregions,
365 std::vector<int>(nsegments, 0));
366 std::vector<std::vector<float>> oContXMean(
367 nregions, std::vector<float>(nsegments, 0.0));
368 std::vector<std::vector<float>> oContYMean(
369 nregions, std::vector<float>(nsegments, 0.0));
370 std::vector<std::vector<float>> oContXStd(nregions,
371 std::vector<float>(nsegments, 0.0));
372 std::vector<std::vector<float>> oContYStd(nregions,
373 std::vector<float>(nsegments, 0.0));
374 std::vector<std::vector<float>> oContLayerMean(
375 nregions, std::vector<float>(nsegments, 0.0));
376 std::vector<std::vector<float>> oContLayerStd(
377 nregions, std::vector<float>(nsegments, 0.0));
382 std::vector<HitData> trackingHitList;
386 <<
" Loop over the hits from the event to calculate the BDT features";
392 ecalLayerEdepRaw_[
id.layer()] =
393 ecalLayerEdepRaw_[
id.layer()] + hit.getEnergy();
394 if (
id.layer() >= 20) ecalBackEnergy_ += hit.getEnergy();
395 if (maxCellDep_ < hit.getEnergy()) maxCellDep_ = hit.getEnergy();
396 if (hit.getEnergy() > 0) {
398 ecalLayerEdepReadout_[
id.layer()] += hit.getEnergy();
399 ecalLayerTime_[
id.layer()] += (hit.getEnergy()) * hit.getTime();
401 xMean += x * hit.getEnergy();
402 yMean += y * hit.getEnergy();
403 avgLayerHit_ +=
id.layer();
404 wavgLayerHit +=
id.layer() * hit.getEnergy();
405 if (deepestLayerHit_ <
id.layer()) {
406 deepestLayerHit_ =
id.layer();
408 XYCoords xy_pair = std::make_pair(x, y);
409 float distance_ele_trajectory =
410 ele_trajectory.size()
412 pow((xy_pair.first - ele_trajectory[
id.layer()].first), 2) +
413 pow((xy_pair.second - ele_trajectory[
id.layer()].second),
416 float distance_photon_trajectory =
417 photon_trajectory.size()
419 pow((xy_pair.first - photon_trajectory[
id.layer()].first),
421 pow((xy_pair.second - photon_trajectory[
id.layer()].second),
426 for (
unsigned int iseg = 0; iseg < nsegments; iseg++) {
427 if (
id.layer() >= segLayers[iseg] &&
428 id.layer() <= segLayers[iseg + 1] - 1) {
429 energySeg[iseg] += hit.getEnergy();
430 xMeanSeg[iseg] += xy_pair.first * hit.getEnergy();
431 yMeanSeg[iseg] += xy_pair.second * hit.getEnergy();
432 layerMeanSeg[iseg] +=
id.layer() * hit.getEnergy();
435 for (
unsigned int ireg = 0; ireg < nregions; ireg++) {
436 if (distance_ele_trajectory >= ireg * ele_radii[
id.layer()] &&
437 distance_ele_trajectory < (ireg + 1) * ele_radii[
id.layer()]) {
438 eContEnergy[ireg][iseg] += hit.getEnergy();
439 eContXMean[ireg][iseg] += xy_pair.first * hit.getEnergy();
440 eContYMean[ireg][iseg] += xy_pair.second * hit.getEnergy();
442 if (distance_photon_trajectory >= ireg * photon_radii[
id.layer()] &&
443 distance_photon_trajectory <
444 (ireg + 1) * photon_radii[
id.layer()]) {
445 gContEnergy[ireg][iseg] += hit.getEnergy();
446 gContNHits[ireg][iseg] += 1;
447 gContXMean[ireg][iseg] += xy_pair.first * hit.getEnergy();
448 gContYMean[ireg][iseg] += xy_pair.second * hit.getEnergy();
450 if (distance_ele_trajectory > (ireg + 1) * ele_radii[
id.layer()] &&
451 distance_photon_trajectory >
452 (ireg + 1) * photon_radii[
id.layer()]) {
453 oContEnergy[ireg][iseg] += hit.getEnergy();
454 oContNHits[ireg][iseg] += 1;
455 oContXMean[ireg][iseg] += xy_pair.first * hit.getEnergy();
456 oContYMean[ireg][iseg] += xy_pair.second * hit.getEnergy();
457 oContLayerMean[ireg][iseg] +=
id.layer() * hit.getEnergy();
464 for (
unsigned int ireg = 0; ireg < nregions; ireg++) {
465 if (distance_ele_trajectory >= ireg * ele_radii[
id.layer()] &&
466 distance_ele_trajectory < (ireg + 1) * ele_radii[
id.layer()])
467 electronContainmentEnergy[ireg] += hit.getEnergy();
468 if (distance_photon_trajectory >= ireg * photon_radii[
id.layer()] &&
469 distance_photon_trajectory < (ireg + 1) * photon_radii[
id.layer()])
470 photonContainmentEnergy[ireg] += hit.getEnergy();
471 if (distance_ele_trajectory > (ireg + 1) * ele_radii[
id.layer()] &&
472 distance_photon_trajectory >
473 (ireg + 1) * photon_radii[
id.layer()]) {
474 outsideContainmentEnergy[ireg] += hit.getEnergy();
475 outsideContainmentNHits[ireg] += 1;
476 outsideContainmentXmean[ireg] += xy_pair.first * hit.getEnergy();
477 outsideContainmentYmean[ireg] += xy_pair.second * hit.getEnergy();
483 if (distance_ele_trajectory >= ele_radii[
id.layer()] ||
484 distance_ele_trajectory == -1.0) {
486 hd.pos = TVector3(xy_pair.first, xy_pair.second,
488 hd.layer =
id.layer();
489 trackingHitList.push_back(hd);
494 for (
const auto &[
id, energy] : cellMapTightIso_) {
495 if (energy > 0) summedTightIso_ += energy;
498 for (
int iLayer = 0; iLayer < ecalLayerEdepReadout_.size(); iLayer++) {
499 ecalLayerTime_[iLayer] =
500 ecalLayerTime_[iLayer] / ecalLayerEdepReadout_[iLayer];
501 summedDet_ += ecalLayerEdepReadout_[iLayer];
504 if (nReadoutHits_ > 0) {
505 avgLayerHit_ /= nReadoutHits_;
506 wavgLayerHit /= summedDet_;
517 for (
unsigned int iseg = 0; iseg < nsegments; iseg++) {
518 if (energySeg[iseg] > 0) {
519 xMeanSeg[iseg] /= energySeg[iseg];
520 yMeanSeg[iseg] /= energySeg[iseg];
521 layerMeanSeg[iseg] /= energySeg[iseg];
523 for (
unsigned int ireg = 0; ireg < nregions; ireg++) {
524 if (eContEnergy[ireg][iseg] > 0) {
525 eContXMean[ireg][iseg] /= eContEnergy[ireg][iseg];
526 eContYMean[ireg][iseg] /= eContEnergy[ireg][iseg];
528 if (gContEnergy[ireg][iseg] > 0) {
529 gContXMean[ireg][iseg] /= gContEnergy[ireg][iseg];
530 gContYMean[ireg][iseg] /= gContEnergy[ireg][iseg];
532 if (oContEnergy[ireg][iseg] > 0) {
533 oContXMean[ireg][iseg] /= oContEnergy[ireg][iseg];
534 oContYMean[ireg][iseg] /= oContEnergy[ireg][iseg];
535 oContLayerMean[ireg][iseg] /= oContEnergy[ireg][iseg];
540 for (
unsigned int ireg = 0; ireg < nregions; ireg++) {
541 if (outsideContainmentEnergy[ireg] > 0) {
542 outsideContainmentXmean[ireg] /= outsideContainmentEnergy[ireg];
543 outsideContainmentYmean[ireg] /= outsideContainmentEnergy[ireg];
551 if (hit.getEnergy() > 0) {
552 xStd_ += pow((x - xMean), 2) * hit.getEnergy();
553 yStd_ += pow((y - yMean), 2) * hit.getEnergy();
554 stdLayerHit_ += pow((
id.layer() - wavgLayerHit), 2) * hit.getEnergy();
556 XYCoords xy_pair = std::make_pair(x, y);
557 float distance_ele_trajectory =
558 ele_trajectory.size()
559 ? sqrt(pow((xy_pair.first - ele_trajectory[
id.layer()].first), 2) +
560 pow((xy_pair.second - ele_trajectory[
id.layer()].second), 2))
562 float distance_photon_trajectory =
563 photon_trajectory.size()
564 ? sqrt(pow((xy_pair.first - photon_trajectory[
id.layer()].first),
566 pow((xy_pair.second - photon_trajectory[
id.layer()].second),
570 for (
unsigned int iseg = 0; iseg < nsegments; iseg++) {
571 if (
id.layer() >= segLayers[iseg] &&
572 id.layer() <= segLayers[iseg + 1] - 1) {
574 pow((xy_pair.first - xMeanSeg[iseg]), 2) * hit.getEnergy();
576 pow((xy_pair.second - yMeanSeg[iseg]), 2) * hit.getEnergy();
578 pow((
id.layer() - layerMeanSeg[iseg]), 2) * hit.getEnergy();
580 for (
unsigned int ireg = 0; ireg < nregions; ireg++) {
581 if (distance_ele_trajectory > (ireg + 1) * ele_radii[
id.layer()] &&
582 distance_photon_trajectory >
583 (ireg + 1) * photon_radii[
id.layer()]) {
584 oContXStd[ireg][iseg] +=
585 pow((xy_pair.first - oContXMean[ireg][iseg]), 2) *
587 oContYStd[ireg][iseg] +=
588 pow((xy_pair.second - oContYMean[ireg][iseg]), 2) *
590 oContLayerStd[ireg][iseg] +=
591 pow((
id.layer() - oContLayerMean[ireg][iseg]), 2) *
598 for (
unsigned int ireg = 0; ireg < nregions; ireg++) {
599 if (distance_ele_trajectory > (ireg + 1) * ele_radii[
id.layer()] &&
600 distance_photon_trajectory > (ireg + 1) * photon_radii[
id.layer()]) {
601 outsideContainmentXstd[ireg] +=
602 pow((xy_pair.first - outsideContainmentXmean[ireg]), 2) *
604 outsideContainmentYstd[ireg] +=
605 pow((xy_pair.second - outsideContainmentYmean[ireg]), 2) *
611 if (nReadoutHits_ > 0) {
612 xStd_ = sqrt(xStd_ / summedDet_);
613 yStd_ = sqrt(yStd_ / summedDet_);
614 stdLayerHit_ = sqrt(stdLayerHit_ / summedDet_);
623 for (
unsigned int iseg = 0; iseg < nsegments; iseg++) {
624 if (energySeg[iseg] > 0) {
625 xStdSeg[iseg] = sqrt(xStdSeg[iseg] / energySeg[iseg]);
626 yStdSeg[iseg] = sqrt(yStdSeg[iseg] / energySeg[iseg]);
627 layerStdSeg[iseg] = sqrt(layerStdSeg[iseg] / energySeg[iseg]);
629 for (
unsigned int ireg = 0; ireg < nregions; ireg++) {
630 if (oContEnergy[ireg][iseg] > 0) {
631 oContXStd[ireg][iseg] =
632 sqrt(oContXStd[ireg][iseg] / oContEnergy[ireg][iseg]);
633 oContYStd[ireg][iseg] =
634 sqrt(oContYStd[ireg][iseg] / oContEnergy[ireg][iseg]);
635 oContLayerStd[ireg][iseg] =
636 sqrt(oContLayerStd[ireg][iseg] / oContEnergy[ireg][iseg]);
641 for (
unsigned int ireg = 0; ireg < nregions; ireg++) {
642 if (outsideContainmentEnergy[ireg] > 0) {
643 outsideContainmentXstd[ireg] =
644 sqrt(outsideContainmentXstd[ireg] / outsideContainmentEnergy[ireg]);
645 outsideContainmentYstd[ireg] =
646 sqrt(outsideContainmentYstd[ireg] / outsideContainmentEnergy[ireg]);
651 ldmx_log(debug) <<
" Find out if the recoil electron is fiducial";
657 const float dz_from_face{7.932};
658 float drifted_recoil_x{-9999.};
659 float drifted_recoil_y{-9999.};
660 if (recoilP.size() > 0) {
662 (dz_from_face * (recoilP[0] / recoilP[2])) + recoilPos[0];
664 (dz_from_face * (recoilP[1] / recoilP[2])) + recoilPos[1];
666 const int recoil_layer_index = 0;
671 const auto ecalID =
geometry_->
getID(drifted_recoil_x, drifted_recoil_y,
672 recoil_layer_index,
true);
673 if (!ecalID.null()) {
676 geometry_->
getID(drifted_recoil_x, drifted_recoil_y, recoil_layer_index,
677 ecalID.getModuleID(),
true);
678 if (!cellID.null()) {
684 ldmx_log(info) <<
"This event is non-fiducial in ECAL";
696 TVector3 e_traj_start;
698 TVector3 p_traj_start;
700 if (ele_trajectory.size() > 0 && photon_trajectory.size() > 0) {
703 e_traj_start.SetXYZ(ele_trajectory[0].first, ele_trajectory[0].second,
705 e_traj_end.SetXYZ(ele_trajectory[(nEcalLayers_ - 1)].first,
706 ele_trajectory[(nEcalLayers_ - 1)].second,
708 p_traj_start.SetXYZ(photon_trajectory[0].first, photon_trajectory[0].second,
710 p_traj_end.SetXYZ(photon_trajectory[(nEcalLayers_ - 1)].first,
711 photon_trajectory[(nEcalLayers_ - 1)].second,
714 TVector3 evec = e_traj_end - e_traj_start;
715 TVector3 e_norm = evec.Unit();
716 TVector3 pvec = p_traj_end - p_traj_start;
717 TVector3 p_norm = pvec.Unit();
718 epDot_ = e_norm.Dot(p_norm);
720 epSep_ = sqrt(pow(e_traj_start.X() - p_traj_start.X(), 2) +
721 pow(e_traj_start.Y() - p_traj_start.Y(), 2));
727 e_traj_end = TVector3(
730 p_traj_end = TVector3(
744 if (photon_trajectory.size() !=
746 for (std::vector<HitData>::iterator it = trackingHitList.begin();
747 it != trackingHitList.end(); ++it) {
749 sqrt(pow((*it).pos.X() - photon_trajectory[(*it).layer].first, 2) +
750 pow((*it).pos.Y() - photon_trajectory[(*it).layer].second, 2));
761 TVector3 gToe = (e_traj_start - p_traj_start).Unit();
762 TVector3 origin = p_traj_start + 0.5 * 8.7 * gToe;
763 if (ele_trajectory.size() > 0) {
764 for (
auto &hitData : trackingHitList) {
765 TVector3 hitPos = hitData.pos;
766 TVector3 hitPrime = hitPos - origin;
767 if (hitPrime.Dot(gToe) <= 0) {
778 std::sort(trackingHitList.begin(), trackingHitList.end(),
784 std::vector<std::vector<HitData>> track_list;
788 ldmx_log(debug) <<
"====== Tracking hit list (original) length "
789 << trackingHitList.size() <<
" ======";
790 for (
int i = 0; i < trackingHitList.size(); i++) {
791 std::cout <<
"[" << trackingHitList[i].pos.X() <<
", "
792 << trackingHitList[i].pos.Y() <<
", "
793 << trackingHitList[i].layer <<
"], ";
795 std::cout << std::endl;
796 ldmx_log(debug) <<
"====== END OF Tracking hit list ======";
802 for (
int iHit = 0; iHit < trackingHitList.size(); iHit++) {
805 int currenthit{iHit};
815 while (jHit < trackingHitList.size()) {
816 if ((trackingHitList[jHit].layer ==
817 trackingHitList[currenthit].layer - 1 ||
818 trackingHitList[jHit].layer ==
819 trackingHitList[currenthit].layer - 2) &&
820 abs(trackingHitList[jHit].pos.X() -
821 trackingHitList[currenthit].pos.X()) <= 0.5 * cellWidth &&
822 abs(trackingHitList[jHit].pos.Y() -
823 trackingHitList[currenthit].pos.Y()) <= 0.5 * cellWidth) {
824 track[trackLen] = jHit;
832 if (trackLen < 2)
continue;
833 float closest_e =
distTwoLines(trackingHitList[track[0]].pos,
834 trackingHitList[track[trackLen - 1]].pos,
835 e_traj_start, e_traj_end);
836 float closest_p =
distTwoLines(trackingHitList[track[0]].pos,
837 trackingHitList[track[trackLen - 1]].pos,
838 p_traj_start, p_traj_end);
841 if (closest_p > cellWidth and closest_e < 2 * cellWidth)
continue;
842 if (trackLen < 4 and closest_e > closest_p)
continue;
844 ldmx_log(debug) <<
"====== After rejection for MIP tracking ======";
845 ldmx_log(debug) <<
"current hit: [" << trackingHitList[iHit].pos.X()
846 <<
", " << trackingHitList[iHit].pos.Y() <<
", "
847 << trackingHitList[iHit].layer <<
"]";
849 for (
int k = 0; k < trackLen; k++) {
850 ldmx_log(debug) <<
"track[" << k <<
"] position = ["
851 << trackingHitList[track[k]].pos.X() <<
", "
852 << trackingHitList[track[k]].pos.Y() <<
", "
853 << trackingHitList[track[k]].layer <<
"]";
860 std::vector<HitData> temp_track_list;
862 for (
int kHit = 0; kHit < trackLen; kHit++) {
863 temp_track_list.push_back(trackingHitList[track[kHit] - n_remove]);
864 trackingHitList.erase(trackingHitList.begin() + track[kHit] - n_remove);
869 ldmx_log(debug) <<
"====== Tracking hit list (after erase) length "
870 << trackingHitList.size() <<
" ======";
871 for (
int i = 0; i < trackingHitList.size(); i++) {
872 std::cout <<
"[" << trackingHitList[i].pos.X() <<
", "
873 << trackingHitList[i].pos.Y() <<
", "
874 << trackingHitList[i].layer <<
"] ";
876 std::cout << std::endl;
877 ldmx_log(debug) <<
"====== END OF Tracking hit list ======";
880 track_list.push_back(temp_track_list);
887 ldmx_log(debug) <<
"Straight tracks found (before merge): "
888 << track_list.size();
890 for (
int iTrack = 0; iTrack < track_list.size(); iTrack++) {
891 ldmx_log(debug) <<
"Track " << iTrack <<
":";
892 for (
int iHit = 0; iHit < track_list[iTrack].size(); iHit++) {
893 std::cout <<
" Hit " << iHit <<
": ["
894 << track_list[iTrack][iHit].pos.X() <<
", "
895 << track_list[iTrack][iHit].pos.Y() <<
", "
896 << track_list[iTrack][iHit].layer <<
"]" << std::endl;
898 std::cout << std::endl;
905 ldmx_log(debug) <<
"Beginning track merging using " << track_list.size()
908 for (
int track_i = 0; track_i < track_list.size(); track_i++) {
911 std::vector<HitData> base_track = track_list[track_i];
912 HitData tail_hitdata = base_track.back();
913 if (verbose_) ldmx_log(debug) <<
" Considering track " << track_i;
914 for (
int track_j = track_i + 1; track_j < track_list.size(); track_j++) {
915 std::vector<HitData> checking_track = track_list[track_j];
916 HitData head_hitdata = checking_track.front();
918 if ((head_hitdata.layer == tail_hitdata.layer + 1 ||
919 head_hitdata.layer == tail_hitdata.layer + 2) &&
920 pow(pow(head_hitdata.pos.X() - tail_hitdata.pos.X(), 2) +
921 pow(head_hitdata.pos.Y() - tail_hitdata.pos.Y(), 2),
927 ldmx_log(debug) <<
" ** Compatible track found at index "
929 ldmx_log(debug) <<
" Tail xylayer: " << head_hitdata.pos.X()
930 <<
"," << head_hitdata.pos.Y() <<
","
931 << head_hitdata.layer;
932 ldmx_log(debug) <<
" Head xylayer: " << tail_hitdata.pos.X()
933 <<
"," << tail_hitdata.pos.Y() <<
","
934 << tail_hitdata.layer;
936 for (
int hit_k = 0; hit_k < checking_track.size(); hit_k++) {
937 base_track.push_back(track_list[track_j][hit_k]);
939 track_list[track_i] = base_track;
940 track_list.erase(track_list.begin() + track_j);
947 ldmx_log(debug) <<
"Straight tracks found (after merge): "
949 for (
int track_i = 0; track_i < track_list.size(); track_i++) {
950 ldmx_log(debug) <<
"Track " << track_i <<
":";
951 for (
int hit_i = 0; hit_i < track_list[track_i].size(); hit_i++) {
952 ldmx_log(debug) <<
" Hit " << hit_i <<
": ["
953 << track_list[track_i][hit_i].pos.X() <<
", "
954 << track_list[track_i][hit_i].pos.Y() <<
", "
955 << track_list[track_i][hit_i].layer <<
"]";
961 ldmx_log(debug) <<
"Finding linreg tracks from a total of "
962 << trackingHitList.size() <<
" hits using a radius of "
963 << linreg_radius_ <<
" mm";
965 for (
int iHit = 0; iHit < trackingHitList.size(); iHit++) {
967 std::vector<int> hitsInRegion;
973 float r_corr_best{0.0};
979 hitsInRegion.push_back(iHit);
981 for (
int jHit = 0; jHit < trackingHitList.size(); jHit++) {
983 if (trackingHitList[iHit].pos(2) == trackingHitList[jHit].pos(2)) {
987 (trackingHitList[iHit].pos - trackingHitList[jHit].pos).Mag();
991 if (dstToHit <= 2 * linreg_radius_) {
992 hitsInRegion.push_back(jHit);
996 bool bestLinRegFound{
false};
998 ldmx_log(debug) <<
"There are " << hitsInRegion.size()
999 <<
" hits within a radius of " << linreg_radius_ <<
" mm";
1004 for (
int jHitInReg = 1; jHitInReg < hitsInRegion.size() - 1; jHitInReg++) {
1006 if (hitsInRegion.size() < 3)
break;
1007 hitNums[1] = hitsInRegion[jHitInReg];
1008 for (
int kHitReg = jHitInReg + 1; kHitReg < hitsInRegion.size();
1010 hitNums[2] = hitsInRegion[kHitReg];
1011 for (
int hInd = 0; hInd < 3; hInd++) {
1014 hmean(hInd) = (trackingHitList[hitNums[0]].pos(hInd) +
1015 trackingHitList[hitNums[1]].pos(hInd) +
1016 trackingHitList[hitNums[2]].pos(hInd)) /
1019 for (
int hInd = 0; hInd < 3; hInd++) {
1020 for (
int lInd = 0; lInd < 3; lInd++) {
1022 trackingHitList[hitNums[hInd]].pos(lInd) - hmean(lInd);
1028 double determinant =
1029 hdt(0, 0) * (hdt(1, 1) * hdt(2, 2) - hdt(1, 2) * hdt(2, 1)) -
1030 hdt(0, 1) * (hdt(1, 0) * hdt(2, 2) - hdt(1, 2) * hdt(2, 0)) +
1031 hdt(0, 2) * (hdt(1, 0) * hdt(2, 1) - hdt(1, 1) * hdt(2, 0));
1033 if (determinant == 0)
continue;
1035 TDecompSVD svdObj(hdt);
1036 bool decomposed = svdObj.Decompose();
1037 if (!decomposed)
continue;
1041 for (
int hInd = 0; hInd < 3; hInd++) {
1042 slopeVec(hInd) = Vm[0][hInd];
1045 hpoint = slopeVec + hmean;
1049 float closest_e =
distTwoLines(hmean, hpoint, e_traj_start, e_traj_end);
1050 float closest_p =
distTwoLines(hmean, hpoint, p_traj_start, p_traj_end);
1053 if (closest_p > cellWidth or closest_e < 1.5 * cellWidth)
continue;
1056 float vrnc = (trackingHitList[hitNums[0]].pos - hmean).Mag() +
1057 (trackingHitList[hitNums[1]].pos - hmean).Mag() +
1058 (trackingHitList[hitNums[2]].pos - hmean).Mag();
1061 distPtToLine(trackingHitList[hitNums[0]].pos, hmean, hpoint) +
1062 distPtToLine(trackingHitList[hitNums[1]].pos, hmean, hpoint) +
1063 distPtToLine(trackingHitList[hitNums[2]].pos, hmean, hpoint);
1064 float r_corr = 1 - sumerr / vrnc;
1068 if (r_corr > r_corr_best and r_corr > .6) {
1069 r_corr_best = r_corr;
1071 bestLinRegFound =
true;
1072 for (
int k = 0; k < 3; k++) {
1073 bestHitNums[k] = hitNums[k];
1080 if (!bestLinRegFound)
continue;
1084 for (
int finalHitIndx = 0; finalHitIndx < 3; finalHitIndx++) {
1085 ldmx_log(debug) <<
" Hit " << finalHitIndx <<
" ["
1086 << trackingHitList[bestHitNums[finalHitIndx]].pos(0)
1088 << trackingHitList[bestHitNums[finalHitIndx]].pos(1)
1090 << trackingHitList[bestHitNums[finalHitIndx]].pos(2)
1095 for (
int lHit = 0; lHit < 3; lHit++) {
1096 trackingHitList.erase(trackingHitList.begin() + bestHitNums[lHit]);
1103 <<
" lin-reg tracks";
1106 nReadoutHits_, deepestLayerHit_, summedDet_, summedTightIso_, maxCellDep_,
1107 showerRMS_, xStd_, yStd_, avgLayerHit_, stdLayerHit_, ecalBackEnergy_,
1110 photonContainmentEnergy, outsideContainmentEnergy,
1111 outsideContainmentNHits, outsideContainmentXstd, outsideContainmentYstd,
1112 energySeg, xMeanSeg, yMeanSeg, xStdSeg, yStdSeg, layerMeanSeg,
1113 layerStdSeg, eContEnergy, eContXMean, eContYMean, gContEnergy, gContNHits,
1114 gContXMean, gContYMean, oContEnergy, oContNHits, oContXMean, oContYMean,
1115 oContXStd, oContYStd, oContLayerMean, oContLayerStd,
1116 ecalLayerEdepReadout_, recoilP, recoilPos);
1119 ldmx::Ort::FloatArrays inputs({bdtFeatures_});
1120 float pred = rt_->run({featureListName_}, inputs, {
"probabilities"})[0].at(1);
1125 result.setVetoResult(pred > bdtCutVal_ && passesTrackingVeto);
1126 result.setDiscValue(pred);
1127 ldmx_log(debug) <<
" The pred > bdtCutVal = " << (pred > bdtCutVal_);
1130 result.setFiducial(inside);