Process the event and put new data products into it.
169 {
170
171 geometry_ = &getCondition<ldmx::EcalGeometry>(
172 ldmx::EcalGeometry::CONDITIONS_OBJECT_NAME);
173
175
176 clearProcessor();
177
178
179
180
181 std::vector<double> recoilP;
182 std::vector<float> recoilPos;
183 std::vector<double> recoilPAtTarget;
184 std::vector<float> recoilPosAtTarget;
185
186 if (verbose_) {
187 ldmx_log(debug) << " Loop through all of the sim particles and find the "
188 "recoil electron";
189 }
190
191 if (event.
exists(
"EcalScoringPlaneHits")) {
192
193
194
195
196
198
199
201
202
203 auto ecalSpHits{
205 float pmax = 0;
208 if (hit_id.plane() != 31 || spHit.getMomentum()[2] <= 0) continue;
209
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) +
217 pow(recoilP[2], 2));
218 }
219 }
220 }
221
222
223 if (event.
exists(
"TargetScoringPlaneHits")) {
224 std::vector<ldmx::SimTrackerHit> targetSpHits =
226 pmax = 0;
229 if (hit_id.plane() != 1 || spHit.getMomentum()[2] <= 0) continue;
230
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();
237 pmax =
238 sqrt(pow(recoilPAtTarget[0], 2) + pow(recoilPAtTarget[1], 2) +
239 pow(recoilPAtTarget[2], 2));
240 }
241 }
242 }
243 }
244 }
245
246 if (verbose_) {
247 ldmx_log(debug) << " Get projected trajectories for electron and photon";
248 }
249
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()
254 ? recoilPAtTarget
255 : std::vector<double>{0.0, 0.0, 0.0};
256 std::vector<float> posvec = recoilPosAtTarget.size()
257 ? recoilPosAtTarget
258 : std::vector<float>{0.0, 0.0, 0.0};
259 photon_trajectory =
260 getTrajectory({-pvec[0], -pvec[1], beamEnergyMeV_ - pvec[2]}, posvec);
261 }
262
263 float recoilPMag =
264 recoilP.size()
265 ? sqrt(pow(recoilP[0], 2) + pow(recoilP[1], 2) + pow(recoilP[2], 2))
266 : -1.0;
267 float recoilTheta =
268 recoilPMag > 0 ? acos(recoilP[2] / recoilPMag) * 180.0 / M_PI : -1.0;
269
270 if (verbose_) {
271 ldmx_log(debug) << " Build Radii of containment (ROC)";
272 }
273
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;
278 bool inrange;
279
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];
285 inrange = true;
286
287 if (theta_min != -1.0) {
288 inrange = inrange && (recoilTheta >= theta_min);
289 }
290 if (theta_max != -1.0) {
291 inrange = inrange && (recoilTheta < theta_max);
292 }
293 if (p_min != -1.0) {
294 inrange = inrange && (recoilPMag >= p_min);
295 }
296 if (p_max != -1.0) {
297 inrange = inrange && (recoilPMag < p_max);
298 }
299 if (inrange) {
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;
303 }
304 }
305
306 std::vector<double> photon_radii = roc_values_bin0;
307
308
309 const std::vector<ldmx::EcalHit> ecalRecHits =
310 event.getCollection<
ldmx::EcalHit>(rec_coll_name_, rec_pass_name_);
311
313 GetShowerCentroidIDAndRMS(ecalRecHits, showerRMS_);
314
316 bool doTight = true;
317
318 fillIsolatedHitMap(ecalRecHits, globalCentroid, cellMap_, cellMapTightIso_,
319 doTight);
320
321
322
323
324 float wavgLayerHit = 0;
325 float xMean = 0;
326 float yMean = 0;
327
328
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);
338
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));
378
379
380
381
382 std::vector<HitData> trackingHitList;
383
384 if (verbose_) {
385 ldmx_log(debug)
386 << " Loop over the hits from the event to calculate the BDT features";
387 }
388
390
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) {
397 nReadoutHits_++;
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();
407 }
408 XYCoords xy_pair = std::make_pair(x, y);
409 float distance_ele_trajectory =
410 ele_trajectory.size()
411 ? sqrt(
412 pow((xy_pair.first - ele_trajectory[id.layer()].first), 2) +
413 pow((xy_pair.second - ele_trajectory[id.layer()].second),
414 2))
415 : -1.0;
416 float distance_photon_trajectory =
417 photon_trajectory.size()
418 ? sqrt(
419 pow((xy_pair.first - photon_trajectory[id.layer()].first),
420 2) +
421 pow((xy_pair.second - photon_trajectory[id.layer()].second),
422 2))
423 : -1.0;
424
425
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();
433
434
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();
441 }
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();
449 }
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();
458 }
459 }
460 }
461 }
462
463
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();
478 }
479 }
480
481
482
483 if (distance_ele_trajectory >= ele_radii[id.layer()] ||
484 distance_ele_trajectory == -1.0) {
485 HitData hd;
486 hd.pos = TVector3(xy_pair.first, xy_pair.second,
488 hd.layer = id.layer();
489 trackingHitList.push_back(hd);
490 }
491 }
492 }
493
494 for (const auto &[id, energy] : cellMapTightIso_) {
495 if (energy > 0) summedTightIso_ += energy;
496 }
497
498 for (int iLayer = 0; iLayer < ecalLayerEdepReadout_.size(); iLayer++) {
499 ecalLayerTime_[iLayer] =
500 ecalLayerTime_[iLayer] / ecalLayerEdepReadout_[iLayer];
501 summedDet_ += ecalLayerEdepReadout_[iLayer];
502 }
503
504 if (nReadoutHits_ > 0) {
505 avgLayerHit_ /= nReadoutHits_;
506 wavgLayerHit /= summedDet_;
507 xMean /= summedDet_;
508 yMean /= summedDet_;
509 } else {
510 wavgLayerHit = 0;
511 avgLayerHit_ = 0;
512 xMean = 0;
513 yMean = 0;
514 }
515
516
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];
522 }
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];
527 }
528 if (gContEnergy[ireg][iseg] > 0) {
529 gContXMean[ireg][iseg] /= gContEnergy[ireg][iseg];
530 gContYMean[ireg][iseg] /= gContEnergy[ireg][iseg];
531 }
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];
536 }
537 }
538 }
539
540 for (unsigned int ireg = 0; ireg < nregions; ireg++) {
541 if (outsideContainmentEnergy[ireg] > 0) {
542 outsideContainmentXmean[ireg] /= outsideContainmentEnergy[ireg];
543 outsideContainmentYmean[ireg] /= outsideContainmentEnergy[ireg];
544 }
545 }
546
547
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();
555 }
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))
561 : -1.0;
562 float distance_photon_trajectory =
563 photon_trajectory.size()
564 ? sqrt(pow((xy_pair.first - photon_trajectory[id.layer()].first),
565 2) +
566 pow((xy_pair.second - photon_trajectory[id.layer()].second),
567 2))
568 : -1.0;
569
570 for (unsigned int iseg = 0; iseg < nsegments; iseg++) {
571 if (id.layer() >= segLayers[iseg] &&
572 id.layer() <= segLayers[iseg + 1] - 1) {
573 xStdSeg[iseg] +=
574 pow((xy_pair.first - xMeanSeg[iseg]), 2) * hit.getEnergy();
575 yStdSeg[iseg] +=
576 pow((xy_pair.second - yMeanSeg[iseg]), 2) * hit.getEnergy();
577 layerStdSeg[iseg] +=
578 pow((id.layer() - layerMeanSeg[iseg]), 2) * hit.getEnergy();
579
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) *
586 hit.getEnergy();
587 oContYStd[ireg][iseg] +=
588 pow((xy_pair.second - oContYMean[ireg][iseg]), 2) *
589 hit.getEnergy();
590 oContLayerStd[ireg][iseg] +=
591 pow((id.layer() - oContLayerMean[ireg][iseg]), 2) *
592 hit.getEnergy();
593 }
594 }
595 }
596 }
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 > (ireg + 1) * photon_radii[id.layer()]) {
601 outsideContainmentXstd[ireg] +=
602 pow((xy_pair.first - outsideContainmentXmean[ireg]), 2) *
603 hit.getEnergy();
604 outsideContainmentYstd[ireg] +=
605 pow((xy_pair.second - outsideContainmentYmean[ireg]), 2) *
606 hit.getEnergy();
607 }
608 }
609 }
610
611 if (nReadoutHits_ > 0) {
612 xStd_ = sqrt(xStd_ / summedDet_);
613 yStd_ = sqrt(yStd_ / summedDet_);
614 stdLayerHit_ = sqrt(stdLayerHit_ / summedDet_);
615 } else {
616 xStd_ = 0;
617 yStd_ = 0;
618 stdLayerHit_ = 0;
619 }
620
621
622
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]);
628 }
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]);
637 }
638 }
639 }
640
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]);
647 }
648 }
649
650 if (verbose_) {
651 ldmx_log(debug) << " Find out if the recoil electron is fiducial";
652 }
653
654
655
656
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) {
661 drifted_recoil_x =
662 (dz_from_face * (recoilP[0] / recoilP[2])) + recoilPos[0];
663 drifted_recoil_y =
664 (dz_from_face * (recoilP[1] / recoilP[2])) + recoilPos[1];
665 }
666 const int recoil_layer_index = 0;
667
668
669 bool inside{false};
670
671 const auto ecalID =
geometry_->
getID(drifted_recoil_x, drifted_recoil_y,
672 recoil_layer_index, true);
673 if (!ecalID.null()) {
674
675 const auto cellID =
676 geometry_->
getID(drifted_recoil_x, drifted_recoil_y, recoil_layer_index,
677 ecalID.getModuleID(), true);
678 if (!cellID.null()) {
679 inside = true;
680 }
681 }
682
683 if (!inside) {
684 ldmx_log(info) << "This event is non-fiducial in ECAL";
685 }
686
687
688
689
690
691
692
693
694
695
696 TVector3 e_traj_start;
697 TVector3 e_traj_end;
698 TVector3 p_traj_start;
699 TVector3 p_traj_end;
700 if (ele_trajectory.size() > 0 && photon_trajectory.size() > 0) {
701
702
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,
713
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));
722 } else {
723
724
725
727 e_traj_end = TVector3(
730 p_traj_end = TVector3(
732
736 }
737
738
739
740
741
743
744 if (photon_trajectory.size() !=
745 0) {
746 for (std::vector<HitData>::iterator it = trackingHitList.begin();
747 it != trackingHitList.end(); ++it) {
748 float ehDist =
749 sqrt(pow((*it).pos.X() - photon_trajectory[(*it).layer].first, 2) +
750 pow((*it).pos.Y() - photon_trajectory[(*it).layer].second, 2));
751 if (ehDist < 8.7) {
755 }
756 }
757 }
758 }
759
760
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) {
769 }
770 }
771 } else {
773 }
774
775
776
777
778 std::sort(trackingHitList.begin(), trackingHitList.end(),
779 [](HitData ha, HitData hb) { return ha.layer > hb.layer; });
780
781
782
783
784 std::vector<std::vector<HitData>> track_list;
785
786
787 if (verbose_) {
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 << "], ";
794 }
795 std::cout << std::endl;
796 ldmx_log(debug) << "====== END OF Tracking hit list ======";
797 }
798
799
800
802 for (int iHit = 0; iHit < trackingHitList.size(); iHit++) {
803
804 int track[34];
805 int currenthit{iHit};
806 int trackLen{1};
807
808 track[0] = iHit;
809
810
811
812
813
814 int jHit = 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;
825 trackLen++;
826 currenthit = jHit;
827 }
828 jHit++;
829 }
830
831
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);
839
840
841 if (closest_p > cellWidth and closest_e < 2 * cellWidth) continue;
842 if (trackLen < 4 and closest_e > closest_p) continue;
843 if (verbose_) {
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 << "]";
848
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 << "]";
854 }
855 }
856
857
858
859 if (trackLen >= 2) {
860 std::vector<HitData> temp_track_list;
861 int n_remove = 0;
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);
865 n_remove++;
866 }
867
868 if (verbose_) {
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 << "] ";
875 }
876 std::cout << std::endl;
877 ldmx_log(debug) << "====== END OF Tracking hit list ======";
878 }
879
880 track_list.push_back(temp_track_list);
881
882
883 iHit--;
884 }
885 }
886
887 ldmx_log(debug) << "Straight tracks found (before merge): "
888 << track_list.size();
889 if (verbose_) {
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;
897 }
898 std::cout << std::endl;
899 }
900 }
901
902
903
904
905 ldmx_log(debug) << "Beginning track merging using " << track_list.size()
906 << " tracks";
907
908 for (int track_i = 0; track_i < track_list.size(); track_i++) {
909
910
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();
917
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),
922 0.5) <= cellWidth) {
923
924
925
926 if (verbose_) {
927 ldmx_log(debug) << " ** Compatible track found at index "
928 << track_j;
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;
935 }
936 for (int hit_k = 0; hit_k < checking_track.size(); hit_k++) {
937 base_track.push_back(track_list[track_j][hit_k]);
938 }
939 track_list[track_i] = base_track;
940 track_list.erase(track_list.begin() + track_j);
941 break;
942 }
943 }
944 }
946
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 << "]";
956 }
957 }
958
959
960
961 ldmx_log(debug) << "Finding linreg tracks from a total of "
962 << trackingHitList.size() << " hits using a radius of "
963 << linreg_radius_ << " mm";
964
965 for (int iHit = 0; iHit < trackingHitList.size(); iHit++) {
966
967 std::vector<int> hitsInRegion;
968 TMatrixD Vm(3, 3);
969 TMatrixD hdt(3, 3);
970 TVector3 slopeVec;
971 TVector3 hmean;
972 TVector3 hpoint;
973 float r_corr_best{0.0};
974
975 int hitNums[3];
976
977 int bestHitNums[3];
978
979 hitsInRegion.push_back(iHit);
980
981 for (int jHit = 0; jHit < trackingHitList.size(); jHit++) {
982
983 if (trackingHitList[iHit].pos(2) == trackingHitList[jHit].pos(2)) {
984 continue;
985 }
986 float dstToHit =
987 (trackingHitList[iHit].pos - trackingHitList[jHit].pos).Mag();
988
989
990
991 if (dstToHit <= 2 * linreg_radius_) {
992 hitsInRegion.push_back(jHit);
993 }
994 }
995
996 bool bestLinRegFound{false};
997 if (verbose_) {
998 ldmx_log(debug) << "There are " << hitsInRegion.size()
999 << " hits within a radius of " << linreg_radius_ << " mm";
1000 }
1001
1002
1003 hitNums[0] = iHit;
1004 for (int jHitInReg = 1; jHitInReg < hitsInRegion.size() - 1; jHitInReg++) {
1005
1006 if (hitsInRegion.size() < 3) break;
1007 hitNums[1] = hitsInRegion[jHitInReg];
1008 for (int kHitReg = jHitInReg + 1; kHitReg < hitsInRegion.size();
1009 kHitReg++) {
1010 hitNums[2] = hitsInRegion[kHitReg];
1011 for (int hInd = 0; hInd < 3; hInd++) {
1012
1013
1014 hmean(hInd) = (trackingHitList[hitNums[0]].pos(hInd) +
1015 trackingHitList[hitNums[1]].pos(hInd) +
1016 trackingHitList[hitNums[2]].pos(hInd)) /
1017 3.0;
1018 }
1019 for (int hInd = 0; hInd < 3; hInd++) {
1020 for (int lInd = 0; lInd < 3; lInd++) {
1021 hdt(hInd, lInd) =
1022 trackingHitList[hitNums[hInd]].pos(lInd) - hmean(lInd);
1023 }
1024 }
1025
1026
1027
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));
1032
1033 if (determinant == 0) continue;
1034
1035 TDecompSVD svdObj(hdt);
1036 bool decomposed = svdObj.Decompose();
1037 if (!decomposed) continue;
1038
1039
1040 Vm = svdObj.GetV();
1041 for (int hInd = 0; hInd < 3; hInd++) {
1042 slopeVec(hInd) = Vm[0][hInd];
1043 }
1044
1045 hpoint = slopeVec + hmean;
1046
1047
1048
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);
1051
1052
1053 if (closest_p > cellWidth or closest_e < 1.5 * cellWidth) continue;
1054
1055
1056 float vrnc = (trackingHitList[hitNums[0]].pos - hmean).Mag() +
1057 (trackingHitList[hitNums[1]].pos - hmean).Mag() +
1058 (trackingHitList[hitNums[2]].pos - hmean).Mag();
1059
1060 float sumerr =
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;
1065
1066
1067
1068 if (r_corr > r_corr_best and r_corr > .6) {
1069 r_corr_best = r_corr;
1070
1071 bestLinRegFound = true;
1072 for (int k = 0; k < 3; k++) {
1073 bestHitNums[k] = hitNums[k];
1074 }
1075 }
1076 }
1077 }
1078
1079
1080 if (!bestLinRegFound) continue;
1081
1084 for (int finalHitIndx = 0; finalHitIndx < 3; finalHitIndx++) {
1085 ldmx_log(debug) << " Hit " << finalHitIndx << " ["
1086 << trackingHitList[bestHitNums[finalHitIndx]].pos(0)
1087 << ", "
1088 << trackingHitList[bestHitNums[finalHitIndx]].pos(1)
1089 << ", "
1090 << trackingHitList[bestHitNums[finalHitIndx]].pos(2)
1091 << "] ";
1092 }
1093
1094
1095 for (int lHit = 0; lHit < 3; lHit++) {
1096 trackingHitList.erase(trackingHitList.begin() + bestHitNums[lHit]);
1097 }
1098 iHit--;
1099 }
1100
1103 << " lin-reg tracks";
1104
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);
1117
1119 ldmx::Ort::FloatArrays inputs({bdtFeatures_});
1120 float pred = rt_->run({featureListName_}, inputs, {"probabilities"})[0].at(1);
1121
1122
1123
1125 result.setVetoResult(pred > bdtCutVal_ && passesTrackingVeto);
1126 result.setDiscValue(pred);
1127 ldmx_log(debug) << " The pred > bdtCutVal = " << (pred > bdtCutVal_);
1128
1129
1130 result.setFiducial(inside);
1131
1132
1133
1136 } else {
1138 }
1139
1141}
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.
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.
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.
constexpr StorageControl::Hint hint_shouldKeep
storage control hint alias for backwards compatibility
constexpr StorageControl::Hint hint_shouldDrop
storage control hint alias for backwards compatibility