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