41 namespace ActsExamples {
42 class IndexSourceLink;
57 throw std::invalid_argument(
"Missing particles input collection");
60 throw std::invalid_argument(
"Missing simulated hits input collection");
63 throw std::invalid_argument(
"Missing hit-particles map input collection");
66 throw std::invalid_argument(
67 "Missing hit-simulated-hits map input collection");
70 throw std::invalid_argument(
"Missing output filename");
73 throw std::invalid_argument(
"Missing tree name");
85 throw std::ios_base::failure(
"Could not open '" +
path);
90 throw std::bad_alloc();
275 m_outputFile->Close();
280 m_outputTree->Write();
281 m_outputFile->Close();
283 ACTS_INFO(
"Wrote states of trajectories to tree '"
284 <<
m_cfg.treeName <<
"' in '" <<
m_cfg.treeName <<
"'");
293 const auto&
particles = m_inputParticles(ctx);
294 const auto& simHits = m_inputSimHits(ctx);
295 const auto& hitParticlesMap = m_inputMeasurementParticlesMap(ctx);
296 const auto& hitSimHitsMap = m_inputMeasurementSimHitsMap(ctx);
299 std::vector<ParticleHitCount> particleHitCounts;
302 std::lock_guard<std::mutex> lock(m_writeMutex);
308 for (
size_t itraj = 0; itraj < trajectories.size(); ++itraj) {
309 const auto& traj = trajectories[itraj];
312 m_multiTrajNr = itraj;
315 const auto& trackTips = traj.tips();
318 if (trackTips.empty()) {
323 const auto& mj = traj.multiTrajectory();
326 for (
unsigned int isubtraj = 0; isubtraj < trackTips.size(); ++isubtraj) {
328 m_subTrajNr = isubtraj;
330 const auto& trackTip = trackTips[isubtraj];
335 m_nStates = trajState.nStates;
341 if (not particleHitCounts.empty()) {
343 auto barcode = particleHitCounts.front().particleId;
349 << barcode <<
"=" << barcode.value());
351 truthQ =
static_cast<int>(
particle.charge());
354 << barcode <<
"=" << barcode.value() <<
" not found!");
359 m_nParams = {0, 0, 0};
360 mj.visitBackwards(trackTip, [&](
const auto&
state) {
362 auto typeFlags =
state.typeFlags();
372 state.getUncalibratedSourceLink().template get<IndexSourceLink>();
373 const auto hitIdx = sl.index();
374 auto indices =
makeRange(hitSimHitsMap.equal_range(hitIdx));
375 auto [truthLocal, truthPos4, truthUnitDir] =
379 float truthQOP = 0.0f;
380 if (not indices.empty()) {
383 const auto simHitIdx0 = indices.begin()->second;
384 const auto& simHit0 = *simHits.nth(simHitIdx0);
387 truthQOP = truthQ /
p;
394 m_t_r.push_back(
perp(truthPos4.template segment<3>(Acts::ePos0)));
403 float truthPHI =
phi(truthUnitDir);
404 float truthTHETA =
theta(truthUnitDir);
407 m_t_eLOC0.push_back(truthLOC0);
408 m_t_eLOC1.push_back(truthLOC1);
409 m_t_ePHI.push_back(truthPHI);
410 m_t_eTHETA.push_back(truthTHETA);
411 m_t_eQOP.push_back(truthQOP);
412 m_t_eT.push_back(truthTIME);
415 auto geoID =
surface.geometryId();
416 m_volumeID.push_back(geoID.volume());
417 m_layerID.push_back(geoID.layer());
418 m_moduleID.push_back(geoID.sensitive());
421 m_pathLength.push_back(
state.pathLength());
425 state.effectiveCalibrated();
433 m_lx_hit.push_back(local[Acts::ePos0]);
434 m_ly_hit.push_back(local[Acts::ePos1]);
435 m_x_hit.push_back(global[Acts::ePos0]);
436 m_y_hit.push_back(global[Acts::ePos1]);
437 m_z_hit.push_back(global[Acts::ePos2]);
440 std::array<bool, 4>
hasParams = {
false,
false,
false,
false};
442 std::optional<std::pair<Acts::BoundVector, Acts::BoundMatrix>>
443 trackParamsOpt = std::nullopt;
445 auto getTrackParams = [&](
unsigned int ipar) {
446 if (ipar == 0 &&
state.hasPredicted()) {
450 std::make_pair(
state.predicted(),
state.predictedCovariance());
451 }
else if (ipar == 1 &&
state.hasFiltered()) {
455 std::make_pair(
state.filtered(),
state.filteredCovariance());
456 }
else if (ipar == 2 &&
state.hasSmoothed()) {
460 std::make_pair(
state.smoothed(),
state.smoothedCovariance());
461 }
else if (ipar == 3 &&
state.hasSmoothed()) {
467 auto m =
state.effectiveCalibrated();
468 auto H =
state.effectiveProjector();
469 auto V =
state.effectiveCalibratedCovariance();
471 (
state.smoothedCovariance() *
H.transpose() *
472 (
H *
state.smoothedCovariance() *
H.transpose() - V).inverse())
474 auto unbiasedParamsVec =
476 auto unbiasedParamsCov =
477 state.smoothedCovariance() - K *
H *
state.smoothedCovariance();
479 std::make_pair(unbiasedParamsVec, unbiasedParamsCov);
484 for (
unsigned int ipar = 0; ipar < 4; ++ipar) {
486 getTrackParams(ipar);
487 if (trackParamsOpt) {
492 auto H =
state.effectiveProjector();
493 auto V =
state.effectiveCalibratedCovariance();
500 m_res_x_hit.push_back(res[Acts::eBoundLoc0]);
501 m_err_x_hit.push_back(
502 std::sqrt(V(Acts::eBoundLoc0, Acts::eBoundLoc0)));
503 m_pull_x_hit.push_back(
504 res[Acts::eBoundLoc0] /
505 std::sqrt(resCov(Acts::eBoundLoc0, Acts::eBoundLoc0)));
507 if (
state.calibratedSize() >= 2) {
508 m_res_y_hit.push_back(res[Acts::eBoundLoc1]);
509 m_err_y_hit.push_back(
510 std::sqrt(V(Acts::eBoundLoc1, Acts::eBoundLoc1)));
511 m_pull_y_hit.push_back(
512 res[Acts::eBoundLoc1] /
513 std::sqrt(resCov(Acts::eBoundLoc1, Acts::eBoundLoc1)));
515 float nan = std::numeric_limits<float>::quiet_NaN();
516 m_res_y_hit.push_back(nan);
517 m_err_y_hit.push_back(nan);
518 m_pull_y_hit.push_back(nan);
521 m_dim_hit.push_back(
state.calibratedSize());
525 m_eLOC0[ipar].push_back(
parameters[Acts::eBoundLoc0]);
526 m_eLOC1[ipar].push_back(
parameters[Acts::eBoundLoc1]);
533 m_res_eLOC0[ipar].push_back(
parameters[Acts::eBoundLoc0] -
535 m_res_eLOC1[ipar].push_back(
parameters[Acts::eBoundLoc1] -
537 float resPhi = Acts::detail::difference_periodic<float>(
539 static_cast<float>(2 * M_PI));
540 m_res_ePHI[ipar].push_back(resPhi);
541 m_res_eTHETA[ipar].push_back(parameters[Acts::eBoundTheta] -
543 m_res_eQOP[ipar].push_back(parameters[Acts::eBoundQOverP] -
545 m_res_eT[ipar].push_back(parameters[Acts::eBoundTime] - truthTIME);
549 m_err_eLOC0[ipar].push_back(
550 std::sqrt(
covariance(Acts::eBoundLoc0, Acts::eBoundLoc0)));
551 m_err_eLOC1[ipar].push_back(
552 std::sqrt(
covariance(Acts::eBoundLoc1, Acts::eBoundLoc1)));
553 m_err_ePHI[ipar].push_back(
554 std::sqrt(
covariance(Acts::eBoundPhi, Acts::eBoundPhi)));
555 m_err_eTHETA[ipar].push_back(
556 std::sqrt(
covariance(Acts::eBoundTheta, Acts::eBoundTheta)));
557 m_err_eQOP[ipar].push_back(
558 std::sqrt(
covariance(Acts::eBoundQOverP, Acts::eBoundQOverP)));
559 m_err_eT[ipar].push_back(
560 std::sqrt(
covariance(Acts::eBoundTime, Acts::eBoundTime)));
564 m_pull_eLOC0[ipar].push_back(
565 (parameters[Acts::eBoundLoc0] - truthLOC0) /
566 std::sqrt(
covariance(Acts::eBoundLoc0, Acts::eBoundLoc0)));
567 m_pull_eLOC1[ipar].push_back(
568 (parameters[Acts::eBoundLoc1] - truthLOC1) /
569 std::sqrt(
covariance(Acts::eBoundLoc1, Acts::eBoundLoc1)));
570 m_pull_ePHI[ipar].push_back(
572 std::sqrt(
covariance(Acts::eBoundPhi, Acts::eBoundPhi)));
573 m_pull_eTHETA[ipar].push_back(
574 (parameters[Acts::eBoundTheta] - truthTHETA) /
575 std::sqrt(
covariance(Acts::eBoundTheta, Acts::eBoundTheta)));
576 m_pull_eQOP[ipar].push_back(
577 (parameters[Acts::eBoundQOverP] - truthQOP) /
578 std::sqrt(
covariance(Acts::eBoundQOverP, Acts::eBoundQOverP)));
580 std::sqrt(
covariance(Acts::eBoundTime, Acts::eBoundTime));
581 m_pull_eT[ipar].push_back(
583 ? std::numeric_limits<double>::quiet_NaN()
584 : (parameters[Acts::eBoundTime] - truthTIME) / sigmaTime);
597 m_pT[ipar].push_back(
p * std::hypot(freeParams[Acts::eFreeDir0],
598 freeParams[Acts::eFreeDir1]));
600 freeParams.segment<3>(Acts::eFreeDir0)));
604 m_res_x_hit.push_back(-99.);
605 m_res_y_hit.push_back(-99.);
606 m_err_x_hit.push_back(-99.);
607 m_err_y_hit.push_back(-99.);
608 m_pull_x_hit.push_back(-99.);
609 m_pull_y_hit.push_back(-99.);
610 m_dim_hit.push_back(-99.);
613 m_eLOC0[ipar].push_back(-99.);
614 m_eLOC1[ipar].push_back(-99.);
615 m_ePHI[ipar].push_back(-99.);
616 m_eTHETA[ipar].push_back(-99.);
617 m_eQOP[ipar].push_back(-99.);
618 m_eT[ipar].push_back(-99.);
619 m_res_eLOC0[ipar].push_back(-99.);
620 m_res_eLOC1[ipar].push_back(-99.);
621 m_res_ePHI[ipar].push_back(-99.);
622 m_res_eTHETA[ipar].push_back(-99.);
623 m_res_eQOP[ipar].push_back(-99.);
624 m_res_eT[ipar].push_back(-99.);
625 m_err_eLOC0[ipar].push_back(-99);
626 m_err_eLOC1[ipar].push_back(-99);
627 m_err_ePHI[ipar].push_back(-99);
628 m_err_eTHETA[ipar].push_back(-99);
629 m_err_eQOP[ipar].push_back(-99);
630 m_err_eT[ipar].push_back(-99);
631 m_pull_eLOC0[ipar].push_back(-99.);
632 m_pull_eLOC1[ipar].push_back(-99.);
633 m_pull_ePHI[ipar].push_back(-99.);
634 m_pull_eTHETA[ipar].push_back(-99.);
635 m_pull_eQOP[ipar].push_back(-99.);
636 m_pull_eT[ipar].push_back(-99.);
637 m_x[ipar].push_back(-99.);
638 m_y[ipar].push_back(-99.);
639 m_z[ipar].push_back(-99.);
640 m_px[ipar].push_back(-99.);
641 m_py[ipar].push_back(-99.);
642 m_pz[ipar].push_back(-99.);
643 m_pT[ipar].push_back(-99.);
644 m_eta[ipar].push_back(-99.);
647 m_hasParams[ipar].push_back(hasParams[ipar]);
657 m_outputTree->Fill();
677 m_pathLength.clear();
687 m_pull_x_hit.clear();
688 m_pull_y_hit.clear();
691 for (
unsigned int ipar = 0; ipar < 4; ++ipar) {
692 m_hasParams[ipar].clear();
693 m_eLOC0[ipar].clear();
694 m_eLOC1[ipar].clear();
695 m_ePHI[ipar].clear();
696 m_eTHETA[ipar].clear();
697 m_eQOP[ipar].clear();
699 m_res_eLOC0[ipar].clear();
700 m_res_eLOC1[ipar].clear();
701 m_res_ePHI[ipar].clear();
702 m_res_eTHETA[ipar].clear();
703 m_res_eQOP[ipar].clear();
704 m_res_eT[ipar].clear();
705 m_err_eLOC0[ipar].clear();
706 m_err_eLOC1[ipar].clear();
707 m_err_ePHI[ipar].clear();
708 m_err_eTHETA[ipar].clear();
709 m_err_eQOP[ipar].clear();
710 m_err_eT[ipar].clear();
711 m_pull_eLOC0[ipar].clear();
712 m_pull_eLOC1[ipar].clear();
713 m_pull_ePHI[ipar].clear();
714 m_pull_eTHETA[ipar].clear();
715 m_pull_eQOP[ipar].clear();
716 m_pull_eT[ipar].clear();