From a5a2c2dfb6f042372194bc1dbd8705ad3aa22d8e Mon Sep 17 00:00:00 2001 From: Wouter Deconinck Date: Mon, 8 Apr 2024 16:15:00 -0500 Subject: [PATCH 1/9] feat(ci): change pre-commit clang-format and enable in ci --- .pre-commit-config.yaml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e33c42eb00..d8ced0cc37 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,5 +1,3 @@ -ci: - skip: [clang-format] repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.6.0 @@ -18,8 +16,8 @@ repos: - id: forbid-tabs - id: remove-tabs args: [--whitespaces-count, '8'] -- repo: https://github.com/pocc/pre-commit-hooks - rev: v1.3.5 +- repo: https://github.com/pre-commit/mirrors-clang-format + rev: v18.1.3 hooks: - id: clang-format - repo: https://github.com/cheshirekow/cmake-format-precommit From 0003f9a857ca720a3ade30dfc2039a231434cf74 Mon Sep 17 00:00:00 2001 From: Wouter Deconinck Date: Mon, 8 Apr 2024 18:19:23 -0500 Subject: [PATCH 2/9] fix: SortIncludes: Never; Standard: Cpp20 --- .clang-format | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.clang-format b/.clang-format index 5c443be69c..b1e62de66a 100644 --- a/.clang-format +++ b/.clang-format @@ -3,7 +3,7 @@ BasedOnStyle: LLVM BreakConstructorInitializersBeforeComma: true ConstructorInitializerAllOnOneLineOrOnePerLine: true Cpp11BracedListStyle: true -Standard: Cpp11 +Standard: Cpp20 #SpaceBeforeParens: ControlStatements SpaceAfterControlStatementKeyword: true PointerBindsToType: true @@ -12,4 +12,5 @@ UseTab: Never ColumnLimit: 100 NamespaceIndentation: Inner AlignConsecutiveAssignments: true +SortIncludes: Never ... From 882dc7dfebe33b1ea20696a851676b2039d86fee Mon Sep 17 00:00:00 2001 From: Wouter Deconinck Date: Fri, 12 Apr 2024 09:00:58 -0500 Subject: [PATCH 3/9] fix: ignore docs/*.json --- .clang-format-ignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 .clang-format-ignore diff --git a/.clang-format-ignore b/.clang-format-ignore new file mode 100644 index 0000000000..0bbcc0e0ee --- /dev/null +++ b/.clang-format-ignore @@ -0,0 +1 @@ +docs/*.json From 104640b096297a389078ac9258e7892552f719d8 Mon Sep 17 00:00:00 2001 From: Wouter Deconinck Date: Fri, 12 Apr 2024 09:05:40 -0500 Subject: [PATCH 4/9] fix: use correct Standard option (Cpp11 is deprecated alias) --- .clang-format | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.clang-format b/.clang-format index b1e62de66a..f5e462c215 100644 --- a/.clang-format +++ b/.clang-format @@ -3,7 +3,7 @@ BasedOnStyle: LLVM BreakConstructorInitializersBeforeComma: true ConstructorInitializerAllOnOneLineOrOnePerLine: true Cpp11BracedListStyle: true -Standard: Cpp20 +Standard: c++20 #SpaceBeforeParens: ControlStatements SpaceAfterControlStatementKeyword: true PointerBindsToType: true From fa0a0800479309a57ce7ce8b2801325802b9ee0f Mon Sep 17 00:00:00 2001 From: Wouter Deconinck Date: Fri, 12 Apr 2024 09:37:53 -0500 Subject: [PATCH 5/9] fix: don't reflow comments --- .clang-format | 1 + 1 file changed, 1 insertion(+) diff --git a/.clang-format b/.clang-format index f5e462c215..6041e26532 100644 --- a/.clang-format +++ b/.clang-format @@ -13,4 +13,5 @@ ColumnLimit: 100 NamespaceIndentation: Inner AlignConsecutiveAssignments: true SortIncludes: Never +ReflowComments: false ... From 20eaf1672b1863a37bcd010547e3d614878babb8 Mon Sep 17 00:00:00 2001 From: Wouter Deconinck Date: Fri, 12 Apr 2024 13:34:58 -0500 Subject: [PATCH 6/9] fix: clang-tidy trips up over bugprone-macro-parentheses --- .clang-tidy | 1 + 1 file changed, 1 insertion(+) diff --git a/.clang-tidy b/.clang-tidy index 3e98e5e442..2dfe9a7ac2 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -6,6 +6,7 @@ Checks: ' modernize-*, portability-*, readability-*, + -bugprone-macro-parentheses, -bugprone-unchecked-optional-access, -modernize-use-trailing-return-type, -modernize-avoid-c-arrays, From 2487714ecea605f09dc2a802ab8a316a94373c7f Mon Sep 17 00:00:00 2001 From: Wouter Deconinck Date: Fri, 12 Apr 2024 14:10:42 -0500 Subject: [PATCH 7/9] fix: also ignore bugprone-macro-parentheses in ci... --- .github/workflows/linux-eic-shell.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/linux-eic-shell.yml b/.github/workflows/linux-eic-shell.yml index a06a307bd9..eff3ec5e8b 100644 --- a/.github/workflows/linux-eic-shell.yml +++ b/.github/workflows/linux-eic-shell.yml @@ -155,7 +155,7 @@ jobs: with: platform-release: "${{ env.platform-release }}" run: | - git diff ${{ github.event.pull_request.head.sha }} ${{ github.event.pull_request.base.sha }} | clang-tidy-diff -p 1 -path build -quiet -export-fixes clang_tidy_fixes.yml -extra-arg='-std=c++20' -checks='-*,bugprone-*,-bugprone-narrowing-conversions' -clang-tidy-binary run-clang-tidy + git diff ${{ github.event.pull_request.head.sha }} ${{ github.event.pull_request.base.sha }} | clang-tidy-diff -p 1 -path build -quiet -export-fixes clang_tidy_fixes.yml -extra-arg='-std=c++20' -checks='-*,bugprone-*,-bugprone-narrowing-conversions,-bugprone-macro-parentheses' -clang-tidy-binary run-clang-tidy - name: Run clang-tidy on all files uses: eic/run-cvmfs-osg-eic-shell@main if: ${{ github.event_name == 'push' }} From 928f37d68f09157f656052f981d3c48a7f7dcb39 Mon Sep 17 00:00:00 2001 From: Wouter Deconinck Date: Fri, 12 Apr 2024 16:08:12 -0500 Subject: [PATCH 8/9] noop: [skip pre-commit.ci] From c114892ddc49604039ee6a5b57581f50ba4d4aff Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 12 Apr 2024 21:33:46 +0000 Subject: [PATCH 9/9] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .devcontainer/devcontainer.json | 20 +- .../calorimetry/CalorimeterClusterRecoCoG.cc | 270 +++--- .../calorimetry/CalorimeterClusterRecoCoG.h | 89 +- .../CalorimeterClusterRecoCoGConfig.h | 33 +- .../calorimetry/CalorimeterHitDigi.cc | 246 +++-- .../calorimetry/CalorimeterHitDigi.h | 54 +- .../calorimetry/CalorimeterHitDigiConfig.h | 37 +- .../calorimetry/CalorimeterHitReco.cc | 411 ++++---- .../calorimetry/CalorimeterHitReco.h | 65 +- .../calorimetry/CalorimeterHitRecoConfig.h | 64 +- .../calorimetry/CalorimeterHitsMerger.cc | 178 ++-- .../calorimetry/CalorimeterHitsMerger.h | 48 +- .../calorimetry/CalorimeterHitsMergerConfig.h | 13 +- .../calorimetry/CalorimeterIslandCluster.cc | 350 ++++--- .../calorimetry/CalorimeterIslandCluster.h | 163 ++-- .../CalorimeterIslandClusterConfig.h | 49 +- .../calorimetry/CalorimeterTruthClustering.cc | 107 +- .../calorimetry/CalorimeterTruthClustering.h | 38 +- .../calorimetry/EnergyPositionClusterMerger.h | 339 ++++--- .../EnergyPositionClusterMergerConfig.h | 13 +- src/algorithms/calorimetry/HEXPLIT.cc | 147 ++- src/algorithms/calorimetry/HEXPLIT.h | 66 +- src/algorithms/calorimetry/HEXPLITConfig.h | 12 +- .../calorimetry/ImagingClusterReco.h | 495 +++++----- .../calorimetry/ImagingClusterRecoConfig.h | 9 +- .../calorimetry/ImagingTopoCluster.h | 300 +++--- .../calorimetry/ImagingTopoClusterConfig.h | 41 +- .../TruthEnergyPositionClusterMerger.h | 341 +++---- src/algorithms/digi/PhotoMultiplierHitDigi.cc | 428 ++++---- src/algorithms/digi/PhotoMultiplierHitDigi.h | 160 ++- .../digi/PhotoMultiplierHitDigiConfig.h | 124 ++- src/algorithms/digi/SiliconTrackerDigi.cc | 132 +-- src/algorithms/digi/SiliconTrackerDigi.h | 61 +- .../digi/SiliconTrackerDigiConfig.h | 14 +- .../fardetectors/MatrixTransferStatic.cc | 221 ++--- .../fardetectors/MatrixTransferStatic.h | 49 +- .../fardetectors/MatrixTransferStaticConfig.h | 76 +- src/algorithms/interfaces/WithPodConfig.h | 35 +- src/algorithms/meta/CollectionCollector.h | 56 +- src/algorithms/meta/SubDivideCollection.h | 63 +- .../meta/SubDivideCollectionConfig.h | 9 +- src/algorithms/meta/SubDivideFunctors.h | 127 ++- src/algorithms/pid/ConvertParticleID.h | 123 ++- src/algorithms/pid/IrtCherenkovParticleID.cc | 259 +++-- src/algorithms/pid/IrtCherenkovParticleID.h | 71 +- .../pid/IrtCherenkovParticleIDConfig.h | 129 ++- src/algorithms/pid/MergeParticleID.cc | 107 +- src/algorithms/pid/MergeParticleID.h | 56 +- src/algorithms/pid/MergeParticleIDConfig.h | 55 +- src/algorithms/pid/MergeTracks.cc | 38 +- src/algorithms/pid/MergeTracks.h | 41 +- src/algorithms/pid/ParticlesWithPID.cc | 589 ++++++----- src/algorithms/pid/ParticlesWithPID.h | 45 +- src/algorithms/pid/ParticlesWithPIDConfig.h | 12 +- src/algorithms/pid/Tools.h | 418 ++++---- src/algorithms/reco/Beam.h | 100 +- src/algorithms/reco/Boost.h | 66 +- .../reco/ChargedMCParticleSelector.h | 40 +- .../ChargedReconstructedParticleSelector.h | 40 +- src/algorithms/reco/ElectronReconstruction.cc | 73 +- src/algorithms/reco/ElectronReconstruction.h | 24 +- .../reco/ElectronReconstructionConfig.h | 5 +- src/algorithms/reco/InclusiveKinematicsDA.cc | 251 +++-- src/algorithms/reco/InclusiveKinematicsDA.h | 51 +- .../reco/InclusiveKinematicsElectron.cc | 277 +++--- .../reco/InclusiveKinematicsElectron.h | 51 +- src/algorithms/reco/InclusiveKinematicsJB.cc | 236 +++-- src/algorithms/reco/InclusiveKinematicsJB.h | 51 +- .../reco/InclusiveKinematicsSigma.cc | 254 +++-- .../reco/InclusiveKinematicsSigma.h | 44 +- .../reco/InclusiveKinematicsTruth.cc | 133 ++- .../reco/InclusiveKinematicsTruth.h | 48 +- .../reco/InclusiveKinematicseSigma.cc | 273 +++--- .../reco/InclusiveKinematicseSigma.h | 47 +- src/algorithms/reco/JetReconstruction.cc | 229 ++--- src/algorithms/reco/JetReconstruction.h | 154 ++- src/algorithms/reco/JetReconstructionConfig.h | 29 +- src/algorithms/reco/MC2SmearedParticle.cc | 66 +- src/algorithms/reco/MC2SmearedParticle.h | 31 +- src/algorithms/reco/MatchClusters.cc | 269 +++-- src/algorithms/reco/MatchClusters.h | 74 +- .../reco/ScatteredElectronsEMinusPz.cc | 206 ++-- .../reco/ScatteredElectronsEMinusPz.h | 24 +- .../reco/ScatteredElectronsEMinusPzConfig.h | 17 +- .../reco/ScatteredElectronsTruth.cc | 167 ++-- src/algorithms/reco/ScatteredElectronsTruth.h | 43 +- src/algorithms/reco/TransformBreitFrame.cc | 252 +++-- src/algorithms/reco/TransformBreitFrame.h | 53 +- .../tracking/ActsGeometryProvider.cc | 281 +++--- .../tracking/ActsGeometryProvider.h | 154 +-- src/algorithms/tracking/CKFTracking.cc | 811 ++++++++-------- src/algorithms/tracking/CKFTracking.h | 121 ++- src/algorithms/tracking/CKFTrackingConfig.h | 12 +- .../tracking/CKFTrackingFunction.cc | 86 +- src/algorithms/tracking/DD4hepBField.cc | 53 +- src/algorithms/tracking/DD4hepBField.h | 57 +- .../tracking/IterativeVertexFinder.cc | 56 +- .../tracking/IterativeVertexFinderConfig.h | 2 +- .../tracking/OrthogonalTrackSeedingConfig.h | 152 +-- src/algorithms/tracking/SpacePoint.h | 54 +- .../tracking/TrackParamTruthInit.cc | 251 ++--- src/algorithms/tracking/TrackParamTruthInit.h | 31 +- .../tracking/TrackParamTruthInitConfig.h | 15 +- src/algorithms/tracking/TrackProjector.cc | 336 +++---- src/algorithms/tracking/TrackProjector.h | 27 +- src/algorithms/tracking/TrackPropagation.cc | 512 +++++----- src/algorithms/tracking/TrackPropagation.h | 104 +- .../tracking/TrackPropagationConfig.h | 32 +- src/algorithms/tracking/TrackSeeding.cc | 499 +++++----- src/algorithms/tracking/TrackSeeding.h | 61 +- .../tracking/TrackerHitReconstruction.cc | 108 ++- .../tracking/TrackerHitReconstruction.h | 48 +- .../tracking/TrackerHitReconstructionConfig.h | 8 +- .../tracking/TrackerMeasurementFromHits.cc | 214 ++-- .../tracking/TrackerMeasurementFromHits.h | 34 +- .../EcalBarrelScFiCheck.cc | 8 +- .../EcalBarrelScFiCheckProcessor.cc | 163 ++-- .../EcalBarrelScFiCheckProcessor.h | 17 +- .../TRACKINGcheck/TRACKINGcheck.cc | 8 +- .../TRACKINGcheck/TRACKINGcheckProcessor.cc | 64 +- .../TRACKINGcheck/TRACKINGcheckProcessor.h | 18 +- .../TRACKINGcheck/macros/TRACKINGcheck.C | 160 +-- .../femc_studies/femc_studies.cc | 8 +- .../femc_studies/femc_studiesProcessor.cc | 417 ++++---- .../femc_studies/femc_studiesProcessor.h | 129 ++- .../lfhcal_studies/clusterizer_MA.h | 250 ++--- .../lfhcal_studies/lfhcal_studies.cc | 8 +- .../lfhcal_studies/lfhcal_studiesProcessor.cc | 559 ++++++----- .../lfhcal_studies/lfhcal_studiesProcessor.h | 166 ++-- .../tof_efficiency/TofEfficiency_processor.cc | 256 ++--- .../tof_efficiency/TofEfficiency_processor.h | 27 +- .../tof_efficiency/tof_efficiency.cc | 8 +- .../TrackingEfficiency_processor.cc | 290 +++--- .../TrackingEfficiency_processor.h | 76 +- .../tracking_efficiency/scripts/Plot_eta.C | 252 ++--- .../scripts/draw_Performance.C | 295 +++--- .../tracking_efficiency/scripts/draw_hits.C | 619 ++++++------ .../tracking_efficiency.cc | 8 +- .../HitReconstructionAnalysis.cc | 76 +- .../HitReconstructionAnalysis.h | 53 +- .../TrackingOccupancyAnalysis.cc | 77 +- .../TrackingOccupancyAnalysis.h | 53 +- .../TrackingOccupancy_processor.cc | 68 +- .../TrackingOccupancy_processor.h | 78 +- .../tracking_occupancy/tracking_occupancy.cc | 8 +- src/detectors/B0ECAL/B0ECAL.cc | 150 ++- src/detectors/B0TRK/B0TRK.cc | 43 +- src/detectors/BEMC/BEMC.cc | 335 +++---- src/detectors/BHCAL/BHCAL.cc | 297 +++--- src/detectors/BTOF/BTOF.cc | 44 +- src/detectors/BTRK/BTRK.cc | 44 +- src/detectors/BVTX/BVTX.cc | 37 +- src/detectors/DIRC/DIRC.cc | 61 +- src/detectors/DRICH/DRICH.cc | 128 ++- src/detectors/ECTOF/ECTOF.cc | 36 +- src/detectors/ECTRK/ECTRK.cc | 37 +- src/detectors/EEMC/EEMC.cc | 177 ++-- src/detectors/EHCAL/EHCAL.cc | 194 ++-- src/detectors/FEMC/FEMC.cc | 346 ++++--- src/detectors/FHCAL/FHCAL.cc | 455 +++++---- src/detectors/FOFFMTRK/FOFFMTRK.cc | 93 +- src/detectors/LOWQ2/LOWQ2.cc | 79 +- src/detectors/LUMISPECCAL/LUMISPECCAL.cc | 160 ++- src/detectors/MPGD/MPGD.cc | 215 ++-- src/detectors/RPOTS/RPOTS.cc | 94 +- src/detectors/ZDC/ZDC.cc | 450 +++++---- .../reco_particles_track_matching.cc | 80 +- .../jana/JChainMultifactoryGeneratorT.h | 133 ++- src/extensions/jana/JChainMultifactoryT.h | 102 +- src/extensions/jana/JOmniFactory.h | 862 ++++++++--------- src/extensions/jana/JOmniFactoryGeneratorT.h | 183 ++-- src/extensions/spdlog/SpdlogExtensions.h | 100 +- src/extensions/spdlog/SpdlogFormatters.h | 10 +- src/extensions/spdlog/SpdlogMixin.h | 46 +- src/extensions/spdlog/SpdlogToActs.h | 170 ++-- .../CalorimeterClusterRecoCoG_factory.h | 62 +- .../calorimetry/CalorimeterHitDigi_factory.h | 62 +- .../calorimetry/CalorimeterHitReco_factory.h | 75 +- .../CalorimeterHitsMerger_factory.h | 48 +- .../CalorimeterIslandCluster_factory.h | 84 +- .../CalorimeterTruthClustering_factory.h | 38 +- .../EnergyPositionClusterMerger_factory.h | 62 +- src/factories/calorimetry/HEXPLIT_factory.h | 47 +- .../calorimetry/ImagingClusterReco_factory.h | 52 +- .../calorimetry/ImagingTopoCluster_factory.h | 55 +- ...TruthEnergyPositionClusterMerger_factory.h | 55 +- .../digi/SiliconTrackerDigi_factory.h | 42 +- .../MatrixTransferStatic_factory.h | 77 +- .../meta/CollectionCollector_factory.h | 44 +- .../meta/SubDivideCollection_factory.h | 42 +- ...InclusiveKinematicsReconstructed_factory.h | 43 +- .../reco/InclusiveKinematicsTruth_factory.h | 31 +- .../reco/JetReconstruction_factory.h | 88 +- .../reco/TransformBreitFrame_factory.h | 53 +- .../TrackerHitReconstruction_factory.h | 34 +- src/global/beam/beam.cc | 33 +- .../digi/PhotoMultiplierHitDigi_factory.h | 99 +- .../pid/IrtCherenkovParticleID_factory.cc | 65 +- .../pid/IrtCherenkovParticleID_factory.h | 64 +- .../pid/MergeCherenkovParticleID_factory.cc | 16 +- .../pid/MergeCherenkovParticleID_factory.h | 47 +- src/global/pid/MergeTrack_factory.h | 47 +- src/global/pid/ParticlesWithPID_factory.h | 45 +- src/global/pid/RichTrackConfig.h | 49 +- src/global/pid/RichTrack_factory.cc | 64 +- src/global/pid/RichTrack_factory.h | 75 +- src/global/pid/pid.cc | 24 +- .../reco/ChargedMCParticleSelector_factory.h | 44 +- ...gedReconstructedParticleSelector_factory.h | 44 +- src/global/reco/MC2SmearedParticle_factory.h | 30 +- src/global/reco/MatchClusters_factory.h | 71 +- .../reco/ReconstructedElectrons_factory.h | 99 +- .../reco/ScatteredElectronsEMinusPz_factory.h | 44 +- .../reco/ScatteredElectronsTruth_factory.h | 48 +- src/global/reco/reco.cc | 300 ++---- src/global/tracking/CKFTracking_factory.h | 65 +- .../tracking/IterativeVertexFinder_factory.h | 49 +- .../tracking/TrackParamTruthInit_factory.h | 63 +- src/global/tracking/TrackProjector_factory.h | 32 +- .../tracking/TrackPropagation_factory.h | 47 +- src/global/tracking/TrackSeeding_factory.h | 131 ++- .../TrackerMeasurementFromHits_factory.h | 35 +- src/global/tracking/tracking.cc | 254 +++-- .../algorithms_init/AlgorithmsInit_service.h | 100 +- .../algorithms_init/algorithms_init.cc | 7 +- src/services/geometry/acts/ACTSGeo_service.cc | 191 ++-- src/services/geometry/acts/ACTSGeo_service.h | 30 +- src/services/geometry/acts/acts.cc | 6 +- .../geometry/dd4hep/DD4hep_service.cc | 249 ++--- src/services/geometry/dd4hep/DD4hep_service.h | 33 +- src/services/geometry/dd4hep/dd4hep.cc | 6 +- src/services/geometry/richgeo/ActsGeo.cc | 100 +- src/services/geometry/richgeo/ActsGeo.h | 46 +- src/services/geometry/richgeo/IrtGeo.cc | 78 +- src/services/geometry/richgeo/IrtGeo.h | 79 +- src/services/geometry/richgeo/IrtGeoDRICH.cc | 131 +-- src/services/geometry/richgeo/IrtGeoDRICH.h | 42 +- src/services/geometry/richgeo/IrtGeoPFRICH.cc | 115 ++- src/services/geometry/richgeo/IrtGeoPFRICH.h | 36 +- src/services/geometry/richgeo/ReadoutGeo.cc | 50 +- src/services/geometry/richgeo/ReadoutGeo.h | 133 ++- src/services/geometry/richgeo/RichGeo.h | 116 ++- .../geometry/richgeo/RichGeo_service.cc | 56 +- .../geometry/richgeo/RichGeo_service.h | 54 +- src/services/geometry/richgeo/richgeo.cc | 8 +- src/services/io/podio/JEventProcessorPODIO.cc | 663 ++++++------- src/services/io/podio/JEventProcessorPODIO.h | 45 +- src/services/io/podio/JEventSourcePODIO.cc | 309 +++--- src/services/io/podio/JEventSourcePODIO.h | 36 +- src/services/io/podio/datamodel_LinkDef.h | 1 - src/services/io/podio/podio.cc | 25 +- src/services/log/Log_service.cc | 72 +- src/services/log/Log_service.h | 30 +- src/services/log/log.cc | 7 +- src/services/rootfile/RootFile_service.h | 147 ++- src/services/rootfile/rootfile.cc | 7 +- src/tests/algorithms_test/algorithmsInit.cc | 8 +- .../calorimetry_CalorimeterHitDigi.cc | 58 +- .../calorimetry_CalorimeterIslandCluster.cc | 241 +++-- .../algorithms_test/calorimetry_HEXPLIT.cc | 105 +- .../algorithms_test/pid_MergeParticleID.cc | 198 ++-- src/tests/algorithms_test/pid_MergeTracks.cc | 142 ++- .../GeometryNavigationSteps_processor.cc | 49 +- .../GeometryNavigationSteps_processor.h | 74 +- .../geometry_navigation_test.cc | 13 +- .../omnifactory_test/JOmniFactoryTests.cc | 599 ++++++------ .../GlobalReconstructionTest_processor.cc | 170 ++-- .../GlobalReconstructionTest_processor.h | 68 +- src/tests/reco_test/reco_test.cc | 12 +- .../TrackPropagationTest_processor.cc | 135 ++- .../TrackPropagationTest_processor.h | 75 +- .../track_propagation_test.cc | 13 +- .../tracking_test/TrackingTest_processor.cc | 232 +++-- .../tracking_test/TrackingTest_processor.h | 75 +- src/tests/tracking_test/tracking_test.cc | 12 +- .../dump_flags/DumpFlags_processor.cc | 207 ++-- .../dump_flags/DumpFlags_processor.h | 203 ++-- src/utilities/dump_flags/dump_flags.cc | 9 +- src/utilities/eicrecon/eicrecon.cc | 63 +- src/utilities/eicrecon/eicrecon_cli.cpp | 915 +++++++++--------- src/utilities/eicrecon/eicrecon_cli.h | 136 +-- src/utilities/eicrecon/print_info.h | 60 +- .../janatop/JEventProcessorJANATOP.h | 483 +++++---- src/utilities/janatop/janatop.cc | 10 +- 284 files changed, 17098 insertions(+), 18026 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 63f2b09f18..d54fa85cf1 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,13 +1,13 @@ { - "image": "ghcr.io/eic/jug_prod:master-nightly", - "postCreateCommand": "./.devcontainer/postCreateCommand.sh", - "customizations": { - "vscode": { - "extensions": [ - "ms-vscode.cmake-tools", - "ms-vscode.cpptools", - "ms-vscode.cpptools-extension-pack" - ] - } + "image": "ghcr.io/eic/jug_prod:master-nightly", + "postCreateCommand": "./.devcontainer/postCreateCommand.sh", + "customizations": { + "vscode": { + "extensions": [ + "ms-vscode.cmake-tools", + "ms-vscode.cpptools", + "ms-vscode.cpptools-extension-pack" + ] } + } } diff --git a/src/algorithms/calorimetry/CalorimeterClusterRecoCoG.cc b/src/algorithms/calorimetry/CalorimeterClusterRecoCoG.cc index 3de49a6260..0f9dbe999f 100644 --- a/src/algorithms/calorimetry/CalorimeterClusterRecoCoG.cc +++ b/src/algorithms/calorimetry/CalorimeterClusterRecoCoG.cc @@ -36,122 +36,128 @@ namespace eicrecon { - using namespace dd4hep; - - void CalorimeterClusterRecoCoG::init() { - - // select weighting method - std::string ew = m_cfg.energyWeight; - // make it case-insensitive - std::transform(ew.begin(), ew.end(), ew.begin(), [](char s) { return std::tolower(s); }); - auto it = weightMethods.find(ew); - if (it == weightMethods.end()) { - error("Cannot find energy weighting method {}, choose one from [{}]", m_cfg.energyWeight, boost::algorithm::join(weightMethods | boost::adaptors::map_keys, ", ")); - return; - } - weightFunc = it->second; +using namespace dd4hep; + +void CalorimeterClusterRecoCoG::init() { + + // select weighting method + std::string ew = m_cfg.energyWeight; + // make it case-insensitive + std::transform(ew.begin(), ew.end(), ew.begin(), [](char s) { return std::tolower(s); }); + auto it = weightMethods.find(ew); + if (it == weightMethods.end()) { + error("Cannot find energy weighting method {}, choose one from [{}]", m_cfg.energyWeight, + boost::algorithm::join(weightMethods | boost::adaptors::map_keys, ", ")); + return; } + weightFunc = it->second; +} - void CalorimeterClusterRecoCoG::process( - const CalorimeterClusterRecoCoG::Input& input, - const CalorimeterClusterRecoCoG::Output& output) const { +void CalorimeterClusterRecoCoG::process(const CalorimeterClusterRecoCoG::Input& input, + const CalorimeterClusterRecoCoG::Output& output) const { - const auto [proto, mchits] = input; - auto [clusters, associations] = output; + const auto [proto, mchits] = input; + auto [clusters, associations] = output; - for (const auto& pcl : *proto) { + for (const auto& pcl : *proto) { - // skip protoclusters with no hits - if (pcl.hits_size() == 0) { - continue; - } + // skip protoclusters with no hits + if (pcl.hits_size() == 0) { + continue; + } - auto cl_opt = reconstruct(pcl); - if (! cl_opt.has_value()) { - continue; + auto cl_opt = reconstruct(pcl); + if (!cl_opt.has_value()) { + continue; + } + auto cl = *std::move(cl_opt); + + debug("{} hits: {} GeV, ({}, {}, {})", cl.getNhits(), cl.getEnergy() / dd4hep::GeV, + cl.getPosition().x / dd4hep::mm, cl.getPosition().y / dd4hep::mm, + cl.getPosition().z / dd4hep::mm); + clusters->push_back(cl); + + // If mcHits are available, associate cluster with MCParticle + // 1. find proto-cluster hit with largest energy deposition + // 2. find first mchit with same CellID + // 3. assign mchit's MCParticle as cluster truth + if (mchits->size() > 0) { + + // 1. find pclhit with largest energy deposition + auto pclhits = pcl.getHits(); + auto pclhit = std::max_element(pclhits.begin(), pclhits.end(), + [](const auto& pclhit1, const auto& pclhit2) { + return pclhit1.getEnergy() < pclhit2.getEnergy(); + }); + + // FIXME: The code below fails for HcalEndcapPClusters. This does not happen for + // FIXME: all calorimeters. A brief scan of the code suggests this could be caused + // FIXME: by the CalorimeterHitDigi algorithm modifying the cellID for the raw hits. + // FIXME: Thus, the cellID values passed on through to here no longer match those + // FIXME: in the low-level truth hits. It likely works for other detectors because + // FIXME: their u_fields and u_refs members are left empty which effectively results + // FIXME: in the cellID being unchanged. + + // 2. find mchit with same CellID + // find_if not working, https://github.com/AIDASoft/podio/pull/273 + //auto mchit = std::find_if( + // mchits->begin(), + // mchits->end(), + // [&pclhit](const auto& mchit1) { + // return mchit1.getCellID() == pclhit->getCellID(); + // } + //); + auto mchit = mchits->begin(); + for (; mchit != mchits->end(); ++mchit) { + // break loop when CellID match found + if (mchit->getCellID() == pclhit->getCellID()) { + break; + } } - auto cl = *std::move(cl_opt); - - debug("{} hits: {} GeV, ({}, {}, {})", cl.getNhits(), cl.getEnergy() / dd4hep::GeV, cl.getPosition().x / dd4hep::mm, cl.getPosition().y / dd4hep::mm, cl.getPosition().z / dd4hep::mm); - clusters->push_back(cl); - - // If mcHits are available, associate cluster with MCParticle - // 1. find proto-cluster hit with largest energy deposition - // 2. find first mchit with same CellID - // 3. assign mchit's MCParticle as cluster truth - if (mchits->size() > 0) { - - // 1. find pclhit with largest energy deposition - auto pclhits = pcl.getHits(); - auto pclhit = std::max_element( - pclhits.begin(), - pclhits.end(), - [](const auto& pclhit1, const auto& pclhit2) { - return pclhit1.getEnergy() < pclhit2.getEnergy(); - } - ); - - // FIXME: The code below fails for HcalEndcapPClusters. This does not happen for - // FIXME: all calorimeters. A brief scan of the code suggests this could be caused - // FIXME: by the CalorimeterHitDigi algorithm modifying the cellID for the raw hits. - // FIXME: Thus, the cellID values passed on through to here no longer match those - // FIXME: in the low-level truth hits. It likely works for other detectors because - // FIXME: their u_fields and u_refs members are left empty which effectively results - // FIXME: in the cellID being unchanged. - - // 2. find mchit with same CellID - // find_if not working, https://github.com/AIDASoft/podio/pull/273 - //auto mchit = std::find_if( - // mchits->begin(), - // mchits->end(), - // [&pclhit](const auto& mchit1) { - // return mchit1.getCellID() == pclhit->getCellID(); - // } - //); - auto mchit = mchits->begin(); - for ( ; mchit != mchits->end(); ++mchit) { - // break loop when CellID match found - if ( mchit->getCellID() == pclhit->getCellID()) { - break; - } + if (!(mchit != mchits->end())) { + // break if no matching hit found for this CellID + warning("Proto-cluster has highest energy in CellID {}, but no mc hit with that CellID was " + "found.", + pclhit->getCellID()); + trace("Proto-cluster hits: "); + for (const auto& pclhit1 : pclhits) { + trace("{}: {}", pclhit1.getCellID(), pclhit1.getEnergy()); } - if (!(mchit != mchits->end())) { - // break if no matching hit found for this CellID - warning("Proto-cluster has highest energy in CellID {}, but no mc hit with that CellID was found.", pclhit->getCellID()); - trace("Proto-cluster hits: "); - for (const auto& pclhit1: pclhits) { - trace("{}: {}", pclhit1.getCellID(), pclhit1.getEnergy()); - } - trace("MC hits: "); - for (const auto& mchit1: *mchits) { - trace("{}: {}", mchit1.getCellID(), mchit1.getEnergy()); - } - break; + trace("MC hits: "); + for (const auto& mchit1 : *mchits) { + trace("{}: {}", mchit1.getCellID(), mchit1.getEnergy()); } - - // 3. find mchit's MCParticle - const auto& mcp = mchit->getContributions(0).getParticle(); - - debug("cluster has largest energy in cellID: {}", pclhit->getCellID()); - debug("pcl hit with highest energy {} at index {}", pclhit->getEnergy(), pclhit->getObjectID().index); - debug("corresponding mc hit energy {} at index {}", mchit->getEnergy(), mchit->getObjectID().index); - debug("from MCParticle index {}, PDG {}, {}", mcp.getObjectID().index, mcp.getPDG(), edm4hep::utils::magnitude(mcp.getMomentum())); - - // set association - auto clusterassoc = associations->create(); - clusterassoc.setRecID(cl.getObjectID().index); // if not using collection, this is always set to -1 - clusterassoc.setSimID(mcp.getObjectID().index); - clusterassoc.setWeight(1.0); - clusterassoc.setRec(cl); - clusterassoc.setSim(mcp); - } else { - debug("No mcHitCollection was provided, so no truth association will be performed."); + break; } + + // 3. find mchit's MCParticle + const auto& mcp = mchit->getContributions(0).getParticle(); + + debug("cluster has largest energy in cellID: {}", pclhit->getCellID()); + debug("pcl hit with highest energy {} at index {}", pclhit->getEnergy(), + pclhit->getObjectID().index); + debug("corresponding mc hit energy {} at index {}", mchit->getEnergy(), + mchit->getObjectID().index); + debug("from MCParticle index {}, PDG {}, {}", mcp.getObjectID().index, mcp.getPDG(), + edm4hep::utils::magnitude(mcp.getMomentum())); + + // set association + auto clusterassoc = associations->create(); + clusterassoc.setRecID( + cl.getObjectID().index); // if not using collection, this is always set to -1 + clusterassoc.setSimID(mcp.getObjectID().index); + clusterassoc.setWeight(1.0); + clusterassoc.setRec(cl); + clusterassoc.setSim(mcp); + } else { + debug("No mcHitCollection was provided, so no truth association will be performed."); } + } } //------------------------------------------------------------------------ -std::optional CalorimeterClusterRecoCoG::reconstruct(const edm4eic::ProtoCluster& pcl) const { +std::optional +CalorimeterClusterRecoCoG::reconstruct(const edm4eic::ProtoCluster& pcl) const { edm4eic::MutableCluster cl; cl.setNhits(pcl.hits_size()); @@ -194,12 +200,12 @@ std::optional CalorimeterClusterRecoCoG::reconstruct(const edm float tw = 0.; auto v = cl.getPosition(); - double logWeightBase=m_cfg.logWeightBase; - if (m_cfg.logWeightBaseCoeffs.size() != 0){ - double l=log(cl.getEnergy()/m_cfg.logWeightBase_Eref); - logWeightBase=0; - for(std::size_t i =0; i CalorimeterClusterRecoCoG::reconstruct(const edm const auto& hit = pcl.getHits()[i]; const auto weight = pcl.getWeights()[i]; // _DBG_<<" -- weight = " << weight << " E=" << hit.getEnergy() << " totalE=" < CalorimeterClusterRecoCoG::reconstruct(const edm // x-y-z cluster widths (3D) float radius = 0, dispersion = 0, w_sum = 0; - Eigen::Matrix2f sum2_2D = Eigen::Matrix2f::Zero(); - Eigen::Matrix3f sum2_3D = Eigen::Matrix3f::Zero(); - Eigen::Vector2f sum1_2D = Eigen::Vector2f::Zero(); - Eigen::Vector3f sum1_3D = Eigen::Vector3f::Zero(); + Eigen::Matrix2f sum2_2D = Eigen::Matrix2f::Zero(); + Eigen::Matrix3f sum2_3D = Eigen::Matrix3f::Zero(); + Eigen::Vector2f sum1_2D = Eigen::Vector2f::Zero(); + Eigen::Vector3f sum1_3D = Eigen::Vector3f::Zero(); Eigen::Vector2cf eigenValues_2D = Eigen::Vector2cf::Zero(); Eigen::Vector3cf eigenValues_3D = Eigen::Vector3cf::Zero(); @@ -262,13 +269,14 @@ std::optional CalorimeterClusterRecoCoG::reconstruct(const edm float w = weightFunc(hit.getEnergy(), cl.getEnergy(), m_cfg.logWeightBase, 0); // theta, phi - Eigen::Vector2f pos2D( edm4hep::utils::anglePolar( hit.getPosition() ), edm4hep::utils::angleAzimuthal( hit.getPosition() ) ); + Eigen::Vector2f pos2D(edm4hep::utils::anglePolar(hit.getPosition()), + edm4hep::utils::angleAzimuthal(hit.getPosition())); // x, y, z - Eigen::Vector3f pos3D( hit.getPosition().x, hit.getPosition().y, hit.getPosition().z ); + Eigen::Vector3f pos3D(hit.getPosition().x, hit.getPosition().y, hit.getPosition().z); const auto delta = cl.getPosition() - hit.getPosition(); - radius += delta * delta; - dispersion += delta * delta * w; + radius += delta * delta; + dispersion += delta * delta * w; // Weighted Sum x*x, x*y, x*z, y*y, etc. sum2_2D += w * pos2D * pos2D.transpose(); @@ -281,9 +289,9 @@ std::optional CalorimeterClusterRecoCoG::reconstruct(const edm w_sum += w; } - if( w_sum > 0 ) { + if (w_sum > 0) { radius = sqrt((1. / (cl.getNhits() - 1.)) * radius); - dispersion = sqrt( dispersion / w_sum ); + dispersion = sqrt(dispersion / w_sum); // normalize matrices sum2_2D /= w_sum; @@ -296,8 +304,10 @@ std::optional CalorimeterClusterRecoCoG::reconstruct(const edm Eigen::Matrix3f cov3 = sum2_3D - sum1_3D * sum1_3D.transpose(); // Solve for eigenvalues. Corresponds to cluster's 2nd moments (widths) - Eigen::EigenSolver es_2D(cov2, false); // set to true for eigenvector calculation - Eigen::EigenSolver es_3D(cov3, false); // set to true for eigenvector calculation + Eigen::EigenSolver es_2D(cov2, + false); // set to true for eigenvector calculation + Eigen::EigenSolver es_3D(cov3, + false); // set to true for eigenvector calculation // eigenvalues of symmetric real matrix are always real eigenValues_2D = es_2D.eigenvalues(); @@ -305,15 +315,15 @@ std::optional CalorimeterClusterRecoCoG::reconstruct(const edm } } - cl.addToShapeParameters( radius ); - cl.addToShapeParameters( dispersion ); - cl.addToShapeParameters( eigenValues_2D[0].real() ); // 2D theta-phi cluster width 1 - cl.addToShapeParameters( eigenValues_2D[1].real() ); // 2D theta-phi cluster width 2 - cl.addToShapeParameters( eigenValues_3D[0].real() ); // 3D x-y-z cluster width 1 - cl.addToShapeParameters( eigenValues_3D[1].real() ); // 3D x-y-z cluster width 2 - cl.addToShapeParameters( eigenValues_3D[2].real() ); // 3D x-y-z cluster width 3 + cl.addToShapeParameters(radius); + cl.addToShapeParameters(dispersion); + cl.addToShapeParameters(eigenValues_2D[0].real()); // 2D theta-phi cluster width 1 + cl.addToShapeParameters(eigenValues_2D[1].real()); // 2D theta-phi cluster width 2 + cl.addToShapeParameters(eigenValues_3D[0].real()); // 3D x-y-z cluster width 1 + cl.addToShapeParameters(eigenValues_3D[1].real()); // 3D x-y-z cluster width 2 + cl.addToShapeParameters(eigenValues_3D[2].real()); // 3D x-y-z cluster width 3 return std::move(cl); } -} // eicrecon +} // namespace eicrecon diff --git a/src/algorithms/calorimetry/CalorimeterClusterRecoCoG.h b/src/algorithms/calorimetry/CalorimeterClusterRecoCoG.h index adf75dba26..3c85ad27a5 100644 --- a/src/algorithms/calorimetry/CalorimeterClusterRecoCoG.h +++ b/src/algorithms/calorimetry/CalorimeterClusterRecoCoG.h @@ -31,56 +31,51 @@ static double constWeight(double /*E*/, double /*tE*/, double /*p*/, int /*type*/) { return 1.0; } static double linearWeight(double E, double /*tE*/, double /*p*/, int /*type*/) { return E; } static double logWeight(double E, double tE, double base, int /*type*/) { - return std::max(0., base + std::log(E / tE)); + return std::max(0., base + std::log(E / tE)); } -static const std::map> weightMethods={ - {"none", constWeight}, - {"linear", linearWeight}, - {"log", logWeight}, +static const std::map> + weightMethods = { + {"none", constWeight}, + {"linear", linearWeight}, + {"log", logWeight}, }; namespace eicrecon { - using ClustersWithAssociations = std::pair< - std::unique_ptr, - std::unique_ptr - >; - - using CalorimeterClusterRecoCoGAlgorithm = algorithms::Algorithm< - algorithms::Input< - edm4eic::ProtoClusterCollection, - std::optional - >, - algorithms::Output< - edm4eic::ClusterCollection, - std::optional - > - >; - - class CalorimeterClusterRecoCoG - : public CalorimeterClusterRecoCoGAlgorithm, - public WithPodConfig { - - public: - CalorimeterClusterRecoCoG(std::string_view name) - : CalorimeterClusterRecoCoGAlgorithm{name, - {"inputProtoClusterCollection", "mcHits"}, - {"outputClusterCollection", "outputAssociations"}, - "Reconstruct a cluster with the Center of Gravity method. For " - "simulation results it optionally creates a Cluster <-> MCParticle " - "association provided both optional arguments are provided."} {} - - public: - void init() final; - - void process(const Input&, const Output&) const final; - - private: - std::function weightFunc; - - private: - std::optional reconstruct(const edm4eic::ProtoCluster& pcl) const; - }; - -} // eicrecon +using ClustersWithAssociations = + std::pair, + std::unique_ptr>; + +using CalorimeterClusterRecoCoGAlgorithm = algorithms::Algorithm< + algorithms::Input>, + algorithms::Output>>; + +class CalorimeterClusterRecoCoG : public CalorimeterClusterRecoCoGAlgorithm, + public WithPodConfig { + +public: + CalorimeterClusterRecoCoG(std::string_view name) + : CalorimeterClusterRecoCoGAlgorithm{ + name, + {"inputProtoClusterCollection", "mcHits"}, + {"outputClusterCollection", "outputAssociations"}, + "Reconstruct a cluster with the Center of Gravity method. For " + "simulation results it optionally creates a Cluster <-> MCParticle " + "association provided both optional arguments are provided."} {} + +public: + void init() final; + + void process(const Input&, const Output&) const final; + +private: + std::function weightFunc; + +private: + std::optional reconstruct(const edm4eic::ProtoCluster& pcl) const; +}; + +} // namespace eicrecon diff --git a/src/algorithms/calorimetry/CalorimeterClusterRecoCoGConfig.h b/src/algorithms/calorimetry/CalorimeterClusterRecoCoGConfig.h index f6ea18e2e2..df38aca48c 100644 --- a/src/algorithms/calorimetry/CalorimeterClusterRecoCoGConfig.h +++ b/src/algorithms/calorimetry/CalorimeterClusterRecoCoGConfig.h @@ -9,25 +9,24 @@ namespace eicrecon { - struct CalorimeterClusterRecoCoGConfig { +struct CalorimeterClusterRecoCoGConfig { - std::string energyWeight; + std::string energyWeight; - double sampFrac = 1.; - double logWeightBase = 3.6; + double sampFrac = 1.; + double logWeightBase = 3.6; - //optional: have the log weight base depend on the energy - // logWeightBaseCoeffs[0]+logWeightBaseCoeffs[1]*l+logWeightBaseCoeffs[2]*l*l + ... - // where l = log(cl.getEnergy()/logWeightBase_Eref) - // If this is empty, use the logWeightBase parameter for backwards compatibility. - std::vector logWeightBaseCoeffs{}; - double logWeightBase_Eref = 50 * dd4hep::MeV; + //optional: have the log weight base depend on the energy + // logWeightBaseCoeffs[0]+logWeightBaseCoeffs[1]*l+logWeightBaseCoeffs[2]*l*l + ... + // where l = log(cl.getEnergy()/logWeightBase_Eref) + // If this is empty, use the logWeightBase parameter for backwards compatibility. + std::vector logWeightBaseCoeffs{}; + double logWeightBase_Eref = 50 * dd4hep::MeV; - // Constrain the cluster position eta to be within - // the eta of the contributing hits. This is useful to avoid edge effects - // for endcaps. - bool enableEtaBounds = false; + // Constrain the cluster position eta to be within + // the eta of the contributing hits. This is useful to avoid edge effects + // for endcaps. + bool enableEtaBounds = false; +}; - }; - -} // eicrecon +} // namespace eicrecon diff --git a/src/algorithms/calorimetry/CalorimeterHitDigi.cc b/src/algorithms/calorimetry/CalorimeterHitDigi.cc index 7d7f6cf9f5..80d8ea8b73 100644 --- a/src/algorithms/calorimetry/CalorimeterHitDigi.cc +++ b/src/algorithms/calorimetry/CalorimeterHitDigi.cc @@ -10,7 +10,6 @@ // Author: Chao Peng // Date: 06/02/2021 - #include "CalorimeterHitDigi.h" #include @@ -45,137 +44,134 @@ namespace eicrecon { // being set in the config. If that is the case, they should be moved into the default // values here. This needs to be confirmed. - void CalorimeterHitDigi::init() { - // Gaudi implements a random number generator service. It is not clear to me how this - // can work. There are multiple race conditions that occur in parallel event processing: - // 1. The exact same events processed by a given thread in one invocation will not - // necessarily be the combination of events any thread sees in a subsequent - // invocation. Thus, you can't rely on thread_local storage. - // 2. Its possible for the factory execution order to be modified by the presence of - // a processor (e.g. monitoring plugin). This is not as serious since changing the - // command line should cause one not to expect reproducibility. Still, one may - // expect the inclusion of an "observer" plugin not to have such side affects. - // - // More information will be needed. In the meantime, we implement a local random number - // generator. Ideally, this would be seeded with the run number+event number, but for - // now, just use default values defined in header file. - - // set energy resolution numbers - if (m_cfg.eRes.empty()) { - m_cfg.eRes.resize(3); - } else if (m_cfg.eRes.size() != 3) { - error("Invalid m_cfg.eRes.size()"); - throw std::runtime_error("Invalid m_cfg.eRes.size()"); - } - - // using juggler internal units (GeV, mm, radian, ns) - tRes = m_cfg.tRes / dd4hep::ns; - stepTDC = dd4hep::ns / m_cfg.resolutionTDC; - - // sanity checks - if (m_cfg.readout.empty()) { - error("readoutClass is not provided, it is needed to know the fields in readout ids"); - throw std::runtime_error("readoutClass is not provided"); - } - - // get decoders - dd4hep::IDDescriptor id_desc; - try { - id_desc = m_geo.detector()->readout(m_cfg.readout).idSpec(); - } catch (...) { - // Can not be more verbose. In JANA2, this will be attempted at each event, which - // pollutes output for geometries that are less than complete. - // We could save an exception and throw it from process. - debug("Failed to load ID decoder for {}", m_cfg.readout); - throw std::runtime_error(fmt::format("Failed to load ID decoder for {}", m_cfg.readout)); - } - - decltype(id_mask) id_inverse_mask = 0; - // all these are for signal sum at digitization level - if (!m_cfg.fields.empty()) { - for (auto & field : m_cfg.fields) { - id_inverse_mask |= id_desc.field(field)->mask(); - } - debug("ID mask in {:s}: {:#064b}", m_cfg.readout, id_mask); + // Gaudi implements a random number generator service. It is not clear to me how this + // can work. There are multiple race conditions that occur in parallel event processing: + // 1. The exact same events processed by a given thread in one invocation will not + // necessarily be the combination of events any thread sees in a subsequent + // invocation. Thus, you can't rely on thread_local storage. + // 2. Its possible for the factory execution order to be modified by the presence of + // a processor (e.g. monitoring plugin). This is not as serious since changing the + // command line should cause one not to expect reproducibility. Still, one may + // expect the inclusion of an "observer" plugin not to have such side affects. + // + // More information will be needed. In the meantime, we implement a local random number + // generator. Ideally, this would be seeded with the run number+event number, but for + // now, just use default values defined in header file. + + // set energy resolution numbers + if (m_cfg.eRes.empty()) { + m_cfg.eRes.resize(3); + } else if (m_cfg.eRes.size() != 3) { + error("Invalid m_cfg.eRes.size()"); + throw std::runtime_error("Invalid m_cfg.eRes.size()"); + } + + // using juggler internal units (GeV, mm, radian, ns) + tRes = m_cfg.tRes / dd4hep::ns; + stepTDC = dd4hep::ns / m_cfg.resolutionTDC; + + // sanity checks + if (m_cfg.readout.empty()) { + error("readoutClass is not provided, it is needed to know the fields in readout ids"); + throw std::runtime_error("readoutClass is not provided"); + } + + // get decoders + dd4hep::IDDescriptor id_desc; + try { + id_desc = m_geo.detector()->readout(m_cfg.readout).idSpec(); + } catch (...) { + // Can not be more verbose. In JANA2, this will be attempted at each event, which + // pollutes output for geometries that are less than complete. + // We could save an exception and throw it from process. + debug("Failed to load ID decoder for {}", m_cfg.readout); + throw std::runtime_error(fmt::format("Failed to load ID decoder for {}", m_cfg.readout)); + } + + decltype(id_mask) id_inverse_mask = 0; + // all these are for signal sum at digitization level + if (!m_cfg.fields.empty()) { + for (auto& field : m_cfg.fields) { + id_inverse_mask |= id_desc.field(field)->mask(); } - id_mask = ~id_inverse_mask; + debug("ID mask in {:s}: {:#064b}", m_cfg.readout, id_mask); + } + id_mask = ~id_inverse_mask; } - -void CalorimeterHitDigi::process( - const CalorimeterHitDigi::Input& input, - const CalorimeterHitDigi::Output& output) const { - - const auto [simhits] = input; - auto [rawhits] = output; - - // find the hits that belong to the same group (for merging) - std::unordered_map> merge_map; - std::size_t ix = 0; - for (const auto &ahit : *simhits) { - uint64_t hid = ahit.getCellID() & id_mask; - - trace("org cell ID in {:s}: {:#064b}", m_cfg.readout, ahit.getCellID()); - trace("new cell ID in {:s}: {:#064b}", m_cfg.readout, hid); - - merge_map[hid].push_back(ix); - - ix++; - } - - // signal sum - // NOTE: we take the cellID of the most energetic hit in this group so it is a real cellID from an MC hit - for (const auto &[id, ixs] : merge_map) { - double edep = 0; - double time = std::numeric_limits::max(); - double max_edep = 0; - auto mid = (*simhits)[ixs[0]].getCellID(); - // sum energy, take time from the most energetic hit - for (size_t i = 0; i < ixs.size(); ++i) { - auto hit = (*simhits)[ixs[i]]; - - double timeC = std::numeric_limits::max(); - for (const auto& c : hit.getContributions()) { - if (c.getTime() <= timeC) { - timeC = c.getTime(); - } - } - if (timeC > m_cfg.capTime) continue; - edep += hit.getEnergy(); - trace("adding {} \t total: {}", hit.getEnergy(), edep); - - // change maximum hit energy & time if necessary - if (hit.getEnergy() > max_edep) { - max_edep = hit.getEnergy(); - mid = hit.getCellID(); - if (timeC <= time) { - time = timeC; - } - } +void CalorimeterHitDigi::process(const CalorimeterHitDigi::Input& input, + const CalorimeterHitDigi::Output& output) const { + + const auto [simhits] = input; + auto [rawhits] = output; + + // find the hits that belong to the same group (for merging) + std::unordered_map> merge_map; + std::size_t ix = 0; + for (const auto& ahit : *simhits) { + uint64_t hid = ahit.getCellID() & id_mask; + + trace("org cell ID in {:s}: {:#064b}", m_cfg.readout, ahit.getCellID()); + trace("new cell ID in {:s}: {:#064b}", m_cfg.readout, hid); + + merge_map[hid].push_back(ix); + + ix++; + } + + // signal sum + // NOTE: we take the cellID of the most energetic hit in this group so it is a real cellID from an MC hit + for (const auto& [id, ixs] : merge_map) { + double edep = 0; + double time = std::numeric_limits::max(); + double max_edep = 0; + auto mid = (*simhits)[ixs[0]].getCellID(); + // sum energy, take time from the most energetic hit + for (size_t i = 0; i < ixs.size(); ++i) { + auto hit = (*simhits)[ixs[i]]; + + double timeC = std::numeric_limits::max(); + for (const auto& c : hit.getContributions()) { + if (c.getTime() <= timeC) { + timeC = c.getTime(); + } + } + if (timeC > m_cfg.capTime) + continue; + edep += hit.getEnergy(); + trace("adding {} \t total: {}", hit.getEnergy(), edep); + + // change maximum hit energy & time if necessary + if (hit.getEnergy() > max_edep) { + max_edep = hit.getEnergy(); + mid = hit.getCellID(); + if (timeC <= time) { + time = timeC; } - if (time > m_cfg.capTime) continue; - - // safety check - const double eResRel = (edep > m_cfg.threshold) - ? m_rng.gaussian(0., 1.) * std::sqrt( - std::pow(m_cfg.eRes[0] / std::sqrt(edep), 2) + - std::pow(m_cfg.eRes[1], 2) + - std::pow(m_cfg.eRes[2] / (edep), 2) - ) - : 0; - double ped = m_cfg.pedMeanADC + m_rng.gaussian(0., 1.) * m_cfg.pedSigmaADC; - unsigned long long adc = std::llround(ped + edep * m_cfg.corrMeanScale * ( 1.0 + eResRel) / m_cfg.dyRangeADC * m_cfg.capADC); - unsigned long long tdc = std::llround((time + m_rng.gaussian(0., 1.) * tRes) * stepTDC); - - if (edep> 1.e-3) trace("E sim {} \t adc: {} \t time: {}\t maxtime: {} \t tdc: {}", edep, adc, time, m_cfg.capTime, tdc); - rawhits->create( - mid, - (adc > m_cfg.capADC ? m_cfg.capADC : adc), - tdc - ); + } } + if (time > m_cfg.capTime) + continue; + + // safety check + const double eResRel = + (edep > m_cfg.threshold) + ? m_rng.gaussian(0., 1.) * + std::sqrt(std::pow(m_cfg.eRes[0] / std::sqrt(edep), 2) + + std::pow(m_cfg.eRes[1], 2) + std::pow(m_cfg.eRes[2] / (edep), 2)) + : 0; + double ped = m_cfg.pedMeanADC + m_rng.gaussian(0., 1.) * m_cfg.pedSigmaADC; + unsigned long long adc = std::llround(ped + edep * m_cfg.corrMeanScale * (1.0 + eResRel) / + m_cfg.dyRangeADC * m_cfg.capADC); + unsigned long long tdc = std::llround((time + m_rng.gaussian(0., 1.) * tRes) * stepTDC); + + if (edep > 1.e-3) + trace("E sim {} \t adc: {} \t time: {}\t maxtime: {} \t tdc: {}", edep, adc, time, + m_cfg.capTime, tdc); + rawhits->create(mid, (adc > m_cfg.capADC ? m_cfg.capADC : adc), tdc); + } } } // namespace eicrecon diff --git a/src/algorithms/calorimetry/CalorimeterHitDigi.h b/src/algorithms/calorimetry/CalorimeterHitDigi.h index 105fe5ba13..ece4bfeb9e 100644 --- a/src/algorithms/calorimetry/CalorimeterHitDigi.h +++ b/src/algorithms/calorimetry/CalorimeterHitDigi.h @@ -10,7 +10,6 @@ // Author: Chao Peng // Date: 06/02/2021 - #pragma once #include @@ -27,41 +26,34 @@ namespace eicrecon { - using CalorimeterHitDigiAlgorithm = algorithms::Algorithm< - algorithms::Input< - edm4hep::SimCalorimeterHitCollection - >, - algorithms::Output< - edm4hep::RawCalorimeterHitCollection - > - >; - - class CalorimeterHitDigi - : public CalorimeterHitDigiAlgorithm, - public WithPodConfig { - - public: - CalorimeterHitDigi(std::string_view name) - : CalorimeterHitDigiAlgorithm{name, - {"inputHitCollection"}, - {"outputRawHitCollection"}, - "Smear energy deposit, digitize within ADC range, add pedestal, " - "convert time with smearing resolution, and sum signals."} {} +using CalorimeterHitDigiAlgorithm = + algorithms::Algorithm, + algorithms::Output>; - void init() final; - void process(const Input&, const Output&) const final; +class CalorimeterHitDigi : public CalorimeterHitDigiAlgorithm, + public WithPodConfig { - private: +public: + CalorimeterHitDigi(std::string_view name) + : CalorimeterHitDigiAlgorithm{ + name, + {"inputHitCollection"}, + {"outputRawHitCollection"}, + "Smear energy deposit, digitize within ADC range, add pedestal, " + "convert time with smearing resolution, and sum signals."} {} - // unitless counterparts of inputs - double dyRangeADC{0}, stepTDC{0}, tRes{0}; + void init() final; + void process(const Input&, const Output&) const final; - uint64_t id_mask{0}; +private: + // unitless counterparts of inputs + double dyRangeADC{0}, stepTDC{0}, tRes{0}; - private: - const algorithms::GeoSvc& m_geo = algorithms::GeoSvc::instance(); - algorithms::Generator m_rng = algorithms::RandomSvc::instance().generator(); + uint64_t id_mask{0}; - }; +private: + const algorithms::GeoSvc& m_geo = algorithms::GeoSvc::instance(); + algorithms::Generator m_rng = algorithms::RandomSvc::instance().generator(); +}; } // namespace eicrecon diff --git a/src/algorithms/calorimetry/CalorimeterHitDigiConfig.h b/src/algorithms/calorimetry/CalorimeterHitDigiConfig.h index 6d6702f011..4a0a6e3fed 100644 --- a/src/algorithms/calorimetry/CalorimeterHitDigiConfig.h +++ b/src/algorithms/calorimetry/CalorimeterHitDigiConfig.h @@ -8,27 +8,26 @@ namespace eicrecon { - struct CalorimeterHitDigiConfig { +struct CalorimeterHitDigiConfig { - std::vector eRes; - double tRes; + std::vector eRes; + double tRes; - // single hit energy deposition threshold - double threshold{1.0*dd4hep::keV}; + // single hit energy deposition threshold + double threshold{1.0 * dd4hep::keV}; - // digitization settings - unsigned int capADC{1}; - double capTime{1000}; // dynamic range in ns - double dyRangeADC{1}; - unsigned int pedMeanADC{0}; - double pedSigmaADC{0}; - double resolutionTDC{1}; - double corrMeanScale{1}; + // digitization settings + unsigned int capADC{1}; + double capTime{1000}; // dynamic range in ns + double dyRangeADC{1}; + unsigned int pedMeanADC{0}; + double pedSigmaADC{0}; + double resolutionTDC{1}; + double corrMeanScale{1}; - // signal sums - std::string readout{""}; - std::vector fields{}; + // signal sums + std::string readout{""}; + std::vector fields{}; +}; - }; - -} // eicrecon +} // namespace eicrecon diff --git a/src/algorithms/calorimetry/CalorimeterHitReco.cc b/src/algorithms/calorimetry/CalorimeterHitReco.cc index 03ff12ec2f..71124b21bf 100644 --- a/src/algorithms/calorimetry/CalorimeterHitReco.cc +++ b/src/algorithms/calorimetry/CalorimeterHitReco.cc @@ -41,236 +41,235 @@ namespace eicrecon { void CalorimeterHitReco::init() { - // threshold for firing - // Should set either m_cfg.thresholdFactor or m_cfg.thresholdValue, not both - if ( m_cfg.thresholdFactor * m_cfg.thresholdValue != 0 ){ - error("thresholdFactor = {}, thresholdValue = {}. Only one of these should be non-zero.", - m_cfg.thresholdFactor, m_cfg.thresholdValue); - throw; // throw with an argument doesn't trigger abort - } - thresholdADC = m_cfg.thresholdFactor * m_cfg.pedSigmaADC + m_cfg.thresholdValue; - // TDC channels to timing conversion - stepTDC = dd4hep::ns / m_cfg.resolutionTDC; + // threshold for firing + // Should set either m_cfg.thresholdFactor or m_cfg.thresholdValue, not both + if (m_cfg.thresholdFactor * m_cfg.thresholdValue != 0) { + error("thresholdFactor = {}, thresholdValue = {}. Only one of these should be non-zero.", + m_cfg.thresholdFactor, m_cfg.thresholdValue); + throw; // throw with an argument doesn't trigger abort + } + thresholdADC = m_cfg.thresholdFactor * m_cfg.pedSigmaADC + m_cfg.thresholdValue; + // TDC channels to timing conversion + stepTDC = dd4hep::ns / m_cfg.resolutionTDC; - // do not get the layer/sector ID if no readout class provided - if (m_cfg.readout.empty()) { - return; - } + // do not get the layer/sector ID if no readout class provided + if (m_cfg.readout.empty()) { + return; + } - // First, try and get the IDDescriptor. This will throw an exception if it fails. - IDDescriptor id_spec; - try { - id_spec = m_detector->readout(m_cfg.readout).idSpec(); - } catch(...) { - warning("Failed to get idSpec for {}", m_cfg.readout); - return; + // First, try and get the IDDescriptor. This will throw an exception if it fails. + IDDescriptor id_spec; + try { + id_spec = m_detector->readout(m_cfg.readout).idSpec(); + } catch (...) { + warning("Failed to get idSpec for {}", m_cfg.readout); + return; + } + // Next, try and get the readout fields. This will throw a different exception. + try { + id_dec = id_spec.decoder(); + if (!m_cfg.sectorField.empty()) { + sector_idx = id_dec->index(m_cfg.sectorField); + debug("Find sector field {}, index = {}", m_cfg.sectorField, sector_idx); } - // Next, try and get the readout fields. This will throw a different exception. - try { - id_dec = id_spec.decoder(); - if (!m_cfg.sectorField.empty()) { - sector_idx = id_dec->index(m_cfg.sectorField); - debug("Find sector field {}, index = {}", m_cfg.sectorField, sector_idx); - } - if (!m_cfg.layerField.empty()) { - layer_idx = id_dec->index(m_cfg.layerField); - debug("Find layer field {}, index = {}", m_cfg.layerField, sector_idx); - } - if (!m_cfg.maskPosFields.empty()) { - size_t tmp_mask = 0; - for (auto &field : m_cfg.maskPosFields) { - tmp_mask |= id_spec.field(field)->mask(); - } - // assign this mask if all fields succeed - gpos_mask = tmp_mask; - } - } catch (...) { - if (!id_dec) { - warning("Failed to load ID decoder for {}", m_cfg.readout); - std::stringstream readouts; - for (auto r: m_detector->readouts()) readouts << "\"" << r.first << "\", "; - warning("Available readouts: {}", readouts.str() ); - } else { - warning("Failed to find field index for {}.", m_cfg.readout); - if (!m_cfg.sectorField.empty()) { warning(" -- looking for sector field \"{}\".", m_cfg.sectorField); } - if (!m_cfg.layerField.empty()) { warning(" -- looking for layer field \"{}\".", m_cfg.layerField); } - if (!m_cfg.maskPosFields.empty()) { - warning(" -- looking for masking fields \"{}\".", fmt::join(m_cfg.maskPosFields, ", ")); - } - std::stringstream fields; - for (auto field: id_spec.decoder()->fields()) fields << "\"" << field.name() << "\", "; - warning("Available fields: {}", fields.str() ); - warning("n.b. The local position, sector id and layer id will not be correct for this."); - warning("Position masking may not be applied."); - warning("however, the position, energy, and time values should still be good."); - } - - return; + if (!m_cfg.layerField.empty()) { + layer_idx = id_dec->index(m_cfg.layerField); + debug("Find layer field {}, index = {}", m_cfg.layerField, sector_idx); } - - - // local detector name has higher priority - if (!m_cfg.localDetElement.empty()) { - try { - m_local = m_detector->detector(m_cfg.localDetElement); - info("local coordinate system from DetElement {}", m_cfg.localDetElement); - } catch (...) { - error("failed to load local coordinate system from DetElement {}", m_cfg.localDetElement); - return; - } + if (!m_cfg.maskPosFields.empty()) { + size_t tmp_mask = 0; + for (auto& field : m_cfg.maskPosFields) { + tmp_mask |= id_spec.field(field)->mask(); + } + // assign this mask if all fields succeed + gpos_mask = tmp_mask; + } + } catch (...) { + if (!id_dec) { + warning("Failed to load ID decoder for {}", m_cfg.readout); + std::stringstream readouts; + for (auto r : m_detector->readouts()) + readouts << "\"" << r.first << "\", "; + warning("Available readouts: {}", readouts.str()); } else { - std::vector > fields; - for (auto f : m_cfg.localDetFields) { - fields.emplace_back(f, 0); - } - local_mask = id_spec.get_mask(fields); - // use all fields if nothing provided - if (fields.empty()) { - local_mask = ~static_cast(0); - } + warning("Failed to find field index for {}.", m_cfg.readout); + if (!m_cfg.sectorField.empty()) { + warning(" -- looking for sector field \"{}\".", m_cfg.sectorField); + } + if (!m_cfg.layerField.empty()) { + warning(" -- looking for layer field \"{}\".", m_cfg.layerField); + } + if (!m_cfg.maskPosFields.empty()) { + warning(" -- looking for masking fields \"{}\".", fmt::join(m_cfg.maskPosFields, ", ")); + } + std::stringstream fields; + for (auto field : id_spec.decoder()->fields()) + fields << "\"" << field.name() << "\", "; + warning("Available fields: {}", fields.str()); + warning("n.b. The local position, sector id and layer id will not be correct for this."); + warning("Position masking may not be applied."); + warning("however, the position, energy, and time values should still be good."); } -} + return; + } -void CalorimeterHitReco::process( - const CalorimeterHitReco::Input& input, - const CalorimeterHitReco::Output& output) const { + // local detector name has higher priority + if (!m_cfg.localDetElement.empty()) { + try { + m_local = m_detector->detector(m_cfg.localDetElement); + info("local coordinate system from DetElement {}", m_cfg.localDetElement); + } catch (...) { + error("failed to load local coordinate system from DetElement {}", m_cfg.localDetElement); + return; + } + } else { + std::vector> fields; + for (auto f : m_cfg.localDetFields) { + fields.emplace_back(f, 0); + } + local_mask = id_spec.get_mask(fields); + // use all fields if nothing provided + if (fields.empty()) { + local_mask = ~static_cast(0); + } + } +} - const auto [rawhits] = input; - auto [recohits] = output; +void CalorimeterHitReco::process(const CalorimeterHitReco::Input& input, + const CalorimeterHitReco::Output& output) const { - // For some detectors, the cellID in the raw hits may be broken - // (currently this is the HcalBarrel). In this case, dd4hep - // prints an error message and throws an exception. We catch - // the exception and handle it, but the screen gets flooded - // with these messages. Keep a count of these and if a max - // number is encountered disable this algorithm. A useful message - // indicating what is going on is printed below where the - // error is detector. - if (NcellIDerrors >= MaxCellIDerrors) return; + const auto [rawhits] = input; + auto [recohits] = output; - for (const auto &rh: *rawhits) { + // For some detectors, the cellID in the raw hits may be broken + // (currently this is the HcalBarrel). In this case, dd4hep + // prints an error message and throws an exception. We catch + // the exception and handle it, but the screen gets flooded + // with these messages. Keep a count of these and if a max + // number is encountered disable this algorithm. A useful message + // indicating what is going on is printed below where the + // error is detector. + if (NcellIDerrors >= MaxCellIDerrors) + return; - //did not pass the zero-suppresion threshold - const auto cellID = rh.getCellID(); - if (rh.getAmplitude() < m_cfg.pedMeanADC + thresholdADC) { - continue; - } + for (const auto& rh : *rawhits) { - // get layer and sector ID - const int lid = - id_dec != nullptr && !m_cfg.layerField.empty() ? static_cast(id_dec->get(cellID, layer_idx)) : -1; - const int sid = - id_dec != nullptr && !m_cfg.sectorField.empty() ? static_cast(id_dec->get(cellID, sector_idx)) : -1; + //did not pass the zero-suppresion threshold + const auto cellID = rh.getCellID(); + if (rh.getAmplitude() < m_cfg.pedMeanADC + thresholdADC) { + continue; + } - // determine sampling fraction - float sampFrac = m_cfg.sampFrac; - if (! m_cfg.sampFracLayer.empty()) { - if (0 <= lid && lid < m_cfg.sampFracLayer.size()) { - sampFrac = m_cfg.sampFracLayer[lid]; - } else { - throw std::runtime_error(fmt::format("CalorimeterHitReco: layer-specific sampling fraction undefined for index {}", lid)); - } - } + // get layer and sector ID + const int lid = id_dec != nullptr && !m_cfg.layerField.empty() + ? static_cast(id_dec->get(cellID, layer_idx)) + : -1; + const int sid = id_dec != nullptr && !m_cfg.sectorField.empty() + ? static_cast(id_dec->get(cellID, sector_idx)) + : -1; - // convert ADC to energy - float energy = (((signed) rh.getAmplitude() - (signed) m_cfg.pedMeanADC)) / static_cast(m_cfg.capADC) * m_cfg.dyRangeADC / - sampFrac; + // determine sampling fraction + float sampFrac = m_cfg.sampFrac; + if (!m_cfg.sampFracLayer.empty()) { + if (0 <= lid && lid < m_cfg.sampFracLayer.size()) { + sampFrac = m_cfg.sampFracLayer[lid]; + } else { + throw std::runtime_error(fmt::format( + "CalorimeterHitReco: layer-specific sampling fraction undefined for index {}", lid)); + } + } - const float time = rh.getTimeStamp() / stepTDC; - trace("cellID {}, \t energy: {}, TDC: {}, time: ", cellID, energy, rh.getTimeStamp(), time); + // convert ADC to energy + float energy = (((signed)rh.getAmplitude() - (signed)m_cfg.pedMeanADC)) / + static_cast(m_cfg.capADC) * m_cfg.dyRangeADC / sampFrac; - dd4hep::DetElement local; - dd4hep::Position gpos; - try { - // global positions - gpos = m_converter->position(cellID); + const float time = rh.getTimeStamp() / stepTDC; + trace("cellID {}, \t energy: {}, TDC: {}, time: ", cellID, energy, rh.getTimeStamp(), time); - // masked position (look for a mother volume) - if (gpos_mask != 0) { - auto mpos = m_converter->position(cellID & ~gpos_mask); - // replace corresponding coords - for (const char &c : m_cfg.maskPos) { - switch (std::tolower(c)) { - case 'x': - gpos.SetX(mpos.X()); - break; - case 'y': - gpos.SetY(mpos.Y()); - break; - case 'z': - gpos.SetZ(mpos.Z()); - break; - default: - break; - } - } - } + dd4hep::DetElement local; + dd4hep::Position gpos; + try { + // global positions + gpos = m_converter->position(cellID); - // local positions - if (m_cfg.localDetElement.empty()) { - auto volman = m_detector->volumeManager(); - local = volman.lookupDetElement(cellID & local_mask); - } else { - local = m_local; - } - } catch (...) { - // Error looking up cellID. Messages should already have been printed. - // Also, see comment at top of this method. - if (++NcellIDerrors >= MaxCellIDerrors) { - error("Maximum number of errors reached: {}", MaxCellIDerrors); - error("This is likely an issue with the cellID being unknown."); - error("Note: local_mask={:X} example cellID={:x}", local_mask, cellID); - error("Disabling this algorithm since it requires a valid cellID."); - error("(See {}:{})", __FILE__,__LINE__); - } - continue; + // masked position (look for a mother volume) + if (gpos_mask != 0) { + auto mpos = m_converter->position(cellID & ~gpos_mask); + // replace corresponding coords + for (const char& c : m_cfg.maskPos) { + switch (std::tolower(c)) { + case 'x': + gpos.SetX(mpos.X()); + break; + case 'y': + gpos.SetY(mpos.Y()); + break; + case 'z': + gpos.SetZ(mpos.Z()); + break; + default: + break; + } } + } - const auto pos = local.nominal().worldToLocal(gpos); - std::vector cdim; - // get segmentation dimensions - auto segmentation_type = m_converter->findReadout(local).segmentation().type(); - if (segmentation_type == "CartesianGridXY" || segmentation_type == "HexGridXY") { - auto cell_dim = m_converter->cellDimensions(cellID); - cdim.resize(3); - cdim[0] = cell_dim[0]; - cdim[1] = cell_dim[1]; - debug("Using segmentation for cell dimensions: {}", fmt::join(cdim, ", ")); - } else { - if ((segmentation_type != "NoSegmentation") && (!warned_unsupported_segmentation)) { - warning("Unsupported segmentation type \"{}\"", segmentation_type); - warned_unsupported_segmentation = true; - } - - // Using bounding box instead of actual solid so the dimensions are always in dim_x, dim_y, dim_z - cdim = m_converter->findContext(cellID)->volumePlacement().volume().boundingBox().dimensions(); - std::transform(cdim.begin(), cdim.end(), cdim.begin(), - std::bind(std::multiplies(), std::placeholders::_1, 2)); - debug("Using bounding box for cell dimensions: {}", fmt::join(cdim, ", ")); - } + // local positions + if (m_cfg.localDetElement.empty()) { + auto volman = m_detector->volumeManager(); + local = volman.lookupDetElement(cellID & local_mask); + } else { + local = m_local; + } + } catch (...) { + // Error looking up cellID. Messages should already have been printed. + // Also, see comment at top of this method. + if (++NcellIDerrors >= MaxCellIDerrors) { + error("Maximum number of errors reached: {}", MaxCellIDerrors); + error("This is likely an issue with the cellID being unknown."); + error("Note: local_mask={:X} example cellID={:x}", local_mask, cellID); + error("Disabling this algorithm since it requires a valid cellID."); + error("(See {}:{})", __FILE__, __LINE__); + } + continue; + } - //create constant vectors for passing to hit initializer list - //FIXME: needs to come from the geometry service/converter - const decltype(edm4eic::CalorimeterHitData::position) position(gpos.x() / dd4hep::mm, gpos.y() / dd4hep::mm, - gpos.z() / dd4hep::mm); - const decltype(edm4eic::CalorimeterHitData::dimension) dimension(cdim.at(0) / dd4hep::mm, cdim.at(1) / dd4hep::mm, - cdim.at(2) / dd4hep::mm); - const decltype(edm4eic::CalorimeterHitData::local) local_position(pos.x() / dd4hep::mm, pos.y() / dd4hep::mm, - pos.z() / dd4hep::mm); + const auto pos = local.nominal().worldToLocal(gpos); + std::vector cdim; + // get segmentation dimensions + auto segmentation_type = m_converter->findReadout(local).segmentation().type(); + if (segmentation_type == "CartesianGridXY" || segmentation_type == "HexGridXY") { + auto cell_dim = m_converter->cellDimensions(cellID); + cdim.resize(3); + cdim[0] = cell_dim[0]; + cdim[1] = cell_dim[1]; + debug("Using segmentation for cell dimensions: {}", fmt::join(cdim, ", ")); + } else { + if ((segmentation_type != "NoSegmentation") && (!warned_unsupported_segmentation)) { + warning("Unsupported segmentation type \"{}\"", segmentation_type); + warned_unsupported_segmentation = true; + } - recohits->create( - rh.getCellID(), - energy, - 0, - time, - 0, - position, - dimension, - sid, - lid, - local_position); + // Using bounding box instead of actual solid so the dimensions are always in dim_x, dim_y, dim_z + cdim = + m_converter->findContext(cellID)->volumePlacement().volume().boundingBox().dimensions(); + std::transform(cdim.begin(), cdim.end(), cdim.begin(), + std::bind(std::multiplies(), std::placeholders::_1, 2)); + debug("Using bounding box for cell dimensions: {}", fmt::join(cdim, ", ")); } + + //create constant vectors for passing to hit initializer list + //FIXME: needs to come from the geometry service/converter + const decltype(edm4eic::CalorimeterHitData::position) position( + gpos.x() / dd4hep::mm, gpos.y() / dd4hep::mm, gpos.z() / dd4hep::mm); + const decltype(edm4eic::CalorimeterHitData::dimension) dimension( + cdim.at(0) / dd4hep::mm, cdim.at(1) / dd4hep::mm, cdim.at(2) / dd4hep::mm); + const decltype(edm4eic::CalorimeterHitData::local) local_position( + pos.x() / dd4hep::mm, pos.y() / dd4hep::mm, pos.z() / dd4hep::mm); + + recohits->create(rh.getCellID(), energy, 0, time, 0, position, dimension, sid, lid, + local_position); + } } } // namespace eicrecon diff --git a/src/algorithms/calorimetry/CalorimeterHitReco.h b/src/algorithms/calorimetry/CalorimeterHitReco.h index 44b906c2b2..1155ed9e16 100644 --- a/src/algorithms/calorimetry/CalorimeterHitReco.h +++ b/src/algorithms/calorimetry/CalorimeterHitReco.h @@ -27,51 +27,44 @@ namespace eicrecon { - using CalorimeterHitRecoAlgorithm = algorithms::Algorithm< - algorithms::Input< - edm4hep::RawCalorimeterHitCollection - >, - algorithms::Output< - edm4eic::CalorimeterHitCollection - > - >; - - class CalorimeterHitReco - : public CalorimeterHitRecoAlgorithm, - public WithPodConfig { - - public: - CalorimeterHitReco(std::string_view name) - : CalorimeterHitRecoAlgorithm{name, - {"inputRawHitCollection"}, - {"outputRecHitCollection"}, - "Reconstruct hit from digitized input."} {} +using CalorimeterHitRecoAlgorithm = + algorithms::Algorithm, + algorithms::Output>; - void init() final; - void process(const Input&, const Output&) const final; +class CalorimeterHitReco : public CalorimeterHitRecoAlgorithm, + public WithPodConfig { - private: +public: + CalorimeterHitReco(std::string_view name) + : CalorimeterHitRecoAlgorithm{name, + {"inputRawHitCollection"}, + {"outputRecHitCollection"}, + "Reconstruct hit from digitized input."} {} - // unitless counterparts of the input parameters - double thresholdADC{0}; - double stepTDC{0}; + void init() final; + void process(const Input&, const Output&) const final; - dd4hep::BitFieldCoder* id_dec = nullptr; +private: + // unitless counterparts of the input parameters + double thresholdADC{0}; + double stepTDC{0}; - mutable uint32_t NcellIDerrors = 0; - uint32_t MaxCellIDerrors = 100; + dd4hep::BitFieldCoder* id_dec = nullptr; - size_t sector_idx{0}, layer_idx{0}; + mutable uint32_t NcellIDerrors = 0; + uint32_t MaxCellIDerrors = 100; - mutable bool warned_unsupported_segmentation = false; + size_t sector_idx{0}, layer_idx{0}; - dd4hep::DetElement m_local; - size_t local_mask = ~static_cast(0), gpos_mask = static_cast(0); + mutable bool warned_unsupported_segmentation = false; - private: - const dd4hep::Detector* m_detector{algorithms::GeoSvc::instance().detector()}; - const dd4hep::rec::CellIDPositionConverter* m_converter{algorithms::GeoSvc::instance().cellIDPositionConverter()}; + dd4hep::DetElement m_local; + size_t local_mask = ~static_cast(0), gpos_mask = static_cast(0); - }; +private: + const dd4hep::Detector* m_detector{algorithms::GeoSvc::instance().detector()}; + const dd4hep::rec::CellIDPositionConverter* m_converter{ + algorithms::GeoSvc::instance().cellIDPositionConverter()}; +}; } // namespace eicrecon diff --git a/src/algorithms/calorimetry/CalorimeterHitRecoConfig.h b/src/algorithms/calorimetry/CalorimeterHitRecoConfig.h index bba111f05a..2f9eb3c6a9 100644 --- a/src/algorithms/calorimetry/CalorimeterHitRecoConfig.h +++ b/src/algorithms/calorimetry/CalorimeterHitRecoConfig.h @@ -8,35 +8,35 @@ namespace eicrecon { - struct CalorimeterHitRecoConfig { - - // digitization settings - unsigned int capADC{1}; - double dyRangeADC{1}; - unsigned int pedMeanADC{0}; - double pedSigmaADC{0}; - double resolutionTDC{1}; - double corrMeanScale{1}; - - // zero suppression - double thresholdFactor{0}; - double thresholdValue{0}; - - // sampling fraction - double sampFrac{1.0}; - std::vector sampFracLayer{}; - - // readout fields - std::string readout{""}; - std::string layerField{""}; - std::string sectorField{""}; - - // name of detelment or fields to find the local detector (for global->local transform) - // if nothing is provided, the lowest level DetElement (from cellID) will be used - std::string localDetElement{""}; - std::vector localDetFields{}; - std::string maskPos{""}; - std::vector maskPosFields{}; - }; - -} // eicrecon +struct CalorimeterHitRecoConfig { + + // digitization settings + unsigned int capADC{1}; + double dyRangeADC{1}; + unsigned int pedMeanADC{0}; + double pedSigmaADC{0}; + double resolutionTDC{1}; + double corrMeanScale{1}; + + // zero suppression + double thresholdFactor{0}; + double thresholdValue{0}; + + // sampling fraction + double sampFrac{1.0}; + std::vector sampFracLayer{}; + + // readout fields + std::string readout{""}; + std::string layerField{""}; + std::string sectorField{""}; + + // name of detelment or fields to find the local detector (for global->local transform) + // if nothing is provided, the lowest level DetElement (from cellID) will be used + std::string localDetElement{""}; + std::vector localDetFields{}; + std::string maskPos{""}; + std::vector maskPosFields{}; +}; + +} // namespace eicrecon diff --git a/src/algorithms/calorimetry/CalorimeterHitsMerger.cc b/src/algorithms/calorimetry/CalorimeterHitsMerger.cc index 305967247b..e04fb8cd40 100644 --- a/src/algorithms/calorimetry/CalorimeterHitsMerger.cc +++ b/src/algorithms/calorimetry/CalorimeterHitsMerger.cc @@ -36,108 +36,96 @@ namespace eicrecon { void CalorimeterHitsMerger::init() { - if (m_cfg.readout.empty()) { - error("readoutClass is not provided, it is needed to know the fields in readout ids"); - return; + if (m_cfg.readout.empty()) { + error("readoutClass is not provided, it is needed to know the fields in readout ids"); + return; + } + + try { + auto id_desc = m_detector->readout(m_cfg.readout).idSpec(); + id_mask = 0; + std::vector> ref_fields; + for (size_t i = 0; i < m_cfg.fields.size(); ++i) { + id_mask |= id_desc.field(m_cfg.fields[i])->mask(); + // use the provided id number to find ref cell, or use 0 + int ref = i < m_cfg.refs.size() ? m_cfg.refs[i] : 0; + ref_fields.emplace_back(m_cfg.fields[i], ref); } - - try { - auto id_desc = m_detector->readout(m_cfg.readout).idSpec(); - id_mask = 0; - std::vector> ref_fields; - for (size_t i = 0; i < m_cfg.fields.size(); ++i) { - id_mask |= id_desc.field(m_cfg.fields[i])->mask(); - // use the provided id number to find ref cell, or use 0 - int ref = i < m_cfg.refs.size() ? m_cfg.refs[i] : 0; - ref_fields.emplace_back(m_cfg.fields[i], ref); - } - ref_mask = id_desc.encode(ref_fields); - } catch (...) { - auto mess = fmt::format("Failed to load ID decoder for {}", m_cfg.readout); - warning(mess); -// throw std::runtime_error(mess); - } - id_mask = ~id_mask; - debug("ID mask in {:s}: {:#064b}", m_cfg.readout, id_mask); + ref_mask = id_desc.encode(ref_fields); + } catch (...) { + auto mess = fmt::format("Failed to load ID decoder for {}", m_cfg.readout); + warning(mess); + // throw std::runtime_error(mess); + } + id_mask = ~id_mask; + debug("ID mask in {:s}: {:#064b}", m_cfg.readout, id_mask); } -void CalorimeterHitsMerger::process( - const CalorimeterHitsMerger::Input& input, - const CalorimeterHitsMerger::Output& output) const { - - const auto [in_hits] = input; - auto [out_hits] = output; - - // find the hits that belong to the same group (for merging) - std::unordered_map> merge_map; - std::size_t ix = 0; - for (const auto &h : *in_hits) { - uint64_t id = h.getCellID() & id_mask; - merge_map[id].push_back(ix); - - ix++; +void CalorimeterHitsMerger::process(const CalorimeterHitsMerger::Input& input, + const CalorimeterHitsMerger::Output& output) const { + + const auto [in_hits] = input; + auto [out_hits] = output; + + // find the hits that belong to the same group (for merging) + std::unordered_map> merge_map; + std::size_t ix = 0; + for (const auto& h : *in_hits) { + uint64_t id = h.getCellID() & id_mask; + merge_map[id].push_back(ix); + + ix++; + } + + // sort hits by energy from large to small + for (auto& it : merge_map) { + std::sort(it.second.begin(), it.second.end(), [&](std::size_t ix1, std::size_t ix2) { + return (*in_hits)[ix1].getEnergy() > (*in_hits)[ix2].getEnergy(); + }); + } + + // reconstruct info for merged hits + // dd4hep decoders + auto volman = m_detector->volumeManager(); + + for (const auto& [id, ixs] : merge_map) { + // reference fields id + const uint64_t ref_id = id | ref_mask; + // global positions + const auto gpos = m_converter->position(ref_id); + // local positions + auto alignment = volman.lookupDetElement(ref_id).nominal(); + const auto pos = alignment.worldToLocal(dd4hep::Position(gpos.x(), gpos.y(), gpos.z())); + debug("{}, {}", volman.lookupDetElement(ref_id).path(), volman.lookupDetector(ref_id).path()); + // sum energy + float energy = 0.; + float energyError = 0.; + float time = 0; + float timeError = 0; + for (auto ix : ixs) { + auto hit = (*in_hits)[ix]; + energy += hit.getEnergy(); + energyError += hit.getEnergyError() * hit.getEnergyError(); + time += hit.getTime(); + timeError += hit.getTimeError() * hit.getTimeError(); } + energyError = sqrt(energyError); + time /= ixs.size(); + timeError = sqrt(timeError) / ixs.size(); - // sort hits by energy from large to small - for (auto &it : merge_map) { - std::sort(it.second.begin(), it.second.end(), [&](std::size_t ix1, std::size_t ix2) { - return (*in_hits)[ix1].getEnergy() > (*in_hits)[ix2].getEnergy(); - }); - } + const auto href = (*in_hits)[ixs.front()]; - // reconstruct info for merged hits - // dd4hep decoders - auto volman = m_detector->volumeManager(); - - for (const auto &[id, ixs] : merge_map) { - // reference fields id - const uint64_t ref_id = id | ref_mask; - // global positions - const auto gpos = m_converter->position(ref_id); - // local positions - auto alignment = volman.lookupDetElement(ref_id).nominal(); - const auto pos = alignment.worldToLocal(dd4hep::Position(gpos.x(), gpos.y(), gpos.z())); - debug("{}, {}", volman.lookupDetElement(ref_id).path(), volman.lookupDetector(ref_id).path()); - // sum energy - float energy = 0.; - float energyError = 0.; - float time = 0; - float timeError = 0; - for (auto ix : ixs) { - auto hit = (*in_hits)[ix]; - energy += hit.getEnergy(); - energyError += hit.getEnergyError() * hit.getEnergyError(); - time += hit.getTime(); - timeError += hit.getTimeError() * hit.getTimeError(); - } - energyError = sqrt(energyError); - time /= ixs.size(); - timeError = sqrt(timeError) / ixs.size(); - - const auto href = (*in_hits)[ixs.front()]; - - // create const vectors for passing to hit initializer list - const decltype(edm4eic::CalorimeterHitData::position) position( - gpos.x() / dd4hep::mm, gpos.y() / dd4hep::mm, gpos.z() / dd4hep::mm - ); - const decltype(edm4eic::CalorimeterHitData::local) local( - pos.x(), pos.y(), pos.z() - ); - - out_hits->create( - href.getCellID(), - energy, - energyError, - time, - timeError, - position, - href.getDimension(), - href.getSector(), - href.getLayer(), - local); // Can do better here? Right now position is mapped on the central hit - } + // create const vectors for passing to hit initializer list + const decltype(edm4eic::CalorimeterHitData::position) position( + gpos.x() / dd4hep::mm, gpos.y() / dd4hep::mm, gpos.z() / dd4hep::mm); + const decltype(edm4eic::CalorimeterHitData::local) local(pos.x(), pos.y(), pos.z()); + + out_hits->create(href.getCellID(), energy, energyError, time, timeError, position, + href.getDimension(), href.getSector(), href.getLayer(), + local); // Can do better here? Right now position is mapped on the central hit + } - debug("Size before = {}, after = {}", in_hits->size(), out_hits->size()); + debug("Size before = {}, after = {}", in_hits->size(), out_hits->size()); } } // namespace eicrecon diff --git a/src/algorithms/calorimetry/CalorimeterHitsMerger.h b/src/algorithms/calorimetry/CalorimeterHitsMerger.h index 763d9d199c..9a2fc661a5 100644 --- a/src/algorithms/calorimetry/CalorimeterHitsMerger.h +++ b/src/algorithms/calorimetry/CalorimeterHitsMerger.h @@ -25,36 +25,30 @@ namespace eicrecon { - using CalorimeterHitsMergerAlgorithm = algorithms::Algorithm< - algorithms::Input< - edm4eic::CalorimeterHitCollection - >, - algorithms::Output< - edm4eic::CalorimeterHitCollection - > - >; - - class CalorimeterHitsMerger - : public CalorimeterHitsMergerAlgorithm, - public WithPodConfig { - - public: - CalorimeterHitsMerger(std::string_view name) - : CalorimeterHitsMergerAlgorithm{name, - {"inputHitCollection"}, - {"outputHitCollection"}, - "Group readout hits from a calorimeter."} {} +using CalorimeterHitsMergerAlgorithm = + algorithms::Algorithm, + algorithms::Output>; + +class CalorimeterHitsMerger : public CalorimeterHitsMergerAlgorithm, + public WithPodConfig { - void init() final; - void process(const Input&, const Output&) const final; +public: + CalorimeterHitsMerger(std::string_view name) + : CalorimeterHitsMergerAlgorithm{name, + {"inputHitCollection"}, + {"outputHitCollection"}, + "Group readout hits from a calorimeter."} {} - private: - uint64_t id_mask{0}, ref_mask{0}; + void init() final; + void process(const Input&, const Output&) const final; - private: - const dd4hep::Detector* m_detector{algorithms::GeoSvc::instance().detector()}; - const dd4hep::rec::CellIDPositionConverter* m_converter{algorithms::GeoSvc::instance().cellIDPositionConverter()}; +private: + uint64_t id_mask{0}, ref_mask{0}; - }; +private: + const dd4hep::Detector* m_detector{algorithms::GeoSvc::instance().detector()}; + const dd4hep::rec::CellIDPositionConverter* m_converter{ + algorithms::GeoSvc::instance().cellIDPositionConverter()}; +}; } // namespace eicrecon diff --git a/src/algorithms/calorimetry/CalorimeterHitsMergerConfig.h b/src/algorithms/calorimetry/CalorimeterHitsMergerConfig.h index 9d5f92df6c..0ae271942d 100644 --- a/src/algorithms/calorimetry/CalorimeterHitsMergerConfig.h +++ b/src/algorithms/calorimetry/CalorimeterHitsMergerConfig.h @@ -8,12 +8,11 @@ namespace eicrecon { - struct CalorimeterHitsMergerConfig { +struct CalorimeterHitsMergerConfig { - std::string readout{""}; - std::vector fields{}; - std::vector refs{}; + std::string readout{""}; + std::vector fields{}; + std::vector refs{}; +}; - }; - -} // eicrecon +} // namespace eicrecon diff --git a/src/algorithms/calorimetry/CalorimeterIslandCluster.cc b/src/algorithms/calorimetry/CalorimeterIslandCluster.cc index 53845fd947..8d9af27603 100644 --- a/src/algorithms/calorimetry/CalorimeterIslandCluster.cc +++ b/src/algorithms/calorimetry/CalorimeterIslandCluster.cc @@ -33,50 +33,40 @@ namespace eicrecon { unsigned int CalorimeterIslandCluster::function_id = 0; -static double Phi_mpi_pi(double phi) { - return std::remainder(phi, 2 * M_PI); -} +static double Phi_mpi_pi(double phi) { return std::remainder(phi, 2 * M_PI); } -static edm4hep::Vector2f localDistXY(const CaloHit &h1, const CaloHit &h2) { - const auto delta =h1.getLocal() - h2.getLocal(); +static edm4hep::Vector2f localDistXY(const CaloHit& h1, const CaloHit& h2) { + const auto delta = h1.getLocal() - h2.getLocal(); return {delta.x, delta.y}; } -static edm4hep::Vector2f localDistXZ(const CaloHit &h1, const CaloHit &h2) { +static edm4hep::Vector2f localDistXZ(const CaloHit& h1, const CaloHit& h2) { const auto delta = h1.getLocal() - h2.getLocal(); return {delta.x, delta.z}; } -static edm4hep::Vector2f localDistYZ(const CaloHit &h1, const CaloHit &h2) { +static edm4hep::Vector2f localDistYZ(const CaloHit& h1, const CaloHit& h2) { const auto delta = h1.getLocal() - h2.getLocal(); return {delta.y, delta.z}; } -static edm4hep::Vector2f dimScaledLocalDistXY(const CaloHit &h1, const CaloHit &h2) { +static edm4hep::Vector2f dimScaledLocalDistXY(const CaloHit& h1, const CaloHit& h2) { const auto delta = h1.getLocal() - h2.getLocal(); const auto dimsum = h1.getDimension() + h2.getDimension(); return {2 * delta.x / dimsum.x, 2 * delta.y / dimsum.y}; } -static edm4hep::Vector2f globalDistRPhi(const CaloHit &h1, const CaloHit &h2) { +static edm4hep::Vector2f globalDistRPhi(const CaloHit& h1, const CaloHit& h2) { using vector_type = decltype(edm4hep::Vector2f::a); - return { - static_cast( - edm4hep::utils::magnitude(h1.getPosition()) - edm4hep::utils::magnitude(h2.getPosition()) - ), - static_cast( - Phi_mpi_pi(edm4hep::utils::angleAzimuthal(h1.getPosition()) - edm4hep::utils::angleAzimuthal(h2.getPosition())) - ) - }; + return {static_cast(edm4hep::utils::magnitude(h1.getPosition()) - + edm4hep::utils::magnitude(h2.getPosition())), + static_cast(Phi_mpi_pi(edm4hep::utils::angleAzimuthal(h1.getPosition()) - + edm4hep::utils::angleAzimuthal(h2.getPosition())))}; } -static edm4hep::Vector2f globalDistEtaPhi(const CaloHit &h1, const CaloHit &h2) { +static edm4hep::Vector2f globalDistEtaPhi(const CaloHit& h1, const CaloHit& h2) { using vector_type = decltype(edm4hep::Vector2f::a); - return { - static_cast( - edm4hep::utils::eta(h1.getPosition()) - edm4hep::utils::eta(h2.getPosition()) - ), - static_cast( - Phi_mpi_pi(edm4hep::utils::angleAzimuthal(h1.getPosition()) - edm4hep::utils::angleAzimuthal(h2.getPosition())) - ) - }; + return {static_cast(edm4hep::utils::eta(h1.getPosition()) - + edm4hep::utils::eta(h2.getPosition())), + static_cast(Phi_mpi_pi(edm4hep::utils::angleAzimuthal(h1.getPosition()) - + edm4hep::utils::angleAzimuthal(h2.getPosition())))}; } //------------------------ @@ -84,174 +74,182 @@ static edm4hep::Vector2f globalDistEtaPhi(const CaloHit &h1, const CaloHit &h2) //------------------------ void CalorimeterIslandCluster::init() { - static std::map, std::vector>> - distMethods{ - {"localDistXY", {localDistXY, {dd4hep::mm, dd4hep::mm}}}, {"localDistXZ", {localDistXZ, {dd4hep::mm, dd4hep::mm}}}, - {"localDistYZ", {localDistYZ, {dd4hep::mm, dd4hep::mm}}}, {"dimScaledLocalDistXY", {dimScaledLocalDistXY, {1., 1.}}}, - {"globalDistRPhi", {globalDistRPhi, {dd4hep::mm, dd4hep::rad}}}, {"globalDistEtaPhi", {globalDistEtaPhi, {1., dd4hep::rad}}} - }; - - - // set coordinate system - auto set_dist_method = [this](std::pair> uprop) { - if (uprop.second.size() == 0) { - return false; - } - auto& [method, units] = distMethods[uprop.first]; - if (uprop.second.size() != units.size()) { - warning("Expect {} values from {}, received {}. ignored it.", units.size(), uprop.first, uprop.second.size()); - return false; - } else { - for (size_t i = 0; i < units.size(); ++i) { - neighbourDist[i] = uprop.second[i] / units[i]; - } - hitsDist = method; - info("Clustering uses {} with distances <= [{}]", uprop.first, fmt::join(neighbourDist, ",")); + static std::map, + std::vector>> + distMethods{{"localDistXY", {localDistXY, {dd4hep::mm, dd4hep::mm}}}, + {"localDistXZ", {localDistXZ, {dd4hep::mm, dd4hep::mm}}}, + {"localDistYZ", {localDistYZ, {dd4hep::mm, dd4hep::mm}}}, + {"dimScaledLocalDistXY", {dimScaledLocalDistXY, {1., 1.}}}, + {"globalDistRPhi", {globalDistRPhi, {dd4hep::mm, dd4hep::rad}}}, + {"globalDistEtaPhi", {globalDistEtaPhi, {1., dd4hep::rad}}}}; + + // set coordinate system + auto set_dist_method = [this](std::pair> uprop) { + if (uprop.second.size() == 0) { + return false; + } + auto& [method, units] = distMethods[uprop.first]; + if (uprop.second.size() != units.size()) { + warning("Expect {} values from {}, received {}. ignored it.", units.size(), uprop.first, + uprop.second.size()); + return false; + } else { + for (size_t i = 0; i < units.size(); ++i) { + neighbourDist[i] = uprop.second[i] / units[i]; } - return true; - }; - - std::map> uprops{ - {"localDistXY", m_cfg.localDistXY}, - {"localDistXZ", m_cfg.localDistXZ}, - {"localDistYZ", m_cfg.localDistYZ}, - {"globalDistRPhi", m_cfg.globalDistRPhi}, - {"globalDistEtaPhi", m_cfg.globalDistEtaPhi}, - // default one should be the last one - {"dimScaledLocalDistXY", m_cfg.dimScaledLocalDistXY} - }; - - bool method_found = false; + hitsDist = method; + info("Clustering uses {} with distances <= [{}]", uprop.first, fmt::join(neighbourDist, ",")); + } + return true; + }; - // Adjacency matrix methods - if (!m_cfg.adjacencyMatrix.empty()) { - // sanity checks - if (m_cfg.readout.empty()) { - error("readoutClass is not provided, it is needed to know the fields in readout ids"); - } - m_idSpec = m_detector->readout(m_cfg.readout).idSpec(); - - std::string func_name = fmt::format("_CalorimeterIslandCluster_{}", function_id++); - std::ostringstream sstr; - sstr << "bool " << func_name << "(double params[]){"; - unsigned int param_ix = 0; - for(const auto &p : m_idSpec.fields()) { - const std::string &name = p.first; + std::map> uprops{ + {"localDistXY", m_cfg.localDistXY}, + {"localDistXZ", m_cfg.localDistXZ}, + {"localDistYZ", m_cfg.localDistYZ}, + {"globalDistRPhi", m_cfg.globalDistRPhi}, + {"globalDistEtaPhi", m_cfg.globalDistEtaPhi}, + // default one should be the last one + {"dimScaledLocalDistXY", m_cfg.dimScaledLocalDistXY}}; + + bool method_found = false; + + // Adjacency matrix methods + if (!m_cfg.adjacencyMatrix.empty()) { + // sanity checks + if (m_cfg.readout.empty()) { + error("readoutClass is not provided, it is needed to know the fields in readout ids"); + } + m_idSpec = m_detector->readout(m_cfg.readout).idSpec(); + + std::string func_name = fmt::format("_CalorimeterIslandCluster_{}", function_id++); + std::ostringstream sstr; + sstr << "bool " << func_name << "(double params[]){"; + unsigned int param_ix = 0; + for (const auto& p : m_idSpec.fields()) { + const std::string& name = p.first; + const dd4hep::IDDescriptor::Field* field = p.second; + sstr << "double " << name << "_1 = params[" << (param_ix++) << "];"; + sstr << "double " << name << "_2 = params[" << (param_ix++) << "];"; + } + sstr << "return " << m_cfg.adjacencyMatrix << ";"; + sstr << "}"; + debug("Compiling {}", sstr.str()); + + TInterpreter* interp = TInterpreter::Instance(); + interp->ProcessLine(sstr.str().c_str()); + std::unique_ptr func_val{gInterpreter->MakeInterpreterValue()}; + interp->Evaluate(func_name.c_str(), *func_val); + typedef bool (*func_t)(double params[]); + func_t func = ((func_t)(func_val->GetAsPointer())); + + is_neighbour = [this, func, param_ix](const CaloHit& h1, const CaloHit& h2) { + std::vector params; + params.reserve(param_ix); + for (const auto& p : m_idSpec.fields()) { + const std::string& name = p.first; const dd4hep::IDDescriptor::Field* field = p.second; - sstr << "double " << name << "_1 = params[" << (param_ix++) << "];"; - sstr << "double " << name << "_2 = params[" << (param_ix++) << "];"; + params.push_back(field->value(h1.getCellID())); + params.push_back(field->value(h2.getCellID())); + trace("{}_1 = {}", name, field->value(h1.getCellID())); + trace("{}_2 = {}", name, field->value(h2.getCellID())); } - sstr << "return " << m_cfg.adjacencyMatrix << ";"; - sstr << "}"; - debug("Compiling {}", sstr.str()); - - TInterpreter *interp = TInterpreter::Instance(); - interp->ProcessLine(sstr.str().c_str()); - std::unique_ptr func_val { gInterpreter->MakeInterpreterValue() }; - interp->Evaluate(func_name.c_str(), *func_val); - typedef bool (*func_t)(double params[]); - func_t func = ((func_t)(func_val->GetAsPointer())); - - is_neighbour = [this, func, param_ix](const CaloHit &h1, const CaloHit &h2) { - std::vector params; - params.reserve(param_ix); - for(const auto &p : m_idSpec.fields()) { - const std::string &name = p.first; - const dd4hep::IDDescriptor::Field* field = p.second; - params.push_back(field->value(h1.getCellID())); - params.push_back(field->value(h2.getCellID())); - trace("{}_1 = {}", name, field->value(h1.getCellID())); - trace("{}_2 = {}", name, field->value(h2.getCellID())); - } - return func(params.data()); - }; - method_found = true; - } - - // Coordinate distance methods - if (not method_found) { - for (auto& uprop : uprops) { - if (set_dist_method(uprop)) { - method_found = true; - - is_neighbour = [this](const CaloHit &h1, const CaloHit &h2) { - // in the same sector - if (h1.getSector() == h2.getSector()) { - auto dist = hitsDist(h1, h2); - return (fabs(dist.a) <= neighbourDist[0]) && (fabs(dist.b) <= neighbourDist[1]); - // different sector, local coordinates do not work, using global coordinates - } else { - // sector may have rotation (barrel), so z is included - // (EDM4hep units are mm, so convert sectorDist to mm) - return (edm4hep::utils::magnitude(h1.getPosition() - h2.getPosition()) <= m_cfg.sectorDist / dd4hep::mm); - } - }; - - info("Using clustering method: {}", uprop.first); - break; - } + return func(params.data()); + }; + method_found = true; + } + + // Coordinate distance methods + if (not method_found) { + for (auto& uprop : uprops) { + if (set_dist_method(uprop)) { + method_found = true; + + is_neighbour = [this](const CaloHit& h1, const CaloHit& h2) { + // in the same sector + if (h1.getSector() == h2.getSector()) { + auto dist = hitsDist(h1, h2); + return (fabs(dist.a) <= neighbourDist[0]) && (fabs(dist.b) <= neighbourDist[1]); + // different sector, local coordinates do not work, using global coordinates + } else { + // sector may have rotation (barrel), so z is included + // (EDM4hep units are mm, so convert sectorDist to mm) + return (edm4hep::utils::magnitude(h1.getPosition() - h2.getPosition()) <= + m_cfg.sectorDist / dd4hep::mm); + } + }; + + info("Using clustering method: {}", uprop.first); + break; } } - - if (not method_found) { - throw std::runtime_error("Cannot determine the clustering coordinates"); + } + + if (not method_found) { + throw std::runtime_error("Cannot determine the clustering coordinates"); + } + + if (m_cfg.splitCluster) { + auto transverseEnergyProfileMetric_it = + std::find_if(distMethods.begin(), distMethods.end(), + [&](auto& p) { return m_cfg.transverseEnergyProfileMetric == p.first; }); + if (transverseEnergyProfileMetric_it == distMethods.end()) { + throw std::runtime_error( + fmt::format("Unsupported value \"{}\" for \"transverseEnergyProfileMetric\"", + m_cfg.transverseEnergyProfileMetric)); } - - if (m_cfg.splitCluster) { - auto transverseEnergyProfileMetric_it = std::find_if(distMethods.begin(), distMethods.end(), [&](auto &p) { return m_cfg.transverseEnergyProfileMetric == p.first; }); - if (transverseEnergyProfileMetric_it == distMethods.end()) { - throw std::runtime_error(fmt::format("Unsupported value \"{}\" for \"transverseEnergyProfileMetric\"", m_cfg.transverseEnergyProfileMetric)); - } - transverseEnergyProfileMetric = std::get<0>(transverseEnergyProfileMetric_it->second); - std::vector &units = std::get<1>(transverseEnergyProfileMetric_it->second); - for (auto unit : units) { - if (unit != units[0]) { - throw std::runtime_error(fmt::format("Metric {} has incompatible dimension units", m_cfg.transverseEnergyProfileMetric)); - } + transverseEnergyProfileMetric = std::get<0>(transverseEnergyProfileMetric_it->second); + std::vector& units = std::get<1>(transverseEnergyProfileMetric_it->second); + for (auto unit : units) { + if (unit != units[0]) { + throw std::runtime_error(fmt::format("Metric {} has incompatible dimension units", + m_cfg.transverseEnergyProfileMetric)); } - transverseEnergyProfileScaleUnits = units[0]; } + transverseEnergyProfileScaleUnits = units[0]; + } - return; + return; } +void CalorimeterIslandCluster::process(const CalorimeterIslandCluster::Input& input, + const CalorimeterIslandCluster::Output& output) const { -void CalorimeterIslandCluster::process( - const CalorimeterIslandCluster::Input& input, - const CalorimeterIslandCluster::Output& output) const { + const auto [hits] = input; + auto [proto_clusters] = output; - const auto [hits] = input; - auto [proto_clusters] = output; + // group neighboring hits + std::vector> groups; - // group neighboring hits - std::vector> groups; + std::vector visits(hits->size(), false); + for (size_t i = 0; i < hits->size(); ++i) { - std::vector visits(hits->size(), false); - for (size_t i = 0; i < hits->size(); ++i) { - - { - const auto& hit = (*hits)[i]; - debug("hit {:d}: energy = {:.4f} MeV, local = ({:.4f}, {:.4f}) mm, global=({:.4f}, {:.4f}, {:.4f}) mm", i, hit.getEnergy() * 1000., hit.getLocal().x, hit.getLocal().y, hit.getPosition().x, hit.getPosition().y, hit.getPosition().z); - } - // already in a group - if (visits[i]) { - continue; - } - groups.emplace_back(); - // create a new group, and group all the neighboring hits - bfs_group(*hits, groups.back(), i, visits); + { + const auto& hit = (*hits)[i]; + debug("hit {:d}: energy = {:.4f} MeV, local = ({:.4f}, {:.4f}) mm, global=({:.4f}, {:.4f}, " + "{:.4f}) mm", + i, hit.getEnergy() * 1000., hit.getLocal().x, hit.getLocal().y, hit.getPosition().x, + hit.getPosition().y, hit.getPosition().z); } - - for (auto& group : groups) { - if (group.empty()) { - continue; - } - auto maxima = find_maxima(*hits, group, !m_cfg.splitCluster); - split_group(*hits, group, maxima, proto_clusters); - - debug("hits in a group: {}, local maxima: {}", group.size(), maxima.size()); + // already in a group + if (visits[i]) { + continue; } + groups.emplace_back(); + // create a new group, and group all the neighboring hits + bfs_group(*hits, groups.back(), i, visits); + } + + for (auto& group : groups) { + if (group.empty()) { + continue; + } + auto maxima = find_maxima(*hits, group, !m_cfg.splitCluster); + split_group(*hits, group, maxima, proto_clusters); + + debug("hits in a group: {}, local maxima: {}", group.size(), maxima.size()); + } } } // namespace eicrecon diff --git a/src/algorithms/calorimetry/CalorimeterIslandCluster.h b/src/algorithms/calorimetry/CalorimeterIslandCluster.h index 2ef8620945..32fb494006 100644 --- a/src/algorithms/calorimetry/CalorimeterIslandCluster.h +++ b/src/algorithms/calorimetry/CalorimeterIslandCluster.h @@ -27,89 +27,84 @@ namespace eicrecon { - using CaloHit = edm4eic::CalorimeterHit; - - using CalorimeterIslandClusterAlgorithm = algorithms::Algorithm< - algorithms::Input< - edm4eic::CalorimeterHitCollection - >, - algorithms::Output< - edm4eic::ProtoClusterCollection - > - >; - - class CalorimeterIslandCluster - : public CalorimeterIslandClusterAlgorithm, - public WithPodConfig { - - public: - CalorimeterIslandCluster(std::string_view name) - : CalorimeterIslandClusterAlgorithm{name, - {"inputProtoClusterCollection"}, - {"outputClusterCollection"}, - "Island clustering."} {} +using CaloHit = edm4eic::CalorimeterHit; - void init() final; - void process(const Input&, const Output&) const final; +using CalorimeterIslandClusterAlgorithm = + algorithms::Algorithm, + algorithms::Output>; - private: - const dd4hep::Detector* m_detector{algorithms::GeoSvc::instance().detector()}; +class CalorimeterIslandCluster : public CalorimeterIslandClusterAlgorithm, + public WithPodConfig { - public: +public: + CalorimeterIslandCluster(std::string_view name) + : CalorimeterIslandClusterAlgorithm{name, + {"inputProtoClusterCollection"}, + {"outputClusterCollection"}, + "Island clustering."} {} - // neighbor checking function - std::function hitsDist; + void init() final; + void process(const Input&, const Output&) const final; - std::function transverseEnergyProfileMetric; - double u_transverseEnergyProfileScale; - double transverseEnergyProfileScaleUnits; +private: + const dd4hep::Detector* m_detector{algorithms::GeoSvc::instance().detector()}; - // helper function to group hits - std::function is_neighbour; +public: + // neighbor checking function + std::function hitsDist; - // unitless counterparts of the input parameters - std::array neighbourDist; + std::function + transverseEnergyProfileMetric; + double u_transverseEnergyProfileScale; + double transverseEnergyProfileScaleUnits; - // Pointer to the geometry service - dd4hep::IDDescriptor m_idSpec; + // helper function to group hits + std::function is_neighbour; - private: + // unitless counterparts of the input parameters + std::array neighbourDist; - static unsigned int function_id; + // Pointer to the geometry service + dd4hep::IDDescriptor m_idSpec; - // grouping function with Breadth-First Search - void bfs_group(const edm4eic::CalorimeterHitCollection &hits, std::set &group, std::size_t idx, std::vector &visits) const { - visits[idx] = true; +private: + static unsigned int function_id; - // not a qualified hit to particpate clustering, stop here - if (hits[idx].getEnergy() < m_cfg.minClusterHitEdep) { - return; - } + // grouping function with Breadth-First Search + void bfs_group(const edm4eic::CalorimeterHitCollection& hits, std::set& group, + std::size_t idx, std::vector& visits) const { + visits[idx] = true; + + // not a qualified hit to particpate clustering, stop here + if (hits[idx].getEnergy() < m_cfg.minClusterHitEdep) { + return; + } - group.insert(idx); - size_t prev_size = 0; - - while (prev_size != group.size()) { - prev_size = group.size(); - for (std::size_t idx1 : group) { - // check neighbours - for (std::size_t idx2 = 0; idx2 < hits.size(); ++idx2) { - // not a qualified hit to particpate clustering, skip - if (hits[idx2].getEnergy() < m_cfg.minClusterHitEdep) { - continue; - } - if ((!visits[idx2]) - && is_neighbour(hits[idx1], hits[idx2])) { - group.insert(idx2); - visits[idx2] = true; - } + group.insert(idx); + size_t prev_size = 0; + + while (prev_size != group.size()) { + prev_size = group.size(); + for (std::size_t idx1 : group) { + // check neighbours + for (std::size_t idx2 = 0; idx2 < hits.size(); ++idx2) { + // not a qualified hit to particpate clustering, skip + if (hits[idx2].getEnergy() < m_cfg.minClusterHitEdep) { + continue; + } + if ((!visits[idx2]) && is_neighbour(hits[idx1], hits[idx2])) { + group.insert(idx2); + visits[idx2] = true; } } } } + } - // find local maxima that above a certain threshold - std::vector find_maxima(const edm4eic::CalorimeterHitCollection &hits, const std::set &group, bool global = false) const { + // find local maxima that above a certain threshold + std::vector find_maxima(const edm4eic::CalorimeterHitCollection& hits, + const std::set& group, + bool global = false) const { std::vector maxima; if (group.empty()) { return maxima; @@ -140,7 +135,8 @@ namespace eicrecon { continue; } - if (is_neighbour(hits[idx1], hits[idx2]) && (hits[idx2].getEnergy() > hits[idx1].getEnergy())) { + if (is_neighbour(hits[idx1], hits[idx2]) && + (hits[idx2].getEnergy() > hits[idx1].getEnergy())) { maximum = false; break; } @@ -153,20 +149,22 @@ namespace eicrecon { return maxima; } - // helper function - inline static void vec_normalize(std::vector& vals) { - double total = 0.; - for (auto& val : vals) { - total += val; - } - for (auto& val : vals) { - val /= total; - } + // helper function + inline static void vec_normalize(std::vector& vals) { + double total = 0.; + for (auto& val : vals) { + total += val; + } + for (auto& val : vals) { + val /= total; } + } - // split a group of hits according to the local maxima - //TODO: confirm protoclustering without protoclustercollection - void split_group(const edm4eic::CalorimeterHitCollection &hits, std::set& group, const std::vector& maxima, edm4eic::ProtoClusterCollection *protoClusters) const { + // split a group of hits according to the local maxima + //TODO: confirm protoclustering without protoclustercollection + void split_group(const edm4eic::CalorimeterHitCollection& hits, std::set& group, + const std::vector& maxima, + edm4eic::ProtoClusterCollection* protoClusters) const { // special cases if (maxima.empty()) { debug("No maxima found, not building any clusters"); @@ -195,9 +193,12 @@ namespace eicrecon { size_t j = 0; // calculate weights for local maxima for (std::size_t cidx : maxima) { - double energy = hits[cidx].getEnergy(); - double dist = edm4hep::utils::magnitude(transverseEnergyProfileMetric(hits[cidx], hits[idx])); - weights[j] = std::exp(-dist * transverseEnergyProfileScaleUnits / m_cfg.transverseEnergyProfileScale) * energy; + double energy = hits[cidx].getEnergy(); + double dist = + edm4hep::utils::magnitude(transverseEnergyProfileMetric(hits[cidx], hits[idx])); + weights[j] = std::exp(-dist * transverseEnergyProfileScaleUnits / + m_cfg.transverseEnergyProfileScale) * + energy; j += 1; } diff --git a/src/algorithms/calorimetry/CalorimeterIslandClusterConfig.h b/src/algorithms/calorimetry/CalorimeterIslandClusterConfig.h index 45dcb567bc..e2b4171e39 100644 --- a/src/algorithms/calorimetry/CalorimeterIslandClusterConfig.h +++ b/src/algorithms/calorimetry/CalorimeterIslandClusterConfig.h @@ -7,28 +7,27 @@ namespace eicrecon { - struct CalorimeterIslandClusterConfig { - - std::string adjacencyMatrix; - std::string readout; - - // neighbour checking distances - double sectorDist; - std::vector localDistXY; - std::vector localDistXZ; - std::vector localDistYZ; - std::vector globalDistRPhi; - std::vector globalDistEtaPhi; - std::vector dimScaledLocalDistXY; - - bool splitCluster{false}; - double minClusterHitEdep; - double minClusterCenterEdep; - - std::string transverseEnergyProfileMetric; - double transverseEnergyProfileScale; - double transverseEnergyProfileScaleUnits; - - }; - -} // eicrecon +struct CalorimeterIslandClusterConfig { + + std::string adjacencyMatrix; + std::string readout; + + // neighbour checking distances + double sectorDist; + std::vector localDistXY; + std::vector localDistXZ; + std::vector localDistYZ; + std::vector globalDistRPhi; + std::vector globalDistEtaPhi; + std::vector dimScaledLocalDistXY; + + bool splitCluster{false}; + double minClusterHitEdep; + double minClusterCenterEdep; + + std::string transverseEnergyProfileMetric; + double transverseEnergyProfileScale; + double transverseEnergyProfileScaleUnits; +}; + +} // namespace eicrecon diff --git a/src/algorithms/calorimetry/CalorimeterTruthClustering.cc b/src/algorithms/calorimetry/CalorimeterTruthClustering.cc index c02b54243b..915791222b 100644 --- a/src/algorithms/calorimetry/CalorimeterTruthClustering.cc +++ b/src/algorithms/calorimetry/CalorimeterTruthClustering.cc @@ -16,67 +16,64 @@ using namespace dd4hep; namespace eicrecon { - void CalorimeterTruthClustering::init() { } +void CalorimeterTruthClustering::init() {} +void CalorimeterTruthClustering::process(const CalorimeterTruthClustering::Input& input, + const CalorimeterTruthClustering::Output& output) const { + const auto [hits, mc] = input; + auto [clusters] = output; - void CalorimeterTruthClustering::process( - const CalorimeterTruthClustering::Input& input, - const CalorimeterTruthClustering::Output& output) const { - const auto [hits, mc] = input; - auto [clusters] = output; + // Map mc track ID to protoCluster index + std::map protoIndex; - // Map mc track ID to protoCluster index - std::map protoIndex; - - // Loop over all calorimeter hits and sort per mcparticle - for (const auto& hit : *hits) { - // The original algorithm used the following to get the mcHit: - // - // const auto& mcHit = mc[hit->getObjectID().index]; - // - // This assumes there is a one-to-one relation between the truth hit - // (hits) and the reconstructed hit (mc). At least insofar as the - // index in "hits" is being used to index the "mc" container. - // - // If the objects in "hits" have not been added to a collection, - // then they will have getObjectID().index = "untracked" = -1 - // - // The way we handle this is here is to check if getObjectID().index - // is within the size limits of mc which includes >=0. If so, then - // assume the old code is valid. If not, then we need to search - // for the right hit. - // FIXME: This is clearly not the right way to do this! Podio needs - // FIXME: to be fixed so proper object tracking can be done without - // FIXME: requiring Collection classes be used to manage all objects. - std::size_t mcIndex; - if ((hit.getObjectID().index >= 0) && (hit.getObjectID().index < mc->size())) { - mcIndex = hit.getObjectID().index; - } else { - mcIndex = 0; - bool success = false; - for (auto tmpmc : *mc) { - if (tmpmc.getCellID() == hit.getCellID()) { - success = true; - break; - } - mcIndex++; - } - if (not success) { - continue; // ignore hit if we couldn't match it to truth hit - } - } - - const auto &trackID = (*mc)[mcIndex].getContributions(0).getParticle().getObjectID().index; - // Create a new protocluster if we don't have one for this trackID - if (protoIndex.count(trackID) == 0) { - clusters->create(); - protoIndex[trackID] = clusters->size() - 1; + // Loop over all calorimeter hits and sort per mcparticle + for (const auto& hit : *hits) { + // The original algorithm used the following to get the mcHit: + // + // const auto& mcHit = mc[hit->getObjectID().index]; + // + // This assumes there is a one-to-one relation between the truth hit + // (hits) and the reconstructed hit (mc). At least insofar as the + // index in "hits" is being used to index the "mc" container. + // + // If the objects in "hits" have not been added to a collection, + // then they will have getObjectID().index = "untracked" = -1 + // + // The way we handle this is here is to check if getObjectID().index + // is within the size limits of mc which includes >=0. If so, then + // assume the old code is valid. If not, then we need to search + // for the right hit. + // FIXME: This is clearly not the right way to do this! Podio needs + // FIXME: to be fixed so proper object tracking can be done without + // FIXME: requiring Collection classes be used to manage all objects. + std::size_t mcIndex; + if ((hit.getObjectID().index >= 0) && (hit.getObjectID().index < mc->size())) { + mcIndex = hit.getObjectID().index; + } else { + mcIndex = 0; + bool success = false; + for (auto tmpmc : *mc) { + if (tmpmc.getCellID() == hit.getCellID()) { + success = true; + break; } - // Add hit to the appropriate protocluster - (*clusters)[protoIndex[trackID]].addToHits(hit); - (*clusters)[protoIndex[trackID]].addToWeights(1); + mcIndex++; + } + if (not success) { + continue; // ignore hit if we couldn't match it to truth hit + } } + const auto& trackID = (*mc)[mcIndex].getContributions(0).getParticle().getObjectID().index; + // Create a new protocluster if we don't have one for this trackID + if (protoIndex.count(trackID) == 0) { + clusters->create(); + protoIndex[trackID] = clusters->size() - 1; + } + // Add hit to the appropriate protocluster + (*clusters)[protoIndex[trackID]].addToHits(hit); + (*clusters)[protoIndex[trackID]].addToWeights(1); } +} } // namespace eicrecon diff --git a/src/algorithms/calorimetry/CalorimeterTruthClustering.h b/src/algorithms/calorimetry/CalorimeterTruthClustering.h index 845d97985d..9b61e6266b 100644 --- a/src/algorithms/calorimetry/CalorimeterTruthClustering.h +++ b/src/algorithms/calorimetry/CalorimeterTruthClustering.h @@ -13,30 +13,22 @@ namespace eicrecon { - using CalorimeterTruthClusteringAlgorithm = algorithms::Algorithm< - algorithms::Input< - edm4eic::CalorimeterHitCollection, - edm4hep::SimCalorimeterHitCollection - >, - algorithms::Output< - edm4eic::ProtoClusterCollection - > - >; - - class CalorimeterTruthClustering - : public CalorimeterTruthClusteringAlgorithm { - - public: - CalorimeterTruthClustering(std::string_view name) - : CalorimeterTruthClusteringAlgorithm{name, - {"inputHitCollection", "inputSimHitCollection"}, - {"outputProtoClusterCollection"}, - "Use truth information for clustering."} {} +using CalorimeterTruthClusteringAlgorithm = algorithms::Algorithm< + algorithms::Input, + algorithms::Output>; - public: - void init() final; - void process(const Input&, const Output&) const final; +class CalorimeterTruthClustering : public CalorimeterTruthClusteringAlgorithm { - }; +public: + CalorimeterTruthClustering(std::string_view name) + : CalorimeterTruthClusteringAlgorithm{name, + {"inputHitCollection", "inputSimHitCollection"}, + {"outputProtoClusterCollection"}, + "Use truth information for clustering."} {} + +public: + void init() final; + void process(const Input&, const Output&) const final; +}; } // namespace eicrecon diff --git a/src/algorithms/calorimetry/EnergyPositionClusterMerger.h b/src/algorithms/calorimetry/EnergyPositionClusterMerger.h index a7eb1565a1..771de5c692 100644 --- a/src/algorithms/calorimetry/EnergyPositionClusterMerger.h +++ b/src/algorithms/calorimetry/EnergyPositionClusterMerger.h @@ -17,20 +17,14 @@ namespace eicrecon { - using EnergyPositionClusterMergerAlgorithm = algorithms::Algorithm< +using EnergyPositionClusterMergerAlgorithm = algorithms::Algorithm< algorithms::Input< - edm4eic::ClusterCollection, - edm4eic::MCRecoClusterParticleAssociationCollection, - edm4eic::ClusterCollection, - edm4eic::MCRecoClusterParticleAssociationCollection - >, - algorithms::Output< - edm4eic::ClusterCollection, - edm4eic::MCRecoClusterParticleAssociationCollection - > - >; - - /** Simple algorithm to merge the energy measurement from cluster1 with the position + edm4eic::ClusterCollection, edm4eic::MCRecoClusterParticleAssociationCollection, + edm4eic::ClusterCollection, edm4eic::MCRecoClusterParticleAssociationCollection>, + algorithms::Output>; + +/** Simple algorithm to merge the energy measurement from cluster1 with the position * measurement of cluster2 (in case matching clusters are found). If not, it will * propagate the raw cluster from cluster1 or cluster2 * @@ -42,180 +36,181 @@ namespace eicrecon { * * \ingroup reco */ - class EnergyPositionClusterMerger - : public EnergyPositionClusterMergerAlgorithm, - public WithPodConfig { +class EnergyPositionClusterMerger : public EnergyPositionClusterMergerAlgorithm, + public WithPodConfig { - public: - EnergyPositionClusterMerger(std::string_view name) - : EnergyPositionClusterMergerAlgorithm{name, - {"energyClusterCollection", "energyClusterAssociations", - "positionClusterCollection", "positionClusterAssociations"}, - {"outputClusterCollection", "outputClusterAssociations"}, - "Merge energy and position clusters if matching."} {} +public: + EnergyPositionClusterMerger(std::string_view name) + : EnergyPositionClusterMergerAlgorithm{ + name, + {"energyClusterCollection", "energyClusterAssociations", "positionClusterCollection", + "positionClusterAssociations"}, + {"outputClusterCollection", "outputClusterAssociations"}, + "Merge energy and position clusters if matching."} {} - public: +public: + void init() {} - void init() { } + void process(const Input& input, const Output& output) const final { - void process(const Input& input, const Output& output) const final { + const auto [energy_clus, energy_assoc, pos_clus, pos_assoc] = input; + auto [merged_clus, merged_assoc] = output; - const auto [energy_clus, energy_assoc, pos_clus, pos_assoc] = input; - auto [merged_clus, merged_assoc] = output; + debug("Merging energy and position clusters for new event"); - debug( "Merging energy and position clusters for new event" ); + if (energy_clus->size() == 0 && pos_clus->size() == 0) { + debug("Nothing to do for this event, returning..."); + return; + } - if (energy_clus->size() == 0 && pos_clus->size() == 0) { - debug( "Nothing to do for this event, returning..." ); - return; - } + std::vector consumed(energy_clus->size(), false); - std::vector consumed(energy_clus->size(), false); - - // use position clusters as starting point - for (const auto& pc : *pos_clus) { - - trace(" --> Processing position cluster {}, energy: {}", pc.getObjectID().index, pc.getEnergy()); - - // check if we find a good match - int best_match = -1; - double best_delta = std::numeric_limits::max(); - for (size_t ie = 0; ie < energy_clus->size(); ++ie) { - if (consumed[ie]) { - continue; - } - - const auto& ec = (*energy_clus)[ie]; - - trace(" --> Evaluating energy cluster {}, energy: {}", ec.getObjectID().index, ec.getEnergy()); - - // 1. stop if not within tolerance - // (make sure to handle rollover of phi properly) - const double de_rel = std::abs((pc.getEnergy() - ec.getEnergy()) / ec.getEnergy()); - const double deta = std::abs(edm4hep::utils::eta(pc.getPosition()) - - edm4hep::utils::eta(ec.getPosition())); - // check the tolerance for sin(dphi/2) to avoid the hemisphere problem and allow - // for phi rollovers - const double dphi = edm4hep::utils::angleAzimuthal(pc.getPosition()) - - edm4hep::utils::angleAzimuthal(ec.getPosition()); - const double dsphi = std::abs(sin(0.5 * dphi)); - if ((m_cfg.energyRelTolerance > 0 && de_rel > m_cfg.energyRelTolerance) || - (m_cfg.etaTolerance > 0 && deta > m_cfg.etaTolerance) || - (m_cfg.phiTolerance > 0 && dsphi > sin(0.5 * m_cfg.phiTolerance))) { - continue; - } - // --> if we get here, we have a match within tolerance. Now treat the case - // where we have multiple matches. In this case take the one with the closest - // energies. - // 2. best match? - const double delta = fabs(pc.getEnergy() - ec.getEnergy()); - if (delta < best_delta) { - best_delta = delta; - best_match = ie; - } - } + // use position clusters as starting point + for (const auto& pc : *pos_clus) { - // Create a merged cluster if we find a good match - if (best_match >= 0) { - - const auto& ec = (*energy_clus)[best_match]; - - auto new_clus = merged_clus->create(); - new_clus.setEnergy(ec.getEnergy()); - new_clus.setEnergyError(ec.getEnergyError()); - new_clus.setTime(pc.getTime()); - new_clus.setNhits(pc.getNhits() + ec.getNhits()); - new_clus.setPosition(pc.getPosition()); - new_clus.setPositionError(pc.getPositionError()); - new_clus.addToClusters(pc); - new_clus.addToClusters(ec); - - trace(" --> Found matching energy cluster {}, energy: {}", ec.getObjectID().index, ec.getEnergy() ); - trace(" --> Created a new combined cluster {}, energy: {}", new_clus.getObjectID().index, new_clus.getEnergy() ); - - // find association from energy cluster - auto ea = energy_assoc->begin(); - for (; ea != energy_assoc->end(); ++ea) { - if (ea->getRec() == ec) { - break; - } - } - // find association from position cluster if different - auto pa = pos_assoc->begin(); - for (; pa != pos_assoc->end(); ++pa) { - if (pa->getRec() == pc) { - break; - } - } - if (ea != energy_assoc->end() || pa != pos_assoc->end()) { - // we must write an association - if (ea != energy_assoc->end() && pa != pos_assoc->end()) { - // we have two associations - if (pa->getSimID() == ea->getSimID()) { - // both associations agree on the MCParticles entry - auto clusterassoc = merged_assoc->create(); - clusterassoc.setRecID(new_clus.getObjectID().index); - clusterassoc.setSimID(ea->getSimID()); - clusterassoc.setWeight(1.0); - clusterassoc.setRec(new_clus); - clusterassoc.setSim(ea->getSim()); - } else { - // both associations disagree on the MCParticles entry - debug(" --> Two associations added to {} and {}", ea->getSimID(), pa->getSimID()); - auto clusterassoc1 = merged_assoc->create(); - clusterassoc1.setRecID(new_clus.getObjectID().index); - clusterassoc1.setSimID(ea->getSimID()); - clusterassoc1.setWeight(0.5); - clusterassoc1.setRec(new_clus); - clusterassoc1.setSim(ea->getSim()); - auto clusterassoc2 = merged_assoc->create(); - clusterassoc2.setRecID(new_clus.getObjectID().index); - clusterassoc2.setSimID(pa->getSimID()); - clusterassoc2.setWeight(0.5); - clusterassoc2.setRec(new_clus); - clusterassoc2.setSim(pa->getSim()); - } - } else if (ea != energy_assoc->end()) { - // no position association - debug(" --> Only added energy cluster association to {}", ea->getSimID()); - auto clusterassoc = merged_assoc->create(); - clusterassoc.setRecID(new_clus.getObjectID().index); - clusterassoc.setSimID(ea->getSimID()); - clusterassoc.setWeight(1.0); - clusterassoc.setRec(new_clus); - clusterassoc.setSim(ea->getSim()); - } else if (pa != pos_assoc->end()) { - // no energy association - debug(" --> Only added position cluster association to {}", pa->getSimID()); - auto clusterassoc = merged_assoc->create(); - clusterassoc.setRecID(new_clus.getObjectID().index); - clusterassoc.setSimID(pa->getSimID()); - clusterassoc.setWeight(1.0); - clusterassoc.setRec(new_clus); - clusterassoc.setSim(pa->getSim()); - } - } - - // label our energy cluster as consumed - consumed[best_match] = true; - - debug(" Matched position cluster {} with energy cluster {}", pc.getObjectID().index, ec.getObjectID().index); - debug(" - Position cluster: (E: {}, phi: {}, z: {})", pc.getEnergy(), - edm4hep::utils::angleAzimuthal(pc.getPosition()), pc.getPosition().z); - debug(" - Energy cluster: (E: {}, phi: {}, z: {})", ec.getEnergy(), - edm4hep::utils::angleAzimuthal(ec.getPosition()), ec.getPosition().z); - debug(" ---> Merged cluster: (E: {}, phi: {}, z: {})", new_clus.getEnergy(), - edm4hep::utils::angleAzimuthal(new_clus.getPosition()), new_clus.getPosition().z); + trace(" --> Processing position cluster {}, energy: {}", pc.getObjectID().index, + pc.getEnergy()); + // check if we find a good match + int best_match = -1; + double best_delta = std::numeric_limits::max(); + for (size_t ie = 0; ie < energy_clus->size(); ++ie) { + if (consumed[ie]) { + continue; + } + const auto& ec = (*energy_clus)[ie]; + + trace(" --> Evaluating energy cluster {}, energy: {}", ec.getObjectID().index, + ec.getEnergy()); + + // 1. stop if not within tolerance + // (make sure to handle rollover of phi properly) + const double de_rel = std::abs((pc.getEnergy() - ec.getEnergy()) / ec.getEnergy()); + const double deta = + std::abs(edm4hep::utils::eta(pc.getPosition()) - edm4hep::utils::eta(ec.getPosition())); + // check the tolerance for sin(dphi/2) to avoid the hemisphere problem and allow + // for phi rollovers + const double dphi = edm4hep::utils::angleAzimuthal(pc.getPosition()) - + edm4hep::utils::angleAzimuthal(ec.getPosition()); + const double dsphi = std::abs(sin(0.5 * dphi)); + if ((m_cfg.energyRelTolerance > 0 && de_rel > m_cfg.energyRelTolerance) || + (m_cfg.etaTolerance > 0 && deta > m_cfg.etaTolerance) || + (m_cfg.phiTolerance > 0 && dsphi > sin(0.5 * m_cfg.phiTolerance))) { + continue; + } + // --> if we get here, we have a match within tolerance. Now treat the case + // where we have multiple matches. In this case take the one with the closest + // energies. + // 2. best match? + const double delta = fabs(pc.getEnergy() - ec.getEnergy()); + if (delta < best_delta) { + best_delta = delta; + best_match = ie; + } + } + + // Create a merged cluster if we find a good match + if (best_match >= 0) { + + const auto& ec = (*energy_clus)[best_match]; + + auto new_clus = merged_clus->create(); + new_clus.setEnergy(ec.getEnergy()); + new_clus.setEnergyError(ec.getEnergyError()); + new_clus.setTime(pc.getTime()); + new_clus.setNhits(pc.getNhits() + ec.getNhits()); + new_clus.setPosition(pc.getPosition()); + new_clus.setPositionError(pc.getPositionError()); + new_clus.addToClusters(pc); + new_clus.addToClusters(ec); + + trace(" --> Found matching energy cluster {}, energy: {}", ec.getObjectID().index, + ec.getEnergy()); + trace(" --> Created a new combined cluster {}, energy: {}", new_clus.getObjectID().index, + new_clus.getEnergy()); + + // find association from energy cluster + auto ea = energy_assoc->begin(); + for (; ea != energy_assoc->end(); ++ea) { + if (ea->getRec() == ec) { + break; + } + } + // find association from position cluster if different + auto pa = pos_assoc->begin(); + for (; pa != pos_assoc->end(); ++pa) { + if (pa->getRec() == pc) { + break; + } + } + if (ea != energy_assoc->end() || pa != pos_assoc->end()) { + // we must write an association + if (ea != energy_assoc->end() && pa != pos_assoc->end()) { + // we have two associations + if (pa->getSimID() == ea->getSimID()) { + // both associations agree on the MCParticles entry + auto clusterassoc = merged_assoc->create(); + clusterassoc.setRecID(new_clus.getObjectID().index); + clusterassoc.setSimID(ea->getSimID()); + clusterassoc.setWeight(1.0); + clusterassoc.setRec(new_clus); + clusterassoc.setSim(ea->getSim()); } else { + // both associations disagree on the MCParticles entry + debug(" --> Two associations added to {} and {}", ea->getSimID(), pa->getSimID()); + auto clusterassoc1 = merged_assoc->create(); + clusterassoc1.setRecID(new_clus.getObjectID().index); + clusterassoc1.setSimID(ea->getSimID()); + clusterassoc1.setWeight(0.5); + clusterassoc1.setRec(new_clus); + clusterassoc1.setSim(ea->getSim()); + auto clusterassoc2 = merged_assoc->create(); + clusterassoc2.setRecID(new_clus.getObjectID().index); + clusterassoc2.setSimID(pa->getSimID()); + clusterassoc2.setWeight(0.5); + clusterassoc2.setRec(new_clus); + clusterassoc2.setSim(pa->getSim()); + } + } else if (ea != energy_assoc->end()) { + // no position association + debug(" --> Only added energy cluster association to {}", ea->getSimID()); + auto clusterassoc = merged_assoc->create(); + clusterassoc.setRecID(new_clus.getObjectID().index); + clusterassoc.setSimID(ea->getSimID()); + clusterassoc.setWeight(1.0); + clusterassoc.setRec(new_clus); + clusterassoc.setSim(ea->getSim()); + } else if (pa != pos_assoc->end()) { + // no energy association + debug(" --> Only added position cluster association to {}", pa->getSimID()); + auto clusterassoc = merged_assoc->create(); + clusterassoc.setRecID(new_clus.getObjectID().index); + clusterassoc.setSimID(pa->getSimID()); + clusterassoc.setWeight(1.0); + clusterassoc.setRec(new_clus); + clusterassoc.setSim(pa->getSim()); + } + } - debug(" Unmatched position cluster {}", pc.getObjectID().index); + // label our energy cluster as consumed + consumed[best_match] = true; - } + debug(" Matched position cluster {} with energy cluster {}", pc.getObjectID().index, + ec.getObjectID().index); + debug(" - Position cluster: (E: {}, phi: {}, z: {})", pc.getEnergy(), + edm4hep::utils::angleAzimuthal(pc.getPosition()), pc.getPosition().z); + debug(" - Energy cluster: (E: {}, phi: {}, z: {})", ec.getEnergy(), + edm4hep::utils::angleAzimuthal(ec.getPosition()), ec.getPosition().z); + debug(" ---> Merged cluster: (E: {}, phi: {}, z: {})", new_clus.getEnergy(), + edm4hep::utils::angleAzimuthal(new_clus.getPosition()), new_clus.getPosition().z); - } + } else { + + debug(" Unmatched position cluster {}", pc.getObjectID().index); + } } - }; + } +}; } // namespace eicrecon diff --git a/src/algorithms/calorimetry/EnergyPositionClusterMergerConfig.h b/src/algorithms/calorimetry/EnergyPositionClusterMergerConfig.h index 95a3d75703..32a8464d5a 100644 --- a/src/algorithms/calorimetry/EnergyPositionClusterMergerConfig.h +++ b/src/algorithms/calorimetry/EnergyPositionClusterMergerConfig.h @@ -5,12 +5,11 @@ namespace eicrecon { - struct EnergyPositionClusterMergerConfig { +struct EnergyPositionClusterMergerConfig { - double energyRelTolerance{0.5}; - double phiTolerance{0.1}; - double etaTolerance{0.2}; + double energyRelTolerance{0.5}; + double phiTolerance{0.1}; + double etaTolerance{0.2}; +}; - }; - -} // eicrecon +} // namespace eicrecon diff --git a/src/algorithms/calorimetry/HEXPLIT.cc b/src/algorithms/calorimetry/HEXPLIT.cc index 498af96847..6752252402 100644 --- a/src/algorithms/calorimetry/HEXPLIT.cc +++ b/src/algorithms/calorimetry/HEXPLIT.cc @@ -15,7 +15,7 @@ #include #include #include -#include // for not_null +#include // for not_null #include #include "HEXPLIT.h" @@ -24,124 +24,127 @@ namespace eicrecon { //positions where the overlapping cells are relative to a given cell (in units of hexagon side length) -const std::vector HEXPLIT::neighbor_offsets_x =[]() { +const std::vector HEXPLIT::neighbor_offsets_x = []() { std::vector x; - double rs[2] ={1.5, sqrt(3)/2.}; - double offsets[2]={0, M_PI/2}; - for (int i = 0; i<2; i++){ + double rs[2] = {1.5, sqrt(3) / 2.}; + double offsets[2] = {0, M_PI / 2}; + for (int i = 0; i < 2; i++) { for (int j = 0; j < 6; j += 1) - x.push_back(rs[i]*cos(j*M_PI/3+offsets[i])); + x.push_back(rs[i] * cos(j * M_PI / 3 + offsets[i])); } return x; }(); -const std::vector HEXPLIT::neighbor_offsets_y =[]() { +const std::vector HEXPLIT::neighbor_offsets_y = []() { std::vector y; - double rs[2] ={1.5, sqrt(3)/2.}; - double offsets[2]={0, M_PI/2}; - for (int i = 0; i<2; i++){ + double rs[2] = {1.5, sqrt(3) / 2.}; + double offsets[2] = {0, M_PI / 2}; + for (int i = 0; i < 2; i++) { for (int j = 0; j < 6; j += 1) - y.push_back(rs[i]*sin(j*M_PI/3+offsets[i])); + y.push_back(rs[i] * sin(j * M_PI / 3 + offsets[i])); } return y; }(); //indices of the neighboring cells which overlap to produce a given subcell -const int HEXPLIT::neighbor_indices[SUBCELLS][OVERLAP]={{0, 11,10}, {1, 6, 11},{2, 7, 6}, {3,8,7}, {4,9,8}, {5,10,9}, - {6, 11, 7}, {7, 6, 8}, {8, 7, 9}, {9,8,10},{10,9,11},{11,10,6}}; +const int HEXPLIT::neighbor_indices[SUBCELLS][OVERLAP] = { + {0, 11, 10}, {1, 6, 11}, {2, 7, 6}, {3, 8, 7}, {4, 9, 8}, {5, 10, 9}, + {6, 11, 7}, {7, 6, 8}, {8, 7, 9}, {9, 8, 10}, {10, 9, 11}, {11, 10, 6}}; //positions of the centers of subcells -const std::vector HEXPLIT::subcell_offsets_x =[]() { +const std::vector HEXPLIT::subcell_offsets_x = []() { std::vector x; - double rs[2] ={0.75, sqrt(3)/4.}; - double offsets[2]={0, M_PI/2}; - for (int i = 0; i<2; i++){ - for (int j = 0; j < 6; j += 1) - x.push_back(rs[i]*cos(j*M_PI/3+offsets[i])); + double rs[2] = {0.75, sqrt(3) / 4.}; + double offsets[2] = {0, M_PI / 2}; + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 6; j += 1) + x.push_back(rs[i] * cos(j * M_PI / 3 + offsets[i])); } return x; }(); -const std::vector HEXPLIT::subcell_offsets_y =[]() { +const std::vector HEXPLIT::subcell_offsets_y = []() { std::vector y; - double rs[2] ={0.75, sqrt(3)/4.}; - double offsets[2]={0, M_PI/2}; - for (int i = 0; i<2; i++){ + double rs[2] = {0.75, sqrt(3) / 4.}; + double offsets[2] = {0, M_PI / 2}; + for (int i = 0; i < 2; i++) { for (int j = 0; j < 6; j += 1) - y.push_back(rs[i]*sin(j*M_PI/3+offsets[i])); + y.push_back(rs[i] * sin(j * M_PI / 3 + offsets[i])); } return y; }(); -void HEXPLIT::init() { } +void HEXPLIT::init() {} -void HEXPLIT::process(const HEXPLIT::Input& input, - const HEXPLIT::Output& output) const { +void HEXPLIT::process(const HEXPLIT::Input& input, const HEXPLIT::Output& output) const { - const auto [hits] = input; + const auto [hits] = input; auto [subcellHits] = output; - double MIP=m_cfg.MIP/dd4hep::GeV; - double Emin=m_cfg.Emin_in_MIPs*MIP; - double tmax=m_cfg.tmax/dd4hep::ns; + double MIP = m_cfg.MIP / dd4hep::GeV; + double Emin = m_cfg.Emin_in_MIPs * MIP; + double tmax = m_cfg.tmax / dd4hep::ns; auto volman = m_detector->volumeManager(); - for(const auto& hit : *hits){ + for (const auto& hit : *hits) { //skip hits that do not pass E and t cuts - if (hit.getEnergy()tmax) + if (hit.getEnergy() < Emin || hit.getTime() > tmax) continue; //keep track of the energy in each neighboring cell std::vector Eneighbors(NEIGHBORS, 0.0); - double sl = hit.getDimension().x/2.; - for (const auto& other_hit : *hits){ + double sl = hit.getDimension().x / 2.; + for (const auto& other_hit : *hits) { // maximum distance between where the neighboring cell is and where it should be // based on an ideal geometry using the staggered tessellation pattern. // Deviations could arise from rounding errors or from detector misalignment. - double tol=0.1; // in units of side lengths. + double tol = 0.1; // in units of side lengths. //only look at hits nearby within two layers of the current layer - int dz=abs(hit.getLayer()-other_hit.getLayer()); - if (dz>2 || dz==0) + int dz = abs(hit.getLayer() - other_hit.getLayer()); + if (dz > 2 || dz == 0) continue; - if (other_hit.getEnergy()tmax) + if (other_hit.getEnergy() < Emin || other_hit.getTime() > tmax) continue; //difference in transverse position (in units of side lengths) - double dx=(other_hit.getLocal().x-hit.getLocal().x)/sl; - double dy=(other_hit.getLocal().y-hit.getLocal().y)/sl; - if (abs(dx)>2 || abs(dy)>sqrt(3)) + double dx = (other_hit.getLocal().x - hit.getLocal().x) / sl; + double dy = (other_hit.getLocal().y - hit.getLocal().y) / sl; + if (abs(dx) > 2 || abs(dy) > sqrt(3)) continue; //loop over locations of the neighboring cells //and check if the jth hit matches this location - for(int k=0;k(global_position.X()/dd4hep::mm), static_cast(global_position.Y()/dd4hep::mm), static_cast(global_position.Z()/dd4hep::mm)}; + const decltype(edm4eic::CalorimeterHitData::position) position = { + static_cast(global_position.X() / dd4hep::mm), + static_cast(global_position.Y() / dd4hep::mm), + static_cast(global_position.Z() / dd4hep::mm)}; //bounding box dimensions depend on the orientation of the rhombus - int orientation = k%3==0; - const decltype(edm4eic::CalorimeterHitData::dimension) dimension(sl*(orientation?1:1.5), sl*sqrt(3)/2.*(orientation?2:1), - hit.getDimension()[2]); - - subcellHits->create( - hit.getCellID(), - hit.getEnergy()*weights[k]/sum_weights, - 0, - hit.getTime(), - 0, - position, - dimension, - hit.getSector(), - hit.getLayer(), - local); + int orientation = k % 3 == 0; + const decltype(edm4eic::CalorimeterHitData::dimension) dimension( + sl * (orientation ? 1 : 1.5), sl * sqrt(3) / 2. * (orientation ? 2 : 1), + hit.getDimension()[2]); + + subcellHits->create(hit.getCellID(), hit.getEnergy() * weights[k] / sum_weights, 0, + hit.getTime(), 0, position, dimension, hit.getSector(), hit.getLayer(), + local); } } } - } // namespace eicrecon diff --git a/src/algorithms/calorimetry/HEXPLIT.h b/src/algorithms/calorimetry/HEXPLIT.h index 04910c897e..56392811e6 100644 --- a/src/algorithms/calorimetry/HEXPLIT.h +++ b/src/algorithms/calorimetry/HEXPLIT.h @@ -14,8 +14,8 @@ #include #include #include -#include // for basic_string -#include // for string_view +#include // for basic_string +#include // for string_view #include #include "HEXPLITConfig.h" @@ -23,48 +23,38 @@ namespace eicrecon { -using HEXPLITAlgorithm = algorithms::Algorithm< - algorithms::Input< - const edm4eic::CalorimeterHitCollection - >, - algorithms::Output< - edm4eic::CalorimeterHitCollection - > - >; +using HEXPLITAlgorithm = + algorithms::Algorithm, + algorithms::Output>; - class HEXPLIT - : public HEXPLITAlgorithm, - public WithPodConfig { +class HEXPLIT : public HEXPLITAlgorithm, public WithPodConfig { - public: - HEXPLIT(std::string_view name) - : HEXPLITAlgorithm{name, - {"inputHits"}, - {"outputSubcellHits"}, - "Split hits into subcell hits"} {} +public: + HEXPLIT(std::string_view name) + : HEXPLITAlgorithm{ + name, {"inputHits"}, {"outputSubcellHits"}, "Split hits into subcell hits"} {} - void init() final; - void process(const Input&, const Output&) const final; + void init() final; + void process(const Input&, const Output&) const final; - private: - // number of subcells that a single cell is divided into - static const int SUBCELLS=12; - // number of neighboring positions whose overlap define the subcells - static const int NEIGHBORS=12; - // number of neighboring cells that overlap to obtain a subcell - static const int OVERLAP=3; +private: + // number of subcells that a single cell is divided into + static const int SUBCELLS = 12; + // number of neighboring positions whose overlap define the subcells + static const int NEIGHBORS = 12; + // number of neighboring cells that overlap to obtain a subcell + static const int OVERLAP = 3; //positions where the overlapping cells are relative to a given cell (in units of hexagon side length) - static const std::vector neighbor_offsets_x; - static const std::vector neighbor_offsets_y; - //indices of the neighboring cells which overlap to produce a given subcell - static const int neighbor_indices[SUBCELLS][OVERLAP]; + static const std::vector neighbor_offsets_x; + static const std::vector neighbor_offsets_y; + //indices of the neighboring cells which overlap to produce a given subcell + static const int neighbor_indices[SUBCELLS][OVERLAP]; //positions of the centers of subcells - static const std::vector subcell_offsets_x; - static const std::vector subcell_offsets_y; + static const std::vector subcell_offsets_x; + static const std::vector subcell_offsets_y; - private: - const dd4hep::Detector* m_detector{algorithms::GeoSvc::instance().detector()}; - - }; +private: + const dd4hep::Detector* m_detector{algorithms::GeoSvc::instance().detector()}; +}; } // namespace eicrecon diff --git a/src/algorithms/calorimetry/HEXPLITConfig.h b/src/algorithms/calorimetry/HEXPLITConfig.h index 1e2d0d1c72..c783e46691 100644 --- a/src/algorithms/calorimetry/HEXPLITConfig.h +++ b/src/algorithms/calorimetry/HEXPLITConfig.h @@ -5,10 +5,10 @@ namespace eicrecon { - struct HEXPLITConfig { - double MIP{472.*dd4hep::keV}; - double Emin_in_MIPs{0.1}; - double tmax{325*dd4hep::ns}; - }; +struct HEXPLITConfig { + double MIP{472. * dd4hep::keV}; + double Emin_in_MIPs{0.1}; + double tmax{325 * dd4hep::ns}; +}; -} // eicrecon +} // namespace eicrecon diff --git a/src/algorithms/calorimetry/ImagingClusterReco.h b/src/algorithms/calorimetry/ImagingClusterReco.h index 17db216db0..deb2f5ad31 100644 --- a/src/algorithms/calorimetry/ImagingClusterReco.h +++ b/src/algorithms/calorimetry/ImagingClusterReco.h @@ -33,275 +33,266 @@ namespace eicrecon { - using ImagingClusterRecoAlgorithm = algorithms::Algorithm< - algorithms::Input< - edm4eic::ProtoClusterCollection, - edm4hep::SimCalorimeterHitCollection - >, - algorithms::Output< - edm4eic::ClusterCollection, - edm4eic::MCRecoClusterParticleAssociationCollection, - edm4eic::ClusterCollection - > - >; - - /** Imaging cluster reconstruction. +using ImagingClusterRecoAlgorithm = algorithms::Algorithm< + algorithms::Input, + algorithms::Output>; + +/** Imaging cluster reconstruction. * * Reconstruct the cluster/layer info for imaging calorimeter * Logarithmic weighting is used to describe energy deposit in transverse direction * * \ingroup reco */ - class ImagingClusterReco - : public ImagingClusterRecoAlgorithm, - public WithPodConfig { - - public: - ImagingClusterReco(std::string_view name) - : ImagingClusterRecoAlgorithm{name, - {"inputProtoClusterCollection", "mcHits"}, - {"outputClusterCollection", "outputClusterAssociations", "outputLayerCollection"}, - "Reconstruct the cluster/layer info for imaging calorimeter."} {} - - public: - - void init() { } - - void process(const Input& input, const Output& output) const final { - - const auto [proto, mchits] = input; - auto [clusters, associations, layers] = output; - - for (const auto& pcl: *proto) { - if (!pcl.getHits().empty() && !pcl.getHits(0).isAvailable()) { - warning("Protocluster hit relation is invalid, skipping protocluster"); - continue; - } - // get cluster and associated layers - auto cl = reconstruct_cluster(pcl); - auto cl_layers = reconstruct_cluster_layers(pcl); - - // Get cluster direction from the layer profile - auto [theta, phi] = fit_track(cl_layers); - cl.setIntrinsicTheta(theta); - cl.setIntrinsicPhi(phi); - // no error on the intrinsic direction TODO - - // store layer and clusters on the datastore - for (const auto& layer: cl_layers) { - layers->push_back(layer); - cl.addToClusters(layer); - } - clusters->push_back(cl); - - // If mcHits are available, associate cluster with MCParticle - if (mchits->size() > 0) { - - // 1. find pclhit with the largest energy deposition - auto pclhits = pcl.getHits(); - auto pclhit = std::max_element( - pclhits.begin(), - pclhits.end(), - [](const auto &pclhit1, const auto &pclhit2) { - return pclhit1.getEnergy() < pclhit2.getEnergy(); - } - ); - - // 2. find mchit with same CellID - const edm4hep::SimCalorimeterHit* mchit = nullptr; - for (auto h : *mchits) { - if (h.getCellID() == pclhit->getCellID()) { - mchit = &h; - break; - } - } - if( !mchit ){ - // break if no matching hit found for this CellID - warning("Proto-cluster has highest energy in CellID {}, but no mc hit with that CellID was found.", pclhit->getCellID()); - break; - } - - // 3. find mchit's MCParticle - const auto &mcp = mchit->getContributions(0).getParticle(); - - // set association - auto clusterassoc = associations->create(); - clusterassoc.setRecID(cl.getObjectID().index); - clusterassoc.setSimID(mcp.getObjectID().index); - clusterassoc.setWeight(1.0); - clusterassoc.setRec(cl); - clusterassoc.setSim(mcp); - } - +class ImagingClusterReco : public ImagingClusterRecoAlgorithm, + public WithPodConfig { + +public: + ImagingClusterReco(std::string_view name) + : ImagingClusterRecoAlgorithm{ + name, + {"inputProtoClusterCollection", "mcHits"}, + {"outputClusterCollection", "outputClusterAssociations", "outputLayerCollection"}, + "Reconstruct the cluster/layer info for imaging calorimeter."} {} + +public: + void init() {} + + void process(const Input& input, const Output& output) const final { + + const auto [proto, mchits] = input; + auto [clusters, associations, layers] = output; + + for (const auto& pcl : *proto) { + if (!pcl.getHits().empty() && !pcl.getHits(0).isAvailable()) { + warning("Protocluster hit relation is invalid, skipping protocluster"); + continue; + } + // get cluster and associated layers + auto cl = reconstruct_cluster(pcl); + auto cl_layers = reconstruct_cluster_layers(pcl); + + // Get cluster direction from the layer profile + auto [theta, phi] = fit_track(cl_layers); + cl.setIntrinsicTheta(theta); + cl.setIntrinsicPhi(phi); + // no error on the intrinsic direction TODO + + // store layer and clusters on the datastore + for (const auto& layer : cl_layers) { + layers->push_back(layer); + cl.addToClusters(layer); + } + clusters->push_back(cl); + + // If mcHits are available, associate cluster with MCParticle + if (mchits->size() > 0) { + + // 1. find pclhit with the largest energy deposition + auto pclhits = pcl.getHits(); + auto pclhit = std::max_element(pclhits.begin(), pclhits.end(), + [](const auto& pclhit1, const auto& pclhit2) { + return pclhit1.getEnergy() < pclhit2.getEnergy(); + }); + + // 2. find mchit with same CellID + const edm4hep::SimCalorimeterHit* mchit = nullptr; + for (auto h : *mchits) { + if (h.getCellID() == pclhit->getCellID()) { + mchit = &h; + break; + } } - - // debug output - for (const auto& cl: *clusters) { - debug("Cluster {:d}: Edep = {:.3f} MeV, Dir = ({:.3f}, {:.3f}) deg", cl.getObjectID().index, - cl.getEnergy() * 1000., cl.getIntrinsicTheta() / M_PI * 180., - cl.getIntrinsicPhi() / M_PI * 180. - ); + if (!mchit) { + // break if no matching hit found for this CellID + warning("Proto-cluster has highest energy in CellID {}, but no mc hit with that CellID " + "was found.", + pclhit->getCellID()); + break; } - } - private: - - static std::vector reconstruct_cluster_layers(const edm4eic::ProtoCluster& pcl) { - const auto& hits = pcl.getHits(); - const auto& weights = pcl.getWeights(); - // using map to have hits sorted by layer - std::map>> layer_map; - for (unsigned i = 0; i < hits.size(); ++i) { - const auto hit = hits[i]; - auto lid = hit.getLayer(); -// if (layer_map.count(lid) == 0) { -// std::vector> v; -// layer_map[lid] = {}; -// } - layer_map[lid].push_back({hit, weights[i]}); - } - - // create layers - std::vector cl_layers; - for (const auto &[lid, layer_hits]: layer_map) { - auto layer = reconstruct_layer(layer_hits); - cl_layers.push_back(layer); - } - return cl_layers; + // 3. find mchit's MCParticle + const auto& mcp = mchit->getContributions(0).getParticle(); + + // set association + auto clusterassoc = associations->create(); + clusterassoc.setRecID(cl.getObjectID().index); + clusterassoc.setSimID(mcp.getObjectID().index); + clusterassoc.setWeight(1.0); + clusterassoc.setRec(cl); + clusterassoc.setSim(mcp); + } } - static edm4eic::Cluster reconstruct_layer(const std::vector>& hits) { - edm4eic::MutableCluster layer; - layer.setType(Jug::Reco::ClusterType::kClusterSlice); - // Calculate averages - double energy{0}; - double energyError{0}; - double time{0}; - double timeError{0}; - double sumOfWeights{0}; - auto pos = layer.getPosition(); - for (const auto &[hit, weight]: hits) { - energy += hit.getEnergy() * weight; - energyError += std::pow(hit.getEnergyError() * weight, 2); - time += hit.getTime() * weight; - timeError += std::pow(hit.getTimeError() * weight, 2); - pos = pos + hit.getPosition() * weight; - sumOfWeights += weight; - layer.addToHits(hit); - } - layer.setEnergy(energy); - layer.setEnergyError(std::sqrt(energyError)); - layer.setTime(time / sumOfWeights); - layer.setTimeError(std::sqrt(timeError) / sumOfWeights); - layer.setNhits(hits.size()); - layer.setPosition(pos / sumOfWeights); - // positionError not set - // Intrinsic direction meaningless in a cluster layer --> not set - - // Calculate radius as the standard deviation of the hits versus the cluster center - double radius = 0.; - for (const auto &[hit, weight]: hits) { - radius += std::pow(edm4hep::utils::magnitude(hit.getPosition() - layer.getPosition()), 2); - } - layer.addToShapeParameters(std::sqrt(radius / layer.getNhits())); - // TODO Skewedness - - return layer; + // debug output + for (const auto& cl : *clusters) { + debug("Cluster {:d}: Edep = {:.3f} MeV, Dir = ({:.3f}, {:.3f}) deg", cl.getObjectID().index, + cl.getEnergy() * 1000., cl.getIntrinsicTheta() / M_PI * 180., + cl.getIntrinsicPhi() / M_PI * 180.); } - - static edm4eic::MutableCluster reconstruct_cluster(const edm4eic::ProtoCluster& pcl) { - edm4eic::MutableCluster cluster; - - const auto& hits = pcl.getHits(); - const auto& weights = pcl.getWeights(); - - cluster.setType(Jug::Reco::ClusterType::kCluster3D); - double energy = 0.; - double energyError = 0.; - double time = 0.; - double timeError = 0.; - double meta = 0.; - double mphi = 0.; - double r = 9999 * dd4hep::cm; - for (unsigned i = 0; i < hits.size(); ++i) { - const auto &hit = hits[i]; - const auto &weight = weights[i]; - energy += hit.getEnergy() * weight; - energyError += std::pow(hit.getEnergyError() * weight, 2); - // energy weighting for the other variables - const double energyWeight = hit.getEnergy() * weight; - time += hit.getTime() * energyWeight; - timeError += std::pow(hit.getTimeError() * energyWeight, 2); - meta += edm4hep::utils::eta(hit.getPosition()) * energyWeight; - mphi += edm4hep::utils::angleAzimuthal(hit.getPosition()) * energyWeight; - r = std::min(edm4hep::utils::magnitude(hit.getPosition()), r); - cluster.addToHits(hit); - } - cluster.setEnergy(energy); - cluster.setEnergyError(std::sqrt(energyError)); - cluster.setTime(time / energy); - cluster.setTimeError(std::sqrt(timeError) / energy); - cluster.setNhits(hits.size()); - cluster.setPosition(edm4hep::utils::sphericalToVector(r, edm4hep::utils::etaToAngle(meta / energy), mphi / energy)); - - // shower radius estimate (eta-phi plane) - double radius = 0.; - for (const auto &hit: hits) { - radius += std::pow( - std::hypot( - (edm4hep::utils::eta(hit.getPosition()) - edm4hep::utils::eta(cluster.getPosition())), - (edm4hep::utils::angleAzimuthal(hit.getPosition()) - edm4hep::utils::angleAzimuthal(cluster.getPosition())) - ), - 2.0 - ); - } - cluster.addToShapeParameters(std::sqrt(radius / cluster.getNhits())); - // Skewedness not calculated TODO - - // Optionally store the MC truth associated with the first hit in this cluster - // FIXME no connection between cluster and truth in edm4hep - // if (mcHits) { - // const auto& mc_hit = (*mcHits)[pcl.getHits(0).ID.value]; - // cluster.mcID({mc_hit.truth().trackID, m_kMonteCarloSource}); - //} - - return cluster; + } + +private: + static std::vector + reconstruct_cluster_layers(const edm4eic::ProtoCluster& pcl) { + const auto& hits = pcl.getHits(); + const auto& weights = pcl.getWeights(); + // using map to have hits sorted by layer + std::map>> layer_map; + for (unsigned i = 0; i < hits.size(); ++i) { + const auto hit = hits[i]; + auto lid = hit.getLayer(); + // if (layer_map.count(lid) == 0) { + // std::vector> v; + // layer_map[lid] = {}; + // } + layer_map[lid].push_back({hit, weights[i]}); } - std::pair fit_track(const std::vector &layers) const { - int nrows = 0; - decltype(edm4eic::ClusterData::position) mean_pos{0, 0, 0}; - for (const auto &layer: layers) { - if ((layer.getNhits() > 0) && (layer.getHits(0).getLayer() <= m_cfg.trackStopLayer)) { - mean_pos = mean_pos + layer.getPosition(); - nrows += 1; - } - } - - // cannot fit - if (nrows < 2) { - return {}; - } + // create layers + std::vector cl_layers; + for (const auto& [lid, layer_hits] : layer_map) { + auto layer = reconstruct_layer(layer_hits); + cl_layers.push_back(layer); + } + return cl_layers; + } + + static edm4eic::Cluster + reconstruct_layer(const std::vector>& hits) { + edm4eic::MutableCluster layer; + layer.setType(Jug::Reco::ClusterType::kClusterSlice); + // Calculate averages + double energy{0}; + double energyError{0}; + double time{0}; + double timeError{0}; + double sumOfWeights{0}; + auto pos = layer.getPosition(); + for (const auto& [hit, weight] : hits) { + energy += hit.getEnergy() * weight; + energyError += std::pow(hit.getEnergyError() * weight, 2); + time += hit.getTime() * weight; + timeError += std::pow(hit.getTimeError() * weight, 2); + pos = pos + hit.getPosition() * weight; + sumOfWeights += weight; + layer.addToHits(hit); + } + layer.setEnergy(energy); + layer.setEnergyError(std::sqrt(energyError)); + layer.setTime(time / sumOfWeights); + layer.setTimeError(std::sqrt(timeError) / sumOfWeights); + layer.setNhits(hits.size()); + layer.setPosition(pos / sumOfWeights); + // positionError not set + // Intrinsic direction meaningless in a cluster layer --> not set + + // Calculate radius as the standard deviation of the hits versus the cluster center + double radius = 0.; + for (const auto& [hit, weight] : hits) { + radius += std::pow(edm4hep::utils::magnitude(hit.getPosition() - layer.getPosition()), 2); + } + layer.addToShapeParameters(std::sqrt(radius / layer.getNhits())); + // TODO Skewedness + + return layer; + } + + static edm4eic::MutableCluster reconstruct_cluster(const edm4eic::ProtoCluster& pcl) { + edm4eic::MutableCluster cluster; + + const auto& hits = pcl.getHits(); + const auto& weights = pcl.getWeights(); + + cluster.setType(Jug::Reco::ClusterType::kCluster3D); + double energy = 0.; + double energyError = 0.; + double time = 0.; + double timeError = 0.; + double meta = 0.; + double mphi = 0.; + double r = 9999 * dd4hep::cm; + for (unsigned i = 0; i < hits.size(); ++i) { + const auto& hit = hits[i]; + const auto& weight = weights[i]; + energy += hit.getEnergy() * weight; + energyError += std::pow(hit.getEnergyError() * weight, 2); + // energy weighting for the other variables + const double energyWeight = hit.getEnergy() * weight; + time += hit.getTime() * energyWeight; + timeError += std::pow(hit.getTimeError() * energyWeight, 2); + meta += edm4hep::utils::eta(hit.getPosition()) * energyWeight; + mphi += edm4hep::utils::angleAzimuthal(hit.getPosition()) * energyWeight; + r = std::min(edm4hep::utils::magnitude(hit.getPosition()), r); + cluster.addToHits(hit); + } + cluster.setEnergy(energy); + cluster.setEnergyError(std::sqrt(energyError)); + cluster.setTime(time / energy); + cluster.setTimeError(std::sqrt(timeError) / energy); + cluster.setNhits(hits.size()); + cluster.setPosition(edm4hep::utils::sphericalToVector( + r, edm4hep::utils::etaToAngle(meta / energy), mphi / energy)); + + // shower radius estimate (eta-phi plane) + double radius = 0.; + for (const auto& hit : hits) { + radius += std::pow(std::hypot((edm4hep::utils::eta(hit.getPosition()) - + edm4hep::utils::eta(cluster.getPosition())), + (edm4hep::utils::angleAzimuthal(hit.getPosition()) - + edm4hep::utils::angleAzimuthal(cluster.getPosition()))), + 2.0); + } + cluster.addToShapeParameters(std::sqrt(radius / cluster.getNhits())); + // Skewedness not calculated TODO + + // Optionally store the MC truth associated with the first hit in this cluster + // FIXME no connection between cluster and truth in edm4hep + // if (mcHits) { + // const auto& mc_hit = (*mcHits)[pcl.getHits(0).ID.value]; + // cluster.mcID({mc_hit.truth().trackID, m_kMonteCarloSource}); + //} + + return cluster; + } + + std::pair + fit_track(const std::vector& layers) const { + int nrows = 0; + decltype(edm4eic::ClusterData::position) mean_pos{0, 0, 0}; + for (const auto& layer : layers) { + if ((layer.getNhits() > 0) && (layer.getHits(0).getLayer() <= m_cfg.trackStopLayer)) { + mean_pos = mean_pos + layer.getPosition(); + nrows += 1; + } + } - mean_pos = mean_pos / nrows; - // fill position data - Eigen::MatrixXd pos(nrows, 3); - int ir = 0; - for (const auto &layer: layers) { - if ((layer.getNhits() > 0) && (layer.getHits(0).getLayer() <= m_cfg.trackStopLayer)) { - auto delta = layer.getPosition() - mean_pos; - pos(ir, 0) = delta.x; - pos(ir, 1) = delta.y; - pos(ir, 2) = delta.z; - ir += 1; - } - } + // cannot fit + if (nrows < 2) { + return {}; + } - Eigen::JacobiSVD svd(pos, Eigen::ComputeThinU | Eigen::ComputeThinV); - const auto dir = svd.matrixV().col(0); - // theta and phi - return {std::acos(dir(2)), std::atan2(dir(1), dir(0))}; + mean_pos = mean_pos / nrows; + // fill position data + Eigen::MatrixXd pos(nrows, 3); + int ir = 0; + for (const auto& layer : layers) { + if ((layer.getNhits() > 0) && (layer.getHits(0).getLayer() <= m_cfg.trackStopLayer)) { + auto delta = layer.getPosition() - mean_pos; + pos(ir, 0) = delta.x; + pos(ir, 1) = delta.y; + pos(ir, 2) = delta.z; + ir += 1; + } } + + Eigen::JacobiSVD svd(pos, Eigen::ComputeThinU | Eigen::ComputeThinV); + const auto dir = svd.matrixV().col(0); + // theta and phi + return {std::acos(dir(2)), std::atan2(dir(1), dir(0))}; + } }; } // namespace eicrecon diff --git a/src/algorithms/calorimetry/ImagingClusterRecoConfig.h b/src/algorithms/calorimetry/ImagingClusterRecoConfig.h index 8ae57def32..9ed22791f6 100644 --- a/src/algorithms/calorimetry/ImagingClusterRecoConfig.h +++ b/src/algorithms/calorimetry/ImagingClusterRecoConfig.h @@ -5,10 +5,9 @@ namespace eicrecon { - struct ImagingClusterRecoConfig { +struct ImagingClusterRecoConfig { - int trackStopLayer = 9; + int trackStopLayer = 9; +}; - }; - -} // eicrecon +} // namespace eicrecon diff --git a/src/algorithms/calorimetry/ImagingTopoCluster.h b/src/algorithms/calorimetry/ImagingTopoCluster.h index 0adde19641..454510b4d3 100644 --- a/src/algorithms/calorimetry/ImagingTopoCluster.h +++ b/src/algorithms/calorimetry/ImagingTopoCluster.h @@ -31,16 +31,11 @@ namespace eicrecon { - using ImagingTopoClusterAlgorithm = algorithms::Algorithm< - algorithms::Input< - edm4eic::CalorimeterHitCollection - >, - algorithms::Output< - edm4eic::ProtoClusterCollection - > - >; - - /** Topological Cell Clustering Algorithm. +using ImagingTopoClusterAlgorithm = + algorithms::Algorithm, + algorithms::Output>; + +/** Topological Cell Clustering Algorithm. * * Topological Cell Clustering Algorithm for Imaging Calorimetry * 1. group all the adjacent pixels @@ -50,164 +45,159 @@ namespace eicrecon { * * \ingroup reco */ - class ImagingTopoCluster - : public ImagingTopoClusterAlgorithm, - public WithPodConfig { - - public: - ImagingTopoCluster(std::string_view name) - : ImagingTopoClusterAlgorithm{name, - {"inputHitCollection"}, - {"outputProtoClusterCollection"}, - "Topological cell clustering algorithm for imaging calorimetry."} {} - - private: - - // unitless counterparts of the input parameters - double localDistXY[2]{0, 0}, layerDistEtaPhi[2]{0, 0}, sectorDist{0}; - double minClusterHitEdep{0}, minClusterCenterEdep{0}, minClusterEdep{0}, minClusterNhits{0}; - - public: - void init() { - // unitless conversion - // sanity checks - if (m_cfg.localDistXY.size() != 2) { - error( "Expected 2 values (x_dist, y_dist) for localDistXY"); - return; - } - if (m_cfg.layerDistEtaPhi.size() != 2) { - error( "Expected 2 values (eta_dist, phi_dist) for layerDistEtaPhi" ); - return; - } - - // using juggler internal units (GeV, dd4hep::mm, dd4hep::ns, dd4hep::rad) - localDistXY[0] = m_cfg.localDistXY[0] / dd4hep::mm; - localDistXY[1] = m_cfg.localDistXY[1] / dd4hep::mm; - layerDistEtaPhi[0] = m_cfg.layerDistEtaPhi[0]; - layerDistEtaPhi[1] = m_cfg.layerDistEtaPhi[1] / dd4hep::rad; - sectorDist = m_cfg.sectorDist / dd4hep::mm; - minClusterHitEdep = m_cfg.minClusterHitEdep / dd4hep::GeV; - minClusterCenterEdep = m_cfg.minClusterCenterEdep / dd4hep::GeV; - minClusterEdep = m_cfg.minClusterEdep / dd4hep::GeV; - - // summarize the clustering parameters - info("Local clustering (same sector and same layer): " - "Local [x, y] distance between hits <= [{:.4f} mm, {:.4f} mm].", - localDistXY[0], localDistXY[1] - ); - info("Neighbour layers clustering (same sector and layer id within +- {:d}: " - "Global [eta, phi] distance between hits <= [{:.4f}, {:.4f} rad].", - m_cfg.neighbourLayersRange, layerDistEtaPhi[0], layerDistEtaPhi[1] - ); - info("Neighbour sectors clustering (different sector): " - "Global distance between hits <= {:.4f} mm.", - sectorDist - ); +class ImagingTopoCluster : public ImagingTopoClusterAlgorithm, + public WithPodConfig { + +public: + ImagingTopoCluster(std::string_view name) + : ImagingTopoClusterAlgorithm{ + name, + {"inputHitCollection"}, + {"outputProtoClusterCollection"}, + "Topological cell clustering algorithm for imaging calorimetry."} {} + +private: + // unitless counterparts of the input parameters + double localDistXY[2]{0, 0}, layerDistEtaPhi[2]{0, 0}, sectorDist{0}; + double minClusterHitEdep{0}, minClusterCenterEdep{0}, minClusterEdep{0}, minClusterNhits{0}; + +public: + void init() { + // unitless conversion + // sanity checks + if (m_cfg.localDistXY.size() != 2) { + error("Expected 2 values (x_dist, y_dist) for localDistXY"); + return; + } + if (m_cfg.layerDistEtaPhi.size() != 2) { + error("Expected 2 values (eta_dist, phi_dist) for layerDistEtaPhi"); + return; } - void process(const Input& input, const Output& output) const final { - - const auto [hits] = input; - auto [proto] = output; - - // group neighbouring hits - std::vector visits(hits->size(), false); - std::vector> groups; - for (size_t i = 0; i < hits->size(); ++i) { - debug("hit {:d}: local position = ({}, {}, {}), global position = ({}, {}, {})", i + 1, - (*hits)[i].getLocal().x, (*hits)[i].getLocal().y, (*hits)[i].getPosition().z, - (*hits)[i].getPosition().x, (*hits)[i].getPosition().y, (*hits)[i].getPosition().z - ); - // already in a group, or not energetic enough to form a cluster - if (visits[i] || (*hits)[i].getEnergy() < minClusterCenterEdep) { - continue; - } - // create a new group, and group all the neighbouring hits - groups.emplace_back(); - bfs_group(*hits, groups.back(), i, visits); - } - debug("found {} potential clusters (groups of hits)", groups.size()); - for (size_t i = 0; i < groups.size(); ++i) { - debug("group {}: {} hits", i, groups[i].size()); - } + // using juggler internal units (GeV, dd4hep::mm, dd4hep::ns, dd4hep::rad) + localDistXY[0] = m_cfg.localDistXY[0] / dd4hep::mm; + localDistXY[1] = m_cfg.localDistXY[1] / dd4hep::mm; + layerDistEtaPhi[0] = m_cfg.layerDistEtaPhi[0]; + layerDistEtaPhi[1] = m_cfg.layerDistEtaPhi[1] / dd4hep::rad; + sectorDist = m_cfg.sectorDist / dd4hep::mm; + minClusterHitEdep = m_cfg.minClusterHitEdep / dd4hep::GeV; + minClusterCenterEdep = m_cfg.minClusterCenterEdep / dd4hep::GeV; + minClusterEdep = m_cfg.minClusterEdep / dd4hep::GeV; + + // summarize the clustering parameters + info("Local clustering (same sector and same layer): " + "Local [x, y] distance between hits <= [{:.4f} mm, {:.4f} mm].", + localDistXY[0], localDistXY[1]); + info("Neighbour layers clustering (same sector and layer id within +- {:d}: " + "Global [eta, phi] distance between hits <= [{:.4f}, {:.4f} rad].", + m_cfg.neighbourLayersRange, layerDistEtaPhi[0], layerDistEtaPhi[1]); + info("Neighbour sectors clustering (different sector): " + "Global distance between hits <= {:.4f} mm.", + sectorDist); + } + + void process(const Input& input, const Output& output) const final { + + const auto [hits] = input; + auto [proto] = output; + + // group neighbouring hits + std::vector visits(hits->size(), false); + std::vector> groups; + for (size_t i = 0; i < hits->size(); ++i) { + debug("hit {:d}: local position = ({}, {}, {}), global position = ({}, {}, {})", i + 1, + (*hits)[i].getLocal().x, (*hits)[i].getLocal().y, (*hits)[i].getPosition().z, + (*hits)[i].getPosition().x, (*hits)[i].getPosition().y, (*hits)[i].getPosition().z); + // already in a group, or not energetic enough to form a cluster + if (visits[i] || (*hits)[i].getEnergy() < minClusterCenterEdep) { + continue; + } + // create a new group, and group all the neighbouring hits + groups.emplace_back(); + bfs_group(*hits, groups.back(), i, visits); + } + debug("found {} potential clusters (groups of hits)", groups.size()); + for (size_t i = 0; i < groups.size(); ++i) { + debug("group {}: {} hits", i, groups[i].size()); + } - // form clusters - for (const auto &group : groups) { - if (static_cast(group.size()) < m_cfg.minClusterNhits) { - continue; - } - double energy = 0.; - for (std::size_t idx : group) { - energy += (*hits)[idx].getEnergy(); - } - if (energy < minClusterEdep) { - continue; - } - auto pcl = proto->create(); - for (std::size_t idx : group) { - pcl.addToHits((*hits)[idx]); - pcl.addToWeights(1); - } - } + // form clusters + for (const auto& group : groups) { + if (static_cast(group.size()) < m_cfg.minClusterNhits) { + continue; + } + double energy = 0.; + for (std::size_t idx : group) { + energy += (*hits)[idx].getEnergy(); + } + if (energy < minClusterEdep) { + continue; + } + auto pcl = proto->create(); + for (std::size_t idx : group) { + pcl.addToHits((*hits)[idx]); + pcl.addToWeights(1); + } + } + } + +private: + // helper function to group hits + bool is_neighbour(const edm4eic::CalorimeterHit& h1, const edm4eic::CalorimeterHit& h2) const { + // different sectors, simple distance check + if (h1.getSector() != h2.getSector()) { + return std::hypot((h1.getPosition().x - h2.getPosition().x), + (h1.getPosition().y - h2.getPosition().y), + (h1.getPosition().z - h2.getPosition().z)) <= sectorDist; } - private: + // layer check + int ldiff = std::abs(h1.getLayer() - h2.getLayer()); + // same layer, check local positions + if (ldiff == 0) { + return (std::abs(h1.getLocal().x - h2.getLocal().x) <= localDistXY[0]) && + (std::abs(h1.getLocal().y - h2.getLocal().y) <= localDistXY[1]); + } else if (ldiff <= m_cfg.neighbourLayersRange) { + return (std::abs(edm4hep::utils::eta(h1.getPosition()) - + edm4hep::utils::eta(h2.getPosition())) <= layerDistEtaPhi[0]) && + (std::abs(edm4hep::utils::angleAzimuthal(h1.getPosition()) - + edm4hep::utils::angleAzimuthal(h2.getPosition())) <= layerDistEtaPhi[1]); + } - // helper function to group hits - bool is_neighbour(const edm4eic::CalorimeterHit& h1, const edm4eic::CalorimeterHit& h2) const { - // different sectors, simple distance check - if (h1.getSector() != h2.getSector()) { - return std::hypot((h1.getPosition().x - h2.getPosition().x), - (h1.getPosition().y - h2.getPosition().y), - (h1.getPosition().z - h2.getPosition().z)) <= sectorDist; - } + // not in adjacent layers + return false; + } - // layer check - int ldiff = std::abs(h1.getLayer() - h2.getLayer()); - // same layer, check local positions - if (ldiff == 0) { - return (std::abs(h1.getLocal().x - h2.getLocal().x) <= localDistXY[0]) && - (std::abs(h1.getLocal().y - h2.getLocal().y) <= localDistXY[1]); - } else if (ldiff <= m_cfg.neighbourLayersRange) { - return (std::abs(edm4hep::utils::eta(h1.getPosition()) - edm4hep::utils::eta(h2.getPosition())) <= layerDistEtaPhi[0]) && - (std::abs(edm4hep::utils::angleAzimuthal(h1.getPosition()) - edm4hep::utils::angleAzimuthal(h2.getPosition())) <= - layerDistEtaPhi[1]); - } + // grouping function with Breadth-First Search + void bfs_group(const edm4eic::CalorimeterHitCollection& hits, std::set& group, + std::size_t idx, std::vector& visits) const { + visits[idx] = true; - // not in adjacent layers - return false; + // not a qualified hit to particpate clustering, stop here + if (hits[idx].getEnergy() < m_cfg.minClusterHitEdep) { + return; } - // grouping function with Breadth-First Search - void bfs_group(const edm4eic::CalorimeterHitCollection &hits, std::set &group, std::size_t idx, std::vector &visits) const { - visits[idx] = true; - - // not a qualified hit to particpate clustering, stop here - if (hits[idx].getEnergy() < m_cfg.minClusterHitEdep) { - return; - } - - group.insert(idx); - size_t prev_size = 0; - - while (prev_size != group.size()) { - prev_size = group.size(); - for (std::size_t idx1 : group) { - // check neighbours - for (std::size_t idx2 = 0; idx2 < hits.size(); ++idx2) { - // not a qualified hit to particpate clustering, skip - if (hits[idx2].getEnergy() < m_cfg.minClusterHitEdep) { - continue; - } - if ((!visits[idx2]) - && is_neighbour(hits[idx1], hits[idx2])) { - group.insert(idx2); - visits[idx2] = true; - } + group.insert(idx); + size_t prev_size = 0; + + while (prev_size != group.size()) { + prev_size = group.size(); + for (std::size_t idx1 : group) { + // check neighbours + for (std::size_t idx2 = 0; idx2 < hits.size(); ++idx2) { + // not a qualified hit to particpate clustering, skip + if (hits[idx2].getEnergy() < m_cfg.minClusterHitEdep) { + continue; + } + if ((!visits[idx2]) && is_neighbour(hits[idx1], hits[idx2])) { + group.insert(idx2); + visits[idx2] = true; } } } } - }; + } +}; } // namespace eicrecon diff --git a/src/algorithms/calorimetry/ImagingTopoClusterConfig.h b/src/algorithms/calorimetry/ImagingTopoClusterConfig.h index 26b80dbe2a..be99f7f68c 100644 --- a/src/algorithms/calorimetry/ImagingTopoClusterConfig.h +++ b/src/algorithms/calorimetry/ImagingTopoClusterConfig.h @@ -7,26 +7,25 @@ namespace eicrecon { - struct ImagingTopoClusterConfig { - - // maximum difference in layer numbers that can be considered as neighbours - int neighbourLayersRange = 1; - // maximum distance of local (x, y) to be considered as neighbors at the same layer - std::vector localDistXY = {1.0 * dd4hep::mm, 1.0 * dd4hep::mm}; - // maximum distance of global (eta, phi) to be considered as neighbors at different layers - std::vector layerDistEtaPhi = {0.01, 0.01}; - // maximum global distance to be considered as neighbors in different sectors - double sectorDist = 1.0 * dd4hep::cm; - - // minimum hit energy to participate clustering - double minClusterHitEdep = 0.; - // minimum cluster center energy (to be considered as a seed for cluster) - double minClusterCenterEdep = 0.; - // minimum cluster energy (to save this cluster) - double minClusterEdep = 0.5 * dd4hep::MeV; - // minimum number of hits (to save this cluster) - int minClusterNhits = 10; - - }; +struct ImagingTopoClusterConfig { + + // maximum difference in layer numbers that can be considered as neighbours + int neighbourLayersRange = 1; + // maximum distance of local (x, y) to be considered as neighbors at the same layer + std::vector localDistXY = {1.0 * dd4hep::mm, 1.0 * dd4hep::mm}; + // maximum distance of global (eta, phi) to be considered as neighbors at different layers + std::vector layerDistEtaPhi = {0.01, 0.01}; + // maximum global distance to be considered as neighbors in different sectors + double sectorDist = 1.0 * dd4hep::cm; + + // minimum hit energy to participate clustering + double minClusterHitEdep = 0.; + // minimum cluster center energy (to be considered as a seed for cluster) + double minClusterCenterEdep = 0.; + // minimum cluster energy (to save this cluster) + double minClusterEdep = 0.5 * dd4hep::MeV; + // minimum number of hits (to save this cluster) + int minClusterNhits = 10; +}; } // namespace eicrecon diff --git a/src/algorithms/calorimetry/TruthEnergyPositionClusterMerger.h b/src/algorithms/calorimetry/TruthEnergyPositionClusterMerger.h index 454cb00bd0..1defcf4596 100644 --- a/src/algorithms/calorimetry/TruthEnergyPositionClusterMerger.h +++ b/src/algorithms/calorimetry/TruthEnergyPositionClusterMerger.h @@ -17,21 +17,15 @@ namespace eicrecon { - using TruthEnergyPositionClusterMergerAlgorithm = algorithms::Algorithm< - algorithms::Input< - edm4hep::MCParticleCollection, - edm4eic::ClusterCollection, - edm4eic::MCRecoClusterParticleAssociationCollection, - edm4eic::ClusterCollection, - edm4eic::MCRecoClusterParticleAssociationCollection - >, - algorithms::Output< - edm4eic::ClusterCollection, - edm4eic::MCRecoClusterParticleAssociationCollection - > - >; - - /** Simple algorithm to merge the energy measurement from cluster1 with the position +using TruthEnergyPositionClusterMergerAlgorithm = algorithms::Algorithm< + algorithms::Input, + algorithms::Output>; + +/** Simple algorithm to merge the energy measurement from cluster1 with the position * measurement of cluster2 (in case matching clusters are found). If not, it will * propagate the raw cluster from cluster1 or cluster2 * @@ -39,176 +33,183 @@ namespace eicrecon { * * \ingroup reco */ - class TruthEnergyPositionClusterMerger - : public TruthEnergyPositionClusterMergerAlgorithm { +class TruthEnergyPositionClusterMerger : public TruthEnergyPositionClusterMergerAlgorithm { - public: - TruthEnergyPositionClusterMerger(std::string_view name) - : TruthEnergyPositionClusterMergerAlgorithm{name, - {"mcParticles", - "energyClusterCollection", "energyClusterAssociations", - "positionClusterCollection", "positionClusterAssociations"}, - {"outputClusterCollection", "outputClusterAssociations"}, - "Merge energy and position clusters based on truth."} {} +public: + TruthEnergyPositionClusterMerger(std::string_view name) + : TruthEnergyPositionClusterMergerAlgorithm{ + name, + {"mcParticles", "energyClusterCollection", "energyClusterAssociations", + "positionClusterCollection", "positionClusterAssociations"}, + {"outputClusterCollection", "outputClusterAssociations"}, + "Merge energy and position clusters based on truth."} {} - public: - void init() { } +public: + void init() {} - void process(const Input& input, const Output& output) const final { + void process(const Input& input, const Output& output) const final { - const auto [mcparticles, energy_clus, energy_assoc, pos_clus, pos_assoc] = input; - auto [merged_clus, merged_assoc] = output; + const auto [mcparticles, energy_clus, energy_assoc, pos_clus, pos_assoc] = input; + auto [merged_clus, merged_assoc] = output; - debug( "Merging energy and position clusters for new event" ); + debug("Merging energy and position clusters for new event"); - if (energy_clus->size() == 0 && pos_clus->size() == 0) { - debug( "Nothing to do for this event, returning..." ); - return; - } + if (energy_clus->size() == 0 && pos_clus->size() == 0) { + debug("Nothing to do for this event, returning..."); + return; + } - debug( "Step 0/2: Getting indexed list of clusters..." ); + debug("Step 0/2: Getting indexed list of clusters..."); - // get an indexed map of all clusters - debug(" --> Indexing energy clusters"); - auto energyMap = indexedClusters(*energy_clus, *energy_assoc); - trace(" --> Found these energy clusters:"); - for (const auto &[mcID, eclus]: energyMap) { - trace(" --> energy cluster {}, mcID: {}, energy: {}", eclus.getObjectID().index, mcID, eclus.getEnergy()); - } - debug(" --> Indexing position clusters"); - auto posMap = indexedClusters(*pos_clus, *pos_assoc); - trace(" --> Found these position clusters:"); - for (const auto &[mcID, pclus]: posMap) { - trace(" --> position cluster {}, mcID: {}, energy: {}", pclus.getObjectID().index, mcID, pclus.getEnergy()); - } + // get an indexed map of all clusters + debug(" --> Indexing energy clusters"); + auto energyMap = indexedClusters(*energy_clus, *energy_assoc); + trace(" --> Found these energy clusters:"); + for (const auto& [mcID, eclus] : energyMap) { + trace(" --> energy cluster {}, mcID: {}, energy: {}", eclus.getObjectID().index, mcID, + eclus.getEnergy()); + } + debug(" --> Indexing position clusters"); + auto posMap = indexedClusters(*pos_clus, *pos_assoc); + trace(" --> Found these position clusters:"); + for (const auto& [mcID, pclus] : posMap) { + trace(" --> position cluster {}, mcID: {}, energy: {}", pclus.getObjectID().index, mcID, + pclus.getEnergy()); + } - // loop over all position clusters and match with energy clusters - debug( "Step 1/2: Matching all position clusters to the available energy clusters..." ); - for (const auto &[mcID, pclus]: posMap) { - - debug(" --> Processing position cluster {}, mcID: {}, energy: {}", pclus.getObjectID().index, mcID, pclus.getEnergy()); - if (energyMap.count(mcID)) { - - const auto &eclus = energyMap[mcID]; - - auto new_clus = merged_clus->create(); - new_clus.setEnergy(eclus.getEnergy()); - new_clus.setEnergyError(eclus.getEnergyError()); - new_clus.setTime(pclus.getTime()); - new_clus.setNhits(pclus.getNhits() + eclus.getNhits()); - new_clus.setPosition(pclus.getPosition()); - new_clus.setPositionError(pclus.getPositionError()); - new_clus.addToClusters(pclus); - new_clus.addToClusters(eclus); - for (const auto &cl: {pclus, eclus}) { - for (const auto &hit: cl.getHits()) { - new_clus.addToHits(hit); - } - new_clus.addToSubdetectorEnergies(cl.getEnergy()); - } - for (const auto ¶m: pclus.getShapeParameters()) { - new_clus.addToShapeParameters(param); - } - debug(" --> Found matching energy cluster {}, energy: {}", eclus.getObjectID().index, eclus.getEnergy() ); - debug(" --> Created new combined cluster {}, energy: {}", new_clus.getObjectID().index, new_clus.getEnergy() ); - - // set association - auto clusterassoc = merged_assoc->create(); - clusterassoc.setRecID(new_clus.getObjectID().index); - clusterassoc.setSimID(mcID); - clusterassoc.setWeight(1.0); - clusterassoc.setRec(new_clus); - clusterassoc.setSim((*mcparticles)[mcID]); - - // erase the energy cluster from the map, so we can in the end account for all - // remaining clusters - energyMap.erase(mcID); - } else { - debug(" --> No matching energy cluster found, copying over position cluster" ); - auto new_clus = pclus.clone(); - new_clus.addToClusters(pclus); - merged_clus->push_back(new_clus); - - // set association - auto clusterassoc = merged_assoc->create(); - clusterassoc.setRecID(new_clus.getObjectID().index); - clusterassoc.setSimID(mcID); - clusterassoc.setWeight(1.0); - clusterassoc.setRec(new_clus); - clusterassoc.setSim((*mcparticles)[mcID]); - } + // loop over all position clusters and match with energy clusters + debug("Step 1/2: Matching all position clusters to the available energy clusters..."); + for (const auto& [mcID, pclus] : posMap) { + + debug(" --> Processing position cluster {}, mcID: {}, energy: {}", pclus.getObjectID().index, + mcID, pclus.getEnergy()); + if (energyMap.count(mcID)) { + + const auto& eclus = energyMap[mcID]; + + auto new_clus = merged_clus->create(); + new_clus.setEnergy(eclus.getEnergy()); + new_clus.setEnergyError(eclus.getEnergyError()); + new_clus.setTime(pclus.getTime()); + new_clus.setNhits(pclus.getNhits() + eclus.getNhits()); + new_clus.setPosition(pclus.getPosition()); + new_clus.setPositionError(pclus.getPositionError()); + new_clus.addToClusters(pclus); + new_clus.addToClusters(eclus); + for (const auto& cl : {pclus, eclus}) { + for (const auto& hit : cl.getHits()) { + new_clus.addToHits(hit); + } + new_clus.addToSubdetectorEnergies(cl.getEnergy()); } - // Collect remaining energy clusters. Use mc truth position for these clusters, as - // they should really have a match in the position clusters (and if they don't it due - // to a clustering error). - debug( "Step 2/2: Collecting remaining energy clusters..." ); - for (const auto &[mcID, eclus]: energyMap) { - const auto &mc = (*mcparticles)[mcID]; - const auto &p = mc.getMomentum(); - const auto phi = std::atan2(p.y, p.x); - const auto theta = std::atan2(std::hypot(p.x, p.y), p.z); - - auto new_clus = merged_clus->create(); - new_clus.setEnergy(eclus.getEnergy()); - new_clus.setEnergyError(eclus.getEnergyError()); - new_clus.setTime(eclus.getTime()); - new_clus.setNhits(eclus.getNhits()); - // FIXME use nominal dd4hep::radius of 110cm, and use start vertex theta and phi - new_clus.setPosition(edm4hep::utils::sphericalToVector(78.5 * dd4hep::cm / dd4hep::mm, theta, phi)); - new_clus.addToClusters(eclus); - - debug(" --> Processing energy cluster {}, mcID: {}, energy: {}", eclus.getObjectID().index, mcID, eclus.getEnergy() ); - debug(" --> Created new 'combined' cluster {}, energy: {}", new_clus.getObjectID().index, new_clus.getEnergy() ); - - // set association - auto clusterassoc = merged_assoc->create(); - clusterassoc.setRecID(new_clus.getObjectID().index); - clusterassoc.setSimID(mcID); - clusterassoc.setWeight(1.0); - clusterassoc.setRec(new_clus); - clusterassoc.setSim(mc); + for (const auto& param : pclus.getShapeParameters()) { + new_clus.addToShapeParameters(param); } + debug(" --> Found matching energy cluster {}, energy: {}", eclus.getObjectID().index, + eclus.getEnergy()); + debug(" --> Created new combined cluster {}, energy: {}", new_clus.getObjectID().index, + new_clus.getEnergy()); + + // set association + auto clusterassoc = merged_assoc->create(); + clusterassoc.setRecID(new_clus.getObjectID().index); + clusterassoc.setSimID(mcID); + clusterassoc.setWeight(1.0); + clusterassoc.setRec(new_clus); + clusterassoc.setSim((*mcparticles)[mcID]); + + // erase the energy cluster from the map, so we can in the end account for all + // remaining clusters + energyMap.erase(mcID); + } else { + debug(" --> No matching energy cluster found, copying over position cluster"); + auto new_clus = pclus.clone(); + new_clus.addToClusters(pclus); + merged_clus->push_back(new_clus); + + // set association + auto clusterassoc = merged_assoc->create(); + clusterassoc.setRecID(new_clus.getObjectID().index); + clusterassoc.setSimID(mcID); + clusterassoc.setWeight(1.0); + clusterassoc.setRec(new_clus); + clusterassoc.setSim((*mcparticles)[mcID]); + } } + // Collect remaining energy clusters. Use mc truth position for these clusters, as + // they should really have a match in the position clusters (and if they don't it due + // to a clustering error). + debug("Step 2/2: Collecting remaining energy clusters..."); + for (const auto& [mcID, eclus] : energyMap) { + const auto& mc = (*mcparticles)[mcID]; + const auto& p = mc.getMomentum(); + const auto phi = std::atan2(p.y, p.x); + const auto theta = std::atan2(std::hypot(p.x, p.y), p.z); + + auto new_clus = merged_clus->create(); + new_clus.setEnergy(eclus.getEnergy()); + new_clus.setEnergyError(eclus.getEnergyError()); + new_clus.setTime(eclus.getTime()); + new_clus.setNhits(eclus.getNhits()); + // FIXME use nominal dd4hep::radius of 110cm, and use start vertex theta and phi + new_clus.setPosition( + edm4hep::utils::sphericalToVector(78.5 * dd4hep::cm / dd4hep::mm, theta, phi)); + new_clus.addToClusters(eclus); + + debug(" --> Processing energy cluster {}, mcID: {}, energy: {}", eclus.getObjectID().index, + mcID, eclus.getEnergy()); + debug(" --> Created new 'combined' cluster {}, energy: {}", new_clus.getObjectID().index, + new_clus.getEnergy()); + + // set association + auto clusterassoc = merged_assoc->create(); + clusterassoc.setRecID(new_clus.getObjectID().index); + clusterassoc.setSimID(mcID); + clusterassoc.setWeight(1.0); + clusterassoc.setRec(new_clus); + clusterassoc.setSim(mc); + } + } + + // get a map of MCParticle index --> cluster + // input: cluster_collections --> list of handles to all cluster collections + std::map + indexedClusters(const edm4eic::ClusterCollection& clusters, + const edm4eic::MCRecoClusterParticleAssociationCollection& associations) const { - // get a map of MCParticle index --> cluster - // input: cluster_collections --> list of handles to all cluster collections - std::map indexedClusters( - const edm4eic::ClusterCollection& clusters, - const edm4eic::MCRecoClusterParticleAssociationCollection& associations - ) const { - - std::map matched = {}; - - for (const auto &cluster: clusters) { - int mcID = -1; - - // find associated particle - for (const auto &assoc: associations) { - if (assoc.getRec() == cluster) { - mcID = assoc.getSimID(); - break; - } - } - - trace(" --> Found cluster: {} with mcID {} and energy {}", cluster.getObjectID().index, mcID, cluster.getEnergy()); - - if (mcID < 0) { - trace( " --> WARNING: no valid MC truth link found, skipping cluster..." ); - continue; - } - - const bool duplicate = matched.count(mcID); - if (duplicate) { - trace( " --> WARNING: this is a duplicate mcID, keeping the higher energy cluster"); - if (cluster.getEnergy() < matched[mcID].getEnergy()) { - continue; - } - } - - matched[mcID] = cluster; + std::map matched = {}; + + for (const auto& cluster : clusters) { + int mcID = -1; + + // find associated particle + for (const auto& assoc : associations) { + if (assoc.getRec() == cluster) { + mcID = assoc.getSimID(); + break; } - return matched; + } + + trace(" --> Found cluster: {} with mcID {} and energy {}", cluster.getObjectID().index, mcID, + cluster.getEnergy()); + + if (mcID < 0) { + trace(" --> WARNING: no valid MC truth link found, skipping cluster..."); + continue; + } + + const bool duplicate = matched.count(mcID); + if (duplicate) { + trace(" --> WARNING: this is a duplicate mcID, keeping the higher energy cluster"); + if (cluster.getEnergy() < matched[mcID].getEnergy()) { + continue; + } + } + + matched[mcID] = cluster; } + return matched; + } }; } // namespace eicrecon diff --git a/src/algorithms/digi/PhotoMultiplierHitDigi.cc b/src/algorithms/digi/PhotoMultiplierHitDigi.cc index 6704a14e18..bea5508359 100644 --- a/src/algorithms/digi/PhotoMultiplierHitDigi.cc +++ b/src/algorithms/digi/PhotoMultiplierHitDigi.cc @@ -12,7 +12,6 @@ * Ported from Juggler by Thomas Britton (JLab) */ - #include "PhotoMultiplierHitDigi.h" #include @@ -32,246 +31,228 @@ namespace eicrecon { //------------------------ // init //------------------------ -void PhotoMultiplierHitDigi::init() -{ - // print the configuration parameters - debug() << m_cfg << endmsg; +void PhotoMultiplierHitDigi::init() { + // print the configuration parameters + debug() << m_cfg << endmsg; - /* warn if using potentially thread-unsafe seed + /* warn if using potentially thread-unsafe seed * FIXME: remove this warning when this issue is resolved: * https://github.com/eic/EICrecon/issues/539 */ - if(m_cfg.seed==0) warning("using seed=0 may cause thread-unsafe behavior of TRandom (EICrecon issue 539)"); - - // random number generators - m_random.SetSeed(m_cfg.seed); - m_rngNorm = [&](){ - return m_random.Gaus(0., 1.0); - }; - m_rngUni = [&](){ - return m_random.Uniform(0., 1.0); - }; - //auto randSvc = svc("RndmGenSvc", true); - auto sc1 = m_rngUni;//m_rngUni.initialize(randSvc, Rndm::Flat(0., 1.)); - auto sc2 = m_rngNorm;//m_rngNorm.initialize(randSvc, Rndm::Gauss(0., 1.)); - //if (!sc1.isSuccess() || !sc2.isSuccess()) { - if (!sc1 || !sc2) { - throw std::runtime_error("Cannot initialize random generator!"); - } + if (m_cfg.seed == 0) + warning("using seed=0 may cause thread-unsafe behavior of TRandom (EICrecon issue 539)"); + + // random number generators + m_random.SetSeed(m_cfg.seed); + m_rngNorm = [&]() { return m_random.Gaus(0., 1.0); }; + m_rngUni = [&]() { return m_random.Uniform(0., 1.0); }; + //auto randSvc = svc("RndmGenSvc", true); + auto sc1 = m_rngUni; //m_rngUni.initialize(randSvc, Rndm::Flat(0., 1.)); + auto sc2 = m_rngNorm; //m_rngNorm.initialize(randSvc, Rndm::Gauss(0., 1.)); + //if (!sc1.isSuccess() || !sc2.isSuccess()) { + if (!sc1 || !sc2) { + throw std::runtime_error("Cannot initialize random generator!"); + } - // initialize quantum efficiency table - qe_init(); + // initialize quantum efficiency table + qe_init(); } - //------------------------ // process //------------------------ -void PhotoMultiplierHitDigi::process( - const PhotoMultiplierHitDigi::Input& input, - const PhotoMultiplierHitDigi::Output& output) const -{ - const auto [sim_hits] = input; - auto [raw_hits, hit_assocs] = output; - - trace("{:=^70}"," call PhotoMultiplierHitDigi::process "); - std::unordered_map> hit_groups; - // collect the photon hit in the same cell - // calculate signal - trace("{:-<70}","Loop over simulated hits "); - for(std::size_t sim_hit_index = 0; sim_hit_index < sim_hits->size(); sim_hit_index++) { - const auto& sim_hit = sim_hits->at(sim_hit_index); - auto edep_eV = sim_hit.getEDep() * 1e9; // [GeV] -> [eV] // FIXME: use common unit converters, when available - auto id = sim_hit.getCellID(); - trace("hit: pixel id={:#018X} edep = {} eV", id, edep_eV); - - // overall safety factor - if (m_rngUni() > m_cfg.safetyFactor) continue; - - // quantum efficiency - if (!qe_pass(edep_eV, m_rngUni())) continue; - - // pixel gap cuts - if(m_cfg.enablePixelGaps) { - auto pos = sim_hit.getPosition(); - if( ! m_PixelGapMask(id, dd4hep::Position(pos.x*dd4hep::mm, pos.y*dd4hep::mm, pos.z*dd4hep::mm)) ) - continue; - } - - // cell time, signal amplitude, truth photon - trace(" -> hit accepted"); - trace(" -> MC hit id={}", sim_hit.getObjectID().index); - auto time = sim_hit.getTime(); - double amp = m_cfg.speMean + m_rngNorm() * m_cfg.speError; - - // insert hit to `hit_groups` - InsertHit( - hit_groups, - id, - amp, - time, - sim_hit_index - ); - } - - // print `hit_groups` - if(level() <= algorithms::LogLevel::kTrace) { - trace("{:-<70}","Accepted hit groups "); - for(auto &[id,hitVec] : hit_groups) - for(auto &hit : hitVec) { - trace("hit_group: pixel id={:#018X} -> npe={} signal={} time={}", id, hit.npe, hit.signal, hit.time); - for(auto i : hit.sim_hit_indices) - trace(" - MC hit: EDep={}, id={}", sim_hits->at(i).getEDep(), sim_hits->at(i).getObjectID().index); - } - } - - //build noise raw hits - if (m_cfg.enableNoise) { - trace("{:=^70}"," BEGIN NOISE INJECTION "); - float p = m_cfg.noiseRate*m_cfg.noiseTimeWindow; - auto cellID_action = [this,&hit_groups] (auto id) { - - // cell time, signal amplitude - double amp = m_cfg.speMean + m_rngNorm()*m_cfg.speError; - TimeType time = m_cfg.noiseTimeWindow*m_rngUni() / dd4hep::ns; - dd4hep::Position pos_hit_global = m_converter->position(id); - - // insert in `hit_groups`, or if the pixel already has a hit, update `npe` and `signal` - this->InsertHit( - hit_groups, - id, - amp, - time, - 0, // not used - true - ); - - }; - m_VisitRngCellIDs(cellID_action, p); - } - - // build output `RawTrackerHit` and `MCRecoTrackerHitAssociation` collections - trace("{:-<70}","Digitized raw hits "); - for (auto &it : hit_groups) { - for (auto &data : it.second) { - - // build `RawTrackerHit` - auto raw_hit = raw_hits->create(); - raw_hit.setCellID(it.first); - raw_hit.setCharge( static_cast (data.signal) ); - raw_hit.setTimeStamp( static_cast (data.time/m_cfg.timeResolution) ); - trace("raw_hit: cellID={:#018X} -> charge={} timeStamp={}", - raw_hit.getCellID(), - raw_hit.getCharge(), - raw_hit.getTimeStamp() - ); - - // build `MCRecoTrackerHitAssociation` (for non-noise hits only) - if(!data.sim_hit_indices.empty()) { - auto hit_assoc = hit_assocs->create(); - hit_assoc.setWeight(1.0); // not used - hit_assoc.setRawHit(raw_hit); - for(auto i : data.sim_hit_indices) - hit_assoc.addToSimHits(sim_hits->at(i)); - } - } - } +void PhotoMultiplierHitDigi::process(const PhotoMultiplierHitDigi::Input& input, + const PhotoMultiplierHitDigi::Output& output) const { + const auto [sim_hits] = input; + auto [raw_hits, hit_assocs] = output; + + trace("{:=^70}", " call PhotoMultiplierHitDigi::process "); + std::unordered_map> hit_groups; + // collect the photon hit in the same cell + // calculate signal + trace("{:-<70}", "Loop over simulated hits "); + for (std::size_t sim_hit_index = 0; sim_hit_index < sim_hits->size(); sim_hit_index++) { + const auto& sim_hit = sim_hits->at(sim_hit_index); + auto edep_eV = sim_hit.getEDep() * + 1e9; // [GeV] -> [eV] // FIXME: use common unit converters, when available + auto id = sim_hit.getCellID(); + trace("hit: pixel id={:#018X} edep = {} eV", id, edep_eV); + + // overall safety factor + if (m_rngUni() > m_cfg.safetyFactor) + continue; + + // quantum efficiency + if (!qe_pass(edep_eV, m_rngUni())) + continue; + + // pixel gap cuts + if (m_cfg.enablePixelGaps) { + auto pos = sim_hit.getPosition(); + if (!m_PixelGapMask( + id, dd4hep::Position(pos.x * dd4hep::mm, pos.y * dd4hep::mm, pos.z * dd4hep::mm))) + continue; + } + + // cell time, signal amplitude, truth photon + trace(" -> hit accepted"); + trace(" -> MC hit id={}", sim_hit.getObjectID().index); + auto time = sim_hit.getTime(); + double amp = m_cfg.speMean + m_rngNorm() * m_cfg.speError; + + // insert hit to `hit_groups` + InsertHit(hit_groups, id, amp, time, sim_hit_index); + } + + // print `hit_groups` + if (level() <= algorithms::LogLevel::kTrace) { + trace("{:-<70}", "Accepted hit groups "); + for (auto& [id, hitVec] : hit_groups) + for (auto& hit : hitVec) { + trace("hit_group: pixel id={:#018X} -> npe={} signal={} time={}", id, hit.npe, hit.signal, + hit.time); + for (auto i : hit.sim_hit_indices) + trace(" - MC hit: EDep={}, id={}", sim_hits->at(i).getEDep(), + sim_hits->at(i).getObjectID().index); + } + } + + //build noise raw hits + if (m_cfg.enableNoise) { + trace("{:=^70}", " BEGIN NOISE INJECTION "); + float p = m_cfg.noiseRate * m_cfg.noiseTimeWindow; + auto cellID_action = [this, &hit_groups](auto id) { + // cell time, signal amplitude + double amp = m_cfg.speMean + m_rngNorm() * m_cfg.speError; + TimeType time = m_cfg.noiseTimeWindow * m_rngUni() / dd4hep::ns; + dd4hep::Position pos_hit_global = m_converter->position(id); + + // insert in `hit_groups`, or if the pixel already has a hit, update `npe` and `signal` + this->InsertHit(hit_groups, id, amp, time, + 0, // not used + true); + }; + m_VisitRngCellIDs(cellID_action, p); + } + + // build output `RawTrackerHit` and `MCRecoTrackerHitAssociation` collections + trace("{:-<70}", "Digitized raw hits "); + for (auto& it : hit_groups) { + for (auto& data : it.second) { + + // build `RawTrackerHit` + auto raw_hit = raw_hits->create(); + raw_hit.setCellID(it.first); + raw_hit.setCharge(static_cast(data.signal)); + raw_hit.setTimeStamp(static_cast( + data.time / m_cfg.timeResolution)); + trace("raw_hit: cellID={:#018X} -> charge={} timeStamp={}", raw_hit.getCellID(), + raw_hit.getCharge(), raw_hit.getTimeStamp()); + + // build `MCRecoTrackerHitAssociation` (for non-noise hits only) + if (!data.sim_hit_indices.empty()) { + auto hit_assoc = hit_assocs->create(); + hit_assoc.setWeight(1.0); // not used + hit_assoc.setRawHit(raw_hit); + for (auto i : data.sim_hit_indices) + hit_assoc.addToSimHits(sim_hits->at(i)); + } + } + } } -void PhotoMultiplierHitDigi::qe_init() -{ - // get quantum efficiency table - qeff.clear(); - auto hc = dd4hep::h_Planck * dd4hep::c_light / (dd4hep::eV * dd4hep::nm); // [eV*nm] - for(const auto &[wl,qe] : m_cfg.quantumEfficiency) { - qeff.emplace_back( hc / wl, qe ); // convert wavelength [nm] -> energy [eV] - } - - // sort quantum efficiency data first - std::sort(qeff.begin(), qeff.end(), - [] (const std::pair &v1, const std::pair &v2) { - return v1.first < v2.first; +void PhotoMultiplierHitDigi::qe_init() { + // get quantum efficiency table + qeff.clear(); + auto hc = dd4hep::h_Planck * dd4hep::c_light / (dd4hep::eV * dd4hep::nm); // [eV*nm] + for (const auto& [wl, qe] : m_cfg.quantumEfficiency) { + qeff.emplace_back(hc / wl, qe); // convert wavelength [nm] -> energy [eV] + } + + // sort quantum efficiency data first + std::sort(qeff.begin(), qeff.end(), + [](const std::pair& v1, const std::pair& v2) { + return v1.first < v2.first; }); - // print the table - debug("{:-^60}"," Quantum Efficiency vs. Energy "); - for(auto& [en,qe] : qeff) - debug(" {:>10.4} {:<}",en,qe); - trace("{:=^60}",""); - - // sanity checks - if (qeff.empty()) { - qeff = {{2.6, 0.3}, {7.0, 0.3}}; - warning("Invalid quantum efficiency data provided, using default values {} {:.2f} {} {:.2f} {} {:.2f} {} {:.2f} {}","{{", qeff.front().first, ",", qeff.front().second, "},{",qeff.back().first,",",qeff.back().second,"}}"); - } - if (qeff.front().first > 3.0) { - warning("Quantum efficiency data start from {:.2f} {}", qeff.front().first, " eV, maybe you are using wrong units?"); - } - if (qeff.back().first < 3.0) { - warning("Quantum efficiency data end at {:.2f} {}", qeff.back().first, " eV, maybe you are using wrong units?"); - } + // print the table + debug("{:-^60}", " Quantum Efficiency vs. Energy "); + for (auto& [en, qe] : qeff) + debug(" {:>10.4} {:<}", en, qe); + trace("{:=^60}", ""); + + // sanity checks + if (qeff.empty()) { + qeff = {{2.6, 0.3}, {7.0, 0.3}}; + warning("Invalid quantum efficiency data provided, using default values {} {:.2f} {} {:.2f} {} " + "{:.2f} {} {:.2f} {}", + "{{", qeff.front().first, ",", qeff.front().second, "},{", qeff.back().first, ",", + qeff.back().second, "}}"); + } + if (qeff.front().first > 3.0) { + warning("Quantum efficiency data start from {:.2f} {}", qeff.front().first, + " eV, maybe you are using wrong units?"); + } + if (qeff.back().first < 3.0) { + warning("Quantum efficiency data end at {:.2f} {}", qeff.back().first, + " eV, maybe you are using wrong units?"); + } } +template +RndmIter PhotoMultiplierHitDigi::interval_search(RndmIter beg, RndmIter end, const T& val, + Compare comp) const { + // special cases + auto dist = std::distance(beg, end); + if ((dist < 2) || (comp(*beg, val) > 0) || (comp(*std::prev(end), val) < 0)) { + return end; + } + auto mid = std::next(beg, dist / 2); + + while (mid != end) { + if (comp(*mid, val) == 0) { + return mid; + } else if (comp(*mid, val) > 0) { + end = mid; + } else { + beg = std::next(mid); + } + mid = std::next(beg, std::distance(beg, end) / 2); + } -template RndmIter PhotoMultiplierHitDigi::interval_search(RndmIter beg, RndmIter end, const T &val, Compare comp) const -{ - // special cases - auto dist = std::distance(beg, end); - if ((dist < 2) || (comp(*beg, val) > 0) || (comp(*std::prev(end), val) < 0)) { - return end; - } - auto mid = std::next(beg, dist / 2); - - while (mid != end) { - if (comp(*mid, val) == 0) { - return mid; - } else if (comp(*mid, val) > 0) { - end = mid; - } else { - beg = std::next(mid); - } - mid = std::next(beg, std::distance(beg, end)/2); - } - - if (mid == end || comp(*mid, val) > 0) { - return std::prev(mid); - } - return mid; + if (mid == end || comp(*mid, val) > 0) { + return std::prev(mid); + } + return mid; } -bool PhotoMultiplierHitDigi::qe_pass(double ev, double rand) const -{ - auto it = interval_search(qeff.begin(), qeff.end(), ev, - [] (const std::pair &vals, double val) { - return vals.first - val; - }); - - if (it == qeff.end()) { - // warning("{} eV is out of QE data range, assuming 0\% efficiency",ev); - return false; - } - - double prob = it->second; - auto itn = std::next(it); - if (itn != qeff.end() && (itn->first - it->first != 0)) { - prob = (it->second*(itn->first - ev) + itn->second*(ev - it->first)) / (itn->first - it->first); - } - - // trace("{} eV, QE: {}\%",ev,prob*100.); - return rand <= prob; -} +bool PhotoMultiplierHitDigi::qe_pass(double ev, double rand) const { + auto it = interval_search( + qeff.begin(), qeff.end(), ev, + [](const std::pair& vals, double val) { return vals.first - val; }); + if (it == qeff.end()) { + // warning("{} eV is out of QE data range, assuming 0\% efficiency",ev); + return false; + } + + double prob = it->second; + auto itn = std::next(it); + if (itn != qeff.end() && (itn->first - it->first != 0)) { + prob = (it->second * (itn->first - ev) + itn->second * (ev - it->first)) / + (itn->first - it->first); + } + + // trace("{} eV, QE: {}\%",ev,prob*100.); + return rand <= prob; +} // add a hit to local `hit_groups` data structure // NOLINTBEGIN(bugprone-easily-swappable-parameters) void PhotoMultiplierHitDigi::InsertHit( - std::unordered_map> &hit_groups, - CellIDType id, - double amp, - TimeType time, - std::size_t sim_hit_index, - bool is_noise_hit - ) const // NOLINTEND(bugprone-easily-swappable-parameters) + std::unordered_map>& hit_groups, CellIDType id, double amp, + TimeType time, std::size_t sim_hit_index, + bool is_noise_hit) const // NOLINTEND(bugprone-easily-swappable-parameters) { auto it = hit_groups.find(id); if (it != hit_groups.end()) { @@ -281,7 +262,8 @@ void PhotoMultiplierHitDigi::InsertHit( // hit group found, update npe, signal, and list of MC hits ghit->npe += 1; ghit->signal += amp; - if(!is_noise_hit) ghit->sim_hit_indices.push_back(sim_hit_index); + if (!is_noise_hit) + ghit->sim_hit_indices.push_back(sim_hit_index); trace(" -> add to group @ {:#018X}: signal={}", id, ghit->signal); break; } @@ -290,16 +272,18 @@ void PhotoMultiplierHitDigi::InsertHit( if (i >= it->second.size()) { auto sig = amp + m_cfg.pedMean + m_cfg.pedError * m_rngNorm(); decltype(HitData::sim_hit_indices) indices; - if(!is_noise_hit) indices.push_back(sim_hit_index); - hit_groups.insert({ id, {HitData{1, sig, time, indices}} }); + if (!is_noise_hit) + indices.push_back(sim_hit_index); + hit_groups.insert({id, {HitData{1, sig, time, indices}}}); trace(" -> no group found,"); trace(" so new group @ {:#018X}: signal={}", id, sig); } } else { auto sig = amp + m_cfg.pedMean + m_cfg.pedError * m_rngNorm(); decltype(HitData::sim_hit_indices) indices; - if(!is_noise_hit) indices.push_back(sim_hit_index); - hit_groups.insert({ id, {HitData{1, sig, time, indices}} }); + if (!is_noise_hit) + indices.push_back(sim_hit_index); + hit_groups.insert({id, {HitData{1, sig, time, indices}}}); trace(" -> new group @ {:#018X}: signal={}", id, sig); } } diff --git a/src/algorithms/digi/PhotoMultiplierHitDigi.h b/src/algorithms/digi/PhotoMultiplierHitDigi.h index 62c4ad2e1f..1f17c2dfad 100644 --- a/src/algorithms/digi/PhotoMultiplierHitDigi.h +++ b/src/algorithms/digi/PhotoMultiplierHitDigi.h @@ -12,7 +12,6 @@ * Ported from Juggler by Thomas Britton (JLab) */ - #pragma once #include @@ -42,99 +41,86 @@ namespace eicrecon { - using PhotoMultiplierHitDigiAlgorithm = algorithms::Algorithm< - algorithms::Input< - edm4hep::SimTrackerHitCollection - >, - algorithms::Output< - edm4eic::RawTrackerHitCollection, - edm4eic::MCRecoTrackerHitAssociationCollection - > - >; - - class PhotoMultiplierHitDigi - : public PhotoMultiplierHitDigiAlgorithm, - public WithPodConfig { - - public: - PhotoMultiplierHitDigi(std::string_view name) +using PhotoMultiplierHitDigiAlgorithm = + algorithms::Algorithm, + algorithms::Output>; + +class PhotoMultiplierHitDigi : public PhotoMultiplierHitDigiAlgorithm, + public WithPodConfig { + +public: + PhotoMultiplierHitDigi(std::string_view name) : PhotoMultiplierHitDigiAlgorithm{name, - {"inputHitCollection"}, - {"outputRawHitCollection", "outputRawHitAssociations"}, - "Digitize within ADC range, add pedestal, convert time " - "with smearing resolution."} {} - - void init() final; - void process(const Input&, const Output&) const final; - - // EDM datatype member types - using CellIDType = decltype(edm4hep::SimTrackerHitData::cellID); - using TimeType = decltype(edm4hep::SimTrackerHitData::time); - - // local structure to hold data for a hit - struct HitData { - uint32_t npe; - double signal; - TimeType time; - std::vector sim_hit_indices; - }; - - // random number generators - TRandomMixMax m_random; - std::function m_rngNorm; - std::function m_rngUni; - //Rndm::Numbers m_rngUni, m_rngNorm; - - // set `m_VisitAllRngPixels`, a visitor to run an action (type - // `function`) on a selection of random CellIDs; must be - // defined externally, since this would be detector-specific - void SetVisitRngCellIDs( - std::function< void(std::function, float) > visitor - ) - { m_VisitRngCellIDs = visitor; } - - // set `m_PixelGapMask`, which takes `cellID` and MC hit position, returning - // true if the hit position is on a pixel, or false if on a pixel gap; must be - // defined externally, since this would be detector-specific - void SetPixelGapMask( - std::function< bool(CellIDType, dd4hep::Position) > mask - ) - { m_PixelGapMask = mask; } + {"inputHitCollection"}, + {"outputRawHitCollection", "outputRawHitAssociations"}, + "Digitize within ADC range, add pedestal, convert time " + "with smearing resolution."} {} + + void init() final; + void process(const Input&, const Output&) const final; + + // EDM datatype member types + using CellIDType = decltype(edm4hep::SimTrackerHitData::cellID); + using TimeType = decltype(edm4hep::SimTrackerHitData::time); + + // local structure to hold data for a hit + struct HitData { + uint32_t npe; + double signal; + TimeType time; + std::vector sim_hit_indices; + }; + + // random number generators + TRandomMixMax m_random; + std::function m_rngNorm; + std::function m_rngUni; + //Rndm::Numbers m_rngUni, m_rngNorm; + + // set `m_VisitAllRngPixels`, a visitor to run an action (type + // `function`) on a selection of random CellIDs; must be + // defined externally, since this would be detector-specific + void SetVisitRngCellIDs(std::function, float)> visitor) { + m_VisitRngCellIDs = visitor; + } + + // set `m_PixelGapMask`, which takes `cellID` and MC hit position, returning + // true if the hit position is on a pixel, or false if on a pixel gap; must be + // defined externally, since this would be detector-specific + void SetPixelGapMask(std::function mask) { + m_PixelGapMask = mask; + } protected: + // visitor of all possible CellIDs (set with SetVisitRngCellIDs) + std::function, float)> m_VisitRngCellIDs = + [](std::function visitor_action, float p) { /* default no-op */ }; - // visitor of all possible CellIDs (set with SetVisitRngCellIDs) - std::function< void(std::function, float) > m_VisitRngCellIDs = - [] ( std::function visitor_action, float p ) { /* default no-op */ }; - - // pixel gap mask - std::function< bool(CellIDType, dd4hep::Position) > m_PixelGapMask = - [] (CellIDType cellID, dd4hep::Position pos_hit_global) { + // pixel gap mask + std::function m_PixelGapMask = + [](CellIDType cellID, dd4hep::Position pos_hit_global) { throw std::runtime_error("pixel gap cuts enabled, but none defined"); return false; }; private: - - // add a hit to local `hit_groups` data structure - void InsertHit( - std::unordered_map> &hit_groups, - CellIDType id, - double amp, - TimeType time, - std::size_t sim_hit_index, - bool is_noise_hit = false - ) const; - - const dd4hep::Detector* m_detector{algorithms::GeoSvc::instance().detector()}; - const dd4hep::rec::CellIDPositionConverter* m_converter{algorithms::GeoSvc::instance().cellIDPositionConverter()}; - - // std::default_random_engine generator; // TODO: need something more appropriate here - // std::normal_distribution m_normDist; // defaults to mean=0, sigma=1 - - std::vector> qeff; - void qe_init(); - template RndmIter interval_search(RndmIter beg, RndmIter end, const T &val, Compare comp) const; - bool qe_pass(double ev, double rand) const; + // add a hit to local `hit_groups` data structure + void InsertHit(std::unordered_map>& hit_groups, CellIDType id, + double amp, TimeType time, std::size_t sim_hit_index, + bool is_noise_hit = false) const; + + const dd4hep::Detector* m_detector{algorithms::GeoSvc::instance().detector()}; + const dd4hep::rec::CellIDPositionConverter* m_converter{ + algorithms::GeoSvc::instance().cellIDPositionConverter()}; + + // std::default_random_engine generator; // TODO: need something more appropriate here + // std::normal_distribution m_normDist; // defaults to mean=0, sigma=1 + + std::vector> qeff; + void qe_init(); + template + RndmIter interval_search(RndmIter beg, RndmIter end, const T& val, Compare comp) const; + bool qe_pass(double ev, double rand) const; }; -} +} // namespace eicrecon diff --git a/src/algorithms/digi/PhotoMultiplierHitDigiConfig.h b/src/algorithms/digi/PhotoMultiplierHitDigiConfig.h index 3d4b7996dc..8945abcb8f 100644 --- a/src/algorithms/digi/PhotoMultiplierHitDigiConfig.h +++ b/src/algorithms/digi/PhotoMultiplierHitDigiConfig.h @@ -6,95 +6,79 @@ #include namespace eicrecon { - class PhotoMultiplierHitDigiConfig { - public: - - // random number generator seed - /* FIXME: don't use 0 if `TRandomMixMax` is the RNG, it can get "stuck" +class PhotoMultiplierHitDigiConfig { +public: + // random number generator seed + /* FIXME: don't use 0 if `TRandomMixMax` is the RNG, it can get "stuck" * FIXME: remove this warning when this issue is resolved: * https://github.com/eic/EICrecon/issues/539 */ - unsigned long seed = 1; // seed for RNG (note: `0` might mean "unique" seed) + unsigned long seed = 1; // seed for RNG (note: `0` might mean "unique" seed) - // triggering - double hitTimeWindow = 20.0; // time gate in which 2 input hits will be grouped to 1 output hit // [ns] - double timeResolution = 1/16.0; // time resolution (= 1 / TDC counts per unit time) // [ns] - double speMean = 80.0; // mean ADC counts for a single photon - double speError = 16.0; // sigma of ADC counts for a single photon - double pedMean = 200.0; // mean ADC counts for the pedestal - double pedError = 3.0; // sigma of ADC counts for the pedestal + // triggering + double hitTimeWindow = + 20.0; // time gate in which 2 input hits will be grouped to 1 output hit // [ns] + double timeResolution = 1 / 16.0; // time resolution (= 1 / TDC counts per unit time) // [ns] + double speMean = 80.0; // mean ADC counts for a single photon + double speError = 16.0; // sigma of ADC counts for a single photon + double pedMean = 200.0; // mean ADC counts for the pedestal + double pedError = 3.0; // sigma of ADC counts for the pedestal - // noise - bool enableNoise = false; - double noiseRate = 20000; // [Hz] - double noiseTimeWindow = 20.0; // [ns] + // noise + bool enableNoise = false; + double noiseRate = 20000; // [Hz] + double noiseTimeWindow = 20.0; // [ns] - // SiPM pixels - bool enablePixelGaps = false; // enable/disable removal of hits in gaps between pixels + // SiPM pixels + bool enablePixelGaps = false; // enable/disable removal of hits in gaps between pixels - // overall safety factor - /* simulations assume the detector is ideal and perfect, but reality is + // overall safety factor + /* simulations assume the detector is ideal and perfect, but reality is * often neither; use this safety factor to reduce the number of initial * photon hits for a more conservative estimate of the number of * photoelectrons, or set to 1 to apply no such factor */ - double safetyFactor = 1.0; // allowed range: (0,1] + double safetyFactor = 1.0; // allowed range: (0,1] - // quantum efficiency - // - wavelength units are [nm] - // FIXME: figure out how users can override this, maybe an external `yaml` file - std::vector > quantumEfficiency = { - {315, 0.00}, - {325, 0.04}, - {340, 0.10}, - {350, 0.20}, - {370, 0.30}, - {400, 0.35}, - {450, 0.40}, - {500, 0.38}, - {550, 0.35}, - {600, 0.27}, - {650, 0.20}, - {700, 0.15}, - {750, 0.12}, - {800, 0.08}, - {850, 0.06}, - {900, 0.04}, - {1000, 0.00} - }; + // quantum efficiency + // - wavelength units are [nm] + // FIXME: figure out how users can override this, maybe an external `yaml` file + std::vector> quantumEfficiency = { + {315, 0.00}, {325, 0.04}, {340, 0.10}, {350, 0.20}, {370, 0.30}, {400, 0.35}, + {450, 0.40}, {500, 0.38}, {550, 0.35}, {600, 0.27}, {650, 0.20}, {700, 0.15}, + {750, 0.12}, {800, 0.08}, {850, 0.06}, {900, 0.04}, {1000, 0.00}}; - /* + /* std::vector > quantumEfficiency = { // test unit QE {325, 1.00}, {900, 1.00} }; */ - friend std::ostream& operator<<(std::ostream& os, const PhotoMultiplierHitDigiConfig& cfg); + friend std::ostream& operator<<(std::ostream& os, const PhotoMultiplierHitDigiConfig& cfg); +}; +std::ostream& operator<<(std::ostream& os, const PhotoMultiplierHitDigiConfig& cfg) { + os << fmt::format("{:=^60}", " PhotoMultiplierHitDigiConfig Settings ") << std::endl; + auto print_param = [&os](auto name, auto val) { + os << fmt::format(" {:>20} = {:<}", name, val) << std::endl; }; - - std::ostream& operator<<(std::ostream& os, const PhotoMultiplierHitDigiConfig& cfg) { - os << fmt::format("{:=^60}", " PhotoMultiplierHitDigiConfig Settings ") << std::endl; - auto print_param = [&os] (auto name, auto val) { - os << fmt::format(" {:>20} = {:<}", name, val) << std::endl; - }; - print_param("seed", cfg.seed); - print_param("hitTimeWindow", cfg.hitTimeWindow); - print_param("timeResolution", cfg.timeResolution); - print_param("speMean", cfg.speMean); - print_param("speError", cfg.speError); - print_param("pedMean", cfg.pedMean); - print_param("pedError", cfg.pedError); - print_param("enablePixelGaps", cfg.enablePixelGaps); - print_param("safetyFactor", cfg.safetyFactor); - print_param("enableNoise", cfg.enableNoise); - print_param("noiseRate", cfg.noiseRate); - print_param("noiseTimeWindow", cfg.noiseTimeWindow); - os << fmt::format("{:-^60}", " Quantum Efficiency vs. Wavelength ") << std::endl; - for(auto& [wl,qe] : cfg.quantumEfficiency) - os << fmt::format(" {:>10} {:<}", wl, qe) << std::endl; - return os; - } - + print_param("seed", cfg.seed); + print_param("hitTimeWindow", cfg.hitTimeWindow); + print_param("timeResolution", cfg.timeResolution); + print_param("speMean", cfg.speMean); + print_param("speError", cfg.speError); + print_param("pedMean", cfg.pedMean); + print_param("pedError", cfg.pedError); + print_param("enablePixelGaps", cfg.enablePixelGaps); + print_param("safetyFactor", cfg.safetyFactor); + print_param("enableNoise", cfg.enableNoise); + print_param("noiseRate", cfg.noiseRate); + print_param("noiseTimeWindow", cfg.noiseTimeWindow); + os << fmt::format("{:-^60}", " Quantum Efficiency vs. Wavelength ") << std::endl; + for (auto& [wl, qe] : cfg.quantumEfficiency) + os << fmt::format(" {:>10} {:<}", wl, qe) << std::endl; + return os; } + +} // namespace eicrecon diff --git a/src/algorithms/digi/SiliconTrackerDigi.cc b/src/algorithms/digi/SiliconTrackerDigi.cc index daefa12ee2..fa0ad008b5 100644 --- a/src/algorithms/digi/SiliconTrackerDigi.cc +++ b/src/algorithms/digi/SiliconTrackerDigi.cc @@ -20,77 +20,77 @@ namespace eicrecon { void SiliconTrackerDigi::init(std::shared_ptr& logger) { - // set logger - m_log = logger; - - // Create random gauss function - m_gauss = [&](){ - return m_random.Gaus(0, m_cfg.timeResolution); - //return m_rng.gaussian(0., m_cfg.timeResolution); - }; + // set logger + m_log = logger; + + // Create random gauss function + m_gauss = [&]() { + return m_random.Gaus(0, m_cfg.timeResolution); + //return m_rng.gaussian(0., m_cfg.timeResolution); + }; } - -void SiliconTrackerDigi::process( - const SiliconTrackerDigi::Input& input, - const SiliconTrackerDigi::Output& output) const { - - const auto [sim_hits] = input; - auto [raw_hits] = output; - - // A map of unique cellIDs with temporary structure RawHit - std::unordered_map cell_hit_map; - - - for (const auto& sim_hit : *sim_hits) { - - // time smearing - double time_smearing = m_gauss(); - double result_time = sim_hit.getTime() + time_smearing; - auto hit_time_stamp = (std::int32_t) (result_time * 1e3); - - m_log->debug("--------------------"); - m_log->debug("Hit cellID = {}", sim_hit.getCellID()); - m_log->debug(" position = ({:.2f}, {:.2f}, {:.2f})", sim_hit.getPosition().x, sim_hit.getPosition().y, sim_hit.getPosition().z); - m_log->debug(" xy_radius = {:.2f}", std::hypot(sim_hit.getPosition().x, sim_hit.getPosition().y)); - m_log->debug(" momentum = ({:.2f}, {:.2f}, {:.2f})", sim_hit.getMomentum().x, sim_hit.getMomentum().y, sim_hit.getMomentum().z); - m_log->debug(" edep = {:.2f}", sim_hit.getEDep()); - m_log->debug(" time = {:.4f}[ns]", sim_hit.getTime()); - m_log->debug(" particle time = {}[ns]", sim_hit.getMCParticle().getTime()); - m_log->debug(" time smearing: {:.4f}, resulting time = {:.4f} [ns]", time_smearing, result_time); - m_log->debug(" hit_time_stamp: {} [~ps]", hit_time_stamp); - - - if (sim_hit.getEDep() < m_cfg.threshold) { - m_log->debug(" edep is below threshold of {:.2f} [keV]", m_cfg.threshold / dd4hep::keV); - continue; - } - - if (cell_hit_map.count(sim_hit.getCellID()) == 0) { - // This cell doesn't have hits - cell_hit_map[sim_hit.getCellID()] = { - sim_hit.getCellID(), - (std::int32_t) std::llround(sim_hit.getEDep() * 1e6), - hit_time_stamp // ns->ps - }; - } else { - // There is previous values in the cell - auto& hit = cell_hit_map[sim_hit.getCellID()]; - m_log->debug(" Hit already exists in cell ID={}, prev. hit time: {}", sim_hit.getCellID(), hit.getTimeStamp()); - - // keep earliest time for hit - auto time_stamp = hit.getTimeStamp(); - hit.setTimeStamp(std::min(hit_time_stamp, hit.getTimeStamp())); - - // sum deposited energy - auto charge = hit.getCharge(); - hit.setCharge(charge + (std::int32_t) std::llround(sim_hit.getEDep() * 1e6)); - } +void SiliconTrackerDigi::process(const SiliconTrackerDigi::Input& input, + const SiliconTrackerDigi::Output& output) const { + + const auto [sim_hits] = input; + auto [raw_hits] = output; + + // A map of unique cellIDs with temporary structure RawHit + std::unordered_map cell_hit_map; + + for (const auto& sim_hit : *sim_hits) { + + // time smearing + double time_smearing = m_gauss(); + double result_time = sim_hit.getTime() + time_smearing; + auto hit_time_stamp = (std::int32_t)(result_time * 1e3); + + m_log->debug("--------------------"); + m_log->debug("Hit cellID = {}", sim_hit.getCellID()); + m_log->debug(" position = ({:.2f}, {:.2f}, {:.2f})", sim_hit.getPosition().x, + sim_hit.getPosition().y, sim_hit.getPosition().z); + m_log->debug(" xy_radius = {:.2f}", + std::hypot(sim_hit.getPosition().x, sim_hit.getPosition().y)); + m_log->debug(" momentum = ({:.2f}, {:.2f}, {:.2f})", sim_hit.getMomentum().x, + sim_hit.getMomentum().y, sim_hit.getMomentum().z); + m_log->debug(" edep = {:.2f}", sim_hit.getEDep()); + m_log->debug(" time = {:.4f}[ns]", sim_hit.getTime()); + m_log->debug(" particle time = {}[ns]", sim_hit.getMCParticle().getTime()); + m_log->debug(" time smearing: {:.4f}, resulting time = {:.4f} [ns]", time_smearing, + result_time); + m_log->debug(" hit_time_stamp: {} [~ps]", hit_time_stamp); + + if (sim_hit.getEDep() < m_cfg.threshold) { + m_log->debug(" edep is below threshold of {:.2f} [keV]", m_cfg.threshold / dd4hep::keV); + continue; } - for (auto item : cell_hit_map) { - raw_hits->push_back(item.second); + if (cell_hit_map.count(sim_hit.getCellID()) == 0) { + // This cell doesn't have hits + cell_hit_map[sim_hit.getCellID()] = { + sim_hit.getCellID(), (std::int32_t)std::llround(sim_hit.getEDep() * 1e6), + hit_time_stamp // ns->ps + }; + } else { + // There is previous values in the cell + auto& hit = cell_hit_map[sim_hit.getCellID()]; + m_log->debug(" Hit already exists in cell ID={}, prev. hit time: {}", sim_hit.getCellID(), + hit.getTimeStamp()); + + // keep earliest time for hit + auto time_stamp = hit.getTimeStamp(); + hit.setTimeStamp(std::min(hit_time_stamp, hit.getTimeStamp())); + + // sum deposited energy + auto charge = hit.getCharge(); + hit.setCharge(charge + (std::int32_t)std::llround(sim_hit.getEDep() * 1e6)); } + } + + for (auto item : cell_hit_map) { + raw_hits->push_back(item.second); + } } } // namespace eicrecon diff --git a/src/algorithms/digi/SiliconTrackerDigi.h b/src/algorithms/digi/SiliconTrackerDigi.h index 0af356edd5..c82c796cc1 100644 --- a/src/algorithms/digi/SiliconTrackerDigi.h +++ b/src/algorithms/digi/SiliconTrackerDigi.h @@ -18,44 +18,37 @@ namespace eicrecon { - using SiliconTrackerDigiAlgorithm = algorithms::Algorithm< - algorithms::Input< - edm4hep::SimTrackerHitCollection - >, - algorithms::Output< - edm4eic::RawTrackerHitCollection - > - >; - - class SiliconTrackerDigi - : public SiliconTrackerDigiAlgorithm, - public WithPodConfig { - - public: - SiliconTrackerDigi(std::string_view name) - : SiliconTrackerDigiAlgorithm{name, - {"inputHitCollection"}, - {"outputRawHitCollection"}, - "Apply threshold, digitize within ADC range, " - "convert time with smearing resolution."} {} +using SiliconTrackerDigiAlgorithm = + algorithms::Algorithm, + algorithms::Output>; + +class SiliconTrackerDigi : public SiliconTrackerDigiAlgorithm, + public WithPodConfig { - void init(std::shared_ptr& logger); - void process(const Input&, const Output&) const final; +public: + SiliconTrackerDigi(std::string_view name) + : SiliconTrackerDigiAlgorithm{name, + {"inputHitCollection"}, + {"outputRawHitCollection"}, + "Apply threshold, digitize within ADC range, " + "convert time with smearing resolution."} {} - private: - /** algorithm logger */ - std::shared_ptr m_log; + void init(std::shared_ptr& logger); + void process(const Input&, const Output&) const final; - /** Random number generation*/ - TRandomMixMax m_random; - std::function m_gauss; +private: + /** algorithm logger */ + std::shared_ptr m_log; - // FIXME replace with standard random engine - //std::default_random_engine generator; // TODO: need something more appropriate here - //std::normal_distribution m_normDist; // defaults to mean=0, sigma=1 + /** Random number generation*/ + TRandomMixMax m_random; + std::function m_gauss; - //algorithms::Generator m_rng = algorithms::RandomSvc::instance().generator(); + // FIXME replace with standard random engine + //std::default_random_engine generator; // TODO: need something more appropriate here + //std::normal_distribution m_normDist; // defaults to mean=0, sigma=1 - }; + //algorithms::Generator m_rng = algorithms::RandomSvc::instance().generator(); +}; -} // eicrecon +} // namespace eicrecon diff --git a/src/algorithms/digi/SiliconTrackerDigiConfig.h b/src/algorithms/digi/SiliconTrackerDigiConfig.h index fb66db252b..e8c4964440 100644 --- a/src/algorithms/digi/SiliconTrackerDigiConfig.h +++ b/src/algorithms/digi/SiliconTrackerDigiConfig.h @@ -7,11 +7,11 @@ namespace eicrecon { - struct SiliconTrackerDigiConfig { - // sub-systems should overwrite their own - // NB: be aware of thresholds in npsim! E.g. https://github.com/eic/npsim/pull/9/files - double threshold = 0 * dd4hep::keV; - double timeResolution = 8; /// TODO 8 of what units??? Same TODO in juggler. Probably [ns] - }; +struct SiliconTrackerDigiConfig { + // sub-systems should overwrite their own + // NB: be aware of thresholds in npsim! E.g. https://github.com/eic/npsim/pull/9/files + double threshold = 0 * dd4hep::keV; + double timeResolution = 8; /// TODO 8 of what units??? Same TODO in juggler. Probably [ns] +}; -} // eicrecon +} // namespace eicrecon diff --git a/src/algorithms/fardetectors/MatrixTransferStatic.cc b/src/algorithms/fardetectors/MatrixTransferStatic.cc index 48331e6c67..3e826f7f7d 100644 --- a/src/algorithms/fardetectors/MatrixTransferStatic.cc +++ b/src/algorithms/fardetectors/MatrixTransferStatic.cc @@ -20,128 +20,123 @@ #include "algorithms/fardetectors/MatrixTransferStaticConfig.h" -void eicrecon::MatrixTransferStatic::init() { +void eicrecon::MatrixTransferStatic::init() {} -} - -void eicrecon::MatrixTransferStatic::process( - const MatrixTransferStatic::Input& input, - const MatrixTransferStatic::Output& output) const { +void eicrecon::MatrixTransferStatic::process(const MatrixTransferStatic::Input& input, + const MatrixTransferStatic::Output& output) const { const auto [mcparts, rechits] = input; - auto [outputParticles] = output; + auto [outputParticles] = output; std::vector> aX(m_cfg.aX); std::vector> aY(m_cfg.aY); //----- Define constants here ------ - double aXinv[2][2] = {{0.0, 0.0}, - {0.0, 0.0}}; - double aYinv[2][2] = {{0.0, 0.0}, - {0.0, 0.0}}; - - double nomMomentum = m_cfg.nomMomentum; //extract the nominal value first -- will be overwritten by MCParticle - double local_x_offset = m_cfg.local_x_offset; - double local_y_offset = m_cfg.local_y_offset; - double local_x_slope_offset = m_cfg.local_x_slope_offset; - double local_y_slope_offset = m_cfg.local_y_slope_offset; - - double numBeamProtons = 0; + double aXinv[2][2] = {{0.0, 0.0}, {0.0, 0.0}}; + double aYinv[2][2] = {{0.0, 0.0}, {0.0, 0.0}}; + + double nomMomentum = + m_cfg.nomMomentum; //extract the nominal value first -- will be overwritten by MCParticle + double local_x_offset = m_cfg.local_x_offset; + double local_y_offset = m_cfg.local_y_offset; + double local_x_slope_offset = m_cfg.local_x_slope_offset; + double local_y_slope_offset = m_cfg.local_y_slope_offset; + + double numBeamProtons = 0; double runningMomentum = 0.0; - for (const auto& p: *mcparts) { - if(mcparts->size() == 1 && p.getPDG() == 2212){ - runningMomentum = p.getMomentum().z; - numBeamProtons++; - } - if (p.getGeneratorStatus() == 4 && p.getPDG() == 2212) { //look for "beam" proton - runningMomentum += p.getMomentum().z; - numBeamProtons++; - } + for (const auto& p : *mcparts) { + if (mcparts->size() == 1 && p.getPDG() == 2212) { + runningMomentum = p.getMomentum().z; + numBeamProtons++; + } + if (p.getGeneratorStatus() == 4 && p.getPDG() == 2212) { //look for "beam" proton + runningMomentum += p.getMomentum().z; + numBeamProtons++; + } } - if(numBeamProtons == 0) {error("No beam protons to choose matrix!! Skipping!!"); return;} + if (numBeamProtons == 0) { + error("No beam protons to choose matrix!! Skipping!!"); + return; + } - nomMomentum = runningMomentum/numBeamProtons; + nomMomentum = runningMomentum / numBeamProtons; double nomMomentumError = 0.05; //This is a temporary solution to get the beam energy information //needed to select the correct matrix - if(abs(275.0 - nomMomentum)/275.0 < nomMomentumError){ + if (abs(275.0 - nomMomentum) / 275.0 < nomMomentumError) { - aX[0][0] = 3.251116; //a - aX[0][1] = 30.285734; //b - aX[1][0] = 0.186036375; //c - aX[1][1] = 0.196439472; //d + aX[0][0] = 3.251116; //a + aX[0][1] = 30.285734; //b + aX[1][0] = 0.186036375; //c + aX[1][1] = 0.196439472; //d - aY[0][0] = 0.4730500000; //a - aY[0][1] = 3.062999454; //b - aY[1][0] = 0.0204108951; //c - aY[1][1] = -0.139318692; //d + aY[0][0] = 0.4730500000; //a + aY[0][1] = 3.062999454; //b + aY[1][0] = 0.0204108951; //c + aY[1][1] = -0.139318692; //d - local_x_offset = -0.339334; - local_y_offset = -0.000299454; - local_x_slope_offset = -0.219603248; - local_y_slope_offset = -0.000176128; + local_x_offset = -0.339334; + local_y_offset = -0.000299454; + local_x_slope_offset = -0.219603248; + local_y_slope_offset = -0.000176128; - } - else if(abs(100.0 - nomMomentum)/100.0 < nomMomentumError){ + } else if (abs(100.0 - nomMomentum) / 100.0 < nomMomentumError) { - aX[0][0] = 3.152158; //a - aX[0][1] = 20.852072; //b - aX[1][0] = 0.181649517; //c - aX[1][1] = -0.303998487; //d + aX[0][0] = 3.152158; //a + aX[0][1] = 20.852072; //b + aX[1][0] = 0.181649517; //c + aX[1][1] = -0.303998487; //d - aY[0][0] = 0.5306100000; //a - aY[0][1] = 3.19623343; //b - aY[1][0] = 0.0226283320; //c - aY[1][1] = -0.082666019; //d + aY[0][0] = 0.5306100000; //a + aY[0][1] = 3.19623343; //b + aY[1][0] = 0.0226283320; //c + aY[1][1] = -0.082666019; //d - local_x_offset = -0.329072; - local_y_offset = -0.00028343; - local_x_slope_offset = -0.218525084; - local_y_slope_offset = -0.00015321; + local_x_offset = -0.329072; + local_y_offset = -0.00028343; + local_x_slope_offset = -0.218525084; + local_y_slope_offset = -0.00015321; - } - else if(abs(41.0 - nomMomentum)/41.0 < nomMomentumError){ + } else if (abs(41.0 - nomMomentum) / 41.0 < nomMomentumError) { - aX[0][0] = 3.135997; //a - aX[0][1] = 18.482273; //b - aX[1][0] = 0.176479921; //c - aX[1][1] = -0.497839483; //d + aX[0][0] = 3.135997; //a + aX[0][1] = 18.482273; //b + aX[1][0] = 0.176479921; //c + aX[1][1] = -0.497839483; //d - aY[0][0] = 0.4914400000; //a - aY[0][1] = 4.53857451; //b - aY[1][0] = 0.0179664765; //c - aY[1][1] = 0.004160679; //d + aY[0][0] = 0.4914400000; //a + aY[0][1] = 4.53857451; //b + aY[1][0] = 0.0179664765; //c + aY[1][1] = 0.004160679; //d - local_x_offset = -0.283273; - local_y_offset = -0.00552451; - local_x_slope_offset = -0.21174031; - local_y_slope_offset = -0.003212011; + local_x_offset = -0.283273; + local_y_offset = -0.00552451; + local_x_slope_offset = -0.21174031; + local_y_slope_offset = -0.003212011; - } - else if(abs(135.0 - nomMomentum)/135.0 < nomMomentumError){ //135 GeV deuterons + } else if (abs(135.0 - nomMomentum) / 135.0 < nomMomentumError) { //135 GeV deuterons - aX[0][0] = 1.6248; - aX[0][1] = 12.966293; - aX[1][0] = 0.1832; - aX[1][1] = -2.8636535; + aX[0][0] = 1.6248; + aX[0][1] = 12.966293; + aX[1][0] = 0.1832; + aX[1][1] = -2.8636535; - aY[0][0] = 0.0001674; //a - aY[0][1] = -28.6003; //b - aY[1][0] = 0.0000837; //c - aY[1][1] = -2.87985; //d + aY[0][0] = 0.0001674; //a + aY[0][1] = -28.6003; //b + aY[1][0] = 0.0000837; //c + aY[1][1] = -2.87985; //d - local_x_offset = -11.9872; - local_y_offset = -0.0146; - local_x_slope_offset = -14.75315; - local_y_slope_offset = -0.0073; + local_x_offset = -11.9872; + local_y_offset = -0.0146; + local_x_slope_offset = -14.75315; + local_y_slope_offset = -0.0073; - } - else { + } else { error("MatrixTransferStatic:: No valid matrix found to match beam momentum!! Skipping!!"); return; } @@ -153,11 +148,10 @@ void eicrecon::MatrixTransferStatic::process( return; } - aXinv[0][0] = aX[1][1] / determinant; + aXinv[0][0] = aX[1][1] / determinant; aXinv[0][1] = -aX[0][1] / determinant; aXinv[1][0] = -aX[1][0] / determinant; - aXinv[1][1] = aX[0][0] / determinant; - + aXinv[1][1] = aX[0][0] / determinant; determinant = aY[0][0] * aY[1][1] - aY[0][1] * aY[1][0]; @@ -166,14 +160,14 @@ void eicrecon::MatrixTransferStatic::process( return; } - aYinv[0][0] = aY[1][1] / determinant; + aYinv[0][0] = aY[1][1] / determinant; aYinv[0][1] = -aY[0][1] / determinant; aYinv[1][0] = -aY[1][0] / determinant; - aYinv[1][1] = aY[0][0] / determinant; + aYinv[1][1] = aY[0][0] / determinant; //---- begin Reconstruction code ---- - edm4hep::Vector3f goodHit[2] = {{0.0,0.0,0.0},{0.0,0.0,0.0}}; + edm4hep::Vector3f goodHit[2] = {{0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}}; double goodHitX[2] = {0.0, 0.0}; double goodHitY[2] = {0.0, 0.0}; @@ -182,41 +176,39 @@ void eicrecon::MatrixTransferStatic::process( bool goodHit1 = false; bool goodHit2 = false; - for (const auto &h: *rechits) { + for (const auto& h : *rechits) { auto cellID = h.getCellID(); // The actual hit position in Global Coordinates auto gpos = m_converter->position(cellID); // local positions auto volman = m_detector->volumeManager(); - auto local = volman.lookupDetElement(cellID); + auto local = volman.lookupDetElement(cellID); - auto pos0 = local.nominal().worldToLocal(dd4hep::Position(gpos.x(), gpos.y(), gpos.z())); // hit position in local coordinates + auto pos0 = local.nominal().worldToLocal( + dd4hep::Position(gpos.x(), gpos.y(), gpos.z())); // hit position in local coordinates // convert into mm - gpos = gpos/dd4hep::mm; - pos0 = pos0/dd4hep::mm; + gpos = gpos / dd4hep::mm; + pos0 = pos0 / dd4hep::mm; //std::cout << "gpos.z() = " << gpos.z() << " pos0.z() = " << pos0.z() << std::endl; //std::cout << "[gpos.x(), gpos.y()] = " << gpos.x() <<", "<< gpos.y() << " and [pos0.x(), pos0.y()] = "<< pos0.x()<< ", " << pos0.y() << std::endl; - if(!goodHit2 && gpos.z() > m_cfg.hit2minZ && gpos.z() < m_cfg.hit2maxZ){ + if (!goodHit2 && gpos.z() > m_cfg.hit2minZ && gpos.z() < m_cfg.hit2maxZ) { goodHit[1].x = pos0.x(); goodHit[1].y = pos0.y(); goodHit[1].z = gpos.z(); - goodHit2 = true; - + goodHit2 = true; } - if(!goodHit1 && gpos.z() > m_cfg.hit1minZ && gpos.z() < m_cfg.hit1maxZ){ + if (!goodHit1 && gpos.z() > m_cfg.hit1minZ && gpos.z() < m_cfg.hit1maxZ) { goodHit[0].x = pos0.x(); goodHit[0].y = pos0.y(); goodHit[0].z = gpos.z(); - goodHit1 = true; - + goodHit1 = true; } - } // NB: @@ -234,13 +226,12 @@ void eicrecon::MatrixTransferStatic::process( if (base == 0) { info("Detector separation = 0! Cannot calculate slope!"); - } - else{ + } else { double Xip[2] = {0.0, 0.0}; - double Xrp[2] = {XL[1], ((XL[1] - XL[0]) / (base))/dd4hep::mrad - local_x_slope_offset}; + double Xrp[2] = {XL[1], ((XL[1] - XL[0]) / (base)) / dd4hep::mrad - local_x_slope_offset}; double Yip[2] = {0.0, 0.0}; - double Yrp[2] = {YL[1], ((YL[1] - YL[0]) / (base))/dd4hep::mrad - local_y_slope_offset}; + double Yrp[2] = {YL[1], ((YL[1] - YL[0]) / (base)) / dd4hep::mrad - local_y_slope_offset}; // use the hit information and calculated slope at the RP + the transfer matrix inverse to calculate the // Polar Angle and deltaP at the IP @@ -257,19 +248,20 @@ void eicrecon::MatrixTransferStatic::process( double rsy = Yip[1] * dd4hep::mrad; // calculate momentum magnitude from measured deltaP – using thin lens optics. - double p = nomMomentum * (1 + 0.01 * Xip[0]); + double p = nomMomentum * (1 + 0.01 * Xip[0]); double norm = std::sqrt(1.0 + rsx * rsx + rsy * rsy); - edm4hep::Vector3f prec = {static_cast(p * rsx / norm), static_cast(p * rsy / norm), - static_cast(p / norm)}; - auto refPoint = goodHit[0]; + edm4hep::Vector3f prec = {static_cast(p * rsx / norm), + static_cast(p * rsy / norm), static_cast(p / norm)}; + auto refPoint = goodHit[0]; //----- end reconstruction code ------ edm4eic::MutableReconstructedParticle reconTrack; reconTrack.setType(0); reconTrack.setMomentum(prec); - reconTrack.setEnergy(std::hypot(edm4hep::utils::magnitude(reconTrack.getMomentum()), m_cfg.partMass)); + reconTrack.setEnergy( + std::hypot(edm4hep::utils::magnitude(reconTrack.getMomentum()), m_cfg.partMass)); reconTrack.setReferencePoint(refPoint); reconTrack.setCharge(m_cfg.partCharge); reconTrack.setMass(m_cfg.partMass); @@ -279,5 +271,4 @@ void eicrecon::MatrixTransferStatic::process( outputParticles->push_back(reconTrack); } } // end enough hits for matrix reco - } diff --git a/src/algorithms/fardetectors/MatrixTransferStatic.h b/src/algorithms/fardetectors/MatrixTransferStatic.h index b823e37e51..8f9b4e4f53 100644 --- a/src/algorithms/fardetectors/MatrixTransferStatic.h +++ b/src/algorithms/fardetectors/MatrixTransferStatic.h @@ -19,33 +19,26 @@ namespace eicrecon { - using MatrixTransferStaticAlgorithm = algorithms::Algorithm< - algorithms::Input< - edm4hep::MCParticleCollection, - edm4eic::TrackerHitCollection - >, - algorithms::Output< - edm4eic::ReconstructedParticleCollection - > - >; - - class MatrixTransferStatic - : public MatrixTransferStaticAlgorithm, - public WithPodConfig { - - public: - MatrixTransferStatic(std::string_view name) - : MatrixTransferStaticAlgorithm{name, - {"mcParticles", "inputHitCollection"}, - {"outputParticleCollection"}, - "Apply matrix method reconstruction to hits."} {} - - void init() final; - void process(const Input&, const Output&) const final; +using MatrixTransferStaticAlgorithm = algorithms::Algorithm< + algorithms::Input, + algorithms::Output>; - private: - const dd4hep::Detector* m_detector{algorithms::GeoSvc::instance().detector()}; - const dd4hep::rec::CellIDPositionConverter* m_converter{algorithms::GeoSvc::instance().cellIDPositionConverter()}; +class MatrixTransferStatic : public MatrixTransferStaticAlgorithm, + public WithPodConfig { - }; -} +public: + MatrixTransferStatic(std::string_view name) + : MatrixTransferStaticAlgorithm{name, + {"mcParticles", "inputHitCollection"}, + {"outputParticleCollection"}, + "Apply matrix method reconstruction to hits."} {} + + void init() final; + void process(const Input&, const Output&) const final; + +private: + const dd4hep::Detector* m_detector{algorithms::GeoSvc::instance().detector()}; + const dd4hep::rec::CellIDPositionConverter* m_converter{ + algorithms::GeoSvc::instance().cellIDPositionConverter()}; +}; +} // namespace eicrecon diff --git a/src/algorithms/fardetectors/MatrixTransferStaticConfig.h b/src/algorithms/fardetectors/MatrixTransferStaticConfig.h index a559e1dc6a..2cb6956a70 100644 --- a/src/algorithms/fardetectors/MatrixTransferStaticConfig.h +++ b/src/algorithms/fardetectors/MatrixTransferStaticConfig.h @@ -5,43 +5,39 @@ namespace eicrecon { - struct MatrixTransferStaticConfig { - - float partMass {0.938272}; - float partCharge{1}; - long long partPDG {2212}; - - // Defaults here are for RPOTS - double local_x_offset {0.0}; - double local_y_offset {0.0}; - double local_x_slope_offset{-0.00622147}; - double local_y_slope_offset{-0.0451035}; - double crossingAngle {0.025}; - double nomMomentum {100.0}; - - //std::vector> aX = {{2.102403743, 29.11067626}, - // {0.186640381, 0.192604619}}; - //std::vector> aY = {{0.0000159900, 3.94082098}, - // {0.0000079946, -0.1402995}}; - - - //x_offset = 0.00979216; - //y_offset = -0.00778646; - //x_slope_offset = 0.004526961; - //y_slope_offset = -0.003907849; - - std::vector> aX = {{2.03459216, 22.85780784}, - {0.179641961, -0.306626961}}; - std::vector> aY = {{0.38879, 3.71612646}, - {0.022685, -0.003907849}}; - - double hit1minZ{0}; - double hit1maxZ{0}; - double hit2minZ{0}; - double hit2maxZ{0}; - - std::string readout{""}; - - }; - -} +struct MatrixTransferStaticConfig { + + float partMass{0.938272}; + float partCharge{1}; + long long partPDG{2212}; + + // Defaults here are for RPOTS + double local_x_offset{0.0}; + double local_y_offset{0.0}; + double local_x_slope_offset{-0.00622147}; + double local_y_slope_offset{-0.0451035}; + double crossingAngle{0.025}; + double nomMomentum{100.0}; + + //std::vector> aX = {{2.102403743, 29.11067626}, + // {0.186640381, 0.192604619}}; + //std::vector> aY = {{0.0000159900, 3.94082098}, + // {0.0000079946, -0.1402995}}; + + //x_offset = 0.00979216; + //y_offset = -0.00778646; + //x_slope_offset = 0.004526961; + //y_slope_offset = -0.003907849; + + std::vector> aX = {{2.03459216, 22.85780784}, {0.179641961, -0.306626961}}; + std::vector> aY = {{0.38879, 3.71612646}, {0.022685, -0.003907849}}; + + double hit1minZ{0}; + double hit1maxZ{0}; + double hit2minZ{0}; + double hit2maxZ{0}; + + std::string readout{""}; +}; + +} // namespace eicrecon diff --git a/src/algorithms/interfaces/WithPodConfig.h b/src/algorithms/interfaces/WithPodConfig.h index ac5a113ceb..dc253f863f 100644 --- a/src/algorithms/interfaces/WithPodConfig.h +++ b/src/algorithms/interfaces/WithPodConfig.h @@ -5,34 +5,35 @@ #pragma once namespace eicrecon { - /** +/** * This struct might be used for factories that has no underlying config class, * for example: * WithPodConfig */ - struct NoConfig { - }; +struct NoConfig {}; - /** +/** * Small helper class that brings common functions interface for classes that have POD type config * @tparam ConfigT * * @example: * */ - template - class WithPodConfig { - public: - using ConfigType = ConfigT; +template class WithPodConfig { +public: + using ConfigType = ConfigT; - /// Get a configuration to be changed - ConfigT& getConfig() {return m_cfg;} + /// Get a configuration to be changed + ConfigT& getConfig() { return m_cfg; } - /// Sets a configuration (config is properly copyible) - ConfigT& applyConfig(ConfigT cfg) { m_cfg = cfg; return m_cfg;} + /// Sets a configuration (config is properly copyible) + ConfigT& applyConfig(ConfigT cfg) { + m_cfg = cfg; + return m_cfg; + } - protected: - /** configuration parameters **/ - ConfigT m_cfg; - }; -} +protected: + /** configuration parameters **/ + ConfigT m_cfg; +}; +} // namespace eicrecon diff --git a/src/algorithms/meta/CollectionCollector.h b/src/algorithms/meta/CollectionCollector.h index accf942f42..baaf51d0ad 100644 --- a/src/algorithms/meta/CollectionCollector.h +++ b/src/algorithms/meta/CollectionCollector.h @@ -11,43 +11,41 @@ namespace eicrecon { - template - using CollectionCollectorAlgorithm = algorithms::Algorithm< - typename algorithms::Input>, - typename algorithms::Output - >; +template +using CollectionCollectorAlgorithm = + algorithms::Algorithm>, + typename algorithms::Output>; - template - class CollectionCollector : public CollectionCollectorAlgorithm { +template class CollectionCollector : public CollectionCollectorAlgorithm { - public: - CollectionCollector(std::string_view name) +public: + CollectionCollector(std::string_view name) : CollectionCollectorAlgorithm{name, - {"inputCollections"}, - {"outputCollection"}, - "Merge content of collections into one subset collection" - }{} + {"inputCollections"}, + {"outputCollection"}, + "Merge content of collections into one subset collection"} { + } - void init(std::shared_ptr& logger){ // set logger - m_log = logger; - }; + void init(std::shared_ptr& logger) { // set logger + m_log = logger; + }; - void process(const typename CollectionCollector::Input& input, const typename CollectionCollector::Output& output) const final{ + void process(const typename CollectionCollector::Input& input, + const typename CollectionCollector::Output& output) const final { - const auto [in_collections] = input; - auto [out_collection] = output; + const auto [in_collections] = input; + auto [out_collection] = output; - out_collection->setSubsetCollection(); + out_collection->setSubsetCollection(); - for (const auto& collection : in_collections) { - for (const auto& hit : *collection) { - out_collection->push_back(hit); - } + for (const auto& collection : in_collections) { + for (const auto& hit : *collection) { + out_collection->push_back(hit); } } + } - private: - std::shared_ptr m_log; // logger - - }; -} // eicrecon +private: + std::shared_ptr m_log; // logger +}; +} // namespace eicrecon diff --git a/src/algorithms/meta/SubDivideCollection.h b/src/algorithms/meta/SubDivideCollection.h index de12a3712d..036033325a 100644 --- a/src/algorithms/meta/SubDivideCollection.h +++ b/src/algorithms/meta/SubDivideCollection.h @@ -15,49 +15,44 @@ namespace eicrecon { - template - using SubDivideCollectionAlgorithm = algorithms::Algorithm< - typename algorithms::Input, - typename algorithms::Output> - >; +template +using SubDivideCollectionAlgorithm = + algorithms::Algorithm, + typename algorithms::Output>>; +template +class SubDivideCollection : public SubDivideCollectionAlgorithm, + public WithPodConfig> { - template - class SubDivideCollection : public SubDivideCollectionAlgorithm, public WithPodConfig> { - - public: - SubDivideCollection(std::string_view name) +public: + SubDivideCollection(std::string_view name) : SubDivideCollectionAlgorithm{name, - {"inputCollection"}, - {"outputCollection"}, - "Sub-Divide collection" - }, - WithPodConfig>() { - }; - - void init() final { }; - - void process(const typename SubDivideCollectionAlgorithm::Input& input, const typename SubDivideCollectionAlgorithm::Output& output) const final{ - - const auto [entries] = input; - auto [subdivided_entries] = output; + {"inputCollection"}, + {"outputCollection"}, + "Sub-Divide collection"} + , WithPodConfig>(){}; - for( auto out : subdivided_entries){ - out->setSubsetCollection(); - } + void init() final {}; - for (const auto& entry : *entries) { + void process(const typename SubDivideCollectionAlgorithm::Input& input, + const typename SubDivideCollectionAlgorithm::Output& output) const final { - auto div_indices = this->m_cfg.function(entry); + const auto [entries] = input; + auto [subdivided_entries] = output; - for (auto index : div_indices){ - subdivided_entries[index]->push_back(entry); - } + for (auto out : subdivided_entries) { + out->setSubsetCollection(); + } - } + for (const auto& entry : *entries) { - }; + auto div_indices = this->m_cfg.function(entry); + for (auto index : div_indices) { + subdivided_entries[index]->push_back(entry); + } + } }; +}; -} // eicrecon +} // namespace eicrecon diff --git a/src/algorithms/meta/SubDivideCollectionConfig.h b/src/algorithms/meta/SubDivideCollectionConfig.h index 47ef9f66f1..d10721a2a8 100644 --- a/src/algorithms/meta/SubDivideCollectionConfig.h +++ b/src/algorithms/meta/SubDivideCollectionConfig.h @@ -5,9 +5,8 @@ namespace eicrecon { - template - struct SubDivideCollectionConfig { - std::function(const T&)> function; - }; +template struct SubDivideCollectionConfig { + std::function(const T&)> function; +}; -} // eicrecon +} // namespace eicrecon diff --git a/src/algorithms/meta/SubDivideFunctors.h b/src/algorithms/meta/SubDivideFunctors.h index 090b54ad89..d11a807ae9 100644 --- a/src/algorithms/meta/SubDivideFunctors.h +++ b/src/algorithms/meta/SubDivideFunctors.h @@ -10,27 +10,24 @@ namespace eicrecon { // ---------------------------------------------------------------------------- // Functor to split collection based on a range of values // ---------------------------------------------------------------------------- -template -class RangeSplit { +template class RangeSplit { public: - - RangeSplit(std::vector> ranges) : m_ranges(ranges) {}; - - template - std::vector operator()(T& instance) const { - std::vector ids; - //Check if requested value is within the ranges - for(size_t i = 0; i < m_ranges.size(); i++){ - if((instance.*MemberFunctionPtr)() > m_ranges[i].first && (instance.*MemberFunctionPtr)() < m_ranges[i].second){ - ids.push_back(i); - } - } - return ids; + RangeSplit(std::vector> ranges) : m_ranges(ranges){}; + + template std::vector operator()(T& instance) const { + std::vector ids; + //Check if requested value is within the ranges + for (size_t i = 0; i < m_ranges.size(); i++) { + if ((instance.*MemberFunctionPtr)() > m_ranges[i].first && + (instance.*MemberFunctionPtr)() < m_ranges[i].second) { + ids.push_back(i); + } } + return ids; + } private: - std::vector> m_ranges; - + std::vector> m_ranges; }; // ---------------------------------------------------------------------------- @@ -38,76 +35,68 @@ class RangeSplit { // ---------------------------------------------------------------------------- class GeometrySplit { public: + GeometrySplit(std::vector> ids, std::string readout, + std::vector divisions) + : m_ids(ids), m_readout(readout), m_divisions(divisions){}; - GeometrySplit(std::vector> ids, std::string readout, std::vector divisions) - : m_ids(ids), m_readout(readout), m_divisions(divisions){}; - - template - std::vector operator()(T& instance) const { + template std::vector operator()(T& instance) const { - // Initialize the decoder and division ids on the first function call - std::call_once(*is_init, &GeometrySplit::init, this); + // Initialize the decoder and division ids on the first function call + std::call_once(*is_init, &GeometrySplit::init, this); - //Check which detector division to put the hit into - auto cellID = instance.getCellID(); - std::vector det_ids; - for(auto d : m_div_ids){ - det_ids.push_back(m_id_dec->get(cellID, d)); - } - auto index = std::find(m_ids.begin(),m_ids.end(),det_ids); + //Check which detector division to put the hit into + auto cellID = instance.getCellID(); + std::vector det_ids; + for (auto d : m_div_ids) { + det_ids.push_back(m_id_dec->get(cellID, d)); + } + auto index = std::find(m_ids.begin(), m_ids.end(), det_ids); - std::vector ids; - if(index != m_ids.end()){ - ids.push_back(std::distance(m_ids.begin(),index)); - } - return ids; + std::vector ids; + if (index != m_ids.end()) { + ids.push_back(std::distance(m_ids.begin(), index)); } + return ids; + } private: - - void init() const { - m_id_dec = algorithms::GeoSvc::instance().detector()->readout(m_readout).idSpec().decoder(); - for (auto d : m_divisions){ - m_div_ids.push_back(m_id_dec->index(d)); - } + void init() const { + m_id_dec = algorithms::GeoSvc::instance().detector()->readout(m_readout).idSpec().decoder(); + for (auto d : m_divisions) { + m_div_ids.push_back(m_id_dec->index(d)); } + } - std::vector> m_ids; - std::vector m_divisions; - std::string m_readout; - - mutable std::shared_ptr is_init = std::make_shared(); - mutable dd4hep::DDSegmentation::BitFieldCoder* m_id_dec; - mutable std::vector m_div_ids; + std::vector> m_ids; + std::vector m_divisions; + std::string m_readout; + mutable std::shared_ptr is_init = std::make_shared(); + mutable dd4hep::DDSegmentation::BitFieldCoder* m_id_dec; + mutable std::vector m_div_ids; }; - // ---------------------------------------------------------------------------- // Functor to split collection based on any number of collection values // ---------------------------------------------------------------------------- -template -class ValueSplit { +template class ValueSplit { public: - - ValueSplit(std::vector> ids) : m_ids(ids) {}; - - template - std::vector operator()(T& instance) const { - std::vector ids; - // Check if requested value matches any configuration combinations - std::vector values; - (values.push_back((instance.*MemberFunctionPtrs)()), ...); - auto index = std::find(m_ids.begin(),m_ids.end(),values); - if(index != m_ids.end()){ - ids.push_back(std::distance(m_ids.begin(),index)); - } - return ids; + ValueSplit(std::vector> ids) : m_ids(ids){}; + + template std::vector operator()(T& instance) const { + std::vector ids; + // Check if requested value matches any configuration combinations + std::vector values; + (values.push_back((instance.*MemberFunctionPtrs)()), ...); + auto index = std::find(m_ids.begin(), m_ids.end(), values); + if (index != m_ids.end()) { + ids.push_back(std::distance(m_ids.begin(), index)); } + return ids; + } private: - std::vector> m_ids; - + std::vector> m_ids; }; -} // eicrecon +} // namespace eicrecon diff --git a/src/algorithms/pid/ConvertParticleID.h b/src/algorithms/pid/ConvertParticleID.h index 6ee30965c6..a92fb4694e 100644 --- a/src/algorithms/pid/ConvertParticleID.h +++ b/src/algorithms/pid/ConvertParticleID.h @@ -16,69 +16,62 @@ namespace eicrecon { - class ConvertParticleID { - public: - - // index map, used for external access to the converted objects - using IndexMap = std::map; // - - // convert edm4eic::CherenkovParticleID hypotheses to list of edm4hep::ParticleID objects - // - requires input `CherenkovParticleID` object `in_pid` - // - adds output `ParticleID` objects to collection `out_pids` - // - sorted by likelihood, if `sort_by_likelihood==true` - // - returns a map of the new `out_pid` indices to new `ParticleID` IDs, so the caller can - // access the newly created `ParticleID` objects - static IndexMap ConvertToParticleIDs( - const edm4eic::CherenkovParticleID& in_pid, - edm4hep::ParticleIDCollection& out_pids, - bool sort_by_likelihood = false - ) - { - - // output vector of collection indices - IndexMap out_indices; - - // build list of (hypothesis index, hypothesis weight) - using HypIndex = std::pair; - std::vector hyp_indices; - for(std::size_t hyp_index=0; hyp_index b.second; } - ); - - // create and fill output objects - for(const auto& [hyp_index, hyp_weight] : hyp_indices) { - - // get the input hypothesis - auto in_hyp = in_pid.getHypotheses(hyp_index); - - // create output `ParticleID` object - auto out_index = out_pids.size(); - auto out_pid = out_pids.create(); - out_indices.insert({out_index, out_pid.getObjectID().index}); - - // fill scalars - out_pid.setPDG( static_cast (in_hyp.PDG) ); - out_pid.setLikelihood( static_cast (in_hyp.weight) ); - out_pid.setType( static_cast (0) ); // FIXME: not used yet - out_pid.setAlgorithmType( static_cast (0) ); // FIXME: not used yet - - // fill parameters vector - out_pid.addToParameters( static_cast (in_hyp.npe) ); // NPE for this hypothesis - - } - - return out_indices; - } - - }; // class ConvertParticleID +class ConvertParticleID { +public: + // index map, used for external access to the converted objects + using IndexMap = std::map; // + + // convert edm4eic::CherenkovParticleID hypotheses to list of edm4hep::ParticleID objects + // - requires input `CherenkovParticleID` object `in_pid` + // - adds output `ParticleID` objects to collection `out_pids` + // - sorted by likelihood, if `sort_by_likelihood==true` + // - returns a map of the new `out_pid` indices to new `ParticleID` IDs, so the caller can + // access the newly created `ParticleID` objects + static IndexMap ConvertToParticleIDs(const edm4eic::CherenkovParticleID& in_pid, + edm4hep::ParticleIDCollection& out_pids, + bool sort_by_likelihood = false) { + + // output vector of collection indices + IndexMap out_indices; + + // build list of (hypothesis index, hypothesis weight) + using HypIndex = + std::pair; + std::vector hyp_indices; + for (std::size_t hyp_index = 0; hyp_index < in_pid.hypotheses_size(); hyp_index++) + hyp_indices.push_back(HypIndex{hyp_index, in_pid.getHypotheses(hyp_index).weight}); + + // sort it by likelihood, if needed + if (sort_by_likelihood) + std::sort(hyp_indices.begin(), hyp_indices.end(), + [](HypIndex& a, HypIndex& b) { return a.second > b.second; }); + + // create and fill output objects + for (const auto& [hyp_index, hyp_weight] : hyp_indices) { + + // get the input hypothesis + auto in_hyp = in_pid.getHypotheses(hyp_index); + + // create output `ParticleID` object + auto out_index = out_pids.size(); + auto out_pid = out_pids.create(); + out_indices.insert({out_index, out_pid.getObjectID().index}); + + // fill scalars + out_pid.setPDG(static_cast(in_hyp.PDG)); + out_pid.setLikelihood( + static_cast(in_hyp.weight)); + out_pid.setType( + static_cast(0)); // FIXME: not used yet + out_pid.setAlgorithmType( + static_cast(0)); // FIXME: not used yet + + // fill parameters vector + out_pid.addToParameters(static_cast(in_hyp.npe)); // NPE for this hypothesis + } + + return out_indices; + } + +}; // class ConvertParticleID } // namespace eicrecon diff --git a/src/algorithms/pid/IrtCherenkovParticleID.cc b/src/algorithms/pid/IrtCherenkovParticleID.cc index 4b2cd508d6..ebd20e92c8 100644 --- a/src/algorithms/pid/IrtCherenkovParticleID.cc +++ b/src/algorithms/pid/IrtCherenkovParticleID.cc @@ -34,11 +34,8 @@ // AlgorithmInit //--------------------------------------------------------------------------- -void eicrecon::IrtCherenkovParticleID::AlgorithmInit( - CherenkovDetectorCollection* irt_det_coll, - std::shared_ptr& logger - ) -{ +void eicrecon::IrtCherenkovParticleID::AlgorithmInit(CherenkovDetectorCollection* irt_det_coll, + std::shared_ptr& logger) { // members m_irt_det_coll = irt_det_coll; m_log = logger; @@ -51,60 +48,62 @@ void eicrecon::IrtCherenkovParticleID::AlgorithmInit( // extract the the relevant `CherenkovDetector`, set to `m_irt_det` auto& detectors = m_irt_det_coll->GetDetectors(); - if(detectors.size() == 0) + if (detectors.size() == 0) throw std::runtime_error("No CherenkovDetectors found in input collection `irt_det_coll`"); - if(detectors.size() > 1) - m_log->warn("IrtCherenkovParticleID currently only supports 1 CherenkovDetector at a time; taking the first"); + if (detectors.size() > 1) + m_log->warn("IrtCherenkovParticleID currently only supports 1 CherenkovDetector at a time; " + "taking the first"); auto this_detector = *detectors.begin(); m_det_name = this_detector.first; m_irt_det = this_detector.second; - m_log->debug("Initializing IrtCherenkovParticleID algorithm for CherenkovDetector '{}'", m_det_name); + m_log->debug("Initializing IrtCherenkovParticleID algorithm for CherenkovDetector '{}'", + m_det_name); // readout decoding m_cell_mask = m_irt_det->GetReadoutCellMask(); m_log->debug("readout cellMask = {:#X}", m_cell_mask); // rebin refractive index tables to have `m_cfg.numRIndexBins` bins - m_log->trace("Rebinning refractive index tables to have {} bins",m_cfg.numRIndexBins); - for(auto [rad_name,irt_rad] : m_irt_det->Radiators()) { + m_log->trace("Rebinning refractive index tables to have {} bins", m_cfg.numRIndexBins); + for (auto [rad_name, irt_rad] : m_irt_det->Radiators()) { auto ri_lookup_table_orig = irt_rad->m_ri_lookup_table; irt_rad->m_ri_lookup_table.clear(); - irt_rad->m_ri_lookup_table = Tools::ApplyFineBinning( ri_lookup_table_orig, m_cfg.numRIndexBins ); + irt_rad->m_ri_lookup_table = Tools::ApplyFineBinning(ri_lookup_table_orig, m_cfg.numRIndexBins); // m_log->trace("- {}", rad_name); // for(auto [energy,rindex] : irt_rad->m_ri_lookup_table) m_log->trace(" {:>5} eV {:<}", energy, rindex); } // build `m_pid_radiators`, the list of radiators to use for PID m_log->debug("Obtain List of Radiators:"); - for(auto [rad_name,irt_rad] : m_irt_det->Radiators()) { - if(rad_name!="Filter") { - m_pid_radiators.insert({ std::string(rad_name), irt_rad }); + for (auto [rad_name, irt_rad] : m_irt_det->Radiators()) { + if (rad_name != "Filter") { + m_pid_radiators.insert({std::string(rad_name), irt_rad}); m_log->debug("- {}", rad_name.Data()); } } // check radiators' configuration, and pass it to `m_irt_det`'s radiators - for(auto [rad_name,irt_rad] : m_pid_radiators) { + for (auto [rad_name, irt_rad] : m_pid_radiators) { // find `cfg_rad`, the associated `IrtCherenkovParticleIDConfig` radiator auto cfg_rad_it = m_cfg.radiators.find(rad_name); - if(cfg_rad_it != m_cfg.radiators.end()) { + if (cfg_rad_it != m_cfg.radiators.end()) { auto cfg_rad = cfg_rad_it->second; // pass `cfg_rad` params to `irt_rad`, the IRT radiator - irt_rad->m_ID = Tools::GetRadiatorID(std::string(rad_name)); + irt_rad->m_ID = Tools::GetRadiatorID(std::string(rad_name)); irt_rad->m_AverageRefractiveIndex = cfg_rad.referenceRIndex; irt_rad->SetReferenceRefractiveIndex(cfg_rad.referenceRIndex); - if(cfg_rad.attenuation>0) + if (cfg_rad.attenuation > 0) irt_rad->SetReferenceAttenuationLength(cfg_rad.attenuation); - if(cfg_rad.smearing>0) { - if(cfg_rad.smearingMode=="uniform") + if (cfg_rad.smearing > 0) { + if (cfg_rad.smearingMode == "uniform") irt_rad->SetUniformSmearing(cfg_rad.smearing); - else if(cfg_rad.smearingMode=="gaussian") + else if (cfg_rad.smearingMode == "gaussian") irt_rad->SetGaussianSmearing(cfg_rad.smearing); else - m_log->error("Unknown smearing mode '{}' for {} radiator", cfg_rad.smearingMode, rad_name); + m_log->error("Unknown smearing mode '{}' for {} radiator", cfg_rad.smearingMode, + rad_name); } - } - else + } else m_log->error("Cannot find radiator '{}' in IrtCherenkovParticleIDConfig instance", rad_name); } @@ -112,76 +111,74 @@ void eicrecon::IrtCherenkovParticleID::AlgorithmInit( // FIXME: cannot use `TDatabasePDG` since it is not thread safe; until we // have a proper PDG database service, we hard-code the masses in Tools.h m_log->debug("List of particles for PID:"); - for(auto pdg : m_cfg.pdgList) { + for (auto pdg : m_cfg.pdgList) { auto mass = Tools::GetPDGMass(pdg); - m_pdg_mass.insert({ pdg, mass }); + m_pdg_mass.insert({pdg, mass}); m_log->debug(" {:>8} M={} GeV", pdg, mass); } - } - // AlgorithmChangeRun //--------------------------------------------------------------------------- -void eicrecon::IrtCherenkovParticleID::AlgorithmChangeRun() { -} - +void eicrecon::IrtCherenkovParticleID::AlgorithmChangeRun() {} // AlgorithmProcess //--------------------------------------------------------------------------- -std::map> eicrecon::IrtCherenkovParticleID::AlgorithmProcess( +std::map> +eicrecon::IrtCherenkovParticleID::AlgorithmProcess( std::map& in_charged_particles, - const edm4eic::RawTrackerHitCollection* in_raw_hits, - const edm4eic::MCRecoTrackerHitAssociationCollection* in_hit_assocs - ) -{ + const edm4eic::RawTrackerHitCollection* in_raw_hits, + const edm4eic::MCRecoTrackerHitAssociationCollection* in_hit_assocs) { // logging - m_log->trace("{:=^70}"," call IrtCherenkovParticleID::AlgorithmProcess "); + m_log->trace("{:=^70}", " call IrtCherenkovParticleID::AlgorithmProcess "); m_log->trace("number of raw sensor hits: {}", in_raw_hits->size()); m_log->trace("number of raw sensor hit with associated photons: {}", in_hit_assocs->size()); // start output collections std::map> result; - for(auto [rad_name,irt_rad] : m_pid_radiators) + for (auto [rad_name, irt_rad] : m_pid_radiators) result.insert({rad_name, std::make_unique()}); // check `in_charged_particles`: each radiator should have the same number of TrackSegments std::unordered_map in_charged_particle_size_distribution; - for(const auto& [rad_name, in_charged_particle] : in_charged_particles) { + for (const auto& [rad_name, in_charged_particle] : in_charged_particles) { ++in_charged_particle_size_distribution[in_charged_particle->size()]; } if (in_charged_particle_size_distribution.size() != 1) { std::vector in_charged_particle_sizes; - std::transform(in_charged_particles.begin(), in_charged_particles.end(), - std::back_inserter(in_charged_particle_sizes), - [](const auto& in_charged_particle) { return in_charged_particle.second->size(); }); - m_log->error("radiators have differing numbers of TrackSegments {}", fmt::join(in_charged_particle_sizes, ", ")); + std::transform( + in_charged_particles.begin(), in_charged_particles.end(), + std::back_inserter(in_charged_particle_sizes), + [](const auto& in_charged_particle) { return in_charged_particle.second->size(); }); + m_log->error("radiators have differing numbers of TrackSegments {}", + fmt::join(in_charged_particle_sizes, ", ")); return result; } // loop over charged particles ******************************************** - m_log->trace("{:#<70}","### CHARGED PARTICLES "); + m_log->trace("{:#<70}", "### CHARGED PARTICLES "); std::size_t num_charged_particles = in_charged_particle_size_distribution.begin()->first; - for(long i_charged_particle=0; i_charged_particletrace("{:-<70}", fmt::format("--- charged particle #{} ", i_charged_particle)); // start an `irt_particle`, for `IRT` auto irt_particle = std::make_unique(); // loop over radiators - for(auto [rad_name,irt_rad] : m_pid_radiators) { + for (auto [rad_name, irt_rad] : m_pid_radiators) { // get the `charged_particle` for this radiator auto charged_particle_list_it = in_charged_particles.find(rad_name); - if(charged_particle_list_it == in_charged_particles.end()) { + if (charged_particle_list_it == in_charged_particles.end()) { m_log->error("Cannot find radiator '{}' in `in_charged_particles`", rad_name); continue; } - const auto *charged_particle_list = charged_particle_list_it->second; - auto charged_particle = charged_particle_list->at(i_charged_particle); + const auto* charged_particle_list = charged_particle_list_it->second; + auto charged_particle = charged_particle_list->at(i_charged_particle); // set number of bins for this radiator and charged particle - if(charged_particle.points_size()==0) { + if (charged_particle.points_size() == 0) { m_log->trace("No propagated track points in radiator '{}'", rad_name); continue; } @@ -190,13 +187,13 @@ std::map> e // start a new IRT `RadiatorHistory` // - must be a raw pointer for `irt` compatibility // - it will be destroyed when `irt_particle` is destroyed - auto *irt_rad_history = new RadiatorHistory(); - irt_particle->StartRadiatorHistory({ irt_rad, irt_rad_history }); + auto* irt_rad_history = new RadiatorHistory(); + irt_particle->StartRadiatorHistory({irt_rad, irt_rad_history}); // loop over `TrackPoint`s of this `charged_particle`, adding each to the IRT radiator irt_rad->ResetLocations(); m_log->trace("TrackPoints in '{}' radiator:", rad_name); - for(const auto& point : charged_particle.getPoints()) { + for (const auto& point : charged_particle.getPoints()) { TVector3 position = Tools::PodioVector3_to_TVector3(point.position); TVector3 momentum = Tools::PodioVector3_to_TVector3(point.momentum); irt_rad->AddLocation(position, momentum); @@ -204,30 +201,28 @@ std::map> e Tools::PrintTVector3(m_log, " p", momentum); } - // loop over raw hits *************************************************** - m_log->trace("{:#<70}","### SENSOR HITS "); - for(const auto& raw_hit : *in_raw_hits) { + m_log->trace("{:#<70}", "### SENSOR HITS "); + for (const auto& raw_hit : *in_raw_hits) { // get MC photon(s), typically only used by cheat modes or trace logging // - loop over `in_hit_assocs`, searching for the matching hit association // - will not exist for noise hits edm4hep::MCParticle mc_photon; bool mc_photon_found = false; - if(m_cfg.cheatPhotonVertex || m_cfg.cheatTrueRadiator) { - for(const auto& hit_assoc : *in_hit_assocs) { - if(hit_assoc.getRawHit().isAvailable()) { - if(hit_assoc.getRawHit().id() == raw_hit.id()) { + if (m_cfg.cheatPhotonVertex || m_cfg.cheatTrueRadiator) { + for (const auto& hit_assoc : *in_hit_assocs) { + if (hit_assoc.getRawHit().isAvailable()) { + if (hit_assoc.getRawHit().id() == raw_hit.id()) { // hit association found, get the MC photon and break the loop // FIXME: occasionally there will be more than one photon associated with a hit; // for now let's just take the first one... - if(hit_assoc.simHits_size() > 0) { - mc_photon = hit_assoc.getSimHits(0).getMCParticle(); + if (hit_assoc.simHits_size() > 0) { + mc_photon = hit_assoc.getSimHits(0).getMCParticle(); mc_photon_found = true; - if(mc_photon.getPDG() != -22) - m_log->warn("non-opticalphoton hit: PDG = {}",mc_photon.getPDG()); - } - else if(m_cfg.CheatModeEnabled()) + if (mc_photon.getPDG() != -22) + m_log->warn("non-opticalphoton hit: PDG = {}", mc_photon.getPDG()); + } else if (m_cfg.CheatModeEnabled()) m_log->error("cheat mode enabled, but no MC photons provided"); break; } @@ -236,57 +231,62 @@ std::map> e } // cheat mode, for testing only: use MC photon to get the actual radiator - if(m_cfg.cheatTrueRadiator && mc_photon_found) { + if (m_cfg.cheatTrueRadiator && mc_photon_found) { auto vtx = Tools::PodioVector3_to_TVector3(mc_photon.getVertex()); auto mc_rad = m_irt_det->GuessRadiator(vtx, vtx); // assume IP is at (0,0,0) - if(mc_rad != irt_rad) continue; // skip this photon, if not from radiator `irt_rad` - Tools::PrintTVector3(m_log, fmt::format("cheat: radiator '{}' determined from photon vertex", rad_name), vtx); + if (mc_rad != irt_rad) + continue; // skip this photon, if not from radiator `irt_rad` + Tools::PrintTVector3( + m_log, fmt::format("cheat: radiator '{}' determined from photon vertex", rad_name), + vtx); } // get sensor and pixel info // FIXME: signal and timing cuts (ADC, TDC, ToT, ...) - auto cell_id = raw_hit.getCellID(); + auto cell_id = raw_hit.getCellID(); uint64_t sensor_id = cell_id & m_cell_mask; TVector3 pixel_pos = m_irt_det->m_ReadoutIDToPosition(cell_id); // trace logging - if(m_log->level() <= spdlog::level::trace) { + if (m_log->level() <= spdlog::level::trace) { m_log->trace("cell_id={:#X} sensor_id={:#X}", cell_id, sensor_id); Tools::PrintTVector3(m_log, "pixel position", pixel_pos); - if(mc_photon_found) { + if (mc_photon_found) { TVector3 mc_endpoint = Tools::PodioVector3_to_TVector3(mc_photon.getEndpoint()); Tools::PrintTVector3(m_log, "photon endpoint", mc_endpoint); - m_log->trace("{:>30} = {}", "dist( pixel, photon )", (pixel_pos - mc_endpoint).Mag()); - } - else m_log->trace(" no MC photon found; probably a noise hit"); + m_log->trace("{:>30} = {}", "dist( pixel, photon )", (pixel_pos - mc_endpoint).Mag()); + } else + m_log->trace(" no MC photon found; probably a noise hit"); } // start new IRT photon - auto *irt_sensor = m_irt_det->m_PhotonDetectors[0]; // NOTE: assumes one sensor type - auto *irt_photon = new OpticalPhoton(); // new raw pointer; it will also be destroyed when `irt_particle` is destroyed + auto* irt_sensor = m_irt_det->m_PhotonDetectors[0]; // NOTE: assumes one sensor type + auto* irt_photon = + new OpticalPhoton(); // new raw pointer; it will also be destroyed when `irt_particle` is destroyed irt_photon->SetVolumeCopy(sensor_id); irt_photon->SetDetectionPosition(pixel_pos); irt_photon->SetPhotonDetector(irt_sensor); irt_photon->SetDetected(true); // cheat mode: get photon vertex info from MC truth - if((m_cfg.cheatPhotonVertex || m_cfg.cheatTrueRadiator) && mc_photon_found) { + if ((m_cfg.cheatPhotonVertex || m_cfg.cheatTrueRadiator) && mc_photon_found) { irt_photon->SetVertexPosition(Tools::PodioVector3_to_TVector3(mc_photon.getVertex())); irt_photon->SetVertexMomentum(Tools::PodioVector3_to_TVector3(mc_photon.getMomentum())); } // cheat mode: retrieve a refractive index estimate; it is not exactly the one, which // was used in GEANT, but should be very close - if(m_cfg.cheatPhotonVertex) { + if (m_cfg.cheatPhotonVertex) { double ri; auto mom = 1e9 * irt_photon->GetVertexMomentum().Mag(); auto ri_set = Tools::GetFinelyBinnedTableEntry(irt_rad->m_ri_lookup_table, mom, &ri); - if(ri_set) { + if (ri_set) { irt_photon->SetVertexRefractiveIndex(ri); m_log->trace("{:>30} = {}", "refractive index", ri); - } - else - m_log->warn("Tools::GetFinelyBinnedTableEntry failed to lookup refractive index for momentum {} eV", mom); + } else + m_log->warn("Tools::GetFinelyBinnedTableEntry failed to lookup refractive index for " + "momentum {} eV", + mom); } // add each `irt_photon` to the radiator history @@ -303,58 +303,55 @@ std::map> e } // end radiator loop - - // particle identification +++++++++++++++++++++++++++++++++++++++++++++++++++++ // define a mass hypothesis for each particle we want to check - m_log->trace("{:+^70}"," PARTICLE IDENTIFICATION "); + m_log->trace("{:+^70}", " PARTICLE IDENTIFICATION "); CherenkovPID irt_pid; - std::unordered_map pdg_to_hyp; // `pdg` -> hypothesis - for(auto [pdg,mass] : m_pdg_mass) { + std::unordered_map pdg_to_hyp; // `pdg` -> hypothesis + for (auto [pdg, mass] : m_pdg_mass) { irt_pid.AddMassHypothesis(mass); - pdg_to_hyp.insert({ pdg, irt_pid.GetHypothesis(irt_pid.GetHypothesesCount()-1) }); + pdg_to_hyp.insert({pdg, irt_pid.GetHypothesis(irt_pid.GetHypothesesCount() - 1)}); } // run IRT PID irt_particle->PIDReconstruction(irt_pid); - m_log->trace("{:-^70}"," IRT RESULTS "); + m_log->trace("{:-^70}", " IRT RESULTS "); // loop over radiators - for(auto [rad_name,irt_rad] : m_pid_radiators) { + for (auto [rad_name, irt_rad] : m_pid_radiators) { m_log->trace("-> {} Radiator (ID={}):", rad_name, irt_rad->m_ID); // Cherenkov angle (theta) estimate - unsigned npe = 0; - double rindex_ave = 0.0; - double energy_ave = 0.0; - std::vector> phot_theta_phi; + unsigned npe = 0; + double rindex_ave = 0.0; + double energy_ave = 0.0; + std::vector> phot_theta_phi; // loop over this radiator's photons, and decide which to include in the theta estimate - auto *irt_rad_history = irt_particle->FindRadiatorHistory(irt_rad); - if(irt_rad_history==nullptr) { + auto* irt_rad_history = irt_particle->FindRadiatorHistory(irt_rad); + if (irt_rad_history == nullptr) { m_log->trace(" No radiator history; skip"); continue; } m_log->trace(" Photoelectrons:"); - for(auto *irt_photon : irt_rad_history->Photons()) { + for (auto* irt_photon : irt_rad_history->Photons()) { // check whether this photon was selected by at least one mass hypothesis bool photon_selected = false; - for(auto irt_photon_sel : irt_photon->_m_Selected) { - if(irt_photon_sel.second == irt_rad) { + for (auto irt_photon_sel : irt_photon->_m_Selected) { + if (irt_photon_sel.second == irt_rad) { photon_selected = true; break; } } - if(!photon_selected) continue; + if (!photon_selected) + continue; // trace logging - Tools::PrintTVector3( - m_log, - fmt::format("- sensor_id={:#X}: hit",irt_photon->GetVolumeCopy()), - irt_photon->GetDetectionPosition() - ); + Tools::PrintTVector3(m_log, + fmt::format("- sensor_id={:#X}: hit", irt_photon->GetVolumeCopy()), + irt_photon->GetDetectionPosition()); Tools::PrintTVector3(m_log, "photon vertex", irt_photon->GetVertexPosition()); // get this photon's theta and phi estimates @@ -363,8 +360,8 @@ std::map> e // add to the total npe++; - phot_theta_phi.emplace_back( phot_theta, phot_phi ); - if(m_cfg.cheatPhotonVertex) { + phot_theta_phi.emplace_back(phot_theta, phot_phi); + if (m_cfg.cheatPhotonVertex) { rindex_ave += irt_photon->GetVertexRefractiveIndex(); energy_ave += irt_photon->GetVertexMomentum().Mag(); } @@ -372,7 +369,7 @@ std::map> e } // end loop over this radiator's photons // compute averages - if(npe>0) { + if (npe > 0) { rindex_ave /= npe; energy_ave /= npe; } @@ -380,27 +377,30 @@ std::map> e // fill photon info auto out_cherenkov_pid = result.at(rad_name)->create(); out_cherenkov_pid.setNpe(static_cast(npe)); - out_cherenkov_pid.setRefractiveIndex(static_cast(rindex_ave)); - out_cherenkov_pid.setPhotonEnergy(static_cast(energy_ave)); - for(auto [phot_theta,phot_phi] : phot_theta_phi) - out_cherenkov_pid.addToThetaPhiPhotons(edm4hep::Vector2f{ - static_cast(phot_theta), - static_cast(phot_phi) - }); + out_cherenkov_pid.setRefractiveIndex( + static_cast(rindex_ave)); + out_cherenkov_pid.setPhotonEnergy( + static_cast(energy_ave)); + for (auto [phot_theta, phot_phi] : phot_theta_phi) + out_cherenkov_pid.addToThetaPhiPhotons( + edm4hep::Vector2f{static_cast(phot_theta), static_cast(phot_phi)}); // relate mass hypotheses - for(auto [pdg,mass] : m_pdg_mass) { + for (auto [pdg, mass] : m_pdg_mass) { // get hypothesis results - auto *irt_hypothesis = pdg_to_hyp.at(pdg); - auto hyp_weight = irt_hypothesis->GetWeight(irt_rad); - auto hyp_npe = irt_hypothesis->GetNpe(irt_rad); + auto* irt_hypothesis = pdg_to_hyp.at(pdg); + auto hyp_weight = irt_hypothesis->GetWeight(irt_rad); + auto hyp_npe = irt_hypothesis->GetNpe(irt_rad); // fill `ParticleID` output collection edm4eic::CherenkovParticleIDHypothesis out_hypothesis; - out_hypothesis.PDG = static_cast(pdg); - out_hypothesis.weight = static_cast(hyp_weight); - out_hypothesis.npe = static_cast(hyp_npe); + out_hypothesis.PDG = + static_cast(pdg); + out_hypothesis.weight = + static_cast(hyp_weight); + out_hypothesis.npe = + static_cast(hyp_npe); // relate out_cherenkov_pid.addToHypotheses(out_hypothesis); @@ -412,16 +412,15 @@ std::map> e // relate charged particle projection auto charged_particle_list_it = in_charged_particles.find("Merged"); - if(charged_particle_list_it != in_charged_particles.end()) { - const auto *charged_particle_list = charged_particle_list_it->second; - auto charged_particle = charged_particle_list->at(i_charged_particle); + if (charged_particle_list_it != in_charged_particles.end()) { + const auto* charged_particle_list = charged_particle_list_it->second; + auto charged_particle = charged_particle_list->at(i_charged_particle); out_cherenkov_pid.setChargedParticle(charged_particle); - } - else + } else m_log->error("Cannot find radiator 'Merged' in `in_charged_particles`"); // relate hit associations - for(const auto& hit_assoc : *in_hit_assocs) + for (const auto& hit_assoc : *in_hit_assocs) out_cherenkov_pid.addToRawHitAssociations(hit_assoc); } // end radiator loop diff --git a/src/algorithms/pid/IrtCherenkovParticleID.h b/src/algorithms/pid/IrtCherenkovParticleID.h index ae7763ab64..e2959da869 100644 --- a/src/algorithms/pid/IrtCherenkovParticleID.h +++ b/src/algorithms/pid/IrtCherenkovParticleID.h @@ -23,41 +23,36 @@ namespace eicrecon { - class IrtCherenkovParticleID : public WithPodConfig { - - public: - IrtCherenkovParticleID() = default; - ~IrtCherenkovParticleID() {} - - void AlgorithmInit( - CherenkovDetectorCollection* irt_det_coll, - std::shared_ptr& logger - ); - void AlgorithmChangeRun(); - - // AlgorithmProcess - // - `in_raw_hits` is a collection of digitized (raw) sensor hits, possibly including noise hits - // - `in_hit_assocs` is a collection of digitized (raw) sensor hits, associated with MC (simulated) hits; - // noise hits are not included since there is no associated simulated photon - // - `in_charged_particles` is a map of a radiator name to a collection of TrackSegments - // - each TrackSegment has a list of TrackPoints: the propagation of reconstructed track (trajectory) points - // - the output is a map: radiator name -> collection of particle ID objects - std::map> AlgorithmProcess( - std::map& in_charged_particles, - const edm4eic::RawTrackerHitCollection* in_raw_hits, - const edm4eic::MCRecoTrackerHitAssociationCollection* in_hit_assocs - ); - - private: - - std::shared_ptr m_log; - CherenkovDetectorCollection* m_irt_det_coll; - CherenkovDetector* m_irt_det; - - uint64_t m_cell_mask; - std::string m_det_name; - std::unordered_map m_pdg_mass; - std::map m_pid_radiators; - - }; -} +class IrtCherenkovParticleID : public WithPodConfig { + +public: + IrtCherenkovParticleID() = default; + ~IrtCherenkovParticleID() {} + + void AlgorithmInit(CherenkovDetectorCollection* irt_det_coll, + std::shared_ptr& logger); + void AlgorithmChangeRun(); + + // AlgorithmProcess + // - `in_raw_hits` is a collection of digitized (raw) sensor hits, possibly including noise hits + // - `in_hit_assocs` is a collection of digitized (raw) sensor hits, associated with MC (simulated) hits; + // noise hits are not included since there is no associated simulated photon + // - `in_charged_particles` is a map of a radiator name to a collection of TrackSegments + // - each TrackSegment has a list of TrackPoints: the propagation of reconstructed track (trajectory) points + // - the output is a map: radiator name -> collection of particle ID objects + std::map> AlgorithmProcess( + std::map& in_charged_particles, + const edm4eic::RawTrackerHitCollection* in_raw_hits, + const edm4eic::MCRecoTrackerHitAssociationCollection* in_hit_assocs); + +private: + std::shared_ptr m_log; + CherenkovDetectorCollection* m_irt_det_coll; + CherenkovDetector* m_irt_det; + + uint64_t m_cell_mask; + std::string m_det_name; + std::unordered_map m_pdg_mass; + std::map m_pid_radiators; +}; +} // namespace eicrecon diff --git a/src/algorithms/pid/IrtCherenkovParticleIDConfig.h b/src/algorithms/pid/IrtCherenkovParticleIDConfig.h index 7f0245e367..0a5593368e 100644 --- a/src/algorithms/pid/IrtCherenkovParticleIDConfig.h +++ b/src/algorithms/pid/IrtCherenkovParticleIDConfig.h @@ -8,87 +8,80 @@ namespace eicrecon { - // radiator config parameters - struct RadiatorConfig { - double referenceRIndex; // reference radiator refractive index - double attenuation; // reference radiator attenuation length [mm]; set to 0 to disable - std::string smearingMode; // smearing type: "gaussian", "uniform" - double smearing; // smearing amount [radians] - }; +// radiator config parameters +struct RadiatorConfig { + double referenceRIndex; // reference radiator refractive index + double attenuation; // reference radiator attenuation length [mm]; set to 0 to disable + std::string smearingMode; // smearing type: "gaussian", "uniform" + double smearing; // smearing amount [radians] +}; - // IRT algorithm config - class IrtCherenkovParticleIDConfig { - public: +// IRT algorithm config +class IrtCherenkovParticleIDConfig { +public: + ///////////////////////////////////////////////////// + // CONFIGURATION PARAMETERS + // NOTE: some defaults are hard-coded here; override externally - ///////////////////////////////////////////////////// - // CONFIGURATION PARAMETERS - // NOTE: some defaults are hard-coded here; override externally + unsigned numRIndexBins = 100; // number of bins to interpolate the refractive index vs. energy - unsigned numRIndexBins = 100; // number of bins to interpolate the refractive index vs. energy - - /* radiator-specific settings; handled by `RadiatorConfig` struct (see above) + /* radiator-specific settings; handled by `RadiatorConfig` struct (see above) * example: radiators.insert({ "Aerogel", RadiatorConfig{ ... }}); * radiators.insert({ "Gas", RadiatorConfig{ ... }}); */ - std::map radiators; + std::map radiators; - /* list of PDG codes to identify with this PID algorithm + /* list of PDG codes to identify with this PID algorithm * example: std::vector pdgList = { 11, 211, 321, 2212 }; */ - std::vector pdgList; + std::vector pdgList; - /* cheat modes: useful for test purposes, or idealizing; the real PID should run with all + /* cheat modes: useful for test purposes, or idealizing; the real PID should run with all * cheat modes off */ - bool cheatPhotonVertex = false; // if true, use MC photon vertex, wavelength, and refractive index - bool cheatTrueRadiator = false; // if true, use MC truth to obtain true radiator, for each hit - - // - ///////////////////////////////////////////////////// + bool cheatPhotonVertex = false; // if true, use MC photon vertex, wavelength, and refractive index + bool cheatTrueRadiator = false; // if true, use MC truth to obtain true radiator, for each hit - // print warnings about cheat modes - void PrintCheats( - std::shared_ptr m_log, - spdlog::level::level_enum lvl=spdlog::level::debug, - bool printAll=false - ) - { - auto print_param = [&m_log, &lvl, &printAll] (auto name, bool val, auto desc) { - if(printAll) m_log->log(lvl, " {:>20} = {:<}", name, val); - else if(val) m_log->warn("CHEAT MODE '{}' ENABLED: {}", name, desc); - }; - print_param("cheatPhotonVertex", cheatPhotonVertex, "use MC photon vertex, wavelength, refractive index"); - print_param("cheatTrueRadiator", cheatTrueRadiator, "use MC truth to obtain true radiator"); - } + // + ///////////////////////////////////////////////////// - // boolean: true if any cheat mode is enabled - bool CheatModeEnabled() { - return cheatPhotonVertex || cheatTrueRadiator; - } + // print warnings about cheat modes + void PrintCheats(std::shared_ptr m_log, + spdlog::level::level_enum lvl = spdlog::level::debug, bool printAll = false) { + auto print_param = [&m_log, &lvl, &printAll](auto name, bool val, auto desc) { + if (printAll) + m_log->log(lvl, " {:>20} = {:<}", name, val); + else if (val) + m_log->warn("CHEAT MODE '{}' ENABLED: {}", name, desc); + }; + print_param("cheatPhotonVertex", cheatPhotonVertex, + "use MC photon vertex, wavelength, refractive index"); + print_param("cheatTrueRadiator", cheatTrueRadiator, "use MC truth to obtain true radiator"); + } - // print all parameters - void Print( - std::shared_ptr m_log, - spdlog::level::level_enum lvl=spdlog::level::debug - ) - { - m_log->log(lvl, "{:=^60}"," IrtCherenkovParticleIDConfig Settings "); - auto print_param = [&m_log, &lvl] (auto name, auto val) { - m_log->log(lvl, " {:>20} = {:<}", name, val); - }; - print_param("numRIndexBins",numRIndexBins); - PrintCheats(m_log, lvl, true); - m_log->log(lvl, "pdgList:"); - for(const auto& pdg : pdgList) m_log->log(lvl, " {}", pdg); - for(const auto& [name,rad] : radiators) { - m_log->log(lvl, "{:-<60}", fmt::format("--- {} config ",name)); - print_param("smearingMode", rad.smearingMode); - print_param("smearing", rad.smearing); - print_param("referenceRIndex", rad.referenceRIndex); - print_param("attenuation", rad.attenuation); - } - m_log->log(lvl, "{:=^60}",""); - } + // boolean: true if any cheat mode is enabled + bool CheatModeEnabled() { return cheatPhotonVertex || cheatTrueRadiator; } - }; -} + // print all parameters + void Print(std::shared_ptr m_log, + spdlog::level::level_enum lvl = spdlog::level::debug) { + m_log->log(lvl, "{:=^60}", " IrtCherenkovParticleIDConfig Settings "); + auto print_param = [&m_log, &lvl](auto name, auto val) { + m_log->log(lvl, " {:>20} = {:<}", name, val); + }; + print_param("numRIndexBins", numRIndexBins); + PrintCheats(m_log, lvl, true); + m_log->log(lvl, "pdgList:"); + for (const auto& pdg : pdgList) + m_log->log(lvl, " {}", pdg); + for (const auto& [name, rad] : radiators) { + m_log->log(lvl, "{:-<60}", fmt::format("--- {} config ", name)); + print_param("smearingMode", rad.smearingMode); + print_param("smearing", rad.smearing); + print_param("referenceRIndex", rad.referenceRIndex); + print_param("attenuation", rad.attenuation); + } + m_log->log(lvl, "{:=^60}", ""); + } +}; +} // namespace eicrecon diff --git a/src/algorithms/pid/MergeParticleID.cc b/src/algorithms/pid/MergeParticleID.cc index 645edc85d8..b920377a90 100644 --- a/src/algorithms/pid/MergeParticleID.cc +++ b/src/algorithms/pid/MergeParticleID.cc @@ -20,18 +20,16 @@ namespace eicrecon { -void MergeParticleID::init(std::shared_ptr& logger) -{ +void MergeParticleID::init(std::shared_ptr& logger) { m_log = logger; m_cfg.Print(m_log, spdlog::level::debug); } -void MergeParticleID::process( - const MergeParticleID::Input& input, - const MergeParticleID::Output& output) const { +void MergeParticleID::process(const MergeParticleID::Input& input, + const MergeParticleID::Output& output) const { const auto [in_pid_collections_list] = input; - auto [out_pids] = output; + auto [out_pids] = output; /* match input `CherenkovParticleIDCollection` elements from each list of * collections in `in_pid_collections_list` @@ -66,20 +64,21 @@ void MergeParticleID::process( // fill `particle_pids` // ------------------------------------------------------------------------------- - std::unordered_map< decltype(podio::ObjectID::index), std::vector> > particle_pids; - m_log->trace("{:-<70}","Build `particle_pids` indexing data structure "); + std::unordered_map>> + particle_pids; + m_log->trace("{:-<70}", "Build `particle_pids` indexing data structure "); // loop over list of PID collections - for(size_t idx_coll = 0; idx_coll < in_pid_collections_list.size(); idx_coll++) { + for (size_t idx_coll = 0; idx_coll < in_pid_collections_list.size(); idx_coll++) { const auto& in_pid_collection = in_pid_collections_list.at(idx_coll); m_log->trace("idx_col={}", idx_coll); // loop over this PID collection - for(size_t idx_pid = 0; idx_pid < in_pid_collection->size(); idx_pid++) { + for (size_t idx_pid = 0; idx_pid < in_pid_collection->size(); idx_pid++) { // make the index pair - const auto& in_pid = in_pid_collection->at(idx_pid); + const auto& in_pid = in_pid_collection->at(idx_pid); auto& charged_particle_track_segment = in_pid.getChargedParticle(); - if(!charged_particle_track_segment.isAvailable()) { + if (!charged_particle_track_segment.isAvailable()) { m_log->error("PID object found with no charged particle"); continue; } @@ -89,7 +88,7 @@ void MergeParticleID::process( // insert in `particle_pids` auto it = particle_pids.find(id_particle); - if(it == particle_pids.end()) + if (it == particle_pids.end()) particle_pids.insert({id_particle, {idx_paired}}); else it->second.push_back(idx_paired); @@ -97,22 +96,21 @@ void MergeParticleID::process( } // trace logging - if(m_log->level() <= spdlog::level::trace) { - m_log->trace("{:-<70}","Resulting `particle_pids` "); - for(auto& [id_particle, idx_paired_list] : particle_pids) { + if (m_log->level() <= spdlog::level::trace) { + m_log->trace("{:-<70}", "Resulting `particle_pids` "); + for (auto& [id_particle, idx_paired_list] : particle_pids) { m_log->trace("id_particle={}", id_particle); - for(auto& [idx_coll, idx_pid] : idx_paired_list) + for (auto& [idx_coll, idx_pid] : idx_paired_list) m_log->trace(" (idx_coll, idx_pid) = ({}, {})", idx_coll, idx_pid); } } // -------------------------------------------------------------------------------- - // loop over charged particles, combine weights from the associated `CherenkovParticleID` objects // and create a merged output `CherenkovParticleID` object - m_log->trace("{:-<70}","Begin Merging PID Objects "); - for(auto& [id_particle, idx_paired_list] : particle_pids) { + m_log->trace("{:-<70}", "Begin Merging PID Objects "); + for (auto& [id_particle, idx_paired_list] : particle_pids) { // trace logging m_log->trace("Charged Particle:"); @@ -120,59 +118,62 @@ void MergeParticleID::process( m_log->trace(" PID Hypotheses:"); // create mutable output `CherenkovParticleID` object `out_pid` - auto out_pid = out_pids->create(); - decltype(edm4eic::CherenkovParticleIDData::npe) out_npe = 0.0; + auto out_pid = out_pids->create(); + decltype(edm4eic::CherenkovParticleIDData::npe) out_npe = 0.0; decltype(edm4eic::CherenkovParticleIDData::refractiveIndex) out_refractiveIndex = 0.0; - decltype(edm4eic::CherenkovParticleIDData::photonEnergy) out_photonEnergy = 0.0; + decltype(edm4eic::CherenkovParticleIDData::photonEnergy) out_photonEnergy = 0.0; // define `pdg_2_out_hyp`: map of PDG => merged output hypothesis - std::unordered_map< decltype(edm4eic::CherenkovParticleIDHypothesis::PDG), edm4eic::CherenkovParticleIDHypothesis > pdg_2_out_hyp; + std::unordered_map + pdg_2_out_hyp; // merge each input `CherenkovParticleID` objects associated with this charged particle - for(auto& [idx_coll, idx_pid] : idx_paired_list) { + for (auto& [idx_coll, idx_pid] : idx_paired_list) { const auto& in_pid = in_pid_collections_list.at(idx_coll)->at(idx_pid); // logging - m_log->trace(" Hypotheses for PID result (idx_coll, idx_pid) = ({}, {}):", idx_coll, idx_pid); - Tools::PrintHypothesisTableHead(m_log,6); + m_log->trace(" Hypotheses for PID result (idx_coll, idx_pid) = ({}, {}):", idx_coll, + idx_pid); + Tools::PrintHypothesisTableHead(m_log, 6); // merge scalar members - out_npe += in_pid.getNpe(); // sum + out_npe += in_pid.getNpe(); // sum out_refractiveIndex += in_pid.getNpe() * in_pid.getRefractiveIndex(); // NPE-weighted average - out_photonEnergy += in_pid.getNpe() * in_pid.getPhotonEnergy(); // NPE-weighted average + out_photonEnergy += in_pid.getNpe() * in_pid.getPhotonEnergy(); // NPE-weighted average // merge photon Cherenkov angles - for(auto in_photon_vec : in_pid.getThetaPhiPhotons()) + for (auto in_photon_vec : in_pid.getThetaPhiPhotons()) out_pid.addToThetaPhiPhotons(in_photon_vec); // relate the charged particle - if(!out_pid.getChargedParticle().isAvailable()) // only needs to be done once + if (!out_pid.getChargedParticle().isAvailable()) // only needs to be done once out_pid.setChargedParticle(in_pid.getChargedParticle()); // merge PDG hypotheses, combining their weights and other members - for(auto in_hyp : in_pid.getHypotheses()) { - Tools::PrintHypothesisTableLine(m_log,in_hyp,6); + for (auto in_hyp : in_pid.getHypotheses()) { + Tools::PrintHypothesisTableLine(m_log, in_hyp, 6); auto out_hyp_it = pdg_2_out_hyp.find(in_hyp.PDG); - if(out_hyp_it == pdg_2_out_hyp.end()) { + if (out_hyp_it == pdg_2_out_hyp.end()) { edm4eic::CherenkovParticleIDHypothesis out_hyp; out_hyp.PDG = in_hyp.PDG; // FIXME: no copy constructor? out_hyp.npe = in_hyp.npe; out_hyp.weight = in_hyp.weight; - pdg_2_out_hyp.insert({out_hyp.PDG,out_hyp}); - } - else { + pdg_2_out_hyp.insert({out_hyp.PDG, out_hyp}); + } else { auto& out_hyp = out_hyp_it->second; out_hyp.npe += in_hyp.npe; // combine hypotheses' weights - switch(m_cfg.mergeMode) { - case MergeParticleIDConfig::kAddWeights: - out_hyp.weight += in_hyp.weight; - break; - case MergeParticleIDConfig::kMultiplyWeights: - out_hyp.weight *= in_hyp.weight; - break; - default: - throw std::runtime_error("unknown MergeParticleIDConfig::mergeMode setting; weights not combined"); + switch (m_cfg.mergeMode) { + case MergeParticleIDConfig::kAddWeights: + out_hyp.weight += in_hyp.weight; + break; + case MergeParticleIDConfig::kMultiplyWeights: + out_hyp.weight *= in_hyp.weight; + break; + default: + throw std::runtime_error( + "unknown MergeParticleIDConfig::mergeMode setting; weights not combined"); } } } // end `in_pid.getHypotheses()` loop, for this charged particle @@ -181,20 +182,20 @@ void MergeParticleID::process( // finish computing averages of scalar members out_pid.setNpe(out_npe); - if(out_npe > 0) { - out_pid.setRefractiveIndex( out_refractiveIndex / out_npe ); - out_pid.setPhotonEnergy( out_photonEnergy / out_npe ); + if (out_npe > 0) { + out_pid.setRefractiveIndex(out_refractiveIndex / out_npe); + out_pid.setPhotonEnergy(out_photonEnergy / out_npe); } // append hypotheses - for(auto [pdg,out_hyp] : pdg_2_out_hyp) + for (auto [pdg, out_hyp] : pdg_2_out_hyp) out_pid.addToHypotheses(out_hyp); // logging: print merged hypothesis table m_log->trace(" => merged hypothesis weights:"); - Tools::PrintHypothesisTableHead(m_log,6); - for(auto out_hyp : out_pid.getHypotheses()) - Tools::PrintHypothesisTableLine(m_log,out_hyp,6); + Tools::PrintHypothesisTableHead(m_log, 6); + for (auto out_hyp : out_pid.getHypotheses()) + Tools::PrintHypothesisTableLine(m_log, out_hyp, 6); } // end `particle_pids` loop over charged particles } diff --git a/src/algorithms/pid/MergeParticleID.h b/src/algorithms/pid/MergeParticleID.h index 6e0ee715d4..d751e80283 100644 --- a/src/algorithms/pid/MergeParticleID.h +++ b/src/algorithms/pid/MergeParticleID.h @@ -18,35 +18,29 @@ namespace eicrecon { - using MergeParticleIDAlgorithm = algorithms::Algorithm< - algorithms::Input< - std::vector - >, - algorithms::Output< - edm4eic::CherenkovParticleIDCollection - > - >; - - class MergeParticleID - : public MergeParticleIDAlgorithm, - public WithPodConfig { - - public: - MergeParticleID(std::string_view name) +using MergeParticleIDAlgorithm = algorithms::Algorithm< + algorithms::Input>, + algorithms::Output>; + +class MergeParticleID : public MergeParticleIDAlgorithm, + public WithPodConfig { + +public: + MergeParticleID(std::string_view name) : MergeParticleIDAlgorithm{name, - {"inputTrackSegments"}, - {"outputTrackSegments"}, - "Effectively 'zip' the input particle IDs"} {} - - void init(std::shared_ptr& logger); - - // - input: a list of particle ID collections, which we want to merge together - // - output: the merged particle ID collection - // - overload this function to support different collections from other PID subsystems, or to support - // merging PID results from overlapping subsystems - void process(const Input&, const Output&) const final; - - private: - std::shared_ptr m_log; - }; -} + {"inputTrackSegments"}, + {"outputTrackSegments"}, + "Effectively 'zip' the input particle IDs"} {} + + void init(std::shared_ptr& logger); + + // - input: a list of particle ID collections, which we want to merge together + // - output: the merged particle ID collection + // - overload this function to support different collections from other PID subsystems, or to support + // merging PID results from overlapping subsystems + void process(const Input&, const Output&) const final; + +private: + std::shared_ptr m_log; +}; +} // namespace eicrecon diff --git a/src/algorithms/pid/MergeParticleIDConfig.h b/src/algorithms/pid/MergeParticleIDConfig.h index b70e2af8b1..08404f3331 100644 --- a/src/algorithms/pid/MergeParticleIDConfig.h +++ b/src/algorithms/pid/MergeParticleIDConfig.h @@ -7,33 +7,28 @@ namespace eicrecon { - class MergeParticleIDConfig { - public: - - ///////////////////////////////////////////////////// - // CONFIGURATION PARAMETERS - // NOTE: some defaults are hard-coded here; override externally - - // decide how to combine the weights - enum math_enum { kAddWeights, kMultiplyWeights }; - int mergeMode = kAddWeights; - - // - ///////////////////////////////////////////////////// - - // print all parameters - void Print( - std::shared_ptr m_log, - spdlog::level::level_enum lvl=spdlog::level::debug - ) - { - m_log->log(lvl, "{:=^60}"," MergeParticleIDConfig Settings "); - auto print_param = [&m_log, &lvl] (auto name, auto val) { - m_log->log(lvl, " {:>20} = {:<}", name, val); - }; - print_param("mergeMode",mergeMode); - m_log->log(lvl, "{:=^60}",""); - } - - }; -} +class MergeParticleIDConfig { +public: + ///////////////////////////////////////////////////// + // CONFIGURATION PARAMETERS + // NOTE: some defaults are hard-coded here; override externally + + // decide how to combine the weights + enum math_enum { kAddWeights, kMultiplyWeights }; + int mergeMode = kAddWeights; + + // + ///////////////////////////////////////////////////// + + // print all parameters + void Print(std::shared_ptr m_log, + spdlog::level::level_enum lvl = spdlog::level::debug) { + m_log->log(lvl, "{:=^60}", " MergeParticleIDConfig Settings "); + auto print_param = [&m_log, &lvl](auto name, auto val) { + m_log->log(lvl, " {:>20} = {:<}", name, val); + }; + print_param("mergeMode", mergeMode); + m_log->log(lvl, "{:=^60}", ""); + } +}; +} // namespace eicrecon diff --git a/src/algorithms/pid/MergeTracks.cc b/src/algorithms/pid/MergeTracks.cc index 41087a91fb..2576063687 100644 --- a/src/algorithms/pid/MergeTracks.cc +++ b/src/algorithms/pid/MergeTracks.cc @@ -15,59 +15,53 @@ namespace eicrecon { -void MergeTracks::init(std::shared_ptr& logger) -{ - m_log = logger; -} +void MergeTracks::init(std::shared_ptr& logger) { m_log = logger; } -void MergeTracks::process( - const MergeTracks::Input& input, - const MergeTracks::Output& output) const { +void MergeTracks::process(const MergeTracks::Input& input, + const MergeTracks::Output& output) const { const auto [in_track_collections] = input; - auto [out_tracks] = output; + auto [out_tracks] = output; // logging - m_log->trace("{:=^70}"," call MergeTracks::AlgorithmProcess "); + m_log->trace("{:=^70}", " call MergeTracks::AlgorithmProcess "); // check that all input collections have the same size std::unordered_map in_track_collection_size_distribution; - for(const auto& in_track_collection : in_track_collections) { + for (const auto& in_track_collection : in_track_collections) { ++in_track_collection_size_distribution[in_track_collection->size()]; } if (in_track_collection_size_distribution.size() != 1) { std::vector in_track_collection_sizes; std::transform(in_track_collections.begin(), in_track_collections.end(), - std::back_inserter(in_track_collection_sizes), - [](const auto& in_track_collection) { return in_track_collection->size(); }); - m_log->error("cannot merge input track collections with different sizes {}", fmt::join(in_track_collection_sizes, ", ")); + std::back_inserter(in_track_collection_sizes), + [](const auto& in_track_collection) { return in_track_collection->size(); }); + m_log->error("cannot merge input track collections with different sizes {}", + fmt::join(in_track_collection_sizes, ", ")); return; } // loop over track collection elements std::size_t n_tracks = in_track_collection_size_distribution.begin()->first; - for(std::size_t i_track=0; i_trackcreate(); std::vector out_track_points; // loop over collections for this track, and add each track's points to `out_track_points` - for(const auto& in_track_collection : in_track_collections) { + for (const auto& in_track_collection : in_track_collections) { const auto& in_track = in_track_collection->at(i_track); - for(const auto& point : in_track.getPoints()) + for (const auto& point : in_track.getPoints()) out_track_points.push_back(point); } // sort all `out_track_points` by time - std::sort( - out_track_points.begin(), - out_track_points.end(), - [] (edm4eic::TrackPoint& a, edm4eic::TrackPoint& b) { return a.time < b.time; } - ); + std::sort(out_track_points.begin(), out_track_points.end(), + [](edm4eic::TrackPoint& a, edm4eic::TrackPoint& b) { return a.time < b.time; }); // add these sorted points to `out_track` - for(const auto& point : out_track_points) + for (const auto& point : out_track_points) out_track.addToPoints(point); /* FIXME: merge other members, such as `length` and `lengthError`; diff --git a/src/algorithms/pid/MergeTracks.h b/src/algorithms/pid/MergeTracks.h index abb5520e13..ef00efe8bb 100644 --- a/src/algorithms/pid/MergeTracks.h +++ b/src/algorithms/pid/MergeTracks.h @@ -18,30 +18,23 @@ namespace eicrecon { - using MergeTracksAlgorithm = algorithms::Algorithm< - algorithms::Input< - std::vector - >, - algorithms::Output< - edm4eic::TrackSegmentCollection - > - >; - - class MergeTracks - : public MergeTracksAlgorithm { - - public: - MergeTracks(std::string_view name) - : MergeTracksAlgorithm{name, - {"inputTrackSegments"}, - {"outputTrackSegments"}, - "Effectively 'zip' the input track segments."} {} +using MergeTracksAlgorithm = + algorithms::Algorithm>, + algorithms::Output>; + +class MergeTracks : public MergeTracksAlgorithm { - void init(std::shared_ptr& logger); - void process(const Input&, const Output&) const final; +public: + MergeTracks(std::string_view name) + : MergeTracksAlgorithm{name, + {"inputTrackSegments"}, + {"outputTrackSegments"}, + "Effectively 'zip' the input track segments."} {} - private: - std::shared_ptr m_log; + void init(std::shared_ptr& logger); + void process(const Input&, const Output&) const final; - }; -} +private: + std::shared_ptr m_log; +}; +} // namespace eicrecon diff --git a/src/algorithms/pid/ParticlesWithPID.cc b/src/algorithms/pid/ParticlesWithPID.cc index 383e3d3b23..0ee712a9e5 100644 --- a/src/algorithms/pid/ParticlesWithPID.cc +++ b/src/algorithms/pid/ParticlesWithPID.cc @@ -28,327 +28,306 @@ #include "algorithms/pid/ParticlesWithPIDConfig.h" #include "algorithms/pid/Tools.h" +namespace eicrecon { +void ParticlesWithPID::init(std::shared_ptr logger) { m_log = logger; } + +ParticlesWithAssociation ParticlesWithPID::process( + const edm4hep::MCParticleCollection* mc_particles, const edm4eic::TrackCollection* tracks, + const edm4eic::CherenkovParticleIDCollection* drich_cherenkov_pid_collections) { + + /// Resulting reconstructed particles + auto parts = std::make_unique(); + auto assocs = std::make_unique(); + auto pids = std::make_unique(); + + const double sinPhiOver2Tolerance = sin(0.5 * m_cfg.phiTolerance); + tracePhiToleranceOnce(sinPhiOver2Tolerance, m_cfg.phiTolerance); + + std::vector mc_prt_is_consumed(mc_particles->size(), + false); // MCParticle is already consumed flag + + for (const auto& track : *tracks) { + auto trajectory = track.getTrajectory(); + for (const auto& trk : trajectory.getTrackParameters()) { + const auto mom = edm4hep::utils::sphericalToVector(1.0 / std::abs(trk.getQOverP()), + trk.getTheta(), trk.getPhi()); + const auto charge_rec = std::copysign(1., trk.getQOverP()); + + m_log->debug("Match: [id] [mom] [theta] [phi] [charge] [PID]"); + m_log->debug(" Track : {:<4} {:<8.3f} {:<8.3f} {:<8.2f} {:<4}", trk.getObjectID().index, + edm4hep::utils::magnitude(mom), edm4hep::utils::anglePolar(mom), + edm4hep::utils::angleAzimuthal(mom), charge_rec); + + // utility variables for matching + int best_match = -1; + double best_delta = std::numeric_limits::max(); + for (size_t ip = 0; ip < mc_particles->size(); ++ip) { + const auto& mc_part = (*mc_particles)[ip]; + const auto& p = mc_part.getMomentum(); + + m_log->trace(" MCParticle with id={:<4} mom={:<8.3f} charge={}", + mc_part.getObjectID().index, edm4hep::utils::magnitude(p), + mc_part.getCharge()); + + // Check if used + if (mc_prt_is_consumed[ip]) { + m_log->trace(" Ignoring. Particle is already used"); + continue; + } -namespace eicrecon { + // Check if non-primary + if (mc_part.getGeneratorStatus() > 1) { + m_log->trace(" Ignoring. GeneratorStatus > 1 => Non-primary particle"); + continue; + } - void ParticlesWithPID::init(std::shared_ptr logger) { - m_log = logger; - } + // Check if neutral + if (mc_part.getCharge() == 0) { + m_log->trace(" Ignoring. Neutral particle"); + continue; + } - ParticlesWithAssociation ParticlesWithPID::process( - const edm4hep::MCParticleCollection* mc_particles, - const edm4eic::TrackCollection* tracks, - const edm4eic::CherenkovParticleIDCollection* drich_cherenkov_pid_collections - ) { - - /// Resulting reconstructed particles - auto parts = std::make_unique(); - auto assocs = std::make_unique(); - auto pids = std::make_unique(); - - const double sinPhiOver2Tolerance = sin(0.5 * m_cfg.phiTolerance); - tracePhiToleranceOnce(sinPhiOver2Tolerance, m_cfg.phiTolerance); - - std::vector mc_prt_is_consumed(mc_particles->size(), false); // MCParticle is already consumed flag - - for (const auto &track: *tracks) { - auto trajectory = track.getTrajectory(); - for (const auto &trk: trajectory.getTrackParameters()) { - const auto mom = edm4hep::utils::sphericalToVector(1.0 / std::abs(trk.getQOverP()), trk.getTheta(), - trk.getPhi()); - const auto charge_rec = std::copysign(1., trk.getQOverP()); - - - m_log->debug("Match: [id] [mom] [theta] [phi] [charge] [PID]"); - m_log->debug(" Track : {:<4} {:<8.3f} {:<8.3f} {:<8.2f} {:<4}", - trk.getObjectID().index, edm4hep::utils::magnitude(mom), edm4hep::utils::anglePolar(mom), edm4hep::utils::angleAzimuthal(mom), charge_rec); - - // utility variables for matching - int best_match = -1; - double best_delta = std::numeric_limits::max(); - for (size_t ip = 0; ip < mc_particles->size(); ++ip) { - const auto &mc_part = (*mc_particles)[ip]; - const auto &p = mc_part.getMomentum(); - - m_log->trace(" MCParticle with id={:<4} mom={:<8.3f} charge={}", mc_part.getObjectID().index, - edm4hep::utils::magnitude(p), mc_part.getCharge()); - - // Check if used - if (mc_prt_is_consumed[ip]) { - m_log->trace(" Ignoring. Particle is already used"); - continue; - } - - // Check if non-primary - if (mc_part.getGeneratorStatus() > 1) { - m_log->trace(" Ignoring. GeneratorStatus > 1 => Non-primary particle"); - continue; - } - - // Check if neutral - if (mc_part.getCharge() == 0) { - m_log->trace(" Ignoring. Neutral particle"); - continue; - } - - // Check opposite charge - if (mc_part.getCharge() * charge_rec < 0) { - m_log->trace(" Ignoring. Opposite charge particle"); - continue; - } - - const auto p_mag = edm4hep::utils::magnitude(p); - const auto p_phi = edm4hep::utils::angleAzimuthal(p); - const auto p_eta = edm4hep::utils::eta(p); - const double dp_rel = std::abs((edm4hep::utils::magnitude(mom) - p_mag) / p_mag); - // check the tolerance for sin(dphi/2) to avoid the hemisphere problem and allow - // for phi rollovers - const double dsphi = std::abs(sin(0.5 * (edm4hep::utils::angleAzimuthal(mom) - p_phi))); - const double deta = std::abs((edm4hep::utils::eta(mom) - p_eta)); - - bool is_matching = dp_rel < m_cfg.momentumRelativeTolerance && - deta < m_cfg.etaTolerance && - dsphi < sinPhiOver2Tolerance; - - // Matching kinematics with the static variables doesn't work at low angles and within beam divergence - // TODO - Maybe reconsider variables used or divide into regions - // Backward going - if ((p_eta < -5) && (edm4hep::utils::eta(mom) < -5)) { - is_matching = true; - } - // Forward going - if ((p_eta > 5) && (edm4hep::utils::eta(mom) > 5)) { - is_matching = true; - } - - m_log->trace(" Decision: {} dp: {:.4f} < {} && d_eta: {:.6f} < {} && d_sin_phi: {:.4e} < {:.4e} ", - is_matching? "Matching":"Ignoring", - dp_rel, m_cfg.momentumRelativeTolerance, - deta, m_cfg.etaTolerance, - dsphi, sinPhiOver2Tolerance); - - if (is_matching) { - const double delta = - std::hypot(dp_rel / m_cfg.momentumRelativeTolerance, deta / m_cfg.etaTolerance, - dsphi / sinPhiOver2Tolerance); - if (delta < best_delta) { - best_match = ip; - best_delta = delta; - m_log->trace(" Is the best match now"); - } - } - } - auto rec_part = parts->create(); - rec_part.addToTracks(track); - int32_t best_pid = 0; - auto referencePoint = rec_part.getReferencePoint(); - // float time = 0; - float mass = 0; - if (best_match >= 0) { - m_log->trace("Best match is found and is: {}", best_match); - mc_prt_is_consumed[best_match] = true; - const auto &best_mc_part = (*mc_particles)[best_match]; - best_pid = best_mc_part.getPDG(); - referencePoint = { - static_cast(best_mc_part.getVertex().x), - static_cast(best_mc_part.getVertex().y), - static_cast(best_mc_part.getVertex().z)}; // @TODO: not sure if vertex/reference point makes sense here - // time = mcpart.getTime(); - mass = best_mc_part.getMass(); - } - - rec_part.setType(static_cast(best_match >= 0 ? 0 : -1)); // @TODO: determine type codes - rec_part.setEnergy((float) std::hypot(edm4hep::utils::magnitude(mom), mass)); - rec_part.setMomentum(mom); - rec_part.setReferencePoint(referencePoint); - rec_part.setCharge(charge_rec); - rec_part.setMass(mass); - rec_part.setGoodnessOfPID(0); // assume no PID until proven otherwise - rec_part.setPDG(best_pid); - // rec_part.covMatrix() // @TODO: covariance matrix on 4-momentum - - // link Cherenkov PID objects - auto success = linkCherenkovPID(rec_part, *drich_cherenkov_pid_collections, *pids); - if (success) - m_log->trace(" true PDG vs. CherenkovPID PDG: {:>10} vs. {:<10}", - best_pid, - rec_part.getParticleIDUsed().isAvailable() ? rec_part.getParticleIDUsed().getPDG() : 0 - ); - - // Also write MC <--> truth particle association if match was found - if (best_match >= 0) { - auto rec_assoc = assocs->create(); - rec_assoc.setRecID(rec_part.getObjectID().index); - rec_assoc.setSimID((*mc_particles)[best_match].getObjectID().index); - rec_assoc.setWeight(1); - rec_assoc.setRec(rec_part); - auto sim = (*mc_particles)[best_match]; - rec_assoc.setSim(sim); - - if (m_log->level() <= spdlog::level::debug) { - - const auto &mcpart = (*mc_particles)[best_match]; - const auto &p = mcpart.getMomentum(); - const auto p_mag = edm4hep::utils::magnitude(p); - const auto p_phi = edm4hep::utils::angleAzimuthal(p); - const auto p_theta = edm4hep::utils::anglePolar(p); - m_log->debug(" MCPart: {:<4} {:<8.3f} {:<8.3f} {:<8.2f} {:<6}", - mcpart.getObjectID().index, p_mag, p_theta, p_phi, mcpart.getCharge(), - mcpart.getPDG()); - - m_log->debug(" Assoc: id={} SimId={} RecId={}", - rec_assoc.getObjectID().index, rec_assoc.getSim().getObjectID().index, rec_assoc.getSim().getObjectID().index); - - m_log->trace(" Assoc PDGs: sim.PDG | rec.PDG | rec.particleIDUsed.PDG = {:^6} | {:^6} | {:^6}", - rec_assoc.getSim().getPDG(), - rec_assoc.getRec().getPDG(), - rec_assoc.getRec().getParticleIDUsed().isAvailable() ? rec_assoc.getRec().getParticleIDUsed().getPDG() : 0); - - - } - } - else { - m_log->debug(" MCPart: Did not find a good match"); - } - } + // Check opposite charge + if (mc_part.getCharge() * charge_rec < 0) { + m_log->trace(" Ignoring. Opposite charge particle"); + continue; } - return std::make_tuple(std::move(parts), std::move(assocs), std::move(pids)); - } + const auto p_mag = edm4hep::utils::magnitude(p); + const auto p_phi = edm4hep::utils::angleAzimuthal(p); + const auto p_eta = edm4hep::utils::eta(p); + const double dp_rel = std::abs((edm4hep::utils::magnitude(mom) - p_mag) / p_mag); + // check the tolerance for sin(dphi/2) to avoid the hemisphere problem and allow + // for phi rollovers + const double dsphi = std::abs(sin(0.5 * (edm4hep::utils::angleAzimuthal(mom) - p_phi))); + const double deta = std::abs((edm4hep::utils::eta(mom) - p_eta)); + + bool is_matching = dp_rel < m_cfg.momentumRelativeTolerance && deta < m_cfg.etaTolerance && + dsphi < sinPhiOver2Tolerance; + + // Matching kinematics with the static variables doesn't work at low angles and within beam divergence + // TODO - Maybe reconsider variables used or divide into regions + // Backward going + if ((p_eta < -5) && (edm4hep::utils::eta(mom) < -5)) { + is_matching = true; + } + // Forward going + if ((p_eta > 5) && (edm4hep::utils::eta(mom) > 5)) { + is_matching = true; + } - void ParticlesWithPID::tracePhiToleranceOnce(const double sinPhiOver2Tolerance, double phiTolerance) { - // This function is called once to print tolerances useful for tracing - static std::once_flag do_it_once; - std::call_once(do_it_once, [this, sinPhiOver2Tolerance, phiTolerance]() { - m_log->trace("m_cfg.phiTolerance: {:<8.4f} => sinPhiOver2Tolerance: {:<8.4f}", sinPhiOver2Tolerance, phiTolerance); - }); + m_log->trace(" Decision: {} dp: {:.4f} < {} && d_eta: {:.6f} < {} && d_sin_phi: " + "{:.4e} < {:.4e} ", + is_matching ? "Matching" : "Ignoring", dp_rel, m_cfg.momentumRelativeTolerance, + deta, m_cfg.etaTolerance, dsphi, sinPhiOver2Tolerance); + + if (is_matching) { + const double delta = std::hypot(dp_rel / m_cfg.momentumRelativeTolerance, + deta / m_cfg.etaTolerance, dsphi / sinPhiOver2Tolerance); + if (delta < best_delta) { + best_match = ip; + best_delta = delta; + m_log->trace(" Is the best match now"); + } + } + } + auto rec_part = parts->create(); + rec_part.addToTracks(track); + int32_t best_pid = 0; + auto referencePoint = rec_part.getReferencePoint(); + // float time = 0; + float mass = 0; + if (best_match >= 0) { + m_log->trace("Best match is found and is: {}", best_match); + mc_prt_is_consumed[best_match] = true; + const auto& best_mc_part = (*mc_particles)[best_match]; + best_pid = best_mc_part.getPDG(); + referencePoint = { + static_cast(best_mc_part.getVertex().x), + static_cast(best_mc_part.getVertex().y), + static_cast( + best_mc_part.getVertex() + .z)}; // @TODO: not sure if vertex/reference point makes sense here + // time = mcpart.getTime(); + mass = best_mc_part.getMass(); + } + + rec_part.setType( + static_cast(best_match >= 0 ? 0 : -1)); // @TODO: determine type codes + rec_part.setEnergy((float)std::hypot(edm4hep::utils::magnitude(mom), mass)); + rec_part.setMomentum(mom); + rec_part.setReferencePoint(referencePoint); + rec_part.setCharge(charge_rec); + rec_part.setMass(mass); + rec_part.setGoodnessOfPID(0); // assume no PID until proven otherwise + rec_part.setPDG(best_pid); + // rec_part.covMatrix() // @TODO: covariance matrix on 4-momentum + + // link Cherenkov PID objects + auto success = linkCherenkovPID(rec_part, *drich_cherenkov_pid_collections, *pids); + if (success) + m_log->trace( + " true PDG vs. CherenkovPID PDG: {:>10} vs. {:<10}", best_pid, + rec_part.getParticleIDUsed().isAvailable() ? rec_part.getParticleIDUsed().getPDG() : 0); + + // Also write MC <--> truth particle association if match was found + if (best_match >= 0) { + auto rec_assoc = assocs->create(); + rec_assoc.setRecID(rec_part.getObjectID().index); + rec_assoc.setSimID((*mc_particles)[best_match].getObjectID().index); + rec_assoc.setWeight(1); + rec_assoc.setRec(rec_part); + auto sim = (*mc_particles)[best_match]; + rec_assoc.setSim(sim); + + if (m_log->level() <= spdlog::level::debug) { + + const auto& mcpart = (*mc_particles)[best_match]; + const auto& p = mcpart.getMomentum(); + const auto p_mag = edm4hep::utils::magnitude(p); + const auto p_phi = edm4hep::utils::angleAzimuthal(p); + const auto p_theta = edm4hep::utils::anglePolar(p); + m_log->debug(" MCPart: {:<4} {:<8.3f} {:<8.3f} {:<8.2f} {:<6}", + mcpart.getObjectID().index, p_mag, p_theta, p_phi, mcpart.getCharge(), + mcpart.getPDG()); + + m_log->debug(" Assoc: id={} SimId={} RecId={}", rec_assoc.getObjectID().index, + rec_assoc.getSim().getObjectID().index, + rec_assoc.getSim().getObjectID().index); + + m_log->trace( + " Assoc PDGs: sim.PDG | rec.PDG | rec.particleIDUsed.PDG = {:^6} | {:^6} | {:^6}", + rec_assoc.getSim().getPDG(), rec_assoc.getRec().getPDG(), + rec_assoc.getRec().getParticleIDUsed().isAvailable() + ? rec_assoc.getRec().getParticleIDUsed().getPDG() + : 0); + } + } else { + m_log->debug(" MCPart: Did not find a good match"); + } } + } + + return std::make_tuple(std::move(parts), std::move(assocs), std::move(pids)); +} +void ParticlesWithPID::tracePhiToleranceOnce(const double sinPhiOver2Tolerance, + double phiTolerance) { + // This function is called once to print tolerances useful for tracing + static std::once_flag do_it_once; + std::call_once(do_it_once, [this, sinPhiOver2Tolerance, phiTolerance]() { + m_log->trace("m_cfg.phiTolerance: {:<8.4f} => sinPhiOver2Tolerance: {:<8.4f}", + sinPhiOver2Tolerance, phiTolerance); + }); +} - /* link PID objects to input particle +/* link PID objects to input particle * - finds `CherenkovParticleID` object in `in_pids` associated to particle `in_part` * by proximity matching to the associated track * - converts this `CherenkovParticleID` object's PID hypotheses to `ParticleID` objects, * relates them to `in_part`, and adds them to the collection `out_pids` for persistency * - returns `true` iff PID objects were found and linked */ - bool ParticlesWithPID::linkCherenkovPID( - edm4eic::MutableReconstructedParticle& in_part, - const edm4eic::CherenkovParticleIDCollection& in_pids, - edm4hep::ParticleIDCollection& out_pids - ) - { - - // skip this particle, if neutral - if (std::abs(in_part.getCharge()) < 0.001) - return false; - - // structure to store list of candidate matches - struct ProxMatch { - double match_dist; - std::size_t pid_idx; - }; - std::vector prox_match_list; - - // get input reconstructed particle momentum angles - auto in_part_p = in_part.getMomentum(); - auto in_part_eta = edm4hep::utils::eta(in_part_p); - auto in_part_phi = edm4hep::utils::angleAzimuthal(in_part_p); - m_log->trace("Input particle: (eta,phi) = ( {:>5.4}, {:>5.4} deg )", - in_part_eta, - in_part_phi * 180.0 / M_PI - ); - - // loop over input CherenkovParticleID objects - for (std::size_t in_pid_idx = 0; in_pid_idx < in_pids.size(); in_pid_idx++) { - auto in_pid = in_pids.at(in_pid_idx); - - // get charged particle track associated to this CherenkovParticleID object - auto in_track = in_pid.getChargedParticle(); - if (!in_track.isAvailable()) { - m_log->error("found CherenkovParticleID object with no chargedParticle"); - return false; - } - if (in_track.points_size() == 0) { - m_log->error("found chargedParticle for CherenkovParticleID, but it has no TrackPoints"); - return false; - } - - // get averge momentum direction of the track's TrackPoints - decltype(edm4eic::TrackPoint::momentum) in_track_p{0.0, 0.0, 0.0}; - for (const auto& in_track_point : in_track.getPoints()) - in_track_p = in_track_p + ( in_track_point.momentum / in_track.points_size() ); - auto in_track_eta = edm4hep::utils::eta(in_track_p); - auto in_track_phi = edm4hep::utils::angleAzimuthal(in_track_p); - - // calculate dist(eta,phi) - auto match_dist = std::hypot( - in_part_eta - in_track_eta, - in_part_phi - in_track_phi - ); - - // check if the match is close enough: within user-specified tolerances - auto match_is_close = - std::abs(in_part_eta - in_track_eta) < m_cfg.etaTolerance && - std::abs(in_part_phi - in_track_phi) < m_cfg.phiTolerance; - if (match_is_close) - prox_match_list.push_back(ProxMatch{match_dist, in_pid_idx}); - - // logging - m_log->trace(" - (eta,phi) = ( {:>5.4}, {:>5.4} deg ), match_dist = {:<5.4}{}", - in_track_eta, - in_track_phi * 180.0 / M_PI, - match_dist, - match_is_close ? " => CLOSE!" : "" - ); - - } // end loop over input CherenkovParticleID objects - - // check if at least one match was found - if (prox_match_list.size() == 0) { - m_log->trace(" => no matching CherenkovParticleID found for this particle"); - return false; - } - - // choose the closest matching CherenkovParticleID object corresponding to this input reconstructed particle - auto closest_prox_match = *std::min_element( - prox_match_list.begin(), - prox_match_list.end(), - [] (ProxMatch a, ProxMatch b) { return a.match_dist < b.match_dist; } - ); - auto in_pid_matched = in_pids.at(closest_prox_match.pid_idx); - m_log->trace(" => best match: match_dist = {:<5.4} at idx = {}", - closest_prox_match.match_dist, - closest_prox_match.pid_idx - ); - - // convert `CherenkovParticleID` object's hypotheses => set of `ParticleID` objects - auto out_pid_index_map = ConvertParticleID::ConvertToParticleIDs(in_pid_matched, out_pids, true); - if (out_pid_index_map.size() == 0) { - m_log->error("found CherenkovParticleID object with no hypotheses"); - return false; - } - - // relate matched ParticleID objects to output particle - for (const auto& [out_pids_index, out_pids_id] : out_pid_index_map) { - const auto& out_pid = out_pids->at(out_pids_index); - if (out_pid.getObjectID().index != out_pids_id) { // sanity check - m_log->error("indexing error in `edm4eic::ParticleID` collection"); - return false; - } - in_part.addToParticleIDs(out_pid); - } - in_part.setParticleIDUsed(in_part.getParticleIDs().at(0)); // highest likelihood is the first - in_part.setGoodnessOfPID(1); // FIXME: not used yet, aside from 0=noPID vs 1=hasPID - - // trace logging - m_log->trace(" {:.^50}"," PID results "); - m_log->trace(" Hypotheses (sorted):"); - for (auto out_pid : in_part.getParticleIDs()) - Tools::PrintHypothesisTableLine(m_log, out_pid, 8); - m_log->trace(" {:'^50}",""); +bool ParticlesWithPID::linkCherenkovPID(edm4eic::MutableReconstructedParticle& in_part, + const edm4eic::CherenkovParticleIDCollection& in_pids, + edm4hep::ParticleIDCollection& out_pids) { + + // skip this particle, if neutral + if (std::abs(in_part.getCharge()) < 0.001) + return false; + + // structure to store list of candidate matches + struct ProxMatch { + double match_dist; + std::size_t pid_idx; + }; + std::vector prox_match_list; + + // get input reconstructed particle momentum angles + auto in_part_p = in_part.getMomentum(); + auto in_part_eta = edm4hep::utils::eta(in_part_p); + auto in_part_phi = edm4hep::utils::angleAzimuthal(in_part_p); + m_log->trace("Input particle: (eta,phi) = ( {:>5.4}, {:>5.4} deg )", in_part_eta, + in_part_phi * 180.0 / M_PI); + + // loop over input CherenkovParticleID objects + for (std::size_t in_pid_idx = 0; in_pid_idx < in_pids.size(); in_pid_idx++) { + auto in_pid = in_pids.at(in_pid_idx); + + // get charged particle track associated to this CherenkovParticleID object + auto in_track = in_pid.getChargedParticle(); + if (!in_track.isAvailable()) { + m_log->error("found CherenkovParticleID object with no chargedParticle"); + return false; + } + if (in_track.points_size() == 0) { + m_log->error("found chargedParticle for CherenkovParticleID, but it has no TrackPoints"); + return false; + } - return true; + // get averge momentum direction of the track's TrackPoints + decltype(edm4eic::TrackPoint::momentum) in_track_p{0.0, 0.0, 0.0}; + for (const auto& in_track_point : in_track.getPoints()) + in_track_p = in_track_p + (in_track_point.momentum / in_track.points_size()); + auto in_track_eta = edm4hep::utils::eta(in_track_p); + auto in_track_phi = edm4hep::utils::angleAzimuthal(in_track_p); + + // calculate dist(eta,phi) + auto match_dist = std::hypot(in_part_eta - in_track_eta, in_part_phi - in_track_phi); + + // check if the match is close enough: within user-specified tolerances + auto match_is_close = std::abs(in_part_eta - in_track_eta) < m_cfg.etaTolerance && + std::abs(in_part_phi - in_track_phi) < m_cfg.phiTolerance; + if (match_is_close) + prox_match_list.push_back(ProxMatch{match_dist, in_pid_idx}); + + // logging + m_log->trace(" - (eta,phi) = ( {:>5.4}, {:>5.4} deg ), match_dist = {:<5.4}{}", in_track_eta, + in_track_phi * 180.0 / M_PI, match_dist, match_is_close ? " => CLOSE!" : ""); + + } // end loop over input CherenkovParticleID objects + + // check if at least one match was found + if (prox_match_list.size() == 0) { + m_log->trace(" => no matching CherenkovParticleID found for this particle"); + return false; + } + + // choose the closest matching CherenkovParticleID object corresponding to this input reconstructed particle + auto closest_prox_match = + *std::min_element(prox_match_list.begin(), prox_match_list.end(), + [](ProxMatch a, ProxMatch b) { return a.match_dist < b.match_dist; }); + auto in_pid_matched = in_pids.at(closest_prox_match.pid_idx); + m_log->trace(" => best match: match_dist = {:<5.4} at idx = {}", closest_prox_match.match_dist, + closest_prox_match.pid_idx); + + // convert `CherenkovParticleID` object's hypotheses => set of `ParticleID` objects + auto out_pid_index_map = ConvertParticleID::ConvertToParticleIDs(in_pid_matched, out_pids, true); + if (out_pid_index_map.size() == 0) { + m_log->error("found CherenkovParticleID object with no hypotheses"); + return false; + } + + // relate matched ParticleID objects to output particle + for (const auto& [out_pids_index, out_pids_id] : out_pid_index_map) { + const auto& out_pid = out_pids->at(out_pids_index); + if (out_pid.getObjectID().index != out_pids_id) { // sanity check + m_log->error("indexing error in `edm4eic::ParticleID` collection"); + return false; } + in_part.addToParticleIDs(out_pid); + } + in_part.setParticleIDUsed(in_part.getParticleIDs().at(0)); // highest likelihood is the first + in_part.setGoodnessOfPID(1); // FIXME: not used yet, aside from 0=noPID vs 1=hasPID + + // trace logging + m_log->trace(" {:.^50}", " PID results "); + m_log->trace(" Hypotheses (sorted):"); + for (auto out_pid : in_part.getParticleIDs()) + Tools::PrintHypothesisTableLine(m_log, out_pid, 8); + m_log->trace(" {:'^50}", ""); + + return true; } +} // namespace eicrecon diff --git a/src/algorithms/pid/ParticlesWithPID.h b/src/algorithms/pid/ParticlesWithPID.h index ccd26b7d6f..38bf6a6aaa 100644 --- a/src/algorithms/pid/ParticlesWithPID.h +++ b/src/algorithms/pid/ParticlesWithPID.h @@ -1,7 +1,6 @@ // Original licence header: SPDX-License-Identifier: LGPL-3.0-or-later // Copyright (C) 2022, 2023, Sylvester Joosten, Wouter Deconinck, Dmitry Romanov, Christopher Dilks - #pragma once #include @@ -17,37 +16,29 @@ #include "ParticlesWithPIDConfig.h" #include "algorithms/interfaces/WithPodConfig.h" - namespace eicrecon { - using ParticlesWithAssociation = std::tuple< - std::unique_ptr, - std::unique_ptr, - std::unique_ptr - >; - - class ParticlesWithPID : public WithPodConfig { - - public: +using ParticlesWithAssociation = + std::tuple, + std::unique_ptr, + std::unique_ptr>; - void init(std::shared_ptr logger); +class ParticlesWithPID : public WithPodConfig { - ParticlesWithAssociation process( - const edm4hep::MCParticleCollection* mc_particles, - const edm4eic::TrackCollection* tracks, - const edm4eic::CherenkovParticleIDCollection* drich_cherenkov_pid_collections - ); +public: + void init(std::shared_ptr logger); - private: + ParticlesWithAssociation + process(const edm4hep::MCParticleCollection* mc_particles, const edm4eic::TrackCollection* tracks, + const edm4eic::CherenkovParticleIDCollection* drich_cherenkov_pid_collections); - std::shared_ptr m_log; +private: + std::shared_ptr m_log; - void tracePhiToleranceOnce(const double sinPhiOver2Tolerance, double phiTolerance); + void tracePhiToleranceOnce(const double sinPhiOver2Tolerance, double phiTolerance); - bool linkCherenkovPID( - edm4eic::MutableReconstructedParticle& in_part, - const edm4eic::CherenkovParticleIDCollection& in_pids, - edm4hep::ParticleIDCollection& out_pids - ); - }; -} + bool linkCherenkovPID(edm4eic::MutableReconstructedParticle& in_part, + const edm4eic::CherenkovParticleIDCollection& in_pids, + edm4hep::ParticleIDCollection& out_pids); +}; +} // namespace eicrecon diff --git a/src/algorithms/pid/ParticlesWithPIDConfig.h b/src/algorithms/pid/ParticlesWithPIDConfig.h index b657576cd4..45bacd518f 100644 --- a/src/algorithms/pid/ParticlesWithPIDConfig.h +++ b/src/algorithms/pid/ParticlesWithPIDConfig.h @@ -6,12 +6,12 @@ namespace eicrecon { - struct ParticlesWithPIDConfig { - double momentumRelativeTolerance = 100.0; /// Matching momentum effectively disabled +struct ParticlesWithPIDConfig { + double momentumRelativeTolerance = 100.0; /// Matching momentum effectively disabled - double phiTolerance = 0.1; /// Matching phi tolerance [rad] + double phiTolerance = 0.1; /// Matching phi tolerance [rad] - double etaTolerance = 0.2; /// Matching eta tolerance - }; + double etaTolerance = 0.2; /// Matching eta tolerance +}; -} // eicrecon +} // namespace eicrecon diff --git a/src/algorithms/pid/Tools.h b/src/algorithms/pid/Tools.h index b74d936fa9..60d30ffd14 100644 --- a/src/algorithms/pid/Tools.h +++ b/src/algorithms/pid/Tools.h @@ -22,228 +22,206 @@ #include #include - namespace eicrecon { - // Tools class, filled with miscellaneous helper functions - class Tools { - public: - - // ------------------------------------------------------------------------------------- - - // h*c constant, for wavelength <=> energy conversion [GeV*nm] - static constexpr double HC = dd4hep::h_Planck * dd4hep::c_light / (dd4hep::GeV * dd4hep::nm); - - - // ------------------------------------------------------------------------------------- - // Radiator IDs - - static std::unordered_map GetRadiatorIDs() { - return std::unordered_map{ - { 0, "Aerogel" }, - { 1, "Gas" } - }; - } - - static std::string GetRadiatorName(int id) { - std::string name; - try { name = GetRadiatorIDs().at(id); } - catch(const std::out_of_range& e) { - throw std::runtime_error(fmt::format("RUNTIME ERROR: unknown radiator ID={} in algorithms/pid/Tools::GetRadiatorName",id)); - } - return name; - } - - static int GetRadiatorID(std::string name) { - for(auto& [id,name_tmp] : GetRadiatorIDs()) - if(name==name_tmp) return id; - throw std::runtime_error(fmt::format("RUNTIME ERROR: unknown radiator '{}' in algorithms/pid/Tools::GetRadiatorID",name)); - return -1; +// Tools class, filled with miscellaneous helper functions +class Tools { +public: + // ------------------------------------------------------------------------------------- + + // h*c constant, for wavelength <=> energy conversion [GeV*nm] + static constexpr double HC = dd4hep::h_Planck * dd4hep::c_light / (dd4hep::GeV * dd4hep::nm); + + // ------------------------------------------------------------------------------------- + // Radiator IDs + + static std::unordered_map GetRadiatorIDs() { + return std::unordered_map{{0, "Aerogel"}, {1, "Gas"}}; + } + + static std::string GetRadiatorName(int id) { + std::string name; + try { + name = GetRadiatorIDs().at(id); + } catch (const std::out_of_range& e) { + throw std::runtime_error(fmt::format( + "RUNTIME ERROR: unknown radiator ID={} in algorithms/pid/Tools::GetRadiatorName", id)); + } + return name; + } + + static int GetRadiatorID(std::string name) { + for (auto& [id, name_tmp] : GetRadiatorIDs()) + if (name == name_tmp) + return id; + throw std::runtime_error(fmt::format( + "RUNTIME ERROR: unknown radiator '{}' in algorithms/pid/Tools::GetRadiatorID", name)); + return -1; + } + + // ------------------------------------------------------------------------------------- + // PDG mass lookup + + // local PDG mass database + // FIXME: cannot use `TDatabasePDG` since it is not thread safe; until we + // have a proper PDG database service, we hard-code the masses we need; + // use Tools::GetPDGMass for access + static std::unordered_map GetPDGMasses() { + return std::unordered_map{ + {11, 0.000510999}, {211, 0.13957}, {321, 0.493677}, {2212, 0.938272}}; + } + + static double GetPDGMass(int pdg) { + double mass; + try { + mass = GetPDGMasses().at(std::abs(pdg)); + } catch (const std::out_of_range& e) { + throw std::runtime_error( + fmt::format("RUNTIME ERROR: unknown PDG={} in algorithms/pid/Tools::GetPDGMass", pdg)); + } + return mass; + } + + static int GetNumPDGs() { return GetPDGMasses().size(); }; + + // ------------------------------------------------------------------------------------- + // Table rebinning and lookup + + // Rebin input table `input` to have `nbins+1` equidistant bins; returns the rebinned table + static std::vector> + ApplyFineBinning(const std::vector>& input, unsigned nbins) { + std::vector> ret; + + // Well, could have probably just reordered the initial vector; + std::map buffer; + + for (auto entry : input) + buffer[entry.first] = entry.second; + + // Sanity checks; return empty map in case do not pass them; + if (buffer.size() < 2 || nbins < 2) + return ret; + + double from = (*buffer.begin()).first; + double to = (*buffer.rbegin()).first; + // Will be "nbins+1" equidistant entries; + double step = (to - from) / nbins; + + for (auto entry : buffer) { + double e1 = entry.first; + double qe1 = entry.second; + + if (!ret.size()) + ret.push_back(std::make_pair(e1, qe1)); + else { + const auto& prev = ret[ret.size() - 1]; + + double e0 = prev.first; + double qe0 = prev.second; + double a = (qe1 - qe0) / (e1 - e0); + double b = qe0 - a * e0; + // FIXME: check floating point accuracy when moving to a next point; do we actually + // care whether the overall number of bins will be "nbins+1" or more?; + for (double e = e0 + step; e < e1; e += step) + ret.push_back(std::make_pair(e, a * e + b)); + } //if + } //for entry + + return ret; + } + + // Find the bin in table `table` that contains entry `argument` in the first column and + // sets `entry` to the corresponding element of the second column; returns true if successful + static bool GetFinelyBinnedTableEntry(const std::vector>& table, + double argument, double* entry) { + // Get the tabulated table reference; perform sanity checks; + //const std::vector> &qe = u_quantumEfficiency.value(); + unsigned dim = table.size(); + if (dim < 2) + return false; + + // Find a proper bin; no tricks, they are all equidistant; + auto const& from = table[0]; + auto const& to = table[dim - 1]; + double emin = from.first; + double emax = to.first; + double step = (emax - emin) / (dim - 1); + int ibin = (int)floor((argument - emin) / step); + + //printf("%f vs %f, %f -> %d\n", ev, from.first, to. first, ibin); + + // Out of range check; + if (ibin < 0 || ibin >= int(dim)) + return false; + + *entry = table[ibin].second; + return true; + } + + // ------------------------------------------------------------------------------------- + // convert PODIO vector datatype to ROOT TVector3 + template static TVector3 PodioVector3_to_TVector3(const PodioVector3 v) { + return TVector3(v.x, v.y, v.z); + } + // convert ROOT::Math::Vector to ROOT TVector3 + template static TVector3 MathVector3_to_TVector3(MathVector3 v) { + return TVector3(v.x(), v.y(), v.z()); + } + + // ------------------------------------------------------------------------------------- + + // printing: vectors + static void PrintTVector3(std::shared_ptr m_log, std::string name, TVector3 vec, + int nameBuffer = 30, + spdlog::level::level_enum lvl = spdlog::level::trace) { + m_log->log(lvl, "{:>{}} = ( {:>10.2f} {:>10.2f} {:>10.2f} )", name, nameBuffer, vec.x(), + vec.y(), vec.z()); + } + + // printing: hypothesis tables + static void PrintHypothesisTableHead(std::shared_ptr m_log, int indent = 4, + spdlog::level::level_enum lvl = spdlog::level::trace) { + m_log->log(lvl, "{:{}}{:>6} {:>10} {:>10}", "", indent, "PDG", "Weight", "NPE"); + } + static void PrintHypothesisTableLine(std::shared_ptr m_log, + edm4eic::CherenkovParticleIDHypothesis hyp, int indent = 4, + spdlog::level::level_enum lvl = spdlog::level::trace) { + m_log->log(lvl, "{:{}}{:>6} {:>10.8} {:>10.8}", "", indent, hyp.PDG, hyp.weight, hyp.npe); + } + static void PrintHypothesisTableLine(std::shared_ptr m_log, + edm4hep::ParticleID hyp, int indent = 4, + spdlog::level::level_enum lvl = spdlog::level::trace) { + float npe = + hyp.parameters_size() > 0 ? hyp.getParameters(0) : -1; // assume NPE is the first parameter + m_log->log(lvl, "{:{}}{:>6} {:>10.8} {:>10.8}", "", indent, hyp.getPDG(), hyp.getLikelihood(), + npe); + } + + // printing: Cherenkov angle estimate + static void PrintCherenkovEstimate(std::shared_ptr m_log, + edm4eic::CherenkovParticleID pid, bool printHypotheses = true, + int indent = 2, + spdlog::level::level_enum lvl = spdlog::level::trace) { + if (m_log->level() <= lvl) { + double thetaAve = 0; + if (pid.getNpe() > 0) + for (const auto& [theta, phi] : pid.getThetaPhiPhotons()) + thetaAve += theta / pid.getNpe(); + m_log->log(lvl, "{:{}}Cherenkov Angle Estimate:", "", indent); + m_log->log(lvl, "{:{}} {:>16}: {:>10}", "", indent, "NPE", pid.getNpe()); + m_log->log(lvl, "{:{}} {:>16}: {:>10.8} mrad", "", indent, "", + thetaAve * 1e3); // [rad] -> [mrad] + m_log->log(lvl, "{:{}} {:>16}: {:>10.8}", "", indent, "", pid.getRefractiveIndex()); + m_log->log(lvl, "{:{}} {:>16}: {:>10.8} eV", "", indent, "", + pid.getPhotonEnergy() * 1e9); // [GeV] -> [eV] + if (printHypotheses) { + m_log->log(lvl, "{:{}}Mass Hypotheses:", "", indent); + Tools::PrintHypothesisTableHead(m_log, indent + 2); + for (const auto& hyp : pid.getHypotheses()) + Tools::PrintHypothesisTableLine(m_log, hyp, indent + 2); } + } + } - - // ------------------------------------------------------------------------------------- - // PDG mass lookup - - // local PDG mass database - // FIXME: cannot use `TDatabasePDG` since it is not thread safe; until we - // have a proper PDG database service, we hard-code the masses we need; - // use Tools::GetPDGMass for access - static std::unordered_map GetPDGMasses() { - return std::unordered_map{ - { 11, 0.000510999 }, - { 211, 0.13957 }, - { 321, 0.493677 }, - { 2212, 0.938272 } - }; - } - - static double GetPDGMass(int pdg) { - double mass; - try { mass = GetPDGMasses().at(std::abs(pdg)); } - catch(const std::out_of_range& e) { - throw std::runtime_error(fmt::format("RUNTIME ERROR: unknown PDG={} in algorithms/pid/Tools::GetPDGMass",pdg)); - } - return mass; - } - - static int GetNumPDGs() { return GetPDGMasses().size(); }; - - - // ------------------------------------------------------------------------------------- - // Table rebinning and lookup - - // Rebin input table `input` to have `nbins+1` equidistant bins; returns the rebinned table - static std::vector> ApplyFineBinning( - const std::vector> &input, - unsigned nbins - ) - { - std::vector> ret; - - // Well, could have probably just reordered the initial vector; - std::map buffer; - - for(auto entry: input) - buffer[entry.first] = entry.second; - - // Sanity checks; return empty map in case do not pass them; - if (buffer.size() < 2 || nbins < 2) return ret; - - double from = (*buffer.begin()).first; - double to = (*buffer.rbegin()).first; - // Will be "nbins+1" equidistant entries; - double step = (to - from) / nbins; - - for(auto entry: buffer) { - double e1 = entry.first; - double qe1 = entry.second; - - if (!ret.size()) - ret.push_back(std::make_pair(e1, qe1)); - else { - const auto &prev = ret[ret.size()-1]; - - double e0 = prev.first; - double qe0 = prev.second; - double a = (qe1 - qe0) / (e1 - e0); - double b = qe0 - a*e0; - // FIXME: check floating point accuracy when moving to a next point; do we actually - // care whether the overall number of bins will be "nbins+1" or more?; - for(double e = e0+step; e> &table, - double argument, - double *entry - ) - { - // Get the tabulated table reference; perform sanity checks; - //const std::vector> &qe = u_quantumEfficiency.value(); - unsigned dim = table.size(); if (dim < 2) return false; - - // Find a proper bin; no tricks, they are all equidistant; - auto const &from = table[0]; - auto const &to = table[dim-1]; - double emin = from.first; - double emax = to.first; - double step = (emax - emin) / (dim - 1); - int ibin = (int)floor((argument - emin) / step); - - //printf("%f vs %f, %f -> %d\n", ev, from.first, to. first, ibin); - - // Out of range check; - if (ibin < 0 || ibin >= int(dim)) return false; - - *entry = table[ibin].second; - return true; - } - - // ------------------------------------------------------------------------------------- - // convert PODIO vector datatype to ROOT TVector3 - template - static TVector3 PodioVector3_to_TVector3(const PodioVector3 v) { - return TVector3(v.x, v.y, v.z); - } - // convert ROOT::Math::Vector to ROOT TVector3 - template - static TVector3 MathVector3_to_TVector3(MathVector3 v) { - return TVector3(v.x(), v.y(), v.z()); - } - - // ------------------------------------------------------------------------------------- - - // printing: vectors - static void PrintTVector3( - std::shared_ptr m_log, - std::string name, TVector3 vec, - int nameBuffer=30, spdlog::level::level_enum lvl=spdlog::level::trace - ) - { - m_log->log(lvl, "{:>{}} = ( {:>10.2f} {:>10.2f} {:>10.2f} )", name, nameBuffer, vec.x(), vec.y(), vec.z()); - } - - // printing: hypothesis tables - static void PrintHypothesisTableHead( - std::shared_ptr m_log, - int indent=4, spdlog::level::level_enum lvl=spdlog::level::trace - ) - { - m_log->log(lvl, "{:{}}{:>6} {:>10} {:>10}", "", indent, "PDG", "Weight", "NPE"); - } - static void PrintHypothesisTableLine( - std::shared_ptr m_log, - edm4eic::CherenkovParticleIDHypothesis hyp, - int indent=4, spdlog::level::level_enum lvl=spdlog::level::trace - ) - { - m_log->log(lvl, "{:{}}{:>6} {:>10.8} {:>10.8}", "", indent, hyp.PDG, hyp.weight, hyp.npe); - } - static void PrintHypothesisTableLine( - std::shared_ptr m_log, - edm4hep::ParticleID hyp, - int indent=4, spdlog::level::level_enum lvl=spdlog::level::trace - ) - { - float npe = hyp.parameters_size() > 0 ? hyp.getParameters(0) : -1; // assume NPE is the first parameter - m_log->log(lvl, "{:{}}{:>6} {:>10.8} {:>10.8}", "", indent, hyp.getPDG(), hyp.getLikelihood(), npe); - } - - // printing: Cherenkov angle estimate - static void PrintCherenkovEstimate( - std::shared_ptr m_log, - edm4eic::CherenkovParticleID pid, - bool printHypotheses = true, - int indent=2, spdlog::level::level_enum lvl=spdlog::level::trace - ) - { - if(m_log->level() <= lvl) { - double thetaAve = 0; - if(pid.getNpe() > 0) - for(const auto& [theta,phi] : pid.getThetaPhiPhotons()) - thetaAve += theta / pid.getNpe(); - m_log->log(lvl, "{:{}}Cherenkov Angle Estimate:", "", indent); - m_log->log(lvl, "{:{}} {:>16}: {:>10}", "", indent, "NPE", pid.getNpe()); - m_log->log(lvl, "{:{}} {:>16}: {:>10.8} mrad", "", indent, "", thetaAve*1e3); // [rad] -> [mrad] - m_log->log(lvl, "{:{}} {:>16}: {:>10.8}", "", indent, "", pid.getRefractiveIndex()); - m_log->log(lvl, "{:{}} {:>16}: {:>10.8} eV", "", indent, "", pid.getPhotonEnergy()*1e9); // [GeV] -> [eV] - if(printHypotheses) { - m_log->log(lvl, "{:{}}Mass Hypotheses:", "", indent); - Tools::PrintHypothesisTableHead(m_log, indent+2); - for(const auto& hyp : pid.getHypotheses()) - Tools::PrintHypothesisTableLine(m_log, hyp, indent+2); - } - } - } - - - }; // class Tools +}; // class Tools } // namespace eicrecon diff --git a/src/algorithms/reco/Beam.h b/src/algorithms/reco/Beam.h index 6c81b1c622..69171f57de 100644 --- a/src/algorithms/reco/Beam.h +++ b/src/algorithms/reco/Beam.h @@ -12,72 +12,62 @@ using ROOT::Math::PxPyPzEVector; namespace eicrecon { - template - auto find_first_with_pdg( - const T* parts, - const std::set& pdg) { - T c; - c.setSubsetCollection(); - for (const auto& p: *parts) { - if (pdg.count(p.getPDG()) > 0) { - c.push_back(p); - break; - } +template auto find_first_with_pdg(const T* parts, const std::set& pdg) { + T c; + c.setSubsetCollection(); + for (const auto& p : *parts) { + if (pdg.count(p.getPDG()) > 0) { + c.push_back(p); + break; } - return c; } + return c; +} - template - auto find_first_with_status_pdg( - const T* parts, - const std::set& status, - const std::set& pdg) { - T c; - c.setSubsetCollection(); - for (const auto& p: *parts) { - if (status.count(p.getGeneratorStatus()) > 0 && - pdg.count(p.getPDG()) > 0) { - c.push_back(p); - break; - } +template +auto find_first_with_status_pdg(const T* parts, const std::set& status, + const std::set& pdg) { + T c; + c.setSubsetCollection(); + for (const auto& p : *parts) { + if (status.count(p.getGeneratorStatus()) > 0 && pdg.count(p.getPDG()) > 0) { + c.push_back(p); + break; } - return c; } + return c; +} - inline auto find_first_beam_electron(const edm4hep::MCParticleCollection* mcparts) { - return find_first_with_status_pdg(mcparts, {4}, {11}); - } +inline auto find_first_beam_electron(const edm4hep::MCParticleCollection* mcparts) { + return find_first_with_status_pdg(mcparts, {4}, {11}); +} - inline auto find_first_beam_hadron(const edm4hep::MCParticleCollection* mcparts) { - return find_first_with_status_pdg(mcparts, {4}, {2212, 2112}); - } +inline auto find_first_beam_hadron(const edm4hep::MCParticleCollection* mcparts) { + return find_first_with_status_pdg(mcparts, {4}, {2212, 2112}); +} - inline auto find_first_scattered_electron(const edm4hep::MCParticleCollection* mcparts) { - return find_first_with_status_pdg(mcparts, {1}, {11}); - } +inline auto find_first_scattered_electron(const edm4hep::MCParticleCollection* mcparts) { + return find_first_with_status_pdg(mcparts, {1}, {11}); +} - inline auto find_first_scattered_electron(const edm4eic::ReconstructedParticleCollection* rcparts) { - return find_first_with_pdg(rcparts, {11}); - } +inline auto find_first_scattered_electron(const edm4eic::ReconstructedParticleCollection* rcparts) { + return find_first_with_pdg(rcparts, {11}); +} - inline - PxPyPzEVector - round_beam_four_momentum( - const edm4hep::Vector3f& p_in, - const float mass, - const std::vector& pz_set, - const float crossing_angle = 0.0) { - PxPyPzEVector p_out; - for (const auto& pz : pz_set) { - if (fabs(p_in.z / pz - 1) < 0.1) { - p_out.SetPz(pz); - break; - } +inline PxPyPzEVector round_beam_four_momentum(const edm4hep::Vector3f& p_in, const float mass, + const std::vector& pz_set, + const float crossing_angle = 0.0) { + PxPyPzEVector p_out; + for (const auto& pz : pz_set) { + if (fabs(p_in.z / pz - 1) < 0.1) { + p_out.SetPz(pz); + break; } - p_out.SetPx(p_out.Pz() * sin(crossing_angle)); - p_out.SetPz(p_out.Pz() * cos(crossing_angle)); - p_out.SetE(std::hypot(p_out.Px(), p_out.Pz(), mass)); - return p_out; } + p_out.SetPx(p_out.Pz() * sin(crossing_angle)); + p_out.SetPz(p_out.Pz() * cos(crossing_angle)); + p_out.SetE(std::hypot(p_out.Px(), p_out.Pz(), mass)); + return p_out; +} } // namespace eicrecon diff --git a/src/algorithms/reco/Boost.h b/src/algorithms/reco/Boost.h index 95c7b0e857..df4edf4b4a 100644 --- a/src/algorithms/reco/Boost.h +++ b/src/algorithms/reco/Boost.h @@ -14,50 +14,50 @@ using ROOT::Math::PxPyPzEVector; namespace eicrecon { - using ROOT::Math::LorentzRotation; +using ROOT::Math::LorentzRotation; - inline LorentzRotation determine_boost(PxPyPzEVector ei, PxPyPzEVector pi) { +inline LorentzRotation determine_boost(PxPyPzEVector ei, PxPyPzEVector pi) { - using ROOT::Math::RotationX; - using ROOT::Math::RotationY; - using ROOT::Math::Boost; + using ROOT::Math::Boost; + using ROOT::Math::RotationX; + using ROOT::Math::RotationY; - // Step 1: Find the needed boosts and rotations from the incoming lepton and hadron beams - // (note, this will give you a perfect boost, in principle you will not know the beam momenta exactly and should use an average) + // Step 1: Find the needed boosts and rotations from the incoming lepton and hadron beams + // (note, this will give you a perfect boost, in principle you will not know the beam momenta exactly and should use an average) - // Define the Boost to make beams back-to-back - const auto cmBoost = (ei + pi).BoostToCM(); + // Define the Boost to make beams back-to-back + const auto cmBoost = (ei + pi).BoostToCM(); - const Boost boost_to_cm(-cmBoost); + const Boost boost_to_cm(-cmBoost); - // This will boost beams from a center of momentum frame back to (nearly) their original energies - const Boost boost_to_headon(cmBoost); // FIXME + // This will boost beams from a center of momentum frame back to (nearly) their original energies + const Boost boost_to_headon(cmBoost); // FIXME - // Boost and rotate the incoming beams to find the proper rotations TLorentzVector + // Boost and rotate the incoming beams to find the proper rotations TLorentzVector - // Boost to COM frame - boost_to_cm(pi); - boost_to_cm(ei); - // Rotate to head-on - RotationY rotAboutY(-1.0*atan2(pi.Px(), pi.Pz())); // Rotate to remove x component of beams - RotationX rotAboutX(+1.0*atan2(pi.Py(), pi.Pz())); // Rotate to remove y component of beams + // Boost to COM frame + boost_to_cm(pi); + boost_to_cm(ei); + // Rotate to head-on + RotationY rotAboutY(-1.0 * atan2(pi.Px(), pi.Pz())); // Rotate to remove x component of beams + RotationX rotAboutX(+1.0 * atan2(pi.Py(), pi.Pz())); // Rotate to remove y component of beams - LorentzRotation tf; - tf *= boost_to_cm; - tf *= rotAboutY; - tf *= rotAboutX; - tf *= boost_to_headon; - return tf; - } + LorentzRotation tf; + tf *= boost_to_cm; + tf *= rotAboutY; + tf *= rotAboutX; + tf *= boost_to_headon; + return tf; +} - inline PxPyPzEVector apply_boost(const LorentzRotation& tf, PxPyPzEVector part) { +inline PxPyPzEVector apply_boost(const LorentzRotation& tf, PxPyPzEVector part) { - // Step 2: Apply boosts and rotations to any particle 4-vector - // (here too, choices will have to be made as to what the 4-vector is for reconstructed particles) + // Step 2: Apply boosts and rotations to any particle 4-vector + // (here too, choices will have to be made as to what the 4-vector is for reconstructed particles) - // Boost and rotate particle 4-momenta into the headon frame - tf(part); - return part; - } + // Boost and rotate particle 4-momenta into the headon frame + tf(part); + return part; +} } // namespace eicrecon diff --git a/src/algorithms/reco/ChargedMCParticleSelector.h b/src/algorithms/reco/ChargedMCParticleSelector.h index f004d83cef..704156a5fc 100644 --- a/src/algorithms/reco/ChargedMCParticleSelector.h +++ b/src/algorithms/reco/ChargedMCParticleSelector.h @@ -13,33 +13,29 @@ namespace eicrecon { - class ChargedMCParticleSelector : public WithPodConfig { +class ChargedMCParticleSelector : public WithPodConfig { - private: +private: + std::shared_ptr m_log; - std::shared_ptr m_log; +public: + // algorithm initialization + void init(std::shared_ptr& logger) { m_log = logger; } - public: + // primary algorithm call + std::unique_ptr + process(const edm4hep::MCParticleCollection* inputs) { + auto outputs = std::make_unique(); + outputs->setSubsetCollection(); - // algorithm initialization - void init(std::shared_ptr& logger) { - m_log = logger; - } - - // primary algorithm call - std::unique_ptr process(const edm4hep::MCParticleCollection* inputs) { - auto outputs = std::make_unique(); - outputs->setSubsetCollection(); - - for (const auto &particle : *inputs) { - if (particle.getCharge() != 0.) { - outputs->push_back(particle); - } + for (const auto& particle : *inputs) { + if (particle.getCharge() != 0.) { + outputs->push_back(particle); } - - return std::move(outputs); } - }; + return std::move(outputs); + } +}; -} +} // namespace eicrecon diff --git a/src/algorithms/reco/ChargedReconstructedParticleSelector.h b/src/algorithms/reco/ChargedReconstructedParticleSelector.h index 93381738e4..3cf26479f5 100644 --- a/src/algorithms/reco/ChargedReconstructedParticleSelector.h +++ b/src/algorithms/reco/ChargedReconstructedParticleSelector.h @@ -13,33 +13,29 @@ namespace eicrecon { - class ChargedReconstructedParticleSelector : public WithPodConfig { +class ChargedReconstructedParticleSelector : public WithPodConfig { - private: +private: + std::shared_ptr m_log; - std::shared_ptr m_log; +public: + // algorithm initialization + void init(std::shared_ptr& logger) { m_log = logger; } - public: + // primary algorithm call + std::unique_ptr + process(const edm4eic::ReconstructedParticleCollection* inputs) { + auto outputs = std::make_unique(); + outputs->setSubsetCollection(); - // algorithm initialization - void init(std::shared_ptr& logger) { - m_log = logger; - } - - // primary algorithm call - std::unique_ptr process(const edm4eic::ReconstructedParticleCollection* inputs) { - auto outputs = std::make_unique(); - outputs->setSubsetCollection(); - - for (const auto &particle : *inputs) { - if (particle.getCharge() != 0.) { - outputs->push_back(particle); - } + for (const auto& particle : *inputs) { + if (particle.getCharge() != 0.) { + outputs->push_back(particle); } - - return std::move(outputs); } - }; + return std::move(outputs); + } +}; -} +} // namespace eicrecon diff --git a/src/algorithms/reco/ElectronReconstruction.cc b/src/algorithms/reco/ElectronReconstruction.cc index 9bc57ba8f1..ffa8c1c092 100644 --- a/src/algorithms/reco/ElectronReconstruction.cc +++ b/src/algorithms/reco/ElectronReconstruction.cc @@ -12,43 +12,42 @@ namespace eicrecon { - void ElectronReconstruction::init(std::shared_ptr logger) { - m_log = logger; - } +void ElectronReconstruction::init(std::shared_ptr logger) { m_log = logger; } + +std::unique_ptr +ElectronReconstruction::execute(const edm4eic::ReconstructedParticleCollection* rcparts) { + + // Some obvious improvements: + // - E/p cut from real study optimized for electron finding and hadron rejection + // - use of any HCAL info? + // - check for duplicates? - std::unique_ptr ElectronReconstruction::execute( - const edm4eic::ReconstructedParticleCollection *rcparts - ) { - - // Some obvious improvements: - // - E/p cut from real study optimized for electron finding and hadron rejection - // - use of any HCAL info? - // - check for duplicates? - - // output container - auto out_electrons = std::make_unique(); - out_electrons->setSubsetCollection(); // out_electrons is a subset of the ReconstructedParticles collection - - for (const auto particle : *rcparts) { - // if we found a reco particle then test for electron compatibility - if (particle.getClusters().size() == 0) { - continue; - } - if (particle.getCharge() == 0) { // Skip over photons/other particles without a track - continue; - } - double E = particle.getClusters()[0].getEnergy(); - double p = edm4hep::utils::magnitude(particle.getMomentum()); - double EOverP = E / p; - - m_log->trace("ReconstructedElectron: Energy={} GeV, p={} GeV, E/p = {} for PDG (from truth): {}", E, p, EOverP, particle.getPDG()); - // Apply the E/p cut here to select electons - if (EOverP >= m_cfg.min_energy_over_momentum && EOverP <= m_cfg.max_energy_over_momentum) { - out_electrons->push_back(particle); - } - - } - m_log->debug("Found {} electron candidates", out_electrons->size()); - return out_electrons; + // output container + auto out_electrons = std::make_unique(); + out_electrons + ->setSubsetCollection(); // out_electrons is a subset of the ReconstructedParticles collection + + for (const auto particle : *rcparts) { + // if we found a reco particle then test for electron compatibility + if (particle.getClusters().size() == 0) { + continue; + } + if (particle.getCharge() == 0) { // Skip over photons/other particles without a track + continue; + } + double E = particle.getClusters()[0].getEnergy(); + double p = edm4hep::utils::magnitude(particle.getMomentum()); + double EOverP = E / p; + + m_log->trace( + "ReconstructedElectron: Energy={} GeV, p={} GeV, E/p = {} for PDG (from truth): {}", E, p, + EOverP, particle.getPDG()); + // Apply the E/p cut here to select electons + if (EOverP >= m_cfg.min_energy_over_momentum && EOverP <= m_cfg.max_energy_over_momentum) { + out_electrons->push_back(particle); } + } + m_log->debug("Found {} electron candidates", out_electrons->size()); + return out_electrons; } +} // namespace eicrecon diff --git a/src/algorithms/reco/ElectronReconstruction.h b/src/algorithms/reco/ElectronReconstruction.h index cb54b06a4a..521efedc80 100644 --- a/src/algorithms/reco/ElectronReconstruction.h +++ b/src/algorithms/reco/ElectronReconstruction.h @@ -10,23 +10,19 @@ #include "ElectronReconstructionConfig.h" #include "algorithms/interfaces/WithPodConfig.h" - namespace eicrecon { - class ElectronReconstruction : public WithPodConfig{ - - public: - - void init(std::shared_ptr logger); +class ElectronReconstruction : public WithPodConfig { - // idea will be to overload this with other version (e.g. reco mode) - std::unique_ptr execute( - const edm4eic::ReconstructedParticleCollection *rcparts - ); +public: + void init(std::shared_ptr logger); - private: - std::shared_ptr m_log; - double m_electron{0.000510998928}; + // idea will be to overload this with other version (e.g. reco mode) + std::unique_ptr + execute(const edm4eic::ReconstructedParticleCollection* rcparts); - }; +private: + std::shared_ptr m_log; + double m_electron{0.000510998928}; +}; } // namespace eicrecon diff --git a/src/algorithms/reco/ElectronReconstructionConfig.h b/src/algorithms/reco/ElectronReconstructionConfig.h index 4f025ad8d6..1ec9bc60bb 100644 --- a/src/algorithms/reco/ElectronReconstructionConfig.h +++ b/src/algorithms/reco/ElectronReconstructionConfig.h @@ -6,9 +6,8 @@ namespace eicrecon { struct ElectronReconstructionConfig { - double min_energy_over_momentum = 0.9; - double max_energy_over_momentum = 1.2; - + double min_energy_over_momentum = 0.9; + double max_energy_over_momentum = 1.2; }; } // namespace eicrecon diff --git a/src/algorithms/reco/InclusiveKinematicsDA.cc b/src/algorithms/reco/InclusiveKinematicsDA.cc index 07a411a90f..80399b80f0 100644 --- a/src/algorithms/reco/InclusiveKinematicsDA.cc +++ b/src/algorithms/reco/InclusiveKinematicsDA.cc @@ -22,144 +22,135 @@ using ROOT::Math::PxPyPzEVector; namespace eicrecon { - void InclusiveKinematicsDA::init(std::shared_ptr& logger) { - m_log = logger; - // m_pidSvc = service("ParticleSvc"); - // if (!m_pidSvc) { - // m_log->debug("Unable to locate Particle Service. " - // "Make sure you have ParticleSvc in the configuration."); - // } +void InclusiveKinematicsDA::init(std::shared_ptr& logger) { + m_log = logger; + // m_pidSvc = service("ParticleSvc"); + // if (!m_pidSvc) { + // m_log->debug("Unable to locate Particle Service. " + // "Make sure you have ParticleSvc in the configuration."); + // } +} + +void InclusiveKinematicsDA::process(const InclusiveKinematicsDA::Input& input, + const InclusiveKinematicsDA::Output& output) const { + + const auto [mcparts, rcparts, rcassoc] = input; + auto [kinematics] = output; + + // Get incoming electron beam + const auto ei_coll = find_first_beam_electron(mcparts); + if (ei_coll.size() == 0) { + m_log->debug("No beam electron found"); + return; } - - void InclusiveKinematicsDA::process( - const InclusiveKinematicsDA::Input& input, - const InclusiveKinematicsDA::Output& output) const { - - const auto [mcparts, rcparts, rcassoc] = input; - auto [kinematics] = output; - - // Get incoming electron beam - const auto ei_coll = find_first_beam_electron(mcparts); - if (ei_coll.size() == 0) { - m_log->debug("No beam electron found"); - return; - } - const PxPyPzEVector ei( - round_beam_four_momentum( - ei_coll[0].getMomentum(), - m_electron, - {-5.0, -10.0, -18.0}, - 0.0) - ); - - // Get incoming hadron beam - const auto pi_coll = find_first_beam_hadron(mcparts); - if (pi_coll.size() == 0) { - m_log->debug("No beam hadron found"); - return; - } - const PxPyPzEVector pi( - round_beam_four_momentum( - pi_coll[0].getMomentum(), - pi_coll[0].getPDG() == 2212 ? m_proton : m_neutron, - {41.0, 100.0, 275.0}, - m_crossingAngle) - ); - - // Get first scattered electron - const auto ef_coll = find_first_scattered_electron(mcparts); - if (ef_coll.size() == 0) { - m_log->debug("No truth scattered electron found"); - return; - } - // Associate first scattered electron with reconstructed electrons - //const auto ef_assoc = std::find_if( - // rcassoc->begin(), - // rcassoc->end(), - // [&ef_coll](const auto& a){ return a.getSim().getObjectID() == ef_coll[0].getObjectID(); }); - auto ef_assoc = rcassoc->begin(); - for (; ef_assoc != rcassoc->end(); ++ef_assoc) { - if (ef_assoc->getSim().getObjectID() == ef_coll[0].getObjectID()) { - break; - } - } - if (!(ef_assoc != rcassoc->end())) { - m_log->debug("Truth scattered electron not in reconstructed particles"); - return; + const PxPyPzEVector ei( + round_beam_four_momentum(ei_coll[0].getMomentum(), m_electron, {-5.0, -10.0, -18.0}, 0.0)); + + // Get incoming hadron beam + const auto pi_coll = find_first_beam_hadron(mcparts); + if (pi_coll.size() == 0) { + m_log->debug("No beam hadron found"); + return; + } + const PxPyPzEVector pi(round_beam_four_momentum( + pi_coll[0].getMomentum(), pi_coll[0].getPDG() == 2212 ? m_proton : m_neutron, + {41.0, 100.0, 275.0}, m_crossingAngle)); + + // Get first scattered electron + const auto ef_coll = find_first_scattered_electron(mcparts); + if (ef_coll.size() == 0) { + m_log->debug("No truth scattered electron found"); + return; + } + // Associate first scattered electron with reconstructed electrons + //const auto ef_assoc = std::find_if( + // rcassoc->begin(), + // rcassoc->end(), + // [&ef_coll](const auto& a){ return a.getSim().getObjectID() == ef_coll[0].getObjectID(); }); + auto ef_assoc = rcassoc->begin(); + for (; ef_assoc != rcassoc->end(); ++ef_assoc) { + if (ef_assoc->getSim().getObjectID() == ef_coll[0].getObjectID()) { + break; } - const auto ef_rc{ef_assoc->getRec()}; - const auto ef_rc_id{ef_rc.getObjectID().index}; - - // Loop over reconstructed particles to get all outgoing particles - // ----------------------------------------------------------------- - // Right now, everything is taken from Reconstructed particles branches. - // - // This means the tracking detector is used for charged particles to calculate the momentum, - // and the magnitude of this momentum plus the true PID to calculate the energy. - // No requirement is made that these particles produce a hit in any other detector - // - // Using the Reconstructed particles branches also means that the reconstruction for neutrals is done using the - // calorimeter(s) information for the energy and angles, and then using this energy and the true PID to get the - // magnitude of the momentum. - // ----------------------------------------------------------------- - - //Sums in colinear frame - double pxsum = 0; - double pysum = 0; - double pzsum = 0; - double Esum = 0; - double theta_e = 0; - - // Get boost to colinear frame - auto boost = determine_boost(ei, pi); - - for (const auto& p: *rcparts) { - // Get the scattered electron index and angle - if (p.getObjectID().index == ef_rc_id) { - // Lorentz vector in lab frame - PxPyPzEVector e_lab(p.getMomentum().x, p.getMomentum().y, p.getMomentum().z, p.getEnergy()); - // Boost to colinear frame - PxPyPzEVector e_boosted = apply_boost(boost, e_lab); - - theta_e = e_boosted.Theta(); + } + if (!(ef_assoc != rcassoc->end())) { + m_log->debug("Truth scattered electron not in reconstructed particles"); + return; + } + const auto ef_rc{ef_assoc->getRec()}; + const auto ef_rc_id{ef_rc.getObjectID().index}; + + // Loop over reconstructed particles to get all outgoing particles + // ----------------------------------------------------------------- + // Right now, everything is taken from Reconstructed particles branches. + // + // This means the tracking detector is used for charged particles to calculate the momentum, + // and the magnitude of this momentum plus the true PID to calculate the energy. + // No requirement is made that these particles produce a hit in any other detector + // + // Using the Reconstructed particles branches also means that the reconstruction for neutrals is done using the + // calorimeter(s) information for the energy and angles, and then using this energy and the true PID to get the + // magnitude of the momentum. + // ----------------------------------------------------------------- + + //Sums in colinear frame + double pxsum = 0; + double pysum = 0; + double pzsum = 0; + double Esum = 0; + double theta_e = 0; + + // Get boost to colinear frame + auto boost = determine_boost(ei, pi); + + for (const auto& p : *rcparts) { + // Get the scattered electron index and angle + if (p.getObjectID().index == ef_rc_id) { + // Lorentz vector in lab frame + PxPyPzEVector e_lab(p.getMomentum().x, p.getMomentum().y, p.getMomentum().z, p.getEnergy()); + // Boost to colinear frame + PxPyPzEVector e_boosted = apply_boost(boost, e_lab); + + theta_e = e_boosted.Theta(); // Sum over all particles other than scattered electron - } else { - // Lorentz vector in lab frame - PxPyPzEVector hf_lab(p.getMomentum().x, p.getMomentum().y, p.getMomentum().z, p.getEnergy()); - // Boost to colinear frame - PxPyPzEVector hf_boosted = apply_boost(boost, hf_lab); - - pxsum += hf_boosted.Px(); - pysum += hf_boosted.Py(); - pzsum += hf_boosted.Pz(); - Esum += hf_boosted.E(); - } + } else { + // Lorentz vector in lab frame + PxPyPzEVector hf_lab(p.getMomentum().x, p.getMomentum().y, p.getMomentum().z, p.getEnergy()); + // Boost to colinear frame + PxPyPzEVector hf_boosted = apply_boost(boost, hf_lab); + + pxsum += hf_boosted.Px(); + pysum += hf_boosted.Py(); + pzsum += hf_boosted.Pz(); + Esum += hf_boosted.E(); } + } - // DIS kinematics calculations - auto sigma_h = Esum - pzsum; + // DIS kinematics calculations + auto sigma_h = Esum - pzsum; - // If no scattered hadron was found - if (sigma_h <= 0) { - m_log->debug("No scattered hadron found"); - return; - } + // If no scattered hadron was found + if (sigma_h <= 0) { + m_log->debug("No scattered hadron found"); + return; + } - auto ptsum = sqrt(pxsum*pxsum + pysum*pysum); - auto theta_h = 2.*atan(sigma_h/ptsum); + auto ptsum = sqrt(pxsum * pxsum + pysum * pysum); + auto theta_h = 2. * atan(sigma_h / ptsum); - // Calculate kinematic variables - const auto y_da = tan(theta_h/2.) / ( tan(theta_e/2.) + tan(theta_h/2.) ); - const auto Q2_da = 4.*ei.energy()*ei.energy() * ( 1. / tan(theta_e/2.) ) * ( 1. / (tan(theta_e/2.) + tan(theta_h/2.)) ); - const auto x_da = Q2_da / (4.*ei.energy()*pi.energy()*y_da); - const auto nu_da = Q2_da / (2.*m_proton*x_da); - const auto W_da = sqrt(m_proton*m_proton + 2*m_proton*nu_da - Q2_da); - auto kin = kinematics->create(x_da, Q2_da, W_da, y_da, nu_da); - kin.setScat(ef_rc); + // Calculate kinematic variables + const auto y_da = tan(theta_h / 2.) / (tan(theta_e / 2.) + tan(theta_h / 2.)); + const auto Q2_da = 4. * ei.energy() * ei.energy() * (1. / tan(theta_e / 2.)) * + (1. / (tan(theta_e / 2.) + tan(theta_h / 2.))); + const auto x_da = Q2_da / (4. * ei.energy() * pi.energy() * y_da); + const auto nu_da = Q2_da / (2. * m_proton * x_da); + const auto W_da = sqrt(m_proton * m_proton + 2 * m_proton * nu_da - Q2_da); + auto kin = kinematics->create(x_da, Q2_da, W_da, y_da, nu_da); + kin.setScat(ef_rc); - m_log->debug("x,Q2,W,y,nu = {},{},{},{},{}", kin.getX(), - kin.getQ2(), kin.getW(), kin.getY(), kin.getNu()); - } + m_log->debug("x,Q2,W,y,nu = {},{},{},{},{}", kin.getX(), kin.getQ2(), kin.getW(), kin.getY(), + kin.getNu()); +} -} // namespace Jug::Reco +} // namespace eicrecon diff --git a/src/algorithms/reco/InclusiveKinematicsDA.h b/src/algorithms/reco/InclusiveKinematicsDA.h index af4cea4fb2..992a954522 100644 --- a/src/algorithms/reco/InclusiveKinematicsDA.h +++ b/src/algorithms/reco/InclusiveKinematicsDA.h @@ -13,36 +13,29 @@ #include #include - namespace eicrecon { - using InclusiveKinematicsDAAlgorithm = algorithms::Algorithm< - algorithms::Input< - edm4hep::MCParticleCollection, - edm4eic::ReconstructedParticleCollection, - edm4eic::MCRecoParticleAssociationCollection - >, - algorithms::Output< - edm4eic::InclusiveKinematicsCollection - > - >; - - class InclusiveKinematicsDA - : public InclusiveKinematicsDAAlgorithm { - - public: - InclusiveKinematicsDA(std::string_view name) - : InclusiveKinematicsDAAlgorithm{name, - {"MCParticles", "inputParticles", "inputAssociations"}, - {"inclusiveKinematics"}, - "Determine inclusive kinematics using double-angle method."} {} - - void init(std::shared_ptr& logger); - void process(const Input&, const Output&) const final; - - private: - std::shared_ptr m_log; - double m_proton{0.93827}, m_neutron{0.93957}, m_electron{0.000510998928}, m_crossingAngle{-0.025}; - }; +using InclusiveKinematicsDAAlgorithm = algorithms::Algorithm< + algorithms::Input, + algorithms::Output>; + +class InclusiveKinematicsDA : public InclusiveKinematicsDAAlgorithm { + +public: + InclusiveKinematicsDA(std::string_view name) + : InclusiveKinematicsDAAlgorithm{ + name, + {"MCParticles", "inputParticles", "inputAssociations"}, + {"inclusiveKinematics"}, + "Determine inclusive kinematics using double-angle method."} {} + + void init(std::shared_ptr& logger); + void process(const Input&, const Output&) const final; + +private: + std::shared_ptr m_log; + double m_proton{0.93827}, m_neutron{0.93957}, m_electron{0.000510998928}, m_crossingAngle{-0.025}; +}; } // namespace eicrecon diff --git a/src/algorithms/reco/InclusiveKinematicsElectron.cc b/src/algorithms/reco/InclusiveKinematicsElectron.cc index 4d27bb4c83..3d2fa26875 100644 --- a/src/algorithms/reco/InclusiveKinematicsElectron.cc +++ b/src/algorithms/reco/InclusiveKinematicsElectron.cc @@ -22,152 +22,143 @@ using ROOT::Math::PxPyPzEVector; namespace eicrecon { - void InclusiveKinematicsElectron::init(std::shared_ptr& logger) { - m_log = logger; - // m_pidSvc = service("ParticleSvc"); - // if (!m_pidSvc) { - // m_log->debug("Unable to locate Particle Service. " - // "Make sure you have ParticleSvc in the configuration."); - // } +void InclusiveKinematicsElectron::init(std::shared_ptr& logger) { + m_log = logger; + // m_pidSvc = service("ParticleSvc"); + // if (!m_pidSvc) { + // m_log->debug("Unable to locate Particle Service. " + // "Make sure you have ParticleSvc in the configuration."); + // } +} + +void InclusiveKinematicsElectron::process(const InclusiveKinematicsElectron::Input& input, + const InclusiveKinematicsElectron::Output& output) const { + + const auto [mcparts, rcparts, rcassoc] = input; + auto [kinematics] = output; + + // 1. find_if + //const auto mc_first_electron = std::find_if( + // mcparts.begin(), + // mcparts.end(), + // [](const auto& p){ return p.getPDG() == 11; }); + + // 2a. simple loop over iterator (post-increment) + //auto mc_first_electron = mcparts.end(); + //for (auto p = mcparts.begin(); p != mcparts.end(); p++) { + // if (p.getPDG() == 11) { + // mc_first_electron = p; + // break; + // } + //} + // 2b. simple loop over iterator (pre-increment) + //auto mc_first_electron = mcparts.end(); + //for (auto p = mcparts.begin(); p != mcparts.end(); ++p) { + // if (p.getPDG() == 11) { + // mc_first_electron = p; + // break; + // } + //} + + // 3. pre-initialized simple loop + //auto mc_first_electron = mcparts.begin(); + //for (; mc_first_electron != mcparts.end(); ++mc_first_electron) { + // if (mc_first_electron.getPDG() == 11) { + // break; + // } + //} + + // 4a. iterator equality + //if (mc_first_electron == mcparts.end()) { + // debug() << "No electron found" << endmsg; + // return StatusCode::FAILURE; + //} + // 4b. iterator inequality + //if (!(mc_first_electron != mcparts.end())) { + // debug() << "No electron found" << endmsg; + // return StatusCode::FAILURE; + //} + + // 5. ranges and views + //auto is_electron = [](const auto& p){ return p.getPDG() == 11; }; + //for (const auto& e: mcparts | std::views::filter(is_electron)) { + // break; + //} + + // Get incoming electron beam + const auto ei_coll = find_first_beam_electron(mcparts); + if (ei_coll.size() == 0) { + m_log->debug("No beam electron found"); + return; } - - void InclusiveKinematicsElectron::process( - const InclusiveKinematicsElectron::Input& input, - const InclusiveKinematicsElectron::Output& output) const { - - const auto [mcparts, rcparts, rcassoc] = input; - auto [kinematics] = output; - - // 1. find_if - //const auto mc_first_electron = std::find_if( - // mcparts.begin(), - // mcparts.end(), - // [](const auto& p){ return p.getPDG() == 11; }); - - // 2a. simple loop over iterator (post-increment) - //auto mc_first_electron = mcparts.end(); - //for (auto p = mcparts.begin(); p != mcparts.end(); p++) { - // if (p.getPDG() == 11) { - // mc_first_electron = p; - // break; - // } - //} - // 2b. simple loop over iterator (pre-increment) - //auto mc_first_electron = mcparts.end(); - //for (auto p = mcparts.begin(); p != mcparts.end(); ++p) { - // if (p.getPDG() == 11) { - // mc_first_electron = p; - // break; - // } - //} - - // 3. pre-initialized simple loop - //auto mc_first_electron = mcparts.begin(); - //for (; mc_first_electron != mcparts.end(); ++mc_first_electron) { - // if (mc_first_electron.getPDG() == 11) { - // break; - // } - //} - - // 4a. iterator equality - //if (mc_first_electron == mcparts.end()) { - // debug() << "No electron found" << endmsg; - // return StatusCode::FAILURE; - //} - // 4b. iterator inequality - //if (!(mc_first_electron != mcparts.end())) { - // debug() << "No electron found" << endmsg; - // return StatusCode::FAILURE; - //} - - // 5. ranges and views - //auto is_electron = [](const auto& p){ return p.getPDG() == 11; }; - //for (const auto& e: mcparts | std::views::filter(is_electron)) { - // break; - //} - - // Get incoming electron beam - const auto ei_coll = find_first_beam_electron(mcparts); - if (ei_coll.size() == 0) { - m_log->debug("No beam electron found"); - return; - } - const PxPyPzEVector ei( - round_beam_four_momentum( - ei_coll[0].getMomentum(), - m_electron, - {-5.0, -10.0, -18.0}, - 0.0) - ); - - // Get incoming hadron beam - const auto pi_coll = find_first_beam_hadron(mcparts); - if (pi_coll.size() == 0) { - m_log->debug("No beam hadron found"); - return; - } - const PxPyPzEVector pi( - round_beam_four_momentum( - pi_coll[0].getMomentum(), - pi_coll[0].getPDG() == 2212 ? m_proton : m_neutron, - {41.0, 100.0, 275.0}, - m_crossingAngle) - ); - - // Get first scattered electron - const auto ef_coll = find_first_scattered_electron(mcparts); - if (ef_coll.size() == 0) { - m_log->debug("No truth scattered electron found"); - return; - } - // Associate first scattered electron with reconstructed electrons - //const auto ef_assoc = std::find_if( - // rcassoc->begin(), - // rcassoc->end(), - // [&ef_coll](const auto& a){ return a.getSim().getObjectID() == ef_coll[0].getObjectID(); }); - auto ef_assoc = rcassoc->begin(); - for (; ef_assoc != rcassoc->end(); ++ef_assoc) { - if (ef_assoc->getSim().getObjectID() == ef_coll[0].getObjectID()) { - break; - } - } - if (!(ef_assoc != rcassoc->end())) { - m_log->debug("Truth scattered electron not in reconstructed particles"); - return; - } - const auto ef_rc{ef_assoc->getRec()}; - const auto ef_rc_id{ef_rc.getObjectID().index}; - - // Loop over reconstructed particles to get outgoing scattered electron - // Use the true scattered electron from the MC information - std::vector electrons; - for (const auto& p: *rcparts) { - if (p.getObjectID().index == ef_rc_id) { - electrons.emplace_back(p.getMomentum().x, p.getMomentum().y, p.getMomentum().z, p.getEnergy()); - break; - } + const PxPyPzEVector ei( + round_beam_four_momentum(ei_coll[0].getMomentum(), m_electron, {-5.0, -10.0, -18.0}, 0.0)); + + // Get incoming hadron beam + const auto pi_coll = find_first_beam_hadron(mcparts); + if (pi_coll.size() == 0) { + m_log->debug("No beam hadron found"); + return; + } + const PxPyPzEVector pi(round_beam_four_momentum( + pi_coll[0].getMomentum(), pi_coll[0].getPDG() == 2212 ? m_proton : m_neutron, + {41.0, 100.0, 275.0}, m_crossingAngle)); + + // Get first scattered electron + const auto ef_coll = find_first_scattered_electron(mcparts); + if (ef_coll.size() == 0) { + m_log->debug("No truth scattered electron found"); + return; + } + // Associate first scattered electron with reconstructed electrons + //const auto ef_assoc = std::find_if( + // rcassoc->begin(), + // rcassoc->end(), + // [&ef_coll](const auto& a){ return a.getSim().getObjectID() == ef_coll[0].getObjectID(); }); + auto ef_assoc = rcassoc->begin(); + for (; ef_assoc != rcassoc->end(); ++ef_assoc) { + if (ef_assoc->getSim().getObjectID() == ef_coll[0].getObjectID()) { + break; } - - // If no scattered electron was found - if (electrons.size() == 0) { - m_log->debug("No scattered electron found"); - return; + } + if (!(ef_assoc != rcassoc->end())) { + m_log->debug("Truth scattered electron not in reconstructed particles"); + return; + } + const auto ef_rc{ef_assoc->getRec()}; + const auto ef_rc_id{ef_rc.getObjectID().index}; + + // Loop over reconstructed particles to get outgoing scattered electron + // Use the true scattered electron from the MC information + std::vector electrons; + for (const auto& p : *rcparts) { + if (p.getObjectID().index == ef_rc_id) { + electrons.emplace_back(p.getMomentum().x, p.getMomentum().y, p.getMomentum().z, + p.getEnergy()); + break; } + } - // DIS kinematics calculations - const auto ef = electrons.front(); - const auto q = ei - ef; - const auto q_dot_pi = q.Dot(pi); - const auto Q2 = -q.Dot(q); - const auto y = q_dot_pi / ei.Dot(pi); - const auto nu = q_dot_pi / m_proton; - const auto x = Q2 / (2. * q_dot_pi); - const auto W = sqrt(m_proton*m_proton + 2.*q_dot_pi - Q2); - auto kin = kinematics->create(x, Q2, W, y, nu); - kin.setScat(ef_rc); - - m_log->debug("x,Q2,W,y,nu = {},{},{},{},{}", kin.getX(), - kin.getQ2(), kin.getW(), kin.getY(), kin.getNu()); + // If no scattered electron was found + if (electrons.size() == 0) { + m_log->debug("No scattered electron found"); + return; } -} // namespace Jug::Reco + // DIS kinematics calculations + const auto ef = electrons.front(); + const auto q = ei - ef; + const auto q_dot_pi = q.Dot(pi); + const auto Q2 = -q.Dot(q); + const auto y = q_dot_pi / ei.Dot(pi); + const auto nu = q_dot_pi / m_proton; + const auto x = Q2 / (2. * q_dot_pi); + const auto W = sqrt(m_proton * m_proton + 2. * q_dot_pi - Q2); + auto kin = kinematics->create(x, Q2, W, y, nu); + kin.setScat(ef_rc); + + m_log->debug("x,Q2,W,y,nu = {},{},{},{},{}", kin.getX(), kin.getQ2(), kin.getW(), kin.getY(), + kin.getNu()); +} + +} // namespace eicrecon diff --git a/src/algorithms/reco/InclusiveKinematicsElectron.h b/src/algorithms/reco/InclusiveKinematicsElectron.h index 2425b8a79a..35271d9c1c 100644 --- a/src/algorithms/reco/InclusiveKinematicsElectron.h +++ b/src/algorithms/reco/InclusiveKinematicsElectron.h @@ -13,36 +13,29 @@ #include #include - namespace eicrecon { - using InclusiveKinematicsElectronAlgorithm = algorithms::Algorithm< - algorithms::Input< - edm4hep::MCParticleCollection, - edm4eic::ReconstructedParticleCollection, - edm4eic::MCRecoParticleAssociationCollection - >, - algorithms::Output< - edm4eic::InclusiveKinematicsCollection - > - >; - - class InclusiveKinematicsElectron - : public InclusiveKinematicsElectronAlgorithm { - - public: - InclusiveKinematicsElectron(std::string_view name) - : InclusiveKinematicsElectronAlgorithm{name, - {"MCParticles", "inputParticles", "inputAssociations"}, - {"inclusiveKinematics"}, - "Determine inclusive kinematics using electron method."} {} - - void init(std::shared_ptr& logger); - void process(const Input&, const Output&) const final; - - private: - std::shared_ptr m_log; - double m_proton{0.93827}, m_neutron{0.93957}, m_electron{0.000510998928}, m_crossingAngle{-0.025}; - }; +using InclusiveKinematicsElectronAlgorithm = algorithms::Algorithm< + algorithms::Input, + algorithms::Output>; + +class InclusiveKinematicsElectron : public InclusiveKinematicsElectronAlgorithm { + +public: + InclusiveKinematicsElectron(std::string_view name) + : InclusiveKinematicsElectronAlgorithm{ + name, + {"MCParticles", "inputParticles", "inputAssociations"}, + {"inclusiveKinematics"}, + "Determine inclusive kinematics using electron method."} {} + + void init(std::shared_ptr& logger); + void process(const Input&, const Output&) const final; + +private: + std::shared_ptr m_log; + double m_proton{0.93827}, m_neutron{0.93957}, m_electron{0.000510998928}, m_crossingAngle{-0.025}; +}; } // namespace eicrecon diff --git a/src/algorithms/reco/InclusiveKinematicsJB.cc b/src/algorithms/reco/InclusiveKinematicsJB.cc index cb8d19c2cf..980d86cea2 100644 --- a/src/algorithms/reco/InclusiveKinematicsJB.cc +++ b/src/algorithms/reco/InclusiveKinematicsJB.cc @@ -22,135 +22,125 @@ using ROOT::Math::PxPyPzEVector; namespace eicrecon { - void InclusiveKinematicsJB::init(std::shared_ptr& logger) { - m_log = logger; - // m_pidSvc = service("ParticleSvc"); - // if (!m_pidSvc) { - // m_log->debug("Unable to locate Particle Service. " - // "Make sure you have ParticleSvc in the configuration."); - // } +void InclusiveKinematicsJB::init(std::shared_ptr& logger) { + m_log = logger; + // m_pidSvc = service("ParticleSvc"); + // if (!m_pidSvc) { + // m_log->debug("Unable to locate Particle Service. " + // "Make sure you have ParticleSvc in the configuration."); + // } +} + +void InclusiveKinematicsJB::process(const InclusiveKinematicsJB::Input& input, + const InclusiveKinematicsJB::Output& output) const { + + const auto [mcparts, rcparts, rcassoc] = input; + auto [kinematics] = output; + + // Get incoming electron beam + const auto ei_coll = find_first_beam_electron(mcparts); + if (ei_coll.size() == 0) { + m_log->debug("No beam electron found"); + return; } - - void InclusiveKinematicsJB::process( - const InclusiveKinematicsJB::Input& input, - const InclusiveKinematicsJB::Output& output) const { - - const auto [mcparts, rcparts, rcassoc] = input; - auto [kinematics] = output; - - // Get incoming electron beam - const auto ei_coll = find_first_beam_electron(mcparts); - if (ei_coll.size() == 0) { - m_log->debug("No beam electron found"); - return; - } - const PxPyPzEVector ei( - round_beam_four_momentum( - ei_coll[0].getMomentum(), - m_electron, - {-5.0, -10.0, -18.0}, - 0.0) - ); - - // Get incoming hadron beam - const auto pi_coll = find_first_beam_hadron(mcparts); - if (pi_coll.size() == 0) { - m_log->debug("No beam hadron found"); - return; - } - const PxPyPzEVector pi( - round_beam_four_momentum( - pi_coll[0].getMomentum(), - pi_coll[0].getPDG() == 2212 ? m_proton : m_neutron, - {41.0, 100.0, 275.0}, - m_crossingAngle) - ); - - // Get first scattered electron - const auto ef_coll = find_first_scattered_electron(mcparts); - if (ef_coll.size() == 0) { - m_log->debug("No truth scattered electron found"); - return; - } - // Associate first scattered electron with reconstructed electrons - //const auto ef_assoc = std::find_if( - // rcassoc->begin(), - // rcassoc->end(), - // [&ef_coll](const auto& a){ return a.getSim().getObjectID() == ef_coll[0].getObjectID(); }); - auto ef_assoc = rcassoc->begin(); - for (; ef_assoc != rcassoc->end(); ++ef_assoc) { - if (ef_assoc->getSim().getObjectID() == ef_coll[0].getObjectID()) { - break; - } - } - if (!(ef_assoc != rcassoc->end())) { - m_log->debug("Truth scattered electron not in reconstructed particles"); - return; + const PxPyPzEVector ei( + round_beam_four_momentum(ei_coll[0].getMomentum(), m_electron, {-5.0, -10.0, -18.0}, 0.0)); + + // Get incoming hadron beam + const auto pi_coll = find_first_beam_hadron(mcparts); + if (pi_coll.size() == 0) { + m_log->debug("No beam hadron found"); + return; + } + const PxPyPzEVector pi(round_beam_four_momentum( + pi_coll[0].getMomentum(), pi_coll[0].getPDG() == 2212 ? m_proton : m_neutron, + {41.0, 100.0, 275.0}, m_crossingAngle)); + + // Get first scattered electron + const auto ef_coll = find_first_scattered_electron(mcparts); + if (ef_coll.size() == 0) { + m_log->debug("No truth scattered electron found"); + return; + } + // Associate first scattered electron with reconstructed electrons + //const auto ef_assoc = std::find_if( + // rcassoc->begin(), + // rcassoc->end(), + // [&ef_coll](const auto& a){ return a.getSim().getObjectID() == ef_coll[0].getObjectID(); }); + auto ef_assoc = rcassoc->begin(); + for (; ef_assoc != rcassoc->end(); ++ef_assoc) { + if (ef_assoc->getSim().getObjectID() == ef_coll[0].getObjectID()) { + break; } - const auto ef_rc{ef_assoc->getRec()}; - const auto ef_rc_id{ef_rc.getObjectID().index}; - - // Loop over reconstructed particles to get all outgoing particles other than the scattered electron - // ----------------------------------------------------------------- - // Right now, everything is taken from Reconstructed particles branches. - // - // This means the tracking detector is used for charged particles to calculate the momentum, - // and the magnitude of this momentum plus the true PID to calculate the energy. - // No requirement is made that these particles produce a hit in any other detector - // - // Using the Reconstructed particles branches also means that the reconstruction for neutrals is done using the - // calorimeter(s) information for the energy and angles, and then using this energy and the true PID to get the - // magnitude of the momentum. - // ----------------------------------------------------------------- - - // Sums in colinear frame - double pxsum = 0; - double pysum = 0; - double pzsum = 0; - double Esum = 0; - - // Get boost to colinear frame - auto boost = determine_boost(ei, pi); - - for (const auto& p: *rcparts) { - // Get the scattered electron index and angle - if (p.getObjectID().index == ef_rc_id) { + } + if (!(ef_assoc != rcassoc->end())) { + m_log->debug("Truth scattered electron not in reconstructed particles"); + return; + } + const auto ef_rc{ef_assoc->getRec()}; + const auto ef_rc_id{ef_rc.getObjectID().index}; + + // Loop over reconstructed particles to get all outgoing particles other than the scattered electron + // ----------------------------------------------------------------- + // Right now, everything is taken from Reconstructed particles branches. + // + // This means the tracking detector is used for charged particles to calculate the momentum, + // and the magnitude of this momentum plus the true PID to calculate the energy. + // No requirement is made that these particles produce a hit in any other detector + // + // Using the Reconstructed particles branches also means that the reconstruction for neutrals is done using the + // calorimeter(s) information for the energy and angles, and then using this energy and the true PID to get the + // magnitude of the momentum. + // ----------------------------------------------------------------- + + // Sums in colinear frame + double pxsum = 0; + double pysum = 0; + double pzsum = 0; + double Esum = 0; + + // Get boost to colinear frame + auto boost = determine_boost(ei, pi); + + for (const auto& p : *rcparts) { + // Get the scattered electron index and angle + if (p.getObjectID().index == ef_rc_id) { // Sum over all particles other than scattered electron - } else { - // Lorentz vector in lab frame - PxPyPzEVector hf_lab(p.getMomentum().x, p.getMomentum().y, p.getMomentum().z, p.getEnergy()); - // Boost to colinear frame - PxPyPzEVector hf_boosted = apply_boost(boost, hf_lab); - - pxsum += hf_boosted.Px(); - pysum += hf_boosted.Py(); - pzsum += hf_boosted.Pz(); - Esum += hf_boosted.E(); - } + } else { + // Lorentz vector in lab frame + PxPyPzEVector hf_lab(p.getMomentum().x, p.getMomentum().y, p.getMomentum().z, p.getEnergy()); + // Boost to colinear frame + PxPyPzEVector hf_boosted = apply_boost(boost, hf_lab); + + pxsum += hf_boosted.Px(); + pysum += hf_boosted.Py(); + pzsum += hf_boosted.Pz(); + Esum += hf_boosted.E(); } + } - // DIS kinematics calculations - auto sigma_h = Esum - pzsum; - auto ptsum = sqrt(pxsum*pxsum + pysum*pysum); - - // Sigma zero or negative - if (sigma_h <= 0) { - m_log->debug("Sigma zero or negative"); - return; - } + // DIS kinematics calculations + auto sigma_h = Esum - pzsum; + auto ptsum = sqrt(pxsum * pxsum + pysum * pysum); - // Calculate kinematic variables - const auto y_jb = sigma_h / (2.*ei.energy()); - const auto Q2_jb = ptsum*ptsum / (1. - y_jb); - const auto x_jb = Q2_jb / (4.*ei.energy()*pi.energy()*y_jb); - const auto nu_jb = Q2_jb / (2.*m_proton*x_jb); - const auto W_jb = sqrt(m_proton*m_proton + 2*m_proton*nu_jb - Q2_jb); - auto kin = kinematics->create(x_jb, Q2_jb, W_jb, y_jb, nu_jb); - kin.setScat(ef_rc); - - m_log->debug("x,Q2,W,y,nu = {},{},{},{},{}", kin.getX(), - kin.getQ2(), kin.getW(), kin.getY(), kin.getNu()); + // Sigma zero or negative + if (sigma_h <= 0) { + m_log->debug("Sigma zero or negative"); + return; } -} // namespace Jug::Reco + // Calculate kinematic variables + const auto y_jb = sigma_h / (2. * ei.energy()); + const auto Q2_jb = ptsum * ptsum / (1. - y_jb); + const auto x_jb = Q2_jb / (4. * ei.energy() * pi.energy() * y_jb); + const auto nu_jb = Q2_jb / (2. * m_proton * x_jb); + const auto W_jb = sqrt(m_proton * m_proton + 2 * m_proton * nu_jb - Q2_jb); + auto kin = kinematics->create(x_jb, Q2_jb, W_jb, y_jb, nu_jb); + kin.setScat(ef_rc); + + m_log->debug("x,Q2,W,y,nu = {},{},{},{},{}", kin.getX(), kin.getQ2(), kin.getW(), kin.getY(), + kin.getNu()); +} + +} // namespace eicrecon diff --git a/src/algorithms/reco/InclusiveKinematicsJB.h b/src/algorithms/reco/InclusiveKinematicsJB.h index 7eac50d22d..ceb2d41917 100644 --- a/src/algorithms/reco/InclusiveKinematicsJB.h +++ b/src/algorithms/reco/InclusiveKinematicsJB.h @@ -13,36 +13,29 @@ #include #include - namespace eicrecon { - using InclusiveKinematicsJBAlgorithm = algorithms::Algorithm< - algorithms::Input< - edm4hep::MCParticleCollection, - edm4eic::ReconstructedParticleCollection, - edm4eic::MCRecoParticleAssociationCollection - >, - algorithms::Output< - edm4eic::InclusiveKinematicsCollection - > - >; - - class InclusiveKinematicsJB - : public InclusiveKinematicsJBAlgorithm { - - public: - InclusiveKinematicsJB(std::string_view name) - : InclusiveKinematicsJBAlgorithm{name, - {"MCParticles", "inputParticles", "inputAssociations"}, - {"inclusiveKinematics"}, - "Determine inclusive kinematics using Jacquet-Blondel method."} {} - - void init(std::shared_ptr& logger); - void process(const Input&, const Output&) const final; - - private: - std::shared_ptr m_log; - double m_proton{0.93827}, m_neutron{0.93957}, m_electron{0.000510998928}, m_crossingAngle{-0.025}; - }; +using InclusiveKinematicsJBAlgorithm = algorithms::Algorithm< + algorithms::Input, + algorithms::Output>; + +class InclusiveKinematicsJB : public InclusiveKinematicsJBAlgorithm { + +public: + InclusiveKinematicsJB(std::string_view name) + : InclusiveKinematicsJBAlgorithm{ + name, + {"MCParticles", "inputParticles", "inputAssociations"}, + {"inclusiveKinematics"}, + "Determine inclusive kinematics using Jacquet-Blondel method."} {} + + void init(std::shared_ptr& logger); + void process(const Input&, const Output&) const final; + +private: + std::shared_ptr m_log; + double m_proton{0.93827}, m_neutron{0.93957}, m_electron{0.000510998928}, m_crossingAngle{-0.025}; +}; } // namespace eicrecon diff --git a/src/algorithms/reco/InclusiveKinematicsSigma.cc b/src/algorithms/reco/InclusiveKinematicsSigma.cc index d25b38555c..d7f1e429f1 100644 --- a/src/algorithms/reco/InclusiveKinematicsSigma.cc +++ b/src/algorithms/reco/InclusiveKinematicsSigma.cc @@ -22,144 +22,134 @@ using ROOT::Math::PxPyPzEVector; namespace eicrecon { - void InclusiveKinematicsSigma::init(std::shared_ptr& logger) { - m_log = logger; - // m_pidSvc = service("ParticleSvc"); - // if (!m_pidSvc) { - // m_log->debug("Unable to locate Particle Service. " - // "Make sure you have ParticleSvc in the configuration."); - // } +void InclusiveKinematicsSigma::init(std::shared_ptr& logger) { + m_log = logger; + // m_pidSvc = service("ParticleSvc"); + // if (!m_pidSvc) { + // m_log->debug("Unable to locate Particle Service. " + // "Make sure you have ParticleSvc in the configuration."); + // } +} + +void InclusiveKinematicsSigma::process(const InclusiveKinematicsSigma::Input& input, + const InclusiveKinematicsSigma::Output& output) const { + + const auto [mcparts, rcparts, rcassoc] = input; + auto [kinematics] = output; + + // Get incoming electron beam + const auto ei_coll = find_first_beam_electron(mcparts); + if (ei_coll.size() == 0) { + m_log->debug("No beam electron found"); + return; } - - void InclusiveKinematicsSigma::process( - const InclusiveKinematicsSigma::Input& input, - const InclusiveKinematicsSigma::Output& output) const { - - const auto [mcparts, rcparts, rcassoc] = input; - auto [kinematics] = output; - - // Get incoming electron beam - const auto ei_coll = find_first_beam_electron(mcparts); - if (ei_coll.size() == 0) { - m_log->debug("No beam electron found"); - return; - } - const PxPyPzEVector ei( - round_beam_four_momentum( - ei_coll[0].getMomentum(), - m_electron, - {-5.0, -10.0, -18.0}, - 0.0) - ); - - // Get incoming hadron beam - const auto pi_coll = find_first_beam_hadron(mcparts); - if (pi_coll.size() == 0) { - m_log->debug("No beam hadron found"); - return; - } - const PxPyPzEVector pi( - round_beam_four_momentum( - pi_coll[0].getMomentum(), - pi_coll[0].getPDG() == 2212 ? m_proton : m_neutron, - {41.0, 100.0, 275.0}, - m_crossingAngle) - ); - - // Get first scattered electron - const auto ef_coll = find_first_scattered_electron(mcparts); - if (ef_coll.size() == 0) { - m_log->debug("No truth scattered electron found"); - return; - } - // Associate first scattered electron with reconstructed electrons - //const auto ef_assoc = std::find_if( - // rcassoc->begin(), - // rcassoc->end(), - // [&ef_coll](const auto& a){ return a.getSim().getObjectID() == ef_coll[0].getObjectID(); }); - auto ef_assoc = rcassoc->begin(); - for (; ef_assoc != rcassoc->end(); ++ef_assoc) { - if (ef_assoc->getSim().getObjectID() == ef_coll[0].getObjectID()) { - break; - } - } - if (!(ef_assoc != rcassoc->end())) { - m_log->debug("Truth scattered electron not in reconstructed particles"); - return; + const PxPyPzEVector ei( + round_beam_four_momentum(ei_coll[0].getMomentum(), m_electron, {-5.0, -10.0, -18.0}, 0.0)); + + // Get incoming hadron beam + const auto pi_coll = find_first_beam_hadron(mcparts); + if (pi_coll.size() == 0) { + m_log->debug("No beam hadron found"); + return; + } + const PxPyPzEVector pi(round_beam_four_momentum( + pi_coll[0].getMomentum(), pi_coll[0].getPDG() == 2212 ? m_proton : m_neutron, + {41.0, 100.0, 275.0}, m_crossingAngle)); + + // Get first scattered electron + const auto ef_coll = find_first_scattered_electron(mcparts); + if (ef_coll.size() == 0) { + m_log->debug("No truth scattered electron found"); + return; + } + // Associate first scattered electron with reconstructed electrons + //const auto ef_assoc = std::find_if( + // rcassoc->begin(), + // rcassoc->end(), + // [&ef_coll](const auto& a){ return a.getSim().getObjectID() == ef_coll[0].getObjectID(); }); + auto ef_assoc = rcassoc->begin(); + for (; ef_assoc != rcassoc->end(); ++ef_assoc) { + if (ef_assoc->getSim().getObjectID() == ef_coll[0].getObjectID()) { + break; } - const auto ef_rc{ef_assoc->getRec()}; - const auto ef_rc_id{ef_rc.getObjectID().index}; - - // Loop over reconstructed particles to get all outgoing particles - // ----------------------------------------------------------------- - // Right now, everything is taken from Reconstructed particles branches. - // - // This means the tracking detector is used for charged particles to calculate the momentum, - // and the magnitude of this momentum plus the true PID to calculate the energy. - // No requirement is made that these particles produce a hit in any other detector - // - // Using the Reconstructed particles branches also means that the reconstruction for neutrals is done using the - // calorimeter(s) information for the energy and angles, and then using this energy and the true PID to get the - // magnitude of the momentum. - // ----------------------------------------------------------------- - - //Sums in colinear frame - double pxsum = 0; - double pysum = 0; - double pzsum = 0; - double Esum = 0; - - double pt_e = 0; - double sigma_e = 0; - - // Get boost to colinear frame - auto boost = determine_boost(ei, pi); - - for (const auto& p: *rcparts) { - // Get the scattered electron index and angle - if (p.getObjectID().index == ef_rc_id) { - // Lorentz vector in lab frame - PxPyPzEVector e_lab(p.getMomentum().x, p.getMomentum().y, p.getMomentum().z, p.getEnergy()); - // Boost to colinear frame - PxPyPzEVector e_boosted = apply_boost(boost, e_lab); - - pt_e = e_boosted.Pt(); - sigma_e = e_boosted.E() - e_boosted.Pz(); + } + if (!(ef_assoc != rcassoc->end())) { + m_log->debug("Truth scattered electron not in reconstructed particles"); + return; + } + const auto ef_rc{ef_assoc->getRec()}; + const auto ef_rc_id{ef_rc.getObjectID().index}; + + // Loop over reconstructed particles to get all outgoing particles + // ----------------------------------------------------------------- + // Right now, everything is taken from Reconstructed particles branches. + // + // This means the tracking detector is used for charged particles to calculate the momentum, + // and the magnitude of this momentum plus the true PID to calculate the energy. + // No requirement is made that these particles produce a hit in any other detector + // + // Using the Reconstructed particles branches also means that the reconstruction for neutrals is done using the + // calorimeter(s) information for the energy and angles, and then using this energy and the true PID to get the + // magnitude of the momentum. + // ----------------------------------------------------------------- + + //Sums in colinear frame + double pxsum = 0; + double pysum = 0; + double pzsum = 0; + double Esum = 0; + + double pt_e = 0; + double sigma_e = 0; + + // Get boost to colinear frame + auto boost = determine_boost(ei, pi); + + for (const auto& p : *rcparts) { + // Get the scattered electron index and angle + if (p.getObjectID().index == ef_rc_id) { + // Lorentz vector in lab frame + PxPyPzEVector e_lab(p.getMomentum().x, p.getMomentum().y, p.getMomentum().z, p.getEnergy()); + // Boost to colinear frame + PxPyPzEVector e_boosted = apply_boost(boost, e_lab); + + pt_e = e_boosted.Pt(); + sigma_e = e_boosted.E() - e_boosted.Pz(); // Sum over all particles other than scattered electron - } else { - // Lorentz vector in lab frame - PxPyPzEVector hf_lab(p.getMomentum().x, p.getMomentum().y, p.getMomentum().z, p.getEnergy()); - // Boost to colinear frame - PxPyPzEVector hf_boosted = apply_boost(boost, hf_lab); - - pxsum += hf_boosted.Px(); - pysum += hf_boosted.Py(); - pzsum += hf_boosted.Pz(); - Esum += hf_boosted.E(); - } + } else { + // Lorentz vector in lab frame + PxPyPzEVector hf_lab(p.getMomentum().x, p.getMomentum().y, p.getMomentum().z, p.getEnergy()); + // Boost to colinear frame + PxPyPzEVector hf_boosted = apply_boost(boost, hf_lab); + + pxsum += hf_boosted.Px(); + pysum += hf_boosted.Py(); + pzsum += hf_boosted.Pz(); + Esum += hf_boosted.E(); } + } - // DIS kinematics calculations - auto sigma_h = Esum - pzsum; - auto sigma_tot = sigma_e + sigma_h; - - if (sigma_h <= 0) { - m_log->debug("No scattered electron found or sigma zero or negative"); - return; - } + // DIS kinematics calculations + auto sigma_h = Esum - pzsum; + auto sigma_tot = sigma_e + sigma_h; - // Calculate kinematic variables - const auto y_sig = sigma_h / sigma_tot; - const auto Q2_sig = (pt_e*pt_e) / (1. - y_sig); - const auto x_sig = Q2_sig / (4.*ei.energy()*pi.energy()*y_sig); - const auto nu_sig = Q2_sig / (2.*m_proton*x_sig); - const auto W_sig = sqrt(m_proton*m_proton + 2*m_proton*nu_sig - Q2_sig); - auto kin = kinematics->create(x_sig, Q2_sig, W_sig, y_sig, nu_sig); - kin.setScat(ef_rc); - - m_log->debug("x,Q2,W,y,nu = {},{},{},{},{}", kin.getX(), - kin.getQ2(), kin.getW(), kin.getY(), kin.getNu()); + if (sigma_h <= 0) { + m_log->debug("No scattered electron found or sigma zero or negative"); + return; } -} // namespace Jug::Reco + // Calculate kinematic variables + const auto y_sig = sigma_h / sigma_tot; + const auto Q2_sig = (pt_e * pt_e) / (1. - y_sig); + const auto x_sig = Q2_sig / (4. * ei.energy() * pi.energy() * y_sig); + const auto nu_sig = Q2_sig / (2. * m_proton * x_sig); + const auto W_sig = sqrt(m_proton * m_proton + 2 * m_proton * nu_sig - Q2_sig); + auto kin = kinematics->create(x_sig, Q2_sig, W_sig, y_sig, nu_sig); + kin.setScat(ef_rc); + + m_log->debug("x,Q2,W,y,nu = {},{},{},{},{}", kin.getX(), kin.getQ2(), kin.getW(), kin.getY(), + kin.getNu()); +} + +} // namespace eicrecon diff --git a/src/algorithms/reco/InclusiveKinematicsSigma.h b/src/algorithms/reco/InclusiveKinematicsSigma.h index 8b2ca96be5..2c6f694682 100644 --- a/src/algorithms/reco/InclusiveKinematicsSigma.h +++ b/src/algorithms/reco/InclusiveKinematicsSigma.h @@ -13,36 +13,28 @@ #include #include - namespace eicrecon { - using InclusiveKinematicsSigmaAlgorithm = algorithms::Algorithm< - algorithms::Input< - edm4hep::MCParticleCollection, - edm4eic::ReconstructedParticleCollection, - edm4eic::MCRecoParticleAssociationCollection - >, - algorithms::Output< - edm4eic::InclusiveKinematicsCollection - > - >; - - class InclusiveKinematicsSigma - : public InclusiveKinematicsSigmaAlgorithm { - - public: - InclusiveKinematicsSigma(std::string_view name) +using InclusiveKinematicsSigmaAlgorithm = algorithms::Algorithm< + algorithms::Input, + algorithms::Output>; + +class InclusiveKinematicsSigma : public InclusiveKinematicsSigmaAlgorithm { + +public: + InclusiveKinematicsSigma(std::string_view name) : InclusiveKinematicsSigmaAlgorithm{name, - {"MCParticles", "inputParticles", "inputAssociations"}, - {"inclusiveKinematics"}, - "Determine inclusive kinematics using Sigma method."} {} + {"MCParticles", "inputParticles", "inputAssociations"}, + {"inclusiveKinematics"}, + "Determine inclusive kinematics using Sigma method."} {} - void init(std::shared_ptr& logger); - void process(const Input&, const Output&) const final; + void init(std::shared_ptr& logger); + void process(const Input&, const Output&) const final; - private: - std::shared_ptr m_log; - double m_proton{0.93827}, m_neutron{0.93957}, m_electron{0.000510998928}, m_crossingAngle{-0.025}; - }; +private: + std::shared_ptr m_log; + double m_proton{0.93827}, m_neutron{0.93957}, m_electron{0.000510998928}, m_crossingAngle{-0.025}; +}; } // namespace eicrecon diff --git a/src/algorithms/reco/InclusiveKinematicsTruth.cc b/src/algorithms/reco/InclusiveKinematicsTruth.cc index 54bc232f88..6d82c1a58d 100644 --- a/src/algorithms/reco/InclusiveKinematicsTruth.cc +++ b/src/algorithms/reco/InclusiveKinematicsTruth.cc @@ -19,80 +19,79 @@ using ROOT::Math::PxPyPzEVector; namespace eicrecon { - void InclusiveKinematicsTruth::init(std::shared_ptr& logger) { - m_log = logger; +void InclusiveKinematicsTruth::init(std::shared_ptr& logger) { + m_log = logger; - // m_pidSvc = service("ParticleSvc"); - // if (!m_pidSvc) { - // error() << "Unable to locate Particle Service. " - // << "Make sure you have ParticleSvc in the configuration." - // << endmsg; - // return StatusCode::FAILURE; - // } - } + // m_pidSvc = service("ParticleSvc"); + // if (!m_pidSvc) { + // error() << "Unable to locate Particle Service. " + // << "Make sure you have ParticleSvc in the configuration." + // << endmsg; + // return StatusCode::FAILURE; + // } +} - void InclusiveKinematicsTruth::process( - const InclusiveKinematicsTruth::Input& input, - const InclusiveKinematicsTruth::Output& output) const { +void InclusiveKinematicsTruth::process(const InclusiveKinematicsTruth::Input& input, + const InclusiveKinematicsTruth::Output& output) const { - const auto [mcparts] = input; - auto [kinematics] = output; + const auto [mcparts] = input; + auto [kinematics] = output; - // Loop over generated particles to get incoming electron and proton beams - // and the scattered electron. In the presence of QED radition on the incoming - // or outgoing electron line, the vertex kinematics will be different than the - // kinematics calculated using the scattered electron as done here. - // Also need to update for CC events. + // Loop over generated particles to get incoming electron and proton beams + // and the scattered electron. In the presence of QED radition on the incoming + // or outgoing electron line, the vertex kinematics will be different than the + // kinematics calculated using the scattered electron as done here. + // Also need to update for CC events. - // Get incoming electron beam - const auto ei_coll = find_first_beam_electron(mcparts); - if (ei_coll.size() == 0) { - m_log->debug("No beam electron found"); - return; - } - const auto ei_p = ei_coll[0].getMomentum(); - const auto ei_p_mag = edm4hep::utils::magnitude(ei_p); - const auto ei_mass = m_electron; - const PxPyPzEVector ei(ei_p.x, ei_p.y, ei_p.z, std::hypot(ei_p_mag, ei_mass)); + // Get incoming electron beam + const auto ei_coll = find_first_beam_electron(mcparts); + if (ei_coll.size() == 0) { + m_log->debug("No beam electron found"); + return; + } + const auto ei_p = ei_coll[0].getMomentum(); + const auto ei_p_mag = edm4hep::utils::magnitude(ei_p); + const auto ei_mass = m_electron; + const PxPyPzEVector ei(ei_p.x, ei_p.y, ei_p.z, std::hypot(ei_p_mag, ei_mass)); - // Get incoming hadron beam - const auto pi_coll = find_first_beam_hadron(mcparts); - if (pi_coll.size() == 0) { - m_log->debug("No beam hadron found"); - return; - } - const auto pi_p = pi_coll[0].getMomentum(); - const auto pi_p_mag = edm4hep::utils::magnitude(pi_p); - const auto pi_mass = pi_coll[0].getPDG() == 2212 ? m_proton : m_neutron; - const PxPyPzEVector pi(pi_p.x, pi_p.y, pi_p.z, std::hypot(pi_p_mag, pi_mass)); + // Get incoming hadron beam + const auto pi_coll = find_first_beam_hadron(mcparts); + if (pi_coll.size() == 0) { + m_log->debug("No beam hadron found"); + return; + } + const auto pi_p = pi_coll[0].getMomentum(); + const auto pi_p_mag = edm4hep::utils::magnitude(pi_p); + const auto pi_mass = pi_coll[0].getPDG() == 2212 ? m_proton : m_neutron; + const PxPyPzEVector pi(pi_p.x, pi_p.y, pi_p.z, std::hypot(pi_p_mag, pi_mass)); - // Get first scattered electron - // Scattered electron. Currently taken as first status==1 electron in HEPMC record, - // which seems to be correct based on a cursory glance at the Pythia8 output. In the future, - // it may be better to trace back each final-state electron and see which one originates from - // the beam. - const auto ef_coll = find_first_scattered_electron(mcparts); - if (ef_coll.size() == 0) { - m_log->debug("No truth scattered electron found"); - return; - } - const auto ef_p = ef_coll[0].getMomentum(); - const auto ef_p_mag = edm4hep::utils::magnitude(ef_p); - const auto ef_mass = m_electron; - const PxPyPzEVector ef(ef_p.x, ef_p.y, ef_p.z, std::hypot(ef_p_mag, ef_mass)); + // Get first scattered electron + // Scattered electron. Currently taken as first status==1 electron in HEPMC record, + // which seems to be correct based on a cursory glance at the Pythia8 output. In the future, + // it may be better to trace back each final-state electron and see which one originates from + // the beam. + const auto ef_coll = find_first_scattered_electron(mcparts); + if (ef_coll.size() == 0) { + m_log->debug("No truth scattered electron found"); + return; + } + const auto ef_p = ef_coll[0].getMomentum(); + const auto ef_p_mag = edm4hep::utils::magnitude(ef_p); + const auto ef_mass = m_electron; + const PxPyPzEVector ef(ef_p.x, ef_p.y, ef_p.z, std::hypot(ef_p_mag, ef_mass)); - // DIS kinematics calculations - const auto q = ei - ef; - const auto q_dot_pi = q.Dot(pi); - const auto Q2 = -q.Dot(q); - const auto y = q_dot_pi / ei.Dot(pi); - const auto nu = q_dot_pi / pi_mass; - const auto x = Q2 / (2.*q_dot_pi); - const auto W = sqrt(pi_mass*pi_mass + 2.*q_dot_pi - Q2); - auto kin = kinematics->create(x, Q2, W, y, nu); + // DIS kinematics calculations + const auto q = ei - ef; + const auto q_dot_pi = q.Dot(pi); + const auto Q2 = -q.Dot(q); + const auto y = q_dot_pi / ei.Dot(pi); + const auto nu = q_dot_pi / pi_mass; + const auto x = Q2 / (2. * q_dot_pi); + const auto W = sqrt(pi_mass * pi_mass + 2. * q_dot_pi - Q2); + auto kin = kinematics->create(x, Q2, W, y, nu); - m_log->debug("x,Q2,W,y,nu = {},{},{},{},{}", kin.getX(), - kin.getQ2(), kin.getW(), kin.getY(), kin.getNu()); - } + m_log->debug("x,Q2,W,y,nu = {},{},{},{},{}", kin.getX(), kin.getQ2(), kin.getW(), kin.getY(), + kin.getNu()); +} -} // namespace Jug::Reco +} // namespace eicrecon diff --git a/src/algorithms/reco/InclusiveKinematicsTruth.h b/src/algorithms/reco/InclusiveKinematicsTruth.h index 8ec7a58cf7..9712fd888b 100644 --- a/src/algorithms/reco/InclusiveKinematicsTruth.h +++ b/src/algorithms/reco/InclusiveKinematicsTruth.h @@ -11,34 +11,28 @@ #include #include - namespace eicrecon { - using InclusiveKinematicsTruthAlgorithm = algorithms::Algorithm< - algorithms::Input< - edm4hep::MCParticleCollection - >, - algorithms::Output< - edm4eic::InclusiveKinematicsCollection - > - >; - - class InclusiveKinematicsTruth - : public InclusiveKinematicsTruthAlgorithm { - - public: - InclusiveKinematicsTruth(std::string_view name) - : InclusiveKinematicsTruthAlgorithm{name, - {"MCParticles"}, - {"inclusiveKinematics"}, - "Determine inclusive kinematics from truth information."} {} - - void init(std::shared_ptr& logger); - void process(const Input&, const Output&) const final; - - private: - std::shared_ptr m_log; - double m_proton{0.93827}, m_neutron{0.93957}, m_electron{0.000510998928}, m_crossingAngle{-0.025}; - }; +using InclusiveKinematicsTruthAlgorithm = + algorithms::Algorithm, + algorithms::Output>; + +class InclusiveKinematicsTruth : public InclusiveKinematicsTruthAlgorithm { + +public: + InclusiveKinematicsTruth(std::string_view name) + : InclusiveKinematicsTruthAlgorithm{ + name, + {"MCParticles"}, + {"inclusiveKinematics"}, + "Determine inclusive kinematics from truth information."} {} + + void init(std::shared_ptr& logger); + void process(const Input&, const Output&) const final; + +private: + std::shared_ptr m_log; + double m_proton{0.93827}, m_neutron{0.93957}, m_electron{0.000510998928}, m_crossingAngle{-0.025}; +}; } // namespace eicrecon diff --git a/src/algorithms/reco/InclusiveKinematicseSigma.cc b/src/algorithms/reco/InclusiveKinematicseSigma.cc index 80880d5a90..c88ffa958d 100644 --- a/src/algorithms/reco/InclusiveKinematicseSigma.cc +++ b/src/algorithms/reco/InclusiveKinematicseSigma.cc @@ -22,153 +22,144 @@ using ROOT::Math::PxPyPzEVector; namespace eicrecon { - void InclusiveKinematicseSigma::init(std::shared_ptr& logger) { - m_log = logger; - // m_pidSvc = service("ParticleSvc"); - // if (!m_pidSvc) { - // m_log->debug("Unable to locate Particle Service. " - // "Make sure you have ParticleSvc in the configuration."); - // } +void InclusiveKinematicseSigma::init(std::shared_ptr& logger) { + m_log = logger; + // m_pidSvc = service("ParticleSvc"); + // if (!m_pidSvc) { + // m_log->debug("Unable to locate Particle Service. " + // "Make sure you have ParticleSvc in the configuration."); + // } +} + +void InclusiveKinematicseSigma::process(const InclusiveKinematicseSigma::Input& input, + const InclusiveKinematicseSigma::Output& output) const { + + const auto [mcparts, rcparts, rcassoc] = input; + auto [kinematics] = output; + + // Get incoming electron beam + const auto ei_coll = find_first_beam_electron(mcparts); + if (ei_coll.size() == 0) { + m_log->debug("No beam electron found"); + return; } - - void InclusiveKinematicseSigma::process( - const InclusiveKinematicseSigma::Input& input, - const InclusiveKinematicseSigma::Output& output) const { - - const auto [mcparts, rcparts, rcassoc] = input; - auto [kinematics] = output; - - // Get incoming electron beam - const auto ei_coll = find_first_beam_electron(mcparts); - if (ei_coll.size() == 0) { - m_log->debug("No beam electron found"); - return; - } - const PxPyPzEVector ei( - round_beam_four_momentum( - ei_coll[0].getMomentum(), - m_electron, - {-5.0, -10.0, -18.0}, - 0.0) - ); - - // Get incoming hadron beam - const auto pi_coll = find_first_beam_hadron(mcparts); - if (pi_coll.size() == 0) { - m_log->debug("No beam hadron found"); - return; - } - const PxPyPzEVector pi( - round_beam_four_momentum( - pi_coll[0].getMomentum(), - pi_coll[0].getPDG() == 2212 ? m_proton : m_neutron, - {41.0, 100.0, 275.0}, - m_crossingAngle) - ); - - // Get first scattered electron - const auto ef_coll = find_first_scattered_electron(mcparts); - if (ef_coll.size() == 0) { - m_log->debug("No truth scattered electron found"); - return; - } - // Associate first scattered electron with reconstructed electrons - //const auto ef_assoc = std::find_if( - // rcassoc->begin(), - // rcassoc->end(), - // [&ef_coll](const auto& a){ return a.getSim().getObjectID() == ef_coll[0].getObjectID(); }); - auto ef_assoc = rcassoc->begin(); - for (; ef_assoc != rcassoc->end(); ++ef_assoc) { - if (ef_assoc->getSim().getObjectID() == ef_coll[0].getObjectID()) { - break; - } - } - if (!(ef_assoc != rcassoc->end())) { - m_log->debug("Truth scattered electron not in reconstructed particles"); - return; + const PxPyPzEVector ei( + round_beam_four_momentum(ei_coll[0].getMomentum(), m_electron, {-5.0, -10.0, -18.0}, 0.0)); + + // Get incoming hadron beam + const auto pi_coll = find_first_beam_hadron(mcparts); + if (pi_coll.size() == 0) { + m_log->debug("No beam hadron found"); + return; + } + const PxPyPzEVector pi(round_beam_four_momentum( + pi_coll[0].getMomentum(), pi_coll[0].getPDG() == 2212 ? m_proton : m_neutron, + {41.0, 100.0, 275.0}, m_crossingAngle)); + + // Get first scattered electron + const auto ef_coll = find_first_scattered_electron(mcparts); + if (ef_coll.size() == 0) { + m_log->debug("No truth scattered electron found"); + return; + } + // Associate first scattered electron with reconstructed electrons + //const auto ef_assoc = std::find_if( + // rcassoc->begin(), + // rcassoc->end(), + // [&ef_coll](const auto& a){ return a.getSim().getObjectID() == ef_coll[0].getObjectID(); }); + auto ef_assoc = rcassoc->begin(); + for (; ef_assoc != rcassoc->end(); ++ef_assoc) { + if (ef_assoc->getSim().getObjectID() == ef_coll[0].getObjectID()) { + break; } - const auto ef_rc{ef_assoc->getRec()}; - const auto ef_rc_id{ef_rc.getObjectID().index}; - - // Loop over reconstructed particles to get all outgoing particles - // ----------------------------------------------------------------- - // Right now, everything is taken from Reconstructed particles branches. - // - // This means the tracking detector is used for charged particles to calculate the momentum, - // and the magnitude of this momentum plus the true PID to calculate the energy. - // No requirement is made that these particles produce a hit in any other detector - // - // Using the Reconstructed particles branches also means that the reconstruction for neutrals is done using the - // calorimeter(s) information for the energy and angles, and then using this energy and the true PID to get the - // magnitude of the momentum. - // ----------------------------------------------------------------- - - //Sums in colinear frame - double pxsum = 0; - double pysum = 0; - double pzsum = 0; - double Esum = 0; - - double pt_e = 0; - double sigma_e = 0; - - // Get boost to colinear frame - auto boost = determine_boost(ei, pi); - - for (const auto& p: *rcparts) { - // Get the scattered electron index and angle - if (p.getObjectID().index == ef_rc_id) { - // Lorentz vector in lab frame - PxPyPzEVector e_lab(p.getMomentum().x, p.getMomentum().y, p.getMomentum().z, p.getEnergy()); - // Boost to colinear frame - PxPyPzEVector e_boosted = apply_boost(boost, e_lab); - - pt_e = e_boosted.Pt(); - sigma_e = e_boosted.E() - e_boosted.Pz(); + } + if (!(ef_assoc != rcassoc->end())) { + m_log->debug("Truth scattered electron not in reconstructed particles"); + return; + } + const auto ef_rc{ef_assoc->getRec()}; + const auto ef_rc_id{ef_rc.getObjectID().index}; + + // Loop over reconstructed particles to get all outgoing particles + // ----------------------------------------------------------------- + // Right now, everything is taken from Reconstructed particles branches. + // + // This means the tracking detector is used for charged particles to calculate the momentum, + // and the magnitude of this momentum plus the true PID to calculate the energy. + // No requirement is made that these particles produce a hit in any other detector + // + // Using the Reconstructed particles branches also means that the reconstruction for neutrals is done using the + // calorimeter(s) information for the energy and angles, and then using this energy and the true PID to get the + // magnitude of the momentum. + // ----------------------------------------------------------------- + + //Sums in colinear frame + double pxsum = 0; + double pysum = 0; + double pzsum = 0; + double Esum = 0; + + double pt_e = 0; + double sigma_e = 0; + + // Get boost to colinear frame + auto boost = determine_boost(ei, pi); + + for (const auto& p : *rcparts) { + // Get the scattered electron index and angle + if (p.getObjectID().index == ef_rc_id) { + // Lorentz vector in lab frame + PxPyPzEVector e_lab(p.getMomentum().x, p.getMomentum().y, p.getMomentum().z, p.getEnergy()); + // Boost to colinear frame + PxPyPzEVector e_boosted = apply_boost(boost, e_lab); + + pt_e = e_boosted.Pt(); + sigma_e = e_boosted.E() - e_boosted.Pz(); // Sum over all particles other than scattered electron - } else { - // Lorentz vector in lab frame - PxPyPzEVector hf_lab(p.getMomentum().x, p.getMomentum().y, p.getMomentum().z, p.getEnergy()); - // Boost to colinear frame - PxPyPzEVector hf_boosted = apply_boost(boost, hf_lab); - - pxsum += hf_boosted.Px(); - pysum += hf_boosted.Py(); - pzsum += hf_boosted.Pz(); - Esum += hf_boosted.E(); - } + } else { + // Lorentz vector in lab frame + PxPyPzEVector hf_lab(p.getMomentum().x, p.getMomentum().y, p.getMomentum().z, p.getEnergy()); + // Boost to colinear frame + PxPyPzEVector hf_boosted = apply_boost(boost, hf_lab); + + pxsum += hf_boosted.Px(); + pysum += hf_boosted.Py(); + pzsum += hf_boosted.Pz(); + Esum += hf_boosted.E(); } + } - // DIS kinematics calculations - auto sigma_h = Esum - pzsum; - auto sigma_tot = sigma_e + sigma_h; - - // If no scattered electron was found - if (sigma_h <= 0) { - m_log->debug("No scattered electron found"); - return; - } + // DIS kinematics calculations + auto sigma_h = Esum - pzsum; + auto sigma_tot = sigma_e + sigma_h; - // Calculate kinematic variables - const auto y_e = 1. - sigma_e / (2.*ei.energy()); - const auto Q2_e = (pt_e*pt_e) / (1. - y_e); - - const auto y_sig = sigma_h / sigma_tot; - const auto Q2_sig = (pt_e*pt_e) / (1. - y_sig); - const auto x_sig = Q2_sig / (4.*ei.energy()*pi.energy()*y_sig); - - const auto Q2_esig = Q2_e; - const auto x_esig = x_sig; - const auto y_esig = Q2_esig / (4.*ei.energy()*pi.energy()*x_esig); //equivalent to (2*ei.energy() / sigma_tot)*y_sig - const auto nu_esig = Q2_esig / (2.*m_proton*x_esig); - const auto W_esig = sqrt(m_proton*m_proton + 2*m_proton*nu_esig - Q2_esig); - auto kin = kinematics->create(x_esig, Q2_esig, W_esig, y_esig, nu_esig); - kin.setScat(ef_rc); - - // Debugging output - m_log->debug("x,Q2,W,y,nu = {},{},{},{},{}", kin.getX(), - kin.getQ2(), kin.getW(), kin.getY(), kin.getNu()); + // If no scattered electron was found + if (sigma_h <= 0) { + m_log->debug("No scattered electron found"); + return; } -} // namespace Jug::Reco + // Calculate kinematic variables + const auto y_e = 1. - sigma_e / (2. * ei.energy()); + const auto Q2_e = (pt_e * pt_e) / (1. - y_e); + + const auto y_sig = sigma_h / sigma_tot; + const auto Q2_sig = (pt_e * pt_e) / (1. - y_sig); + const auto x_sig = Q2_sig / (4. * ei.energy() * pi.energy() * y_sig); + + const auto Q2_esig = Q2_e; + const auto x_esig = x_sig; + const auto y_esig = Q2_esig / (4. * ei.energy() * pi.energy() * + x_esig); //equivalent to (2*ei.energy() / sigma_tot)*y_sig + const auto nu_esig = Q2_esig / (2. * m_proton * x_esig); + const auto W_esig = sqrt(m_proton * m_proton + 2 * m_proton * nu_esig - Q2_esig); + auto kin = kinematics->create(x_esig, Q2_esig, W_esig, y_esig, nu_esig); + kin.setScat(ef_rc); + + // Debugging output + m_log->debug("x,Q2,W,y,nu = {},{},{},{},{}", kin.getX(), kin.getQ2(), kin.getW(), kin.getY(), + kin.getNu()); +} + +} // namespace eicrecon diff --git a/src/algorithms/reco/InclusiveKinematicseSigma.h b/src/algorithms/reco/InclusiveKinematicseSigma.h index 9ed9fb7d0a..4a1e1baab9 100644 --- a/src/algorithms/reco/InclusiveKinematicseSigma.h +++ b/src/algorithms/reco/InclusiveKinematicseSigma.h @@ -13,36 +13,29 @@ #include #include - namespace eicrecon { - using InclusiveKinematicseSigmaAlgorithm = algorithms::Algorithm< - algorithms::Input< - edm4hep::MCParticleCollection, - edm4eic::ReconstructedParticleCollection, - edm4eic::MCRecoParticleAssociationCollection - >, - algorithms::Output< - edm4eic::InclusiveKinematicsCollection - > - >; - - class InclusiveKinematicseSigma - : public InclusiveKinematicseSigmaAlgorithm { - - public: - InclusiveKinematicseSigma(std::string_view name) - : InclusiveKinematicseSigmaAlgorithm{name, - {"MCParticles", "inputParticles", "inputAssociations"}, - {"inclusiveKinematics"}, - "Determine inclusive kinematics using e-Sigma method."} {} +using InclusiveKinematicseSigmaAlgorithm = algorithms::Algorithm< + algorithms::Input, + algorithms::Output>; - void init(std::shared_ptr& logger); - void process(const Input&, const Output&) const final; +class InclusiveKinematicseSigma : public InclusiveKinematicseSigmaAlgorithm { - private: - std::shared_ptr m_log; - double m_proton{0.93827}, m_neutron{0.93957}, m_electron{0.000510998928}, m_crossingAngle{-0.025}; - }; +public: + InclusiveKinematicseSigma(std::string_view name) + : InclusiveKinematicseSigmaAlgorithm{name, + {"MCParticles", "inputParticles", "inputAssociations"}, + {"inclusiveKinematics"}, + "Determine inclusive kinematics using e-Sigma method."} { + } + + void init(std::shared_ptr& logger); + void process(const Input&, const Output&) const final; + +private: + std::shared_ptr m_log; + double m_proton{0.93827}, m_neutron{0.93957}, m_electron{0.000510998928}, m_crossingAngle{-0.025}; +}; } // namespace eicrecon diff --git a/src/algorithms/reco/JetReconstruction.cc b/src/algorithms/reco/JetReconstruction.cc index a57c6ea774..ca581ce07a 100644 --- a/src/algorithms/reco/JetReconstruction.cc +++ b/src/algorithms/reco/JetReconstruction.cc @@ -6,7 +6,7 @@ // for error handling #include -#include // IWYU pragma: keep +#include // IWYU pragma: keep #include #include #include @@ -23,125 +23,130 @@ using namespace fastjet; namespace eicrecon { - template - void JetReconstruction::init(std::shared_ptr logger) { - - m_log = logger; - m_log->trace("Initialized"); - - // if specified algorithm, recomb. scheme, or area type - // are not defined, then issue error and throw exception - try { - m_mapJetAlgo.at(m_cfg.jetAlgo); - } catch (std::out_of_range &out) { - m_log->error(" Unknown jet algorithm \"{}\" specified!", m_cfg.jetAlgo); - throw JException(out.what()); - } - - try { - m_mapRecombScheme.at(m_cfg.recombScheme); - } catch (std::out_of_range &out) { - m_log->error(" Unknown recombination scheme \"{}\" specified!", m_cfg.recombScheme); - throw JException(out.what()); - } - - try { - m_mapAreaType.at(m_cfg.areaType); - } catch (std::out_of_range &out) { - m_log->error(" Unknown area type \"{}\" specified!", m_cfg.areaType); - throw JException(out.what()); +template +void JetReconstruction::init(std::shared_ptr logger) { + + m_log = logger; + m_log->trace("Initialized"); + + // if specified algorithm, recomb. scheme, or area type + // are not defined, then issue error and throw exception + try { + m_mapJetAlgo.at(m_cfg.jetAlgo); + } catch (std::out_of_range& out) { + m_log->error(" Unknown jet algorithm \"{}\" specified!", m_cfg.jetAlgo); + throw JException(out.what()); + } + + try { + m_mapRecombScheme.at(m_cfg.recombScheme); + } catch (std::out_of_range& out) { + m_log->error(" Unknown recombination scheme \"{}\" specified!", m_cfg.recombScheme); + throw JException(out.what()); + } + + try { + m_mapAreaType.at(m_cfg.areaType); + } catch (std::out_of_range& out) { + m_log->error(" Unknown area type \"{}\" specified!", m_cfg.areaType); + throw JException(out.what()); + } + + // Choose jet definition based on no. of parameters + switch (m_mapJetAlgo[m_cfg.jetAlgo]) { + + // 0 parameter algorithms + case JetAlgorithm::ee_kt_algorithm: + m_jet_def = std::make_unique(m_mapJetAlgo[m_cfg.jetAlgo], + m_mapRecombScheme[m_cfg.recombScheme]); + break; + + // 2 parameter algorithms + case JetAlgorithm::genkt_algorithm: + [[fallthrough]]; + + case JetAlgorithm::ee_genkt_algorithm: + m_jet_def = std::make_unique(m_mapJetAlgo[m_cfg.jetAlgo], m_cfg.rJet, m_cfg.pJet, + m_mapRecombScheme[m_cfg.recombScheme]); + break; + + // all others have only 1 parameter + default: + m_jet_def = std::make_unique(m_mapJetAlgo[m_cfg.jetAlgo], m_cfg.rJet, + m_mapRecombScheme[m_cfg.recombScheme]); + break; + + } // end switch (jet algorithm) + + // Define jet area + m_area_def = std::make_unique( + m_mapAreaType[m_cfg.areaType], + GhostedAreaSpec(m_cfg.ghostMaxRap, m_cfg.numGhostRepeat, m_cfg.ghostArea)); + +} // end 'init(std::shared_ptr)' + +template +void JetReconstruction::process( + const typename JetReconstructionAlgorithm::Input& input, + const typename JetReconstructionAlgorithm::Output& output) const { + // Grab input collections + const auto [input_collection] = input; + auto [jet_collection] = output; + + // extract input momenta and collect into pseudojets + std::vector particles; + for (unsigned iInput = 0; const auto& input : *input_collection) { + + // get 4-vector + const auto& momentum = input.getMomentum(); + const auto& energy = input.getEnergy(); + const auto pt = edm4hep::utils::magnitudeTransverse(momentum); + + // Only cluster particles within the given pt Range + if ((pt > m_cfg.minCstPt) && (pt < m_cfg.maxCstPt)) { + particles.emplace_back(momentum.x, momentum.y, momentum.z, energy); + particles.back().set_user_index(iInput); } + ++iInput; + } - // Choose jet definition based on no. of parameters - switch (m_mapJetAlgo[m_cfg.jetAlgo]) { - - // 0 parameter algorithms - case JetAlgorithm::ee_kt_algorithm: - m_jet_def = std::make_unique(m_mapJetAlgo[m_cfg.jetAlgo], m_mapRecombScheme[m_cfg.recombScheme]); - break; - - // 2 parameter algorithms - case JetAlgorithm::genkt_algorithm: - [[fallthrough]]; - - case JetAlgorithm::ee_genkt_algorithm: - m_jet_def = std::make_unique(m_mapJetAlgo[m_cfg.jetAlgo], m_cfg.rJet, m_cfg.pJet, m_mapRecombScheme[m_cfg.recombScheme]); - break; - - // all others have only 1 parameter - default: - m_jet_def = std::make_unique(m_mapJetAlgo[m_cfg.jetAlgo], m_cfg.rJet, m_mapRecombScheme[m_cfg.recombScheme]); - break; - - } // end switch (jet algorithm) - - // Define jet area - m_area_def = std::make_unique(m_mapAreaType[m_cfg.areaType], GhostedAreaSpec(m_cfg.ghostMaxRap, m_cfg.numGhostRepeat, m_cfg.ghostArea)); - - } // end 'init(std::shared_ptr)' - - template - void JetReconstruction::process( - const typename JetReconstructionAlgorithm::Input& input, - const typename JetReconstructionAlgorithm::Output& output - ) const { - // Grab input collections - const auto [input_collection] = input; - auto [jet_collection] = output; - - // extract input momenta and collect into pseudojets - std::vector particles; - for (unsigned iInput = 0; const auto& input : *input_collection) { - - // get 4-vector - const auto& momentum = input.getMomentum(); - const auto& energy = input.getEnergy(); - const auto pt = edm4hep::utils::magnitudeTransverse(momentum); - - // Only cluster particles within the given pt Range - if ((pt > m_cfg.minCstPt) && (pt < m_cfg.maxCstPt)) { - particles.emplace_back(momentum.x, momentum.y, momentum.z, energy); - particles.back().set_user_index(iInput); - } - ++iInput; - } - - // Skip empty - if (particles.empty()) { - m_log->trace(" Empty particle list."); - return; - } - m_log->trace(" Number of particles: {}", particles.size()); + // Skip empty + if (particles.empty()) { + m_log->trace(" Empty particle list."); + return; + } + m_log->trace(" Number of particles: {}", particles.size()); - // Run the clustering, extract the jets - fastjet::ClusterSequenceArea m_clus_seq(particles, *m_jet_def, *m_area_def); - std::vector jets = sorted_by_pt(m_clus_seq.inclusive_jets(m_cfg.minJetPt)); + // Run the clustering, extract the jets + fastjet::ClusterSequenceArea m_clus_seq(particles, *m_jet_def, *m_area_def); + std::vector jets = sorted_by_pt(m_clus_seq.inclusive_jets(m_cfg.minJetPt)); - // Print out some infos - m_log->trace(" Clustering with : {}", m_jet_def->description()); + // Print out some infos + m_log->trace(" Clustering with : {}", m_jet_def->description()); - // loop over jets - for (unsigned i = 0; i < jets.size(); i++) { + // loop over jets + for (unsigned i = 0; i < jets.size(); i++) { - m_log->trace(" jet {}: pt = {}, y = {}, phi = {}", i, jets[i].pt(), jets[i].rap(), jets[i].phi()); + m_log->trace(" jet {}: pt = {}, y = {}, phi = {}", i, jets[i].pt(), jets[i].rap(), + jets[i].phi()); - // create jet to store in output collection - edm4eic::MutableReconstructedParticle jet_output = jet_collection->create(); - jet_output.setMomentum(edm4hep::Vector3f(jets[i].px(), jets[i].py(), jets[i].pz())); - jet_output.setEnergy(jets[i].e()); - jet_output.setMass(jets[i].m()); + // create jet to store in output collection + edm4eic::MutableReconstructedParticle jet_output = jet_collection->create(); + jet_output.setMomentum(edm4hep::Vector3f(jets[i].px(), jets[i].py(), jets[i].pz())); + jet_output.setEnergy(jets[i].e()); + jet_output.setMass(jets[i].m()); - // link constituents to jet kinematic info - std::vector csts = jets[i].constituents(); - for (unsigned j = 0; j < csts.size(); j++) { - jet_output.addToParticles(input_collection->at(csts[j].user_index())); - } // for constituent j - } // for jet i + // link constituents to jet kinematic info + std::vector csts = jets[i].constituents(); + for (unsigned j = 0; j < csts.size(); j++) { + jet_output.addToParticles(input_collection->at(csts[j].user_index())); + } // for constituent j + } // for jet i - // return the jets - return; - } // end 'process(const T&)' + // return the jets + return; +} // end 'process(const T&)' - template class JetReconstruction; +template class JetReconstruction; -} // end namespace eicrecon +} // end namespace eicrecon diff --git a/src/algorithms/reco/JetReconstruction.h b/src/algorithms/reco/JetReconstruction.h index 774ef75c46..cb74e1a7e8 100644 --- a/src/algorithms/reco/JetReconstruction.h +++ b/src/algorithms/reco/JetReconstruction.h @@ -20,86 +20,74 @@ namespace eicrecon { - template - using JetReconstructionAlgorithm = algorithms::Algorithm< - algorithms::Input< - typename InputT::collection_type - >, - algorithms::Output< - edm4eic::ReconstructedParticleCollection - > - >; - - template - class JetReconstruction - : public JetReconstructionAlgorithm, - public WithPodConfig { - - public: - - JetReconstruction(std::string_view name) : - JetReconstructionAlgorithm { - name, - {"inputReconstructedParticles"}, - {"outputReconstructedParticles"}, - "Performs jet reconstruction using a FastJet algorithm." - } {} - - public: - - // algorithm initialization - void init(std::shared_ptr logger); - - // run algorithm - void process(const typename eicrecon::JetReconstructionAlgorithm::Input&, const typename eicrecon::JetReconstructionAlgorithm::Output&) const final; - - private: - - std::shared_ptr m_log; - - // fastjet components - std::unique_ptr m_jet_def; - std::unique_ptr m_area_def; - - // maps of user input onto fastjet options - std::map m_mapJetAlgo = { - {"kt_algorithm", fastjet::JetAlgorithm::kt_algorithm}, - {"cambridge_algorithm", fastjet::JetAlgorithm::cambridge_algorithm}, - {"antikt_algorithm", fastjet::JetAlgorithm::antikt_algorithm}, - {"genkt_algorithm", fastjet::JetAlgorithm::genkt_algorithm}, - {"cambridge_for_passive_algorithm", fastjet::JetAlgorithm::cambridge_for_passive_algorithm}, - {"genkt_for_passive_algorithm", fastjet::JetAlgorithm::genkt_for_passive_algorithm}, - {"ee_kt_algorithm", fastjet::JetAlgorithm::ee_kt_algorithm}, - {"ee_genkt_algorithm", fastjet::JetAlgorithm::ee_genkt_algorithm}, - {"plugin_algorithm", fastjet::JetAlgorithm::plugin_algorithm} - }; - std::map m_mapRecombScheme = { - {"E_scheme", fastjet::RecombinationScheme::E_scheme}, - {"pt_scheme", fastjet::RecombinationScheme::pt_scheme}, - {"pt2_scheme", fastjet::RecombinationScheme::pt2_scheme}, - {"Et_scheme", fastjet::RecombinationScheme::Et_scheme}, - {"Et2_scheme", fastjet::RecombinationScheme::Et2_scheme}, - {"BIpt_scheme", fastjet::RecombinationScheme::BIpt_scheme}, - {"BIpt2_scheme", fastjet::RecombinationScheme::BIpt2_scheme}, - {"WTA_pt_scheme", fastjet::RecombinationScheme::WTA_pt_scheme}, - {"WTA_modp_scheme", fastjet::RecombinationScheme::WTA_modp_scheme}, - {"external_scheme", fastjet::RecombinationScheme::external_scheme} - }; - std::map m_mapAreaType = { - {"active_area", fastjet::AreaType::active_area}, - {"active_area_explicit_ghosts", fastjet::AreaType::active_area_explicit_ghosts}, - {"one_ghost_passive_area", fastjet::AreaType::one_ghost_passive_area}, - {"passive_area", fastjet::AreaType::passive_area}, - {"voronoi_area", fastjet::AreaType::voronoi_area} - }; - - // default fastjet options - const struct defaults { - std::string jetAlgo; - std::string recombScheme; - std::string areaType; - } m_defaultFastjetOpts = {"antikt_algorithm", "E_scheme", "active_area"}; - - }; // end JetReconstruction definition - -} // end eicrecon namespace +template +using JetReconstructionAlgorithm = + algorithms::Algorithm, + algorithms::Output>; + +template +class JetReconstruction : public JetReconstructionAlgorithm, + public WithPodConfig { + +public: + JetReconstruction(std::string_view name) + : JetReconstructionAlgorithm{ + name, + {"inputReconstructedParticles"}, + {"outputReconstructedParticles"}, + "Performs jet reconstruction using a FastJet algorithm."} {} + +public: + // algorithm initialization + void init(std::shared_ptr logger); + + // run algorithm + void process(const typename eicrecon::JetReconstructionAlgorithm::Input&, + const typename eicrecon::JetReconstructionAlgorithm::Output&) const final; + +private: + std::shared_ptr m_log; + + // fastjet components + std::unique_ptr m_jet_def; + std::unique_ptr m_area_def; + + // maps of user input onto fastjet options + std::map m_mapJetAlgo = { + {"kt_algorithm", fastjet::JetAlgorithm::kt_algorithm}, + {"cambridge_algorithm", fastjet::JetAlgorithm::cambridge_algorithm}, + {"antikt_algorithm", fastjet::JetAlgorithm::antikt_algorithm}, + {"genkt_algorithm", fastjet::JetAlgorithm::genkt_algorithm}, + {"cambridge_for_passive_algorithm", fastjet::JetAlgorithm::cambridge_for_passive_algorithm}, + {"genkt_for_passive_algorithm", fastjet::JetAlgorithm::genkt_for_passive_algorithm}, + {"ee_kt_algorithm", fastjet::JetAlgorithm::ee_kt_algorithm}, + {"ee_genkt_algorithm", fastjet::JetAlgorithm::ee_genkt_algorithm}, + {"plugin_algorithm", fastjet::JetAlgorithm::plugin_algorithm}}; + std::map m_mapRecombScheme = { + {"E_scheme", fastjet::RecombinationScheme::E_scheme}, + {"pt_scheme", fastjet::RecombinationScheme::pt_scheme}, + {"pt2_scheme", fastjet::RecombinationScheme::pt2_scheme}, + {"Et_scheme", fastjet::RecombinationScheme::Et_scheme}, + {"Et2_scheme", fastjet::RecombinationScheme::Et2_scheme}, + {"BIpt_scheme", fastjet::RecombinationScheme::BIpt_scheme}, + {"BIpt2_scheme", fastjet::RecombinationScheme::BIpt2_scheme}, + {"WTA_pt_scheme", fastjet::RecombinationScheme::WTA_pt_scheme}, + {"WTA_modp_scheme", fastjet::RecombinationScheme::WTA_modp_scheme}, + {"external_scheme", fastjet::RecombinationScheme::external_scheme}}; + std::map m_mapAreaType = { + {"active_area", fastjet::AreaType::active_area}, + {"active_area_explicit_ghosts", fastjet::AreaType::active_area_explicit_ghosts}, + {"one_ghost_passive_area", fastjet::AreaType::one_ghost_passive_area}, + {"passive_area", fastjet::AreaType::passive_area}, + {"voronoi_area", fastjet::AreaType::voronoi_area}}; + + // default fastjet options + const struct defaults { + std::string jetAlgo; + std::string recombScheme; + std::string areaType; + } m_defaultFastjetOpts = {"antikt_algorithm", "E_scheme", "active_area"}; + +}; // end JetReconstruction definition + +} // namespace eicrecon diff --git a/src/algorithms/reco/JetReconstructionConfig.h b/src/algorithms/reco/JetReconstructionConfig.h index 76f8c00227..a8b20deef0 100644 --- a/src/algorithms/reco/JetReconstructionConfig.h +++ b/src/algorithms/reco/JetReconstructionConfig.h @@ -8,20 +8,19 @@ namespace eicrecon { - struct JetReconstructionConfig { +struct JetReconstructionConfig { - float rJet = 1.0; // jet resolution parameter - float pJet = -1.0; // exponent for generalized kt algorithms - double minCstPt = 0.2 * dd4hep::GeV; // minimum pT of objects fed to cluster sequence - double maxCstPt = 100. * dd4hep::GeV; // maximum pT of objects fed to clsuter sequence - double minJetPt = 1.0 * dd4hep::GeV; // minimum jet pT - double ghostMaxRap = 3.5; // maximum rapidity of ghosts - double ghostArea = 0.001; // area per ghost - int numGhostRepeat = 1; // number of times a ghost is reused per grid site - std::string jetAlgo = "antikt_algorithm"; // jet finding algorithm - std::string recombScheme = "E_scheme"; // particle recombination scheme - std::string areaType = "active_area"; // type of area calculated + float rJet = 1.0; // jet resolution parameter + float pJet = -1.0; // exponent for generalized kt algorithms + double minCstPt = 0.2 * dd4hep::GeV; // minimum pT of objects fed to cluster sequence + double maxCstPt = 100. * dd4hep::GeV; // maximum pT of objects fed to clsuter sequence + double minJetPt = 1.0 * dd4hep::GeV; // minimum jet pT + double ghostMaxRap = 3.5; // maximum rapidity of ghosts + double ghostArea = 0.001; // area per ghost + int numGhostRepeat = 1; // number of times a ghost is reused per grid site + std::string jetAlgo = "antikt_algorithm"; // jet finding algorithm + std::string recombScheme = "E_scheme"; // particle recombination scheme + std::string areaType = "active_area"; // type of area calculated +}; - }; - -} // end eicrecon namespace +} // namespace eicrecon diff --git a/src/algorithms/reco/MC2SmearedParticle.cc b/src/algorithms/reco/MC2SmearedParticle.cc index 93c85d936a..9dccc7a884 100644 --- a/src/algorithms/reco/MC2SmearedParticle.cc +++ b/src/algorithms/reco/MC2SmearedParticle.cc @@ -9,41 +9,39 @@ #include #include +void eicrecon::MC2SmearedParticle::init(std::shared_ptr logger) { m_log = logger; } -void eicrecon::MC2SmearedParticle::init(std::shared_ptr logger) { - m_log = logger; -} +std::unique_ptr +eicrecon::MC2SmearedParticle::produce(const edm4hep::MCParticleCollection* mc_particles) { + auto rec_particles = std::make_unique(); + for (const auto& mc_particle : *mc_particles) { -std::unique_ptr eicrecon::MC2SmearedParticle::produce(const edm4hep::MCParticleCollection* mc_particles) { - auto rec_particles = std::make_unique(); - for (const auto& mc_particle: *mc_particles) { - - if (mc_particle.getGeneratorStatus() != 1) { - m_log->debug("ignoring particle with generatorStatus = {}", mc_particle.getGeneratorStatus()); - continue; - } - - // make sure we keep types consistent - using MomType = decltype(edm4eic::ReconstructedParticle().getMomentum().x); - - const MomType px = mc_particle.getMomentum().x; - const MomType py = mc_particle.getMomentum().y; - const MomType pz = mc_particle.getMomentum().z; - - const MomType vx = mc_particle.getVertex().x; - const MomType vy = mc_particle.getVertex().y; - const MomType vz = mc_particle.getVertex().z; - - auto rec_part = rec_particles->create(); - rec_part.setType(mc_particle.getGeneratorStatus()); // @TODO: determine type codes - rec_part.setEnergy(mc_particle.getEnergy()); - rec_part.setMomentum({px, py, pz}); - rec_part.setReferencePoint({vx, vy, vz}); // @FIXME: probably not what we want? - rec_part.setCharge(mc_particle.getCharge()); - rec_part.setMass(mc_particle.getMass()); - rec_part.setGoodnessOfPID(1); // Perfect PID - rec_part.setCovMatrix({0, 0, 0, 0}); - rec_part.setPDG(mc_particle.getPDG()); + if (mc_particle.getGeneratorStatus() != 1) { + m_log->debug("ignoring particle with generatorStatus = {}", mc_particle.getGeneratorStatus()); + continue; } - return std::move(rec_particles); + + // make sure we keep types consistent + using MomType = decltype(edm4eic::ReconstructedParticle().getMomentum().x); + + const MomType px = mc_particle.getMomentum().x; + const MomType py = mc_particle.getMomentum().y; + const MomType pz = mc_particle.getMomentum().z; + + const MomType vx = mc_particle.getVertex().x; + const MomType vy = mc_particle.getVertex().y; + const MomType vz = mc_particle.getVertex().z; + + auto rec_part = rec_particles->create(); + rec_part.setType(mc_particle.getGeneratorStatus()); // @TODO: determine type codes + rec_part.setEnergy(mc_particle.getEnergy()); + rec_part.setMomentum({px, py, pz}); + rec_part.setReferencePoint({vx, vy, vz}); // @FIXME: probably not what we want? + rec_part.setCharge(mc_particle.getCharge()); + rec_part.setMass(mc_particle.getMass()); + rec_part.setGoodnessOfPID(1); // Perfect PID + rec_part.setCovMatrix({0, 0, 0, 0}); + rec_part.setPDG(mc_particle.getPDG()); + } + return std::move(rec_particles); } diff --git a/src/algorithms/reco/MC2SmearedParticle.h b/src/algorithms/reco/MC2SmearedParticle.h index 6b81fe0c44..217996baec 100644 --- a/src/algorithms/reco/MC2SmearedParticle.h +++ b/src/algorithms/reco/MC2SmearedParticle.h @@ -8,23 +8,22 @@ #include #include - namespace eicrecon { - /** +/** * Converts edm4hep::MCParticle to edm4eic::ReconstructedParticle */ - class MC2SmearedParticle { - public: - - /** Initialized algorithms with required data. Init function is assumed to be called once **/ - void init(std::shared_ptr logger); - - /** process function convert one data type to another **/ - std::unique_ptr produce(const edm4hep::MCParticleCollection* mc_particles); - - private: - /** algorithm logger */ - std::shared_ptr m_log; - }; -} +class MC2SmearedParticle { +public: + /** Initialized algorithms with required data. Init function is assumed to be called once **/ + void init(std::shared_ptr logger); + + /** process function convert one data type to another **/ + std::unique_ptr + produce(const edm4hep::MCParticleCollection* mc_particles); + +private: + /** algorithm logger */ + std::shared_ptr m_log; +}; +} // namespace eicrecon diff --git a/src/algorithms/reco/MatchClusters.cc b/src/algorithms/reco/MatchClusters.cc index 675d21ad83..1800ba0ab3 100644 --- a/src/algorithms/reco/MatchClusters.cc +++ b/src/algorithms/reco/MatchClusters.cc @@ -23,162 +23,161 @@ namespace eicrecon { -void MatchClusters::process( - const MatchClusters::Input& input, - const MatchClusters::Output& output) const { - - const auto [mcparticles, inparts, inpartsassoc, clusters, clustersassoc] = input; - auto [outparts, outpartsassoc] = output; - - debug("Processing cluster info for new event"); - - debug("Step 0/2: Getting indexed list of clusters..."); - - // get an indexed map of all clusters - auto clusterMap = indexedClusters(clusters, clustersassoc); - - // 1. Loop over all tracks and link matched clusters where applicable - // (removing matched clusters from the cluster maps) - debug("Step 1/2: Matching clusters to charged particles..."); - - for (const auto inpart: *inparts) { - debug(" --> Processing charged particle {}, PDG {}, energy {}", inpart.getObjectID().index, - inpart.getPDG(), inpart.getEnergy()); - - auto outpart = inpart.clone(); - outparts->push_back(outpart); - - int mcID = -1; - - // find associated particle - for (const auto &assoc: *inpartsassoc) { - if (assoc.getRec().getObjectID() == inpart.getObjectID()) { - mcID = assoc.getSim().getObjectID().index; - break; - } - } - - trace(" --> Found particle with mcID {}", mcID); - - if (mcID < 0) { - debug(" --> cannot match track without associated mcID"); - continue; - } - - if (clusterMap.count(mcID)) { - const auto &clus = clusterMap[mcID]; - debug(" --> found matching cluster with energy: {}", clus.getEnergy()); - debug(" --> adding cluster to reconstructed particle"); - outpart.addToClusters(clus); - clusterMap.erase(mcID); - } - - // create truth associations - auto assoc = outpartsassoc->create(); - assoc.setRecID(outpart.getObjectID().index); - assoc.setSimID(mcID); - assoc.setWeight(1.0); - assoc.setRec(outpart); - assoc.setSim((*mcparticles)[mcID]); +void MatchClusters::process(const MatchClusters::Input& input, + const MatchClusters::Output& output) const { + + const auto [mcparticles, inparts, inpartsassoc, clusters, clustersassoc] = input; + auto [outparts, outpartsassoc] = output; + + debug("Processing cluster info for new event"); + + debug("Step 0/2: Getting indexed list of clusters..."); + + // get an indexed map of all clusters + auto clusterMap = indexedClusters(clusters, clustersassoc); + + // 1. Loop over all tracks and link matched clusters where applicable + // (removing matched clusters from the cluster maps) + debug("Step 1/2: Matching clusters to charged particles..."); + + for (const auto inpart : *inparts) { + debug(" --> Processing charged particle {}, PDG {}, energy {}", inpart.getObjectID().index, + inpart.getPDG(), inpart.getEnergy()); + + auto outpart = inpart.clone(); + outparts->push_back(outpart); + + int mcID = -1; + + // find associated particle + for (const auto& assoc : *inpartsassoc) { + if (assoc.getRec().getObjectID() == inpart.getObjectID()) { + mcID = assoc.getSim().getObjectID().index; + break; + } } - // 2. Now loop over all remaining clusters and add neutrals. Also add in Hcal energy - // if a matching cluster is available - debug("Step 2/2: Creating neutrals for remaining clusters..."); - for (const auto &[mcID, clus]: clusterMap) { - debug(" --> Processing unmatched cluster with energy: {}", clus.getEnergy()); - - - // get mass/PDG from mcparticles, 0 (unidentified) in case the matched particle is charged. - const auto mc = (*mcparticles)[mcID]; - const double mass = (!mc.getCharge()) ? mc.getMass() : 0; - const int32_t pdg = (!mc.getCharge()) ? mc.getPDG() : 0; - if (level() <= algorithms::LogLevel::kDebug) { - if (mc.getCharge()) { - debug(" --> associated mcparticle is not a neutral (PDG: {}), " - "setting the reconstructed particle ID to 0 (unidentified)", mc.getPDG()); - } - debug(" --> found matching associated mcparticle with PDG: {}, energy: {}", pdg, - mc.getEnergy()); - } - - // Reconstruct our neutrals and add them to the list - const auto outpart = reconstruct_neutral(&clus, mass, pdg); - debug(" --> Reconstructed neutral particle with PDG: {}, energy: {}", outpart.getPDG(), - outpart.getEnergy()); - - outparts->push_back(outpart); - - // Create truth associations - auto assoc = outpartsassoc->create(); - assoc.setRecID(outpart.getObjectID().index); - assoc.setSimID(mcID); - assoc.setWeight(1.0); - assoc.setRec(outpart); - assoc.setSim((*mcparticles)[mcID]); + trace(" --> Found particle with mcID {}", mcID); + + if (mcID < 0) { + debug(" --> cannot match track without associated mcID"); + continue; + } + + if (clusterMap.count(mcID)) { + const auto& clus = clusterMap[mcID]; + debug(" --> found matching cluster with energy: {}", clus.getEnergy()); + debug(" --> adding cluster to reconstructed particle"); + outpart.addToClusters(clus); + clusterMap.erase(mcID); + } + + // create truth associations + auto assoc = outpartsassoc->create(); + assoc.setRecID(outpart.getObjectID().index); + assoc.setSimID(mcID); + assoc.setWeight(1.0); + assoc.setRec(outpart); + assoc.setSim((*mcparticles)[mcID]); + } + + // 2. Now loop over all remaining clusters and add neutrals. Also add in Hcal energy + // if a matching cluster is available + debug("Step 2/2: Creating neutrals for remaining clusters..."); + for (const auto& [mcID, clus] : clusterMap) { + debug(" --> Processing unmatched cluster with energy: {}", clus.getEnergy()); + + // get mass/PDG from mcparticles, 0 (unidentified) in case the matched particle is charged. + const auto mc = (*mcparticles)[mcID]; + const double mass = (!mc.getCharge()) ? mc.getMass() : 0; + const int32_t pdg = (!mc.getCharge()) ? mc.getPDG() : 0; + if (level() <= algorithms::LogLevel::kDebug) { + if (mc.getCharge()) { + debug(" --> associated mcparticle is not a neutral (PDG: {}), " + "setting the reconstructed particle ID to 0 (unidentified)", + mc.getPDG()); + } + debug(" --> found matching associated mcparticle with PDG: {}, energy: {}", pdg, + mc.getEnergy()); } + + // Reconstruct our neutrals and add them to the list + const auto outpart = reconstruct_neutral(&clus, mass, pdg); + debug(" --> Reconstructed neutral particle with PDG: {}, energy: {}", outpart.getPDG(), + outpart.getEnergy()); + + outparts->push_back(outpart); + + // Create truth associations + auto assoc = outpartsassoc->create(); + assoc.setRecID(outpart.getObjectID().index); + assoc.setSimID(mcID); + assoc.setWeight(1.0); + assoc.setRec(outpart); + assoc.setSim((*mcparticles)[mcID]); + } } // get a map of mcID --> cluster // input: clusters --> all clusters std::map MatchClusters::indexedClusters( - const edm4eic::ClusterCollection* clusters, - const edm4eic::MCRecoClusterParticleAssociationCollection* associations) const { + const edm4eic::ClusterCollection* clusters, + const edm4eic::MCRecoClusterParticleAssociationCollection* associations) const { - std::map matched = {}; + std::map matched = {}; - // loop over clusters - for (const auto cluster: *clusters) { + // loop over clusters + for (const auto cluster : *clusters) { - int mcID = -1; + int mcID = -1; - // find associated particle - for (const auto assoc: *associations) { - if (assoc.getRec() == cluster) { - mcID = assoc.getSim().getObjectID().index; - break; - } - } + // find associated particle + for (const auto assoc : *associations) { + if (assoc.getRec() == cluster) { + mcID = assoc.getSim().getObjectID().index; + break; + } + } - trace(" --> Found cluster with mcID {} and energy {}", mcID, cluster.getEnergy()); + trace(" --> Found cluster with mcID {} and energy {}", mcID, cluster.getEnergy()); - if (mcID < 0) { - trace(" --> WARNING: no valid MC truth link found, skipping cluster..."); - continue; - } + if (mcID < 0) { + trace(" --> WARNING: no valid MC truth link found, skipping cluster..."); + continue; + } - const bool duplicate = matched.count(mcID); - if (duplicate) { - trace(" --> WARNING: this is a duplicate mcID, keeping the higher energy cluster"); + const bool duplicate = matched.count(mcID); + if (duplicate) { + trace(" --> WARNING: this is a duplicate mcID, keeping the higher energy cluster"); - if (cluster.getEnergy() < matched[mcID].getEnergy()) { - continue; - } - } - matched[mcID] = cluster; + if (cluster.getEnergy() < matched[mcID].getEnergy()) { + continue; + } } - return matched; + matched[mcID] = cluster; + } + return matched; } - // reconstruct a neutral cluster // (for now assuming the vertex is at (0,0,0)) -edm4eic::ReconstructedParticle MatchClusters::reconstruct_neutral( - const edm4eic::Cluster *cluster, const double mass, const int32_t pdg) const { - - const float energy = cluster->getEnergy(); - const float p = energy < mass ? 0 : std::sqrt(energy * energy - mass * mass); - const auto position = cluster->getPosition(); - const auto momentum = p * (position / edm4hep::utils::magnitude(position)); - // setup our particle - edm4eic::MutableReconstructedParticle part; - part.setMomentum(momentum); - part.setPDG(pdg); - part.setCharge(0); - part.setEnergy(energy); - part.setMass(mass); - part.addToClusters(*cluster); - return part; +edm4eic::ReconstructedParticle MatchClusters::reconstruct_neutral(const edm4eic::Cluster* cluster, + const double mass, + const int32_t pdg) const { + + const float energy = cluster->getEnergy(); + const float p = energy < mass ? 0 : std::sqrt(energy * energy - mass * mass); + const auto position = cluster->getPosition(); + const auto momentum = p * (position / edm4hep::utils::magnitude(position)); + // setup our particle + edm4eic::MutableReconstructedParticle part; + part.setMomentum(momentum); + part.setPDG(pdg); + part.setCharge(0); + part.setEnergy(energy); + part.setMass(mass); + part.addToClusters(*cluster); + return part; } } // namespace eicrecon diff --git a/src/algorithms/reco/MatchClusters.h b/src/algorithms/reco/MatchClusters.h index 55581746bf..5b9af4d91a 100644 --- a/src/algorithms/reco/MatchClusters.h +++ b/src/algorithms/reco/MatchClusters.h @@ -18,55 +18,39 @@ #include #include - namespace eicrecon { - using MatchClustersAlgorithm = algorithms::Algorithm< - algorithms::Input< - edm4hep::MCParticleCollection, - edm4eic::ReconstructedParticleCollection, - edm4eic::MCRecoParticleAssociationCollection, - edm4eic::ClusterCollection, - edm4eic::MCRecoClusterParticleAssociationCollection - >, - algorithms::Output< - edm4eic::ReconstructedParticleCollection, - edm4eic::MCRecoParticleAssociationCollection - > - >; +using MatchClustersAlgorithm = algorithms::Algorithm< + algorithms::Input, + algorithms::Output>; - class MatchClusters - : public MatchClustersAlgorithm { +class MatchClusters : public MatchClustersAlgorithm { - public: - MatchClusters(std::string_view name) +public: + MatchClusters(std::string_view name) : MatchClustersAlgorithm{name, - { - "MCParticles", - "CentralTracks", "CentralTrackAssociations", - "EcalClusters", "EcalClusterAssociations" - }, - { - "ReconstructedParticles", "ReconstructedParticleAssociations" - }, - "Match tracks with clusters, and assign associations."} {} - - void init() final { }; - void process(const Input&, const Output&) const final; - - private: - // get a map of mcID --> cluster - // input: clusters --> all clusters - std::map indexedClusters( - const edm4eic::ClusterCollection* clusters, - const edm4eic::MCRecoClusterParticleAssociationCollection* associations) const; - - // reconstruct a neutral cluster - // (for now assuming the vertex is at (0,0,0)) - edm4eic::ReconstructedParticle reconstruct_neutral( - const edm4eic::Cluster *cluster, - const double mass, const int32_t pdg) const; - - }; + {"MCParticles", "CentralTracks", "CentralTrackAssociations", + "EcalClusters", "EcalClusterAssociations"}, + {"ReconstructedParticles", "ReconstructedParticleAssociations"}, + "Match tracks with clusters, and assign associations."} {} + + void init() final {}; + void process(const Input&, const Output&) const final; + +private: + // get a map of mcID --> cluster + // input: clusters --> all clusters + std::map + indexedClusters(const edm4eic::ClusterCollection* clusters, + const edm4eic::MCRecoClusterParticleAssociationCollection* associations) const; + + // reconstruct a neutral cluster + // (for now assuming the vertex is at (0,0,0)) + edm4eic::ReconstructedParticle reconstruct_neutral(const edm4eic::Cluster* cluster, + const double mass, const int32_t pdg) const; +}; } // namespace eicrecon diff --git a/src/algorithms/reco/ScatteredElectronsEMinusPz.cc b/src/algorithms/reco/ScatteredElectronsEMinusPz.cc index adecb6382a..d246bb8f7a 100644 --- a/src/algorithms/reco/ScatteredElectronsEMinusPz.cc +++ b/src/algorithms/reco/ScatteredElectronsEMinusPz.cc @@ -20,129 +20,115 @@ using ROOT::Math::PxPyPzMVector; namespace eicrecon { - /** +/** * @brief Initialize the ScatteredElectronsEMinusPz Algorithm * * @param logger */ - void ScatteredElectronsEMinusPz::init(std::shared_ptr& logger) { - m_log = logger; - } +void ScatteredElectronsEMinusPz::init(std::shared_ptr& logger) { m_log = logger; } - /** +/** * @brief Produce a list of scattered electron candidates * * @param rcparts - input collection of all reconstructed particles * @param rcele - input collection of all electron candidates * @return std::unique_ptr */ - std::unique_ptr ScatteredElectronsEMinusPz::execute( - const edm4eic::ReconstructedParticleCollection *rcparts, - const edm4eic::ReconstructedParticleCollection *rcele - ){ - - // this map will store intermediate results - // so that we can sort them before filling output - // collection - std::map scatteredElectronsMap; - - // our output collection of scattered electrons - // ordered by E-Pz - auto out_electrons = std::make_unique< - edm4eic::ReconstructedParticleCollection - >(); - out_electrons->setSubsetCollection(); - - m_log->trace( "We have {} candidate electrons", - rcele->size() - ); - - // Lorentz Vector for the scattered electron, - // hadronic final state, and individual hadron - // We do it here to avoid creating objects inside the loops - PxPyPzMVector vScatteredElectron; - PxPyPzMVector vHadronicFinalState; - PxPyPzMVector vHadron; - - for ( const auto& e: *rcele ) { - // Do not cut on charge to account for charge-symmetric background - - // reset the HadronicFinalState - vHadronicFinalState.SetCoordinates(0, 0, 0, 0); - - // Set a vector for the electron we are considering now - vScatteredElectron.SetCoordinates( - e.getMomentum().x, - e.getMomentum().y, - e.getMomentum().z, - m_electron +std::unique_ptr +ScatteredElectronsEMinusPz::execute(const edm4eic::ReconstructedParticleCollection* rcparts, + const edm4eic::ReconstructedParticleCollection* rcele) { + + // this map will store intermediate results + // so that we can sort them before filling output + // collection + std::map scatteredElectronsMap; + + // our output collection of scattered electrons + // ordered by E-Pz + auto out_electrons = std::make_unique(); + out_electrons->setSubsetCollection(); + + m_log->trace("We have {} candidate electrons", rcele->size()); + + // Lorentz Vector for the scattered electron, + // hadronic final state, and individual hadron + // We do it here to avoid creating objects inside the loops + PxPyPzMVector vScatteredElectron; + PxPyPzMVector vHadronicFinalState; + PxPyPzMVector vHadron; + + for (const auto& e : *rcele) { + // Do not cut on charge to account for charge-symmetric background + + // reset the HadronicFinalState + vHadronicFinalState.SetCoordinates(0, 0, 0, 0); + + // Set a vector for the electron we are considering now + vScatteredElectron.SetCoordinates(e.getMomentum().x, e.getMomentum().y, e.getMomentum().z, + m_electron); + + // Loop over reconstructed particles to + // sum hadronic final state + for (const auto& p : *rcparts) { + // What we want is to add all reconstructed particles + // except the one we are currently considering as the + // (scattered) electron candidate. + if (p.getObjectID() != e.getObjectID()) { + vHadron.SetCoordinates(p.getMomentum().x, p.getMomentum().y, p.getMomentum().z, + m_pion // Assume pion for hadronic state ); - // Loop over reconstructed particles to - // sum hadronic final state - for (const auto& p: *rcparts) { - // What we want is to add all reconstructed particles - // except the one we are currently considering as the - // (scattered) electron candidate. - if (p.getObjectID() != e.getObjectID()) { - vHadron.SetCoordinates( - p.getMomentum().x, - p.getMomentum().y, - p.getMomentum().z, - m_pion // Assume pion for hadronic state - ); - - // Sum hadronic final state - vHadronicFinalState += vHadron; - } else { - m_log->trace( "Skipping electron in hadronic final state" ); - } - } // hadron loop (reconstructed particles) - - // Calculate the E-Pz for this electron - // + hadron final state combination - // For now we keep all electron - // candidates but we will rank them by their E-Pz - double EPz=(vScatteredElectron+vHadronicFinalState).E() - - (vScatteredElectron+vHadronicFinalState).Pz(); - m_log->trace( "\tE-Pz={}", EPz ); - m_log->trace( "\tScatteredElectron has Pxyz=( {}, {}, {} )", e.getMomentum().x, e.getMomentum().y, e.getMomentum().z ); - - // Store the result of this calculation - scatteredElectronsMap[ EPz ] = e; - } // electron loop - - m_log->trace( "Selecting candidates with {} < E-Pz < {}", m_cfg.minEMinusPz, m_cfg.maxEMinusPz ); - - // map sorts in descending order by default - // sort by descending - bool first = true; - // for (auto kv : scatteredElectronsMap) { - for (auto kv = scatteredElectronsMap.rbegin(); kv != scatteredElectronsMap.rend(); ++kv) { - - double EMinusPz = kv->first; - // Do not save electron candidates that - // are not within range - if ( EMinusPz > m_cfg.maxEMinusPz - || EMinusPz < m_cfg.minEMinusPz ){ - continue; + // Sum hadronic final state + vHadronicFinalState += vHadron; + } else { + m_log->trace("Skipping electron in hadronic final state"); } - - // For logging and development - // report the highest E-Pz candidate chosen - if ( first ){ - m_log->trace( "Max E-Pz Candidate:" ); - m_log->trace( "\tE-Pz={}", EMinusPz ); - m_log->trace( "\tScatteredElectron has Pxyz=( {}, {}, {} )", kv->second.getMomentum().x, kv->second.getMomentum().y, kv->second.getMomentum().z ); - first = false; - } - out_electrons->push_back( kv->second ); - } // reverse loop on scatteredElectronsMap - - - // Return Electron candidates ranked - // in order from largest E-Pz to smallest - return out_electrons; - } + } // hadron loop (reconstructed particles) + + // Calculate the E-Pz for this electron + // + hadron final state combination + // For now we keep all electron + // candidates but we will rank them by their E-Pz + double EPz = (vScatteredElectron + vHadronicFinalState).E() - + (vScatteredElectron + vHadronicFinalState).Pz(); + m_log->trace("\tE-Pz={}", EPz); + m_log->trace("\tScatteredElectron has Pxyz=( {}, {}, {} )", e.getMomentum().x, + e.getMomentum().y, e.getMomentum().z); + + // Store the result of this calculation + scatteredElectronsMap[EPz] = e; + } // electron loop + + m_log->trace("Selecting candidates with {} < E-Pz < {}", m_cfg.minEMinusPz, m_cfg.maxEMinusPz); + + // map sorts in descending order by default + // sort by descending + bool first = true; + // for (auto kv : scatteredElectronsMap) { + for (auto kv = scatteredElectronsMap.rbegin(); kv != scatteredElectronsMap.rend(); ++kv) { + + double EMinusPz = kv->first; + // Do not save electron candidates that + // are not within range + if (EMinusPz > m_cfg.maxEMinusPz || EMinusPz < m_cfg.minEMinusPz) { + continue; + } + + // For logging and development + // report the highest E-Pz candidate chosen + if (first) { + m_log->trace("Max E-Pz Candidate:"); + m_log->trace("\tE-Pz={}", EMinusPz); + m_log->trace("\tScatteredElectron has Pxyz=( {}, {}, {} )", kv->second.getMomentum().x, + kv->second.getMomentum().y, kv->second.getMomentum().z); + first = false; + } + out_electrons->push_back(kv->second); + } // reverse loop on scatteredElectronsMap + + // Return Electron candidates ranked + // in order from largest E-Pz to smallest + return out_electrons; +} } // namespace eicrecon diff --git a/src/algorithms/reco/ScatteredElectronsEMinusPz.h b/src/algorithms/reco/ScatteredElectronsEMinusPz.h index 9bad30da7f..3c3d4846ba 100644 --- a/src/algorithms/reco/ScatteredElectronsEMinusPz.h +++ b/src/algorithms/reco/ScatteredElectronsEMinusPz.h @@ -10,22 +10,18 @@ #include "algorithms/reco/ScatteredElectronsEMinusPzConfig.h" #include "algorithms/interfaces/WithPodConfig.h" - namespace eicrecon { - class ScatteredElectronsEMinusPz : public WithPodConfig{ - - public: - - void init(std::shared_ptr& logger); - std::unique_ptr execute( - const edm4eic::ReconstructedParticleCollection *rcparts, - const edm4eic::ReconstructedParticleCollection *rcele - ); +class ScatteredElectronsEMinusPz : public WithPodConfig { - private: - std::shared_ptr m_log; - double m_electron{0.000510998928}, m_pion{0.13957}; +public: + void init(std::shared_ptr& logger); + std::unique_ptr + execute(const edm4eic::ReconstructedParticleCollection* rcparts, + const edm4eic::ReconstructedParticleCollection* rcele); - }; +private: + std::shared_ptr m_log; + double m_electron{0.000510998928}, m_pion{0.13957}; +}; } // namespace eicrecon diff --git a/src/algorithms/reco/ScatteredElectronsEMinusPzConfig.h b/src/algorithms/reco/ScatteredElectronsEMinusPzConfig.h index 58f12d2ded..f8ef3bd5e9 100644 --- a/src/algorithms/reco/ScatteredElectronsEMinusPzConfig.h +++ b/src/algorithms/reco/ScatteredElectronsEMinusPzConfig.h @@ -8,14 +8,13 @@ namespace eicrecon { - struct ScatteredElectronsEMinusPzConfig { +struct ScatteredElectronsEMinusPzConfig { - // For now these are wide open - // In the future the cut should depend - // on the generator settings - float minEMinusPz = 0.0; // GeV - float maxEMinusPz = 1000000.0; // GeV + // For now these are wide open + // In the future the cut should depend + // on the generator settings + float minEMinusPz = 0.0; // GeV + float maxEMinusPz = 1000000.0; // GeV +}; - }; - -} // end eicrecon namespace +} // namespace eicrecon diff --git a/src/algorithms/reco/ScatteredElectronsTruth.cc b/src/algorithms/reco/ScatteredElectronsTruth.cc index 3fead2e236..fe0a35ea0c 100644 --- a/src/algorithms/reco/ScatteredElectronsTruth.cc +++ b/src/algorithms/reco/ScatteredElectronsTruth.cc @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LGPL-3.0-or-later - // Copyright (C) 2024 Daniel Brandenburg +// Copyright (C) 2024 Daniel Brandenburg #include #include @@ -22,12 +22,12 @@ using ROOT::Math::PxPyPzMVector; namespace eicrecon { - /** +/** * @brief Initialize ScatteredElectronsTruth algorithm */ - void ScatteredElectronsTruth::init() { } +void ScatteredElectronsTruth::init() {} - /** +/** * @brief Selects the scattered electron based * on TRUTH information (Mc particle info). * Returns a collection of reconstructed particles @@ -38,89 +38,84 @@ namespace eicrecon { * MCRecoParticleAssociationCollection * @param output - ReconstructedParticleCollection */ - void ScatteredElectronsTruth::process( - const ScatteredElectronsTruth::Input& input, - const ScatteredElectronsTruth::Output& output) const { - - // get our input and outputs - const auto [mcparts, rcparts, rcassoc] = input; - auto [output_electrons] = output; - output_electrons->setSubsetCollection(); - - - // Get first scattered electron - const auto ef_coll = find_first_scattered_electron(mcparts); - if (ef_coll.size() == 0) { - trace("No truth scattered electron found"); - return; +void ScatteredElectronsTruth::process(const ScatteredElectronsTruth::Input& input, + const ScatteredElectronsTruth::Output& output) const { + + // get our input and outputs + const auto [mcparts, rcparts, rcassoc] = input; + auto [output_electrons] = output; + output_electrons->setSubsetCollection(); + + // Get first scattered electron + const auto ef_coll = find_first_scattered_electron(mcparts); + if (ef_coll.size() == 0) { + trace("No truth scattered electron found"); + return; + } + + // Associate first scattered electron + // with reconstructed electron + auto ef_assoc = rcassoc->begin(); + for (; ef_assoc != rcassoc->end(); ++ef_assoc) { + if (ef_assoc->getSim().getObjectID() == ef_coll[0].getObjectID()) { + break; } - - // Associate first scattered electron - // with reconstructed electron - auto ef_assoc = rcassoc->begin(); - for (; ef_assoc != rcassoc->end(); ++ef_assoc) { - if (ef_assoc->getSim().getObjectID() == ef_coll[0].getObjectID()) { - break; - } - } - - // Check to see if the associated reconstructed - // particle is available - if (!(ef_assoc != rcassoc->end())) { - trace("Truth scattered electron not in reconstructed particles"); - return; + } + + // Check to see if the associated reconstructed + // particle is available + if (!(ef_assoc != rcassoc->end())) { + trace("Truth scattered electron not in reconstructed particles"); + return; + } + + // Get the reconstructed electron object + const auto ef_rc{ef_assoc->getRec()}; + const auto ef_rc_id{ef_rc.getObjectID()}; + + // Use these to compute the E-Pz + // This is for development of the EMinusPz + // algorithm + PxPyPzMVector vScatteredElectron; + PxPyPzMVector vHadronicFinalState; + PxPyPzMVector vHadron; + + // Loop over reconstructed particles to + // get outgoing scattered electron. + // Use the true scattered electron from the + // MC information + std::vector electrons; + for (const auto& p : *rcparts) { + if (p.getObjectID() == ef_rc_id) { + + output_electrons->push_back(p); + vScatteredElectron.SetCoordinates(p.getMomentum().x, p.getMomentum().y, p.getMomentum().z, + m_electron); + electrons.emplace_back(p.getMomentum().x, p.getMomentum().y, p.getMomentum().z, + p.getEnergy()); + // break; NOTE: if we are not computing E-Pz + // we can safely break here and save precious CPUs + } else { + // Compute the sum hadronic final state + vHadron.SetCoordinates(p.getMomentum().x, p.getMomentum().y, p.getMomentum().z, m_pion); + vHadronicFinalState += vHadron; } - - // Get the reconstructed electron object - const auto ef_rc{ef_assoc->getRec()}; - const auto ef_rc_id{ef_rc.getObjectID()}; - - // Use these to compute the E-Pz - // This is for development of the EMinusPz - // algorithm - PxPyPzMVector vScatteredElectron; - PxPyPzMVector vHadronicFinalState; - PxPyPzMVector vHadron; - - // Loop over reconstructed particles to - // get outgoing scattered electron. - // Use the true scattered electron from the - // MC information - std::vector electrons; - for (const auto& p: *rcparts) { - if (p.getObjectID() == ef_rc_id) { - - output_electrons->push_back( p ); - vScatteredElectron.SetCoordinates( p.getMomentum().x, p.getMomentum().y, p.getMomentum().z, m_electron ); - electrons.emplace_back(p.getMomentum().x, p.getMomentum().y, p.getMomentum().z, p.getEnergy()); - // break; NOTE: if we are not computing E-Pz - // we can safely break here and save precious CPUs - } else { - // Compute the sum hadronic final state - vHadron.SetCoordinates( p.getMomentum().x, p.getMomentum().y, p.getMomentum().z, m_pion ); - vHadronicFinalState += vHadron; - } - } - - // If no scattered electron was found, too bad - if (electrons.size() == 0) { - trace("No Truth scattered electron found"); - return; - } - - // Just for debug/development - // report the computed E-Pz for the chosen electron - double EPz = (vScatteredElectron+vHadronicFinalState).E() - - (vScatteredElectron+vHadronicFinalState).Pz(); - trace("We found {} scattered electrons using Truth association", electrons.size()); - trace( "TRUTH scattered electron has E-Pz = {}", EPz ); - trace( - "TRUTH scattered electron has Pxyz=( {}, {}, {} ) and E/p = {}", - electrons[0].Px(), - electrons[0].Py(), - electrons[0].Pz(), - (electrons[0].E()/electrons[0].P()) - ); - } // process + } + + // If no scattered electron was found, too bad + if (electrons.size() == 0) { + trace("No Truth scattered electron found"); + return; + } + + // Just for debug/development + // report the computed E-Pz for the chosen electron + double EPz = (vScatteredElectron + vHadronicFinalState).E() - + (vScatteredElectron + vHadronicFinalState).Pz(); + trace("We found {} scattered electrons using Truth association", electrons.size()); + trace("TRUTH scattered electron has E-Pz = {}", EPz); + trace("TRUTH scattered electron has Pxyz=( {}, {}, {} ) and E/p = {}", electrons[0].Px(), + electrons[0].Py(), electrons[0].Pz(), (electrons[0].E() / electrons[0].P())); +} // process } // namespace eicrecon diff --git a/src/algorithms/reco/ScatteredElectronsTruth.h b/src/algorithms/reco/ScatteredElectronsTruth.h index 291d6cc3b3..157f9a44e4 100644 --- a/src/algorithms/reco/ScatteredElectronsTruth.h +++ b/src/algorithms/reco/ScatteredElectronsTruth.h @@ -10,35 +10,28 @@ #include #include - namespace eicrecon { - using ScatteredElectronsTruthAlgorithm = algorithms::Algorithm< - algorithms::Input< - edm4hep::MCParticleCollection, - edm4eic::ReconstructedParticleCollection, - edm4eic::MCRecoParticleAssociationCollection - >, - algorithms::Output< - edm4eic::ReconstructedParticleCollection - > - >; - - class ScatteredElectronsTruth - : public ScatteredElectronsTruthAlgorithm { - - public: - ScatteredElectronsTruth(std::string_view name) +using ScatteredElectronsTruthAlgorithm = algorithms::Algorithm< + algorithms::Input, + algorithms::Output>; + +class ScatteredElectronsTruth : public ScatteredElectronsTruthAlgorithm { + +public: + ScatteredElectronsTruth(std::string_view name) : ScatteredElectronsTruthAlgorithm{name, - {"MCParticles", "inputParticles", "inputAssociations"}, - {"ReconstructedParticles"}, - "Output a list of possible scattered electrons using truth MC Particle associations."} {} + {"MCParticles", "inputParticles", "inputAssociations"}, + {"ReconstructedParticles"}, + "Output a list of possible scattered electrons using " + "truth MC Particle associations."} {} - void init() final; - void process(const Input&, const Output&) const final; + void init() final; + void process(const Input&, const Output&) const final; - private: - double m_proton{0.93827}, m_neutron{0.93957}, m_electron{0.000510998928}, m_pion{0.13957}; - }; +private: + double m_proton{0.93827}, m_neutron{0.93957}, m_electron{0.000510998928}, m_pion{0.13957}; +}; } // namespace eicrecon diff --git a/src/algorithms/reco/TransformBreitFrame.cc b/src/algorithms/reco/TransformBreitFrame.cc index c8eff8221d..534837d0ec 100644 --- a/src/algorithms/reco/TransformBreitFrame.cc +++ b/src/algorithms/reco/TransformBreitFrame.cc @@ -20,138 +20,128 @@ namespace eicrecon { - void TransformBreitFrame::init(std::shared_ptr logger) { - - m_log = logger; - m_log->trace("Initialized"); - - } // end 'init(std::shared_ptr)' - - - void TransformBreitFrame::process( - const TransformBreitFrame::Input& input, - const TransformBreitFrame::Output& output - ) const { - // Grab input collections - const auto [mcpart, kine, lab_collection] = input; - auto [breit_collection] = output; - - // Beam momenta extracted from MCParticle - // This is the only place truth information is used! - - // Get incoming electron beam - const auto ei_coll = find_first_beam_electron(mcpart); - if (ei_coll.size() == 0) { - m_log->debug("No beam electron found"); - return; - } - const PxPyPzEVector e_initial( - round_beam_four_momentum( - ei_coll[0].getMomentum(), - m_electron, - {-5.0, -10.0, -18.0}, - 0.0) - ); - - // Get incoming hadron beam - const auto pi_coll = find_first_beam_hadron(mcpart); - if (pi_coll.size() == 0) { - m_log->debug("No beam hadron found"); - return; - } - const PxPyPzEVector p_initial( - round_beam_four_momentum( - pi_coll[0].getMomentum(), - pi_coll[0].getPDG() == 2212 ? m_proton : m_neutron, - {41.0, 100.0, 275.0}, - m_crossingAngle) - ); - - m_log->debug("electron energy, proton energy = {},{}",e_initial.E(),p_initial.E()); - - // Get the event kinematics, set up transform - if (kine->size() == 0) { - m_log->debug("No kinematics found"); - return; - } - - const auto& evt_kin = kine->at(0); - - const auto meas_x = evt_kin.getX(); - const auto meas_Q2 = evt_kin.getQ2(); - - // Use relation to get reconstructed scattered electron - const PxPyPzEVector e_final = edm4hep::utils::detail::p4(evt_kin.getScat(),&edm4hep::utils::UseEnergy); - m_log->debug("scattered electron in lab frame px,py,pz,E = {},{},{},{}", - e_final.Px(),e_final.Py(),e_final.Pz(),e_final.E()); - - // Set up the transformation - const PxPyPzEVector virtual_photon = (e_initial - e_final); - m_log->debug("virtual photon in lab frame px,py,pz,E = {},{},{},{}", - virtual_photon.Px(),virtual_photon.Py(),virtual_photon.Pz(),virtual_photon.E()); - - m_log->debug("x, Q^2 = {},{}",meas_x,meas_Q2); - - // Set up the transformation (boost) to the Breit frame - const auto P3 = p_initial.Vect(); - const auto q3 = virtual_photon.Vect(); - const ROOT::Math::Boost breit(-(2.0*meas_x*P3 + q3)*(1.0/(2.0*meas_x*p_initial.E() + virtual_photon.E()))); - - PxPyPzEVector p_initial_breit = (breit * p_initial); - PxPyPzEVector e_initial_breit = (breit * e_initial); - PxPyPzEVector e_final_breit = (breit * e_final); - PxPyPzEVector virtual_photon_breit = (breit * virtual_photon); - - // Now rotate so the virtual photon momentum is all along the negative z-axis - const auto zhat = -virtual_photon_breit.Vect().Unit(); - const auto yhat = (e_initial_breit.Vect().Cross(e_final_breit.Vect())).Unit(); - const auto xhat = yhat.Cross(zhat); - - const ROOT::Math::Rotation3D breitRotInv(xhat,yhat,zhat); - const ROOT::Math::Rotation3D breitRot = breitRotInv.Inverse(); - - // Diagnostics - p_initial_breit = breitRot*p_initial_breit; - e_initial_breit = breitRot*e_initial_breit; - e_final_breit = breitRot*e_final_breit; - virtual_photon_breit = breitRot*virtual_photon_breit; - - m_log->debug("incoming hadron in Breit frame px,py,pz,E = {},{},{},{}", - p_initial_breit.Px(),p_initial_breit.Py(),p_initial_breit.Pz(),p_initial_breit.E()); - m_log->debug("virtual photon in Breit frame px,py,pz,E = {},{},{},{}", - virtual_photon_breit.Px(),virtual_photon_breit.Py(),virtual_photon_breit.Pz(),virtual_photon_breit.E()); - - // look over the input particles and transform - for (const auto& lab : *lab_collection) { - - // Transform to Breit frame - PxPyPzEVector lab_particle(lab.getMomentum().x,lab.getMomentum().y,lab.getMomentum().z,lab.getEnergy()); - PxPyPzEVector breit_particle = breitRot*(breit*lab_particle); - - // create particle to store in output collection - auto breit_out = breit_collection->create(); - breit_out.setMomentum(edm4hep::Vector3f(breit_particle.Px(), breit_particle.Py(), breit_particle.Pz())); - breit_out.setEnergy(breit_particle.E()); - - // Copy the rest of the particle information - breit_out.setType(lab.getType()); - breit_out.setReferencePoint(lab.getReferencePoint()); - breit_out.setCharge(lab.getCharge()); - breit_out.setMass(lab.getMass()); - breit_out.setGoodnessOfPID(lab.getGoodnessOfPID()); - breit_out.setCovMatrix(lab.getCovMatrix()); - breit_out.setPDG(lab.getPDG()); - breit_out.setStartVertex(lab.getStartVertex()); - breit_out.setParticleIDUsed(lab.getParticleIDUsed()); - - // set up a relation between the lab and Breit frame representations - breit_out.addToParticles( lab ); - - } +void TransformBreitFrame::init(std::shared_ptr logger) { - return; + m_log = logger; + m_log->trace("Initialized"); + +} // end 'init(std::shared_ptr)' - } // end 'process' +void TransformBreitFrame::process(const TransformBreitFrame::Input& input, + const TransformBreitFrame::Output& output) const { + // Grab input collections + const auto [mcpart, kine, lab_collection] = input; + auto [breit_collection] = output; + // Beam momenta extracted from MCParticle + // This is the only place truth information is used! -} // end namespace eicrecon + // Get incoming electron beam + const auto ei_coll = find_first_beam_electron(mcpart); + if (ei_coll.size() == 0) { + m_log->debug("No beam electron found"); + return; + } + const PxPyPzEVector e_initial( + round_beam_four_momentum(ei_coll[0].getMomentum(), m_electron, {-5.0, -10.0, -18.0}, 0.0)); + + // Get incoming hadron beam + const auto pi_coll = find_first_beam_hadron(mcpart); + if (pi_coll.size() == 0) { + m_log->debug("No beam hadron found"); + return; + } + const PxPyPzEVector p_initial(round_beam_four_momentum( + pi_coll[0].getMomentum(), pi_coll[0].getPDG() == 2212 ? m_proton : m_neutron, + {41.0, 100.0, 275.0}, m_crossingAngle)); + + m_log->debug("electron energy, proton energy = {},{}", e_initial.E(), p_initial.E()); + + // Get the event kinematics, set up transform + if (kine->size() == 0) { + m_log->debug("No kinematics found"); + return; + } + + const auto& evt_kin = kine->at(0); + + const auto meas_x = evt_kin.getX(); + const auto meas_Q2 = evt_kin.getQ2(); + + // Use relation to get reconstructed scattered electron + const PxPyPzEVector e_final = + edm4hep::utils::detail::p4(evt_kin.getScat(), &edm4hep::utils::UseEnergy); + m_log->debug("scattered electron in lab frame px,py,pz,E = {},{},{},{}", e_final.Px(), + e_final.Py(), e_final.Pz(), e_final.E()); + + // Set up the transformation + const PxPyPzEVector virtual_photon = (e_initial - e_final); + m_log->debug("virtual photon in lab frame px,py,pz,E = {},{},{},{}", virtual_photon.Px(), + virtual_photon.Py(), virtual_photon.Pz(), virtual_photon.E()); + + m_log->debug("x, Q^2 = {},{}", meas_x, meas_Q2); + + // Set up the transformation (boost) to the Breit frame + const auto P3 = p_initial.Vect(); + const auto q3 = virtual_photon.Vect(); + const ROOT::Math::Boost breit(-(2.0 * meas_x * P3 + q3) * + (1.0 / (2.0 * meas_x * p_initial.E() + virtual_photon.E()))); + + PxPyPzEVector p_initial_breit = (breit * p_initial); + PxPyPzEVector e_initial_breit = (breit * e_initial); + PxPyPzEVector e_final_breit = (breit * e_final); + PxPyPzEVector virtual_photon_breit = (breit * virtual_photon); + + // Now rotate so the virtual photon momentum is all along the negative z-axis + const auto zhat = -virtual_photon_breit.Vect().Unit(); + const auto yhat = (e_initial_breit.Vect().Cross(e_final_breit.Vect())).Unit(); + const auto xhat = yhat.Cross(zhat); + + const ROOT::Math::Rotation3D breitRotInv(xhat, yhat, zhat); + const ROOT::Math::Rotation3D breitRot = breitRotInv.Inverse(); + + // Diagnostics + p_initial_breit = breitRot * p_initial_breit; + e_initial_breit = breitRot * e_initial_breit; + e_final_breit = breitRot * e_final_breit; + virtual_photon_breit = breitRot * virtual_photon_breit; + + m_log->debug("incoming hadron in Breit frame px,py,pz,E = {},{},{},{}", p_initial_breit.Px(), + p_initial_breit.Py(), p_initial_breit.Pz(), p_initial_breit.E()); + m_log->debug("virtual photon in Breit frame px,py,pz,E = {},{},{},{}", virtual_photon_breit.Px(), + virtual_photon_breit.Py(), virtual_photon_breit.Pz(), virtual_photon_breit.E()); + + // look over the input particles and transform + for (const auto& lab : *lab_collection) { + + // Transform to Breit frame + PxPyPzEVector lab_particle(lab.getMomentum().x, lab.getMomentum().y, lab.getMomentum().z, + lab.getEnergy()); + PxPyPzEVector breit_particle = breitRot * (breit * lab_particle); + + // create particle to store in output collection + auto breit_out = breit_collection->create(); + breit_out.setMomentum( + edm4hep::Vector3f(breit_particle.Px(), breit_particle.Py(), breit_particle.Pz())); + breit_out.setEnergy(breit_particle.E()); + + // Copy the rest of the particle information + breit_out.setType(lab.getType()); + breit_out.setReferencePoint(lab.getReferencePoint()); + breit_out.setCharge(lab.getCharge()); + breit_out.setMass(lab.getMass()); + breit_out.setGoodnessOfPID(lab.getGoodnessOfPID()); + breit_out.setCovMatrix(lab.getCovMatrix()); + breit_out.setPDG(lab.getPDG()); + breit_out.setStartVertex(lab.getStartVertex()); + breit_out.setParticleIDUsed(lab.getParticleIDUsed()); + + // set up a relation between the lab and Breit frame representations + breit_out.addToParticles(lab); + } + + return; + +} // end 'process' + +} // end namespace eicrecon diff --git a/src/algorithms/reco/TransformBreitFrame.h b/src/algorithms/reco/TransformBreitFrame.h index af654c2772..5f19d74058 100644 --- a/src/algorithms/reco/TransformBreitFrame.h +++ b/src/algorithms/reco/TransformBreitFrame.h @@ -16,42 +16,31 @@ namespace eicrecon { - using TransformBreitFrameAlgorithm = algorithms::Algorithm< - algorithms::Input< - edm4hep::MCParticleCollection, - edm4eic::InclusiveKinematicsCollection, - edm4eic::ReconstructedParticleCollection - >, - algorithms::Output< - edm4eic::ReconstructedParticleCollection - > - >; +using TransformBreitFrameAlgorithm = algorithms::Algorithm< + algorithms::Input, + algorithms::Output>; - class TransformBreitFrame - : public TransformBreitFrameAlgorithm, - public WithPodConfig { +class TransformBreitFrame : public TransformBreitFrameAlgorithm, public WithPodConfig { - public: +public: + TransformBreitFrame(std::string_view name) + : TransformBreitFrameAlgorithm{ + name, + {"inputMCParticles", "inputInclusiveKinematics", "inputReconstructedParticles"}, + {"outputReconstructedParticles"}, + "Transforms a set of particles from the lab frame to the Breit frame"} {} - TransformBreitFrame(std::string_view name) : - TransformBreitFrameAlgorithm { - name, - {"inputMCParticles", "inputInclusiveKinematics", "inputReconstructedParticles"}, - {"outputReconstructedParticles"}, - "Transforms a set of particles from the lab frame to the Breit frame" - } {} + // algorithm initialization + void init(std::shared_ptr logger); - // algorithm initialization - void init(std::shared_ptr logger); + // run algorithm + void process(const Input&, const Output&) const final; - // run algorithm - void process(const Input&, const Output&) const final; +private: + std::shared_ptr m_log; + double m_proton{0.93827}, m_neutron{0.93957}, m_electron{0.000510998928}, m_crossingAngle{-0.025}; - private: +}; // end TransformBreitFrame definition - std::shared_ptr m_log; - double m_proton{0.93827}, m_neutron{0.93957}, m_electron{0.000510998928}, m_crossingAngle{-0.025}; - - }; // end TransformBreitFrame definition - -} // end eicrecon namespace +} // namespace eicrecon diff --git a/src/algorithms/tracking/ActsGeometryProvider.cc b/src/algorithms/tracking/ActsGeometryProvider.cc index bc54725632..a1867fa3c7 100644 --- a/src/algorithms/tracking/ActsGeometryProvider.cc +++ b/src/algorithms/tracking/ActsGeometryProvider.cc @@ -36,162 +36,143 @@ #include template -struct fmt::formatter< - T, - std::enable_if_t< - std::is_base_of_v, T>, - char - > -> : fmt::ostream_formatter {}; +struct fmt::formatter, T>, char>> + : fmt::ostream_formatter {}; #endif // FMT_VERSION >= 90000 -void ActsGeometryProvider::initialize(const dd4hep::Detector* dd4hep_geo, - std::string material_file, +void ActsGeometryProvider::initialize(const dd4hep::Detector* dd4hep_geo, std::string material_file, std::shared_ptr log, std::shared_ptr init_log) { - // LOGGING - m_log = log; - m_init_log = init_log; - - m_init_log->debug("ActsGeometryProvider initializing..."); - - m_init_log->debug("Set TGeoManager and acts_init_log_level log levels"); - // Turn off TGeo printouts if appropriate for the msg level - if (m_log->level() >= (int) spdlog::level::info) { - TGeoManager::SetVerboseLevel(0); - } - - // Set ACTS logging level - auto acts_init_log_level = eicrecon::SpdlogToActsLevel(m_init_log->level()); - - m_dd4hepDetector = dd4hep_geo; - - // Load ACTS materials maps - std::shared_ptr materialDeco{nullptr}; - if (!material_file.empty()) { - m_init_log->info("loading materials map from file: '{}'", material_file); - // Set up the converter first - Acts::MaterialMapJsonConverter::Config jsonGeoConvConfig; - // Set up the json-based decorator - materialDeco = std::make_shared(jsonGeoConvConfig, material_file, acts_init_log_level); - } - - // Geometry identifier hook to write detector ID to extra field - class ConvertDD4hepDetectorGeometryIdentifierHook: public Acts::GeometryIdentifierHook { - Acts::GeometryIdentifier decorateIdentifier( - Acts::GeometryIdentifier identifier, const Acts::Surface& surface) const { - const auto* dd4hep_det_element = - dynamic_cast(surface.associatedDetectorElement()); - if (dd4hep_det_element == nullptr) { - return identifier; - } - // set 8-bit extra field to 8-bit DD4hep detector ID - return identifier.setExtra(0xff & dd4hep_det_element->identifier()); - }; + // LOGGING + m_log = log; + m_init_log = init_log; + + m_init_log->debug("ActsGeometryProvider initializing..."); + + m_init_log->debug("Set TGeoManager and acts_init_log_level log levels"); + // Turn off TGeo printouts if appropriate for the msg level + if (m_log->level() >= (int)spdlog::level::info) { + TGeoManager::SetVerboseLevel(0); + } + + // Set ACTS logging level + auto acts_init_log_level = eicrecon::SpdlogToActsLevel(m_init_log->level()); + + m_dd4hepDetector = dd4hep_geo; + + // Load ACTS materials maps + std::shared_ptr materialDeco{nullptr}; + if (!material_file.empty()) { + m_init_log->info("loading materials map from file: '{}'", material_file); + // Set up the converter first + Acts::MaterialMapJsonConverter::Config jsonGeoConvConfig; + // Set up the json-based decorator + materialDeco = std::make_shared( + jsonGeoConvConfig, material_file, acts_init_log_level); + } + + // Geometry identifier hook to write detector ID to extra field + class ConvertDD4hepDetectorGeometryIdentifierHook : public Acts::GeometryIdentifierHook { + Acts::GeometryIdentifier decorateIdentifier(Acts::GeometryIdentifier identifier, + const Acts::Surface& surface) const { + const auto* dd4hep_det_element = + dynamic_cast(surface.associatedDetectorElement()); + if (dd4hep_det_element == nullptr) { + return identifier; + } + // set 8-bit extra field to 8-bit DD4hep detector ID + return identifier.setExtra(0xff & dd4hep_det_element->identifier()); }; - auto geometryIdHook = std::make_shared(); - - // Convert DD4hep geometry to ACTS - m_init_log->info("Converting DD4Hep geometry to ACTS..."); - auto logger = eicrecon::getSpdlogLogger("CONV", m_log); - Acts::BinningType bTypePhi = Acts::equidistant; - Acts::BinningType bTypeR = Acts::equidistant; - Acts::BinningType bTypeZ = Acts::equidistant; - double layerEnvelopeR = Acts::UnitConstants::mm; - double layerEnvelopeZ = Acts::UnitConstants::mm; - double defaultLayerThickness = Acts::UnitConstants::fm; - using Acts::sortDetElementsByID; - - try { - m_trackingGeo = Acts::convertDD4hepDetector( - m_dd4hepDetector->world(), - *logger, - bTypePhi, - bTypeR, - bTypeZ, - layerEnvelopeR, - layerEnvelopeZ, - defaultLayerThickness, - sortDetElementsByID, - m_trackingGeoCtx, - materialDeco, - geometryIdHook); - } - catch(std::exception &ex) { - m_init_log->error("Error during DD4Hep -> ACTS geometry conversion: {}", ex.what()); - m_init_log->info ("Set parameter acts::InitLogLevel=trace to see conversion info and possibly identify failing geometry"); - throw JException(ex.what()); - } - - m_init_log->info("DD4Hep geometry converted!"); - - // Visit surfaces - m_init_log->info("Checking surfaces..."); - if (m_trackingGeo) { - // Write tracking geometry to collection of obj or ply files - const Acts::TrackingVolume* world = m_trackingGeo->highestTrackingVolume(); - if (m_objWriteIt) { - m_init_log->info("Writing obj files to {}...", m_outputDir); - Acts::ObjVisualization3D objVis; - Acts::GeometryView3D::drawTrackingVolume( - objVis, *world, m_trackingGeoCtx, - m_containerView, m_volumeView, m_passiveView, m_sensitiveView, m_gridView, - m_objWriteIt, m_outputTag, m_outputDir - ); - } - if (m_plyWriteIt) { - m_init_log->info("Writing ply files to {}...", m_outputDir); - Acts::PlyVisualization3D plyVis; - Acts::GeometryView3D::drawTrackingVolume( - plyVis, *world, m_trackingGeoCtx, - m_containerView, m_volumeView, m_passiveView, m_sensitiveView, m_gridView, - m_plyWriteIt, m_outputTag, m_outputDir - ); - } - - m_init_log->debug("visiting all the surfaces "); - m_trackingGeo->visitSurfaces([this](const Acts::Surface *surface) { - // for now we just require a valid surface - if (surface == nullptr) { - m_init_log->info("no surface??? "); - return; - } - const auto *det_element = - dynamic_cast(surface->associatedDetectorElement()); - - if (det_element == nullptr) { - m_init_log->error("invalid det_element!!! det_element == nullptr "); - return; - } - - // more verbose output is lower enum value - m_init_log->debug(" det_element->identifier() = {} ", det_element->identifier()); - auto volman = m_dd4hepDetector->volumeManager(); - auto *vol_ctx = volman.lookupContext(det_element->identifier()); - auto vol_id = vol_ctx->identifier; - - if (m_init_log->level() <= spdlog::level::debug) { - auto de = vol_ctx->element; - m_init_log->debug(" de.path = {}", de.path()); - m_init_log->debug(" de.placementPath = {}", de.placementPath()); - } - - this->m_surfaces.insert_or_assign(vol_id, surface); - }); - } - else { - m_init_log->error("m_trackingGeo==null why am I still alive???"); + }; + auto geometryIdHook = std::make_shared(); + + // Convert DD4hep geometry to ACTS + m_init_log->info("Converting DD4Hep geometry to ACTS..."); + auto logger = eicrecon::getSpdlogLogger("CONV", m_log); + Acts::BinningType bTypePhi = Acts::equidistant; + Acts::BinningType bTypeR = Acts::equidistant; + Acts::BinningType bTypeZ = Acts::equidistant; + double layerEnvelopeR = Acts::UnitConstants::mm; + double layerEnvelopeZ = Acts::UnitConstants::mm; + double defaultLayerThickness = Acts::UnitConstants::fm; + using Acts::sortDetElementsByID; + + try { + m_trackingGeo = Acts::convertDD4hepDetector(m_dd4hepDetector->world(), *logger, bTypePhi, + bTypeR, bTypeZ, layerEnvelopeR, layerEnvelopeZ, + defaultLayerThickness, sortDetElementsByID, + m_trackingGeoCtx, materialDeco, geometryIdHook); + } catch (std::exception& ex) { + m_init_log->error("Error during DD4Hep -> ACTS geometry conversion: {}", ex.what()); + m_init_log->info("Set parameter acts::InitLogLevel=trace to see conversion info and possibly " + "identify failing geometry"); + throw JException(ex.what()); + } + + m_init_log->info("DD4Hep geometry converted!"); + + // Visit surfaces + m_init_log->info("Checking surfaces..."); + if (m_trackingGeo) { + // Write tracking geometry to collection of obj or ply files + const Acts::TrackingVolume* world = m_trackingGeo->highestTrackingVolume(); + if (m_objWriteIt) { + m_init_log->info("Writing obj files to {}...", m_outputDir); + Acts::ObjVisualization3D objVis; + Acts::GeometryView3D::drawTrackingVolume(objVis, *world, m_trackingGeoCtx, m_containerView, + m_volumeView, m_passiveView, m_sensitiveView, + m_gridView, m_objWriteIt, m_outputTag, m_outputDir); } - - // Load ACTS magnetic field - m_init_log->info("Loading magnetic field..."); - m_magneticField = std::make_shared(m_dd4hepDetector); - Acts::MagneticFieldContext m_fieldctx{eicrecon::BField::BFieldVariant(m_magneticField)}; - auto bCache = m_magneticField->makeCache(m_fieldctx); - for (int z: {0, 500, 1000, 1500, 2000, 3000, 4000}) { - auto b = m_magneticField->getField({0.0, 0.0, double(z)}, bCache).value(); - m_init_log->debug("B(z = {:>5} [mm]) = {} T", z, b.transpose() / Acts::UnitConstants::T); + if (m_plyWriteIt) { + m_init_log->info("Writing ply files to {}...", m_outputDir); + Acts::PlyVisualization3D plyVis; + Acts::GeometryView3D::drawTrackingVolume(plyVis, *world, m_trackingGeoCtx, m_containerView, + m_volumeView, m_passiveView, m_sensitiveView, + m_gridView, m_plyWriteIt, m_outputTag, m_outputDir); } - m_init_log->info("ActsGeometryProvider initialization complete"); + m_init_log->debug("visiting all the surfaces "); + m_trackingGeo->visitSurfaces([this](const Acts::Surface* surface) { + // for now we just require a valid surface + if (surface == nullptr) { + m_init_log->info("no surface??? "); + return; + } + const auto* det_element = + dynamic_cast(surface->associatedDetectorElement()); + + if (det_element == nullptr) { + m_init_log->error("invalid det_element!!! det_element == nullptr "); + return; + } + + // more verbose output is lower enum value + m_init_log->debug(" det_element->identifier() = {} ", det_element->identifier()); + auto volman = m_dd4hepDetector->volumeManager(); + auto* vol_ctx = volman.lookupContext(det_element->identifier()); + auto vol_id = vol_ctx->identifier; + + if (m_init_log->level() <= spdlog::level::debug) { + auto de = vol_ctx->element; + m_init_log->debug(" de.path = {}", de.path()); + m_init_log->debug(" de.placementPath = {}", de.placementPath()); + } + + this->m_surfaces.insert_or_assign(vol_id, surface); + }); + } else { + m_init_log->error("m_trackingGeo==null why am I still alive???"); + } + + // Load ACTS magnetic field + m_init_log->info("Loading magnetic field..."); + m_magneticField = std::make_shared(m_dd4hepDetector); + Acts::MagneticFieldContext m_fieldctx{eicrecon::BField::BFieldVariant(m_magneticField)}; + auto bCache = m_magneticField->makeCache(m_fieldctx); + for (int z : {0, 500, 1000, 1500, 2000, 3000, 4000}) { + auto b = m_magneticField->getField({0.0, 0.0, double(z)}, bCache).value(); + m_init_log->debug("B(z = {:>5} [mm]) = {} T", z, b.transpose() / Acts::UnitConstants::T); + } + + m_init_log->info("ActsGeometryProvider initialization complete"); } diff --git a/src/algorithms/tracking/ActsGeometryProvider.h b/src/algorithms/tracking/ActsGeometryProvider.h index bfe3f6403f..75c77f7fad 100644 --- a/src/algorithms/tracking/ActsGeometryProvider.h +++ b/src/algorithms/tracking/ActsGeometryProvider.h @@ -27,117 +27,117 @@ #include "DD4hepBField.h" namespace dd4hep::rec { - class Surface; +class Surface; } /** Draw the surfaces and save to obj file. * This is useful for debugging the ACTS geometry. The obj file can * be loaded into various tools, such as FreeCAD, for inspection. */ -void draw_surfaces(std::shared_ptr trk_geo, std::shared_ptr init_log, const std::string &fname); +void draw_surfaces(std::shared_ptr trk_geo, + std::shared_ptr init_log, const std::string& fname); class ActsGeometryProvider { public: - ActsGeometryProvider() {} - using VolumeSurfaceMap = std::unordered_map; + ActsGeometryProvider() {} + using VolumeSurfaceMap = std::unordered_map; - virtual void initialize(const dd4hep::Detector* dd4hep_geo, - std::string material_file, - std::shared_ptr log, - std::shared_ptr init_log) final; + virtual void initialize(const dd4hep::Detector* dd4hep_geo, std::string material_file, + std::shared_ptr log, + std::shared_ptr init_log) final; - const dd4hep::Detector* dd4hepDetector() const { return m_dd4hepDetector; } + const dd4hep::Detector* dd4hepDetector() const { return m_dd4hepDetector; } - /** Gets the ACTS tracking geometry. + /** Gets the ACTS tracking geometry. */ - std::shared_ptr trackingGeometry() const { return m_trackingGeo;} + std::shared_ptr trackingGeometry() const { return m_trackingGeo; } - std::shared_ptr getFieldProvider() const { return m_magneticField; } + std::shared_ptr getFieldProvider() const { + return m_magneticField; + } - double centralMagneticField() const { - return m_dd4hepDetector->field().magneticField({0, 0, 0}).z() * (Acts::UnitConstants::T / dd4hep::tesla); - } + double centralMagneticField() const { + return m_dd4hepDetector->field().magneticField({0, 0, 0}).z() * + (Acts::UnitConstants::T / dd4hep::tesla); + } - const VolumeSurfaceMap &surfaceMap() const { return m_surfaces; } + const VolumeSurfaceMap& surfaceMap() const { return m_surfaces; } + std::map getDD4hepSurfaceMap() const { return m_surfaceMap; } - std::map getDD4hepSurfaceMap() const { return m_surfaceMap; } + const Acts::GeometryContext& getActsGeometryContext() const { return m_trackingGeoCtx; } - const Acts::GeometryContext& getActsGeometryContext() const {return m_trackingGeoCtx;} + /// ACTS general logger that is used for running ACTS + std::shared_ptr getActsRelatedLogger() const { return m_log; } - /// ACTS general logger that is used for running ACTS - std::shared_ptr getActsRelatedLogger() const { return m_log; } - - /// Logger that is used for geometry initialization - /// By default its level the same as ACTS general logger (m_log) - /// But it might be customized to solely printout geometry information - std::shared_ptr getActsInitRelatedLogger() const { return m_init_log; } + /// Logger that is used for geometry initialization + /// By default its level the same as ACTS general logger (m_log) + /// But it might be customized to solely printout geometry information + std::shared_ptr getActsInitRelatedLogger() const { return m_init_log; } private: - - /** DD4hep detector interface class. + /** DD4hep detector interface class. * This is the main dd4hep detector handle. * See DD4hep Detector documentation */ - const dd4hep::Detector* m_dd4hepDetector = nullptr; + const dd4hep::Detector* m_dd4hepDetector = nullptr; - /// DD4hep surface map - std::map m_surfaceMap; + /// DD4hep surface map + std::map m_surfaceMap; - /// ACTS Logging Level - Acts::Logging::Level acts_log_level = Acts::Logging::INFO; + /// ACTS Logging Level + Acts::Logging::Level acts_log_level = Acts::Logging::INFO; - /// ACTS Tracking Geometry Context - Acts::GeometryContext m_trackingGeoCtx; + /// ACTS Tracking Geometry Context + Acts::GeometryContext m_trackingGeoCtx; - /// ACTS Tracking Geometry - std::shared_ptr m_trackingGeo{nullptr}; + /// ACTS Tracking Geometry + std::shared_ptr m_trackingGeo{nullptr}; - /// ACTS surface lookup container for hit surfaces that generate smeared hits - VolumeSurfaceMap m_surfaces; + /// ACTS surface lookup container for hit surfaces that generate smeared hits + VolumeSurfaceMap m_surfaces; - /// Acts magnetic field - std::shared_ptr m_magneticField = nullptr; + /// Acts magnetic field + std::shared_ptr m_magneticField = nullptr; - /// ACTS general logger that is used for running ACTS - std::shared_ptr m_log; + /// ACTS general logger that is used for running ACTS + std::shared_ptr m_log; - /// Logger that is used for geometry initialization - /// By default its level the same as ACTS general logger (m_log) - /// But it might be customized to solely printout geometry information - std::shared_ptr m_init_log; + /// Logger that is used for geometry initialization + /// By default its level the same as ACTS general logger (m_log) + /// But it might be customized to solely printout geometry information + std::shared_ptr m_init_log; - /// Configuration for obj export - Acts::ViewConfig m_containerView{{220, 220, 220}}; - Acts::ViewConfig m_volumeView{{220, 220, 0}}; - Acts::ViewConfig m_sensitiveView{{0, 180, 240}}; - Acts::ViewConfig m_passiveView{{240, 280, 0}}; - Acts::ViewConfig m_gridView{{220, 0, 0}}; - bool m_objWriteIt{false}; - bool m_plyWriteIt{false}; - std::string m_outputTag{""}; - std::string m_outputDir{""}; + /// Configuration for obj export + Acts::ViewConfig m_containerView{{220, 220, 220}}; + Acts::ViewConfig m_volumeView{{220, 220, 0}}; + Acts::ViewConfig m_sensitiveView{{0, 180, 240}}; + Acts::ViewConfig m_passiveView{{240, 280, 0}}; + Acts::ViewConfig m_gridView{{220, 0, 0}}; + bool m_objWriteIt{false}; + bool m_plyWriteIt{false}; + std::string m_outputTag{""}; + std::string m_outputDir{""}; public: - void setObjWriteIt(bool writeit) { m_objWriteIt = writeit; } - bool getObjWriteIt() const { return m_objWriteIt; } - void setPlyWriteIt(bool writeit) { m_plyWriteIt = writeit; } - bool getPlyWriteIt() const { return m_plyWriteIt; } - - void setOutputTag(std::string tag) { m_outputTag = tag; } - std::string getOutputTag() const { return m_outputTag; } - void setOutputDir(std::string dir) { m_outputDir = dir; } - std::string getOutputDir() const { return m_outputDir; } - - void setContainerView(std::array view) { m_containerView = Acts::ViewConfig{view}; } - const Acts::ViewConfig& getContainerView() const { return m_containerView; } - void setVolumeView(std::array view) { m_volumeView = Acts::ViewConfig{view}; } - const Acts::ViewConfig& getVolumeView() const { return m_volumeView; } - void setSensitiveView(std::array view) { m_sensitiveView = Acts::ViewConfig{view}; } - const Acts::ViewConfig& getSensitiveView() const { return m_sensitiveView; } - void setPassiveView(std::array view) { m_passiveView = Acts::ViewConfig{view}; } - const Acts::ViewConfig& getPassiveView() const { return m_passiveView; } - void setGridView(std::array view) { m_gridView = Acts::ViewConfig{view}; } - const Acts::ViewConfig& getGridView() const { return m_gridView; } - + void setObjWriteIt(bool writeit) { m_objWriteIt = writeit; } + bool getObjWriteIt() const { return m_objWriteIt; } + void setPlyWriteIt(bool writeit) { m_plyWriteIt = writeit; } + bool getPlyWriteIt() const { return m_plyWriteIt; } + + void setOutputTag(std::string tag) { m_outputTag = tag; } + std::string getOutputTag() const { return m_outputTag; } + void setOutputDir(std::string dir) { m_outputDir = dir; } + std::string getOutputDir() const { return m_outputDir; } + + void setContainerView(std::array view) { m_containerView = Acts::ViewConfig{view}; } + const Acts::ViewConfig& getContainerView() const { return m_containerView; } + void setVolumeView(std::array view) { m_volumeView = Acts::ViewConfig{view}; } + const Acts::ViewConfig& getVolumeView() const { return m_volumeView; } + void setSensitiveView(std::array view) { m_sensitiveView = Acts::ViewConfig{view}; } + const Acts::ViewConfig& getSensitiveView() const { return m_sensitiveView; } + void setPassiveView(std::array view) { m_passiveView = Acts::ViewConfig{view}; } + const Acts::ViewConfig& getPassiveView() const { return m_passiveView; } + void setGridView(std::array view) { m_gridView = Acts::ViewConfig{view}; } + const Acts::ViewConfig& getGridView() const { return m_gridView; } }; diff --git a/src/algorithms/tracking/CKFTracking.cc b/src/algorithms/tracking/CKFTracking.cc index 44ce50f62f..b26fdec22f 100644 --- a/src/algorithms/tracking/CKFTracking.cc +++ b/src/algorithms/tracking/CKFTracking.cc @@ -57,450 +57,415 @@ namespace eicrecon { - using namespace Acts::UnitLiterals; - - #if EDM4EIC_VERSION_MAJOR >= 5 - // This array relates the Acts and EDM4eic covariance matrices, including - // the unit conversion to get from Acts units into EDM4eic units. - // - // Note: std::map is not constexpr, so we use a constexpr std::array - // std::array initialization need double braces since arrays are aggregates - // ref: https://en.cppreference.com/w/cpp/language/aggregate_initialization - static constexpr std::array, 6> edm4eic_indexed_units{{ - {Acts::eBoundLoc0, Acts::UnitConstants::mm}, - {Acts::eBoundLoc1, Acts::UnitConstants::mm}, - {Acts::eBoundPhi, 1.}, - {Acts::eBoundTheta, 1.}, - {Acts::eBoundQOverP, 1. / Acts::UnitConstants::GeV}, - {Acts::eBoundTime, Acts::UnitConstants::ns} - }}; - #endif - - CKFTracking::CKFTracking() { - } - - void CKFTracking::init(std::shared_ptr geo_svc, std::shared_ptr log) { - m_log = log; - m_acts_logger = eicrecon::getSpdlogLogger("CKF", m_log); +using namespace Acts::UnitLiterals; - m_geoSvc = geo_svc; - - m_BField = std::dynamic_pointer_cast(m_geoSvc->getFieldProvider()); - m_fieldctx = eicrecon::BField::BFieldVariant(m_BField); +#if EDM4EIC_VERSION_MAJOR >= 5 +// This array relates the Acts and EDM4eic covariance matrices, including +// the unit conversion to get from Acts units into EDM4eic units. +// +// Note: std::map is not constexpr, so we use a constexpr std::array +// std::array initialization need double braces since arrays are aggregates +// ref: https://en.cppreference.com/w/cpp/language/aggregate_initialization +static constexpr std::array, 6> edm4eic_indexed_units{ + {{Acts::eBoundLoc0, Acts::UnitConstants::mm}, + {Acts::eBoundLoc1, Acts::UnitConstants::mm}, + {Acts::eBoundPhi, 1.}, + {Acts::eBoundTheta, 1.}, + {Acts::eBoundQOverP, 1. / Acts::UnitConstants::GeV}, + {Acts::eBoundTime, Acts::UnitConstants::ns}}}; +#endif - // eta bins, chi2 and #sourclinks per surface cutoffs - m_sourcelinkSelectorCfg = { - {Acts::GeometryIdentifier(), - {m_cfg.etaBins, m_cfg.chi2CutOff, - {m_cfg.numMeasurementsCutOff.begin(), m_cfg.numMeasurementsCutOff.end()} - } - }, - }; - m_trackFinderFunc = CKFTracking::makeCKFTrackingFunction(m_geoSvc->trackingGeometry(), m_BField, logger()); +CKFTracking::CKFTracking() {} + +void CKFTracking::init(std::shared_ptr geo_svc, + std::shared_ptr log) { + m_log = log; + m_acts_logger = eicrecon::getSpdlogLogger("CKF", m_log); + + m_geoSvc = geo_svc; + + m_BField = + std::dynamic_pointer_cast(m_geoSvc->getFieldProvider()); + m_fieldctx = eicrecon::BField::BFieldVariant(m_BField); + + // eta bins, chi2 and #sourclinks per surface cutoffs + m_sourcelinkSelectorCfg = { + {Acts::GeometryIdentifier(), + {m_cfg.etaBins, + m_cfg.chi2CutOff, + {m_cfg.numMeasurementsCutOff.begin(), m_cfg.numMeasurementsCutOff.end()}}}, + }; + m_trackFinderFunc = + CKFTracking::makeCKFTrackingFunction(m_geoSvc->trackingGeometry(), m_BField, logger()); +} + +std::tuple, + std::unique_ptr, + std::unique_ptr, std::vector, + std::vector> +CKFTracking::process(const edm4eic::Measurement2DCollection& meas2Ds, + const edm4eic::TrackParametersCollection& init_trk_params) { + + // create sourcelink and measurement containers + auto measurements = std::make_shared(); + + // need list here for stable addresses + std::list sourceLinkStorage; + ActsExamples::IndexSourceLinkContainer src_links; + src_links.reserve(meas2Ds.size()); + std::size_t hit_index = 0; + + for (const auto& meas2D : meas2Ds) { + + // --follow example from ACTS to create source links + sourceLinkStorage.emplace_back(meas2D.getSurface(), hit_index); + ActsExamples::IndexSourceLink& sourceLink = sourceLinkStorage.back(); + // Add to output containers: + // index map and source link container are geometry-ordered. + // since the input is also geometry-ordered, new items can + // be added at the end. + src_links.insert(src_links.end(), sourceLink); + // --- + // Create ACTS measurements + Acts::Vector2 loc = Acts::Vector2::Zero(); + loc[Acts::eBoundLoc0] = meas2D.getLoc().a; + loc[Acts::eBoundLoc1] = meas2D.getLoc().b; + + Acts::SquareMatrix2 cov = Acts::SquareMatrix2::Zero(); + cov(0, 0) = meas2D.getCovariance().xx; + cov(1, 1) = meas2D.getCovariance().yy; + cov(0, 1) = meas2D.getCovariance().xy; + cov(1, 0) = meas2D.getCovariance().xy; + + auto measurement = Acts::makeMeasurement(Acts::SourceLink{sourceLink}, loc, cov, + Acts::eBoundLoc0, Acts::eBoundLoc1); + measurements->emplace_back(std::move(measurement)); + + hit_index++; + } + + ActsExamples::TrackParametersContainer acts_init_trk_params; + for (const auto& track_parameter : init_trk_params) { + + Acts::BoundVector params; + params(Acts::eBoundLoc0) = + track_parameter.getLoc().a * Acts::UnitConstants::mm; // cylinder radius + params(Acts::eBoundLoc1) = + track_parameter.getLoc().b * Acts::UnitConstants::mm; // cylinder length + params(Acts::eBoundPhi) = track_parameter.getPhi(); + params(Acts::eBoundTheta) = track_parameter.getTheta(); + params(Acts::eBoundQOverP) = track_parameter.getQOverP() / Acts::UnitConstants::GeV; + params(Acts::eBoundTime) = track_parameter.getTime() * Acts::UnitConstants::ns; + + double charge = std::copysign(1., track_parameter.getQOverP()); + + Acts::BoundSquareMatrix cov = Acts::BoundSquareMatrix::Zero(); +#if EDM4EIC_VERSION_MAJOR >= 5 + for (size_t i = 0; const auto& [a, x] : edm4eic_indexed_units) { + for (size_t j = 0; const auto& [b, y] : edm4eic_indexed_units) { + cov(a, b) = track_parameter.getCovariance()(i, j) * x * y; + ++j; + } + ++i; } +#else + cov(Acts::eBoundLoc0, Acts::eBoundLoc0) = std::pow(track_parameter.getLocError().xx, 2) * + Acts::UnitConstants::mm * Acts::UnitConstants::mm; + cov(Acts::eBoundLoc1, Acts::eBoundLoc1) = std::pow(track_parameter.getLocError().yy, 2) * + Acts::UnitConstants::mm * Acts::UnitConstants::mm; + cov(Acts::eBoundTheta, Acts::eBoundTheta) = std::pow(track_parameter.getMomentumError().xx, 2); + cov(Acts::eBoundPhi, Acts::eBoundPhi) = std::pow(track_parameter.getMomentumError().yy, 2); + cov(Acts::eBoundQOverP, Acts::eBoundQOverP) = + std::pow(track_parameter.getMomentumError().zz, 2) / + (Acts::UnitConstants::GeV * Acts::UnitConstants::GeV); + cov(Acts::eBoundTime, Acts::eBoundTime) = std::pow(track_parameter.getTimeError(), 2) * + Acts::UnitConstants::ns * Acts::UnitConstants::ns; +#endif - std::tuple< - std::unique_ptr, - std::unique_ptr, - std::unique_ptr, - std::vector, - std::vector - > - CKFTracking::process(const edm4eic::Measurement2DCollection& meas2Ds, - const edm4eic::TrackParametersCollection &init_trk_params) { - - - // create sourcelink and measurement containers - auto measurements = std::make_shared(); - - // need list here for stable addresses - std::list sourceLinkStorage; - ActsExamples::IndexSourceLinkContainer src_links; - src_links.reserve(meas2Ds.size()); - std::size_t hit_index = 0; - - - for (const auto& meas2D : meas2Ds) { - - // --follow example from ACTS to create source links - sourceLinkStorage.emplace_back(meas2D.getSurface(), hit_index); - ActsExamples::IndexSourceLink& sourceLink = sourceLinkStorage.back(); - // Add to output containers: - // index map and source link container are geometry-ordered. - // since the input is also geometry-ordered, new items can - // be added at the end. - src_links.insert(src_links.end(), sourceLink); - // --- - // Create ACTS measurements - Acts::Vector2 loc = Acts::Vector2::Zero(); - loc[Acts::eBoundLoc0] = meas2D.getLoc().a; - loc[Acts::eBoundLoc1] = meas2D.getLoc().b; - - - Acts::SquareMatrix2 cov = Acts::SquareMatrix2::Zero(); - cov(0, 0) = meas2D.getCovariance().xx; - cov(1, 1) = meas2D.getCovariance().yy; - cov(0, 1) = meas2D.getCovariance().xy; - cov(1, 0) = meas2D.getCovariance().xy; - - auto measurement = Acts::makeMeasurement(Acts::SourceLink{sourceLink}, loc, cov, Acts::eBoundLoc0, Acts::eBoundLoc1); - measurements->emplace_back(std::move(measurement)); - - hit_index++; - } - - ActsExamples::TrackParametersContainer acts_init_trk_params; - for (const auto& track_parameter: init_trk_params) { - - Acts::BoundVector params; - params(Acts::eBoundLoc0) = track_parameter.getLoc().a * Acts::UnitConstants::mm; // cylinder radius - params(Acts::eBoundLoc1) = track_parameter.getLoc().b * Acts::UnitConstants::mm; // cylinder length - params(Acts::eBoundPhi) = track_parameter.getPhi(); - params(Acts::eBoundTheta) = track_parameter.getTheta(); - params(Acts::eBoundQOverP) = track_parameter.getQOverP() / Acts::UnitConstants::GeV; - params(Acts::eBoundTime) = track_parameter.getTime() * Acts::UnitConstants::ns; - - double charge = std::copysign(1., track_parameter.getQOverP()); - - Acts::BoundSquareMatrix cov = Acts::BoundSquareMatrix::Zero(); - #if EDM4EIC_VERSION_MAJOR >= 5 - for (size_t i = 0; const auto& [a, x] : edm4eic_indexed_units) { - for (size_t j = 0; const auto& [b, y] : edm4eic_indexed_units) { - cov(a, b) = track_parameter.getCovariance()(i,j) * x * y; - ++j; - } - ++i; - } - #else - cov(Acts::eBoundLoc0, Acts::eBoundLoc0) = std::pow( track_parameter.getLocError().xx ,2)*Acts::UnitConstants::mm*Acts::UnitConstants::mm; - cov(Acts::eBoundLoc1, Acts::eBoundLoc1) = std::pow( track_parameter.getLocError().yy,2)*Acts::UnitConstants::mm*Acts::UnitConstants::mm; - cov(Acts::eBoundTheta, Acts::eBoundTheta) = std::pow( track_parameter.getMomentumError().xx,2); - cov(Acts::eBoundPhi, Acts::eBoundPhi) = std::pow( track_parameter.getMomentumError().yy,2); - cov(Acts::eBoundQOverP, Acts::eBoundQOverP) = std::pow( track_parameter.getMomentumError().zz,2) / (Acts::UnitConstants::GeV*Acts::UnitConstants::GeV); - cov(Acts::eBoundTime, Acts::eBoundTime) = std::pow( track_parameter.getTimeError(),2)*Acts::UnitConstants::ns*Acts::UnitConstants::ns; - #endif - - // Construct a perigee surface as the target surface - auto pSurface = Acts::Surface::makeShared(Acts::Vector3(0,0,0)); - - // Create parameters - acts_init_trk_params.emplace_back(pSurface, params, cov, Acts::ParticleHypothesis::pion()); - } - - auto trajectories = std::make_unique(); - auto track_parameters = std::make_unique(); - auto tracks = std::make_unique(); - - //// Construct a perigee surface as the target surface - auto pSurface = Acts::Surface::makeShared(Acts::Vector3{0., 0., 0.}); - - ACTS_LOCAL_LOGGER(eicrecon::getSpdlogLogger("CKF", m_log, {"^No tracks found$"})); - - Acts::PropagatorPlainOptions pOptions; - pOptions.maxSteps = 10000; - - ActsExamples::PassThroughCalibrator pcalibrator; - ActsExamples::MeasurementCalibratorAdapter calibrator(pcalibrator, *measurements); - Acts::GainMatrixUpdater kfUpdater; - Acts::GainMatrixSmoother kfSmoother; - Acts::MeasurementSelector measSel{m_sourcelinkSelectorCfg}; - - Acts::CombinatorialKalmanFilterExtensions - extensions; - extensions.calibrator.connect<&ActsExamples::MeasurementCalibratorAdapter::calibrate>( - &calibrator); - extensions.updater.connect< - &Acts::GainMatrixUpdater::operator()>( - &kfUpdater); - extensions.smoother.connect< - &Acts::GainMatrixSmoother::operator()>( - &kfSmoother); - extensions.measurementSelector.connect< - &Acts::MeasurementSelector::select>( - &measSel); - - ActsExamples::IndexSourceLinkAccessor slAccessor; - slAccessor.container = &src_links; - Acts::SourceLinkAccessorDelegate - slAccessorDelegate; - slAccessorDelegate.connect<&ActsExamples::IndexSourceLinkAccessor::range>(&slAccessor); - - // Set the CombinatorialKalmanFilter options - CKFTracking::TrackFinderOptions options( - m_geoctx, m_fieldctx, m_calibctx, slAccessorDelegate, - extensions, pOptions, &(*pSurface)); - - // Create track container - auto trackContainer = std::make_shared(); - auto trackStateContainer = std::make_shared(); - ActsExamples::TrackContainer acts_tracks(trackContainer, trackStateContainer); - - // Add seed number column - acts_tracks.addColumn("seed"); - Acts::TrackAccessor seedNumber("seed"); - - // Loop over seeds - for (std::size_t iseed = 0; iseed < acts_init_trk_params.size(); ++iseed) { - auto result = - (*m_trackFinderFunc)(acts_init_trk_params.at(iseed), options, acts_tracks); - - if (!result.ok()) { - m_log->debug("Track finding failed for seed {} with error {}", iseed, result.error()); - continue; - } - - // Set seed number for all found tracks - auto& tracksForSeed = result.value(); - for (auto& track : tracksForSeed) { - seedNumber(track) = iseed; - } - } - - - // Move track states and track container to const containers - // NOTE Using the non-const containers leads to references to - // implicitly converted temporaries inside the Trajectories. - auto constTrackStateContainer = - std::make_shared( - std::move(*trackStateContainer)); - - auto constTrackContainer = - std::make_shared( - std::move(*trackContainer)); - - // FIXME JANA2 std::vector requires wrapping ConstTrackContainer, instead of: - //ConstTrackContainer constTracks(constTrackContainer, constTrackStateContainer); - std::vector constTracks_v; - constTracks_v.push_back( - new ActsExamples::ConstTrackContainer( - constTrackContainer, - constTrackStateContainer)); - auto& constTracks = *(constTracks_v.front()); - - // Seed number column accessor - const Acts::ConstTrackAccessor constSeedNumber("seed"); - - - // Prepare the output data with MultiTrajectory, per seed - std::vector acts_trajectories; - acts_trajectories.reserve(init_trk_params.size()); - - ActsExamples::Trajectories::IndexedParameters parameters; - std::vector tips; - - std::optional lastSeed; - for (const auto& track : constTracks) { - if (!lastSeed) { - lastSeed = constSeedNumber(track); - } + // Construct a perigee surface as the target surface + auto pSurface = Acts::Surface::makeShared(Acts::Vector3(0, 0, 0)); + + // Create parameters + acts_init_trk_params.emplace_back(pSurface, params, cov, Acts::ParticleHypothesis::pion()); + } + + auto trajectories = std::make_unique(); + auto track_parameters = std::make_unique(); + auto tracks = std::make_unique(); + + //// Construct a perigee surface as the target surface + auto pSurface = Acts::Surface::makeShared(Acts::Vector3{0., 0., 0.}); + + ACTS_LOCAL_LOGGER(eicrecon::getSpdlogLogger("CKF", m_log, {"^No tracks found$"})); + + Acts::PropagatorPlainOptions pOptions; + pOptions.maxSteps = 10000; + + ActsExamples::PassThroughCalibrator pcalibrator; + ActsExamples::MeasurementCalibratorAdapter calibrator(pcalibrator, *measurements); + Acts::GainMatrixUpdater kfUpdater; + Acts::GainMatrixSmoother kfSmoother; + Acts::MeasurementSelector measSel{m_sourcelinkSelectorCfg}; + + Acts::CombinatorialKalmanFilterExtensions extensions; + extensions.calibrator.connect<&ActsExamples::MeasurementCalibratorAdapter::calibrate>( + &calibrator); + extensions.updater.connect<&Acts::GainMatrixUpdater::operator()>( + &kfUpdater); + extensions.smoother.connect<&Acts::GainMatrixSmoother::operator()>( + &kfSmoother); + extensions.measurementSelector + .connect<&Acts::MeasurementSelector::select>(&measSel); + + ActsExamples::IndexSourceLinkAccessor slAccessor; + slAccessor.container = &src_links; + Acts::SourceLinkAccessorDelegate + slAccessorDelegate; + slAccessorDelegate.connect<&ActsExamples::IndexSourceLinkAccessor::range>(&slAccessor); + + // Set the CombinatorialKalmanFilter options + CKFTracking::TrackFinderOptions options(m_geoctx, m_fieldctx, m_calibctx, slAccessorDelegate, + extensions, pOptions, &(*pSurface)); + + // Create track container + auto trackContainer = std::make_shared(); + auto trackStateContainer = std::make_shared(); + ActsExamples::TrackContainer acts_tracks(trackContainer, trackStateContainer); + + // Add seed number column + acts_tracks.addColumn("seed"); + Acts::TrackAccessor seedNumber("seed"); + + // Loop over seeds + for (std::size_t iseed = 0; iseed < acts_init_trk_params.size(); ++iseed) { + auto result = (*m_trackFinderFunc)(acts_init_trk_params.at(iseed), options, acts_tracks); + + if (!result.ok()) { + m_log->debug("Track finding failed for seed {} with error {}", iseed, result.error()); + continue; + } - if (constSeedNumber(track) != lastSeed.value()) { - // make copies and clear vectors - acts_trajectories.push_back(new ActsExamples::Trajectories( - constTracks.trackStateContainer(), - tips, parameters)); + // Set seed number for all found tracks + auto& tracksForSeed = result.value(); + for (auto& track : tracksForSeed) { + seedNumber(track) = iseed; + } + } + + // Move track states and track container to const containers + // NOTE Using the non-const containers leads to references to + // implicitly converted temporaries inside the Trajectories. + auto constTrackStateContainer = + std::make_shared(std::move(*trackStateContainer)); + + auto constTrackContainer = + std::make_shared(std::move(*trackContainer)); + + // FIXME JANA2 std::vector requires wrapping ConstTrackContainer, instead of: + //ConstTrackContainer constTracks(constTrackContainer, constTrackStateContainer); + std::vector constTracks_v; + constTracks_v.push_back( + new ActsExamples::ConstTrackContainer(constTrackContainer, constTrackStateContainer)); + auto& constTracks = *(constTracks_v.front()); + + // Seed number column accessor + const Acts::ConstTrackAccessor constSeedNumber("seed"); + + // Prepare the output data with MultiTrajectory, per seed + std::vector acts_trajectories; + acts_trajectories.reserve(init_trk_params.size()); + + ActsExamples::Trajectories::IndexedParameters parameters; + std::vector tips; + + std::optional lastSeed; + for (const auto& track : constTracks) { + if (!lastSeed) { + lastSeed = constSeedNumber(track); + } - tips.clear(); - parameters.clear(); - } + if (constSeedNumber(track) != lastSeed.value()) { + // make copies and clear vectors + acts_trajectories.push_back( + new ActsExamples::Trajectories(constTracks.trackStateContainer(), tips, parameters)); - lastSeed = constSeedNumber(track); + tips.clear(); + parameters.clear(); + } - tips.push_back(track.tipIndex()); - parameters.emplace( - std::pair{track.tipIndex(), - ActsExamples::TrackParameters{track.referenceSurface().getSharedPtr(), - track.parameters(), track.covariance(), - track.particleHypothesis()}}); - } + lastSeed = constSeedNumber(track); + + tips.push_back(track.tipIndex()); + parameters.emplace(std::pair{ + track.tipIndex(), + ActsExamples::TrackParameters{track.referenceSurface().getSharedPtr(), track.parameters(), + track.covariance(), track.particleHypothesis()}}); + } + + if (tips.empty()) { + m_log->info("Last trajectory is empty"); + } + + // last entry: move vectors + acts_trajectories.push_back(new ActsExamples::Trajectories( + constTracks.trackStateContainer(), std::move(tips), std::move(parameters))); + + // Loop over trajectories + for (const auto* traj : acts_trajectories) { + // The trajectory entry indices and the multiTrajectory + const auto& trackTips = traj->tips(); + const auto& mj = traj->multiTrajectory(); + if (trackTips.empty()) { + m_log->warn("Empty multiTrajectory."); + continue; + } - if (tips.empty()) { - m_log->info("Last trajectory is empty"); + // Loop over all trajectories in a multiTrajectory + // FIXME: we only retain the first trackTips entry + for (auto trackTip : decltype(trackTips){trackTips.front()}) { + // Collect the trajectory summary info + auto trajectoryState = Acts::MultiTrajectoryHelpers::trajectoryState(mj, trackTip); + + // Check if the reco track has fitted track parameters + if (not traj->hasTrackParameters(trackTip)) { + m_log->warn("No fitted track parameters for trajectory with entry index = {}", trackTip); + continue; + } + + // Create trajectory + auto trajectory = trajectories->create(); +#if EDM4EIC_VERSION_MAJOR < 5 + trajectory.setChi2(trajectoryState.chi2Sum); + trajectory.setNdf(trajectoryState.NDF); +#endif + trajectory.setNMeasurements(trajectoryState.nMeasurements); + trajectory.setNStates(trajectoryState.nStates); + trajectory.setNOutliers(trajectoryState.nOutliers); + trajectory.setNHoles(trajectoryState.nHoles); + trajectory.setNSharedHits(trajectoryState.nSharedHits); + + m_log->debug("trajectory state, measurement, outlier, hole: {} {} {} {}", + trajectoryState.nStates, trajectoryState.nMeasurements, + trajectoryState.nOutliers, trajectoryState.nHoles); + + for (const auto& measurementChi2 : trajectoryState.measurementChi2) { + trajectory.addToMeasurementChi2(measurementChi2); + } + + for (const auto& outlierChi2 : trajectoryState.outlierChi2) { + trajectory.addToOutlierChi2(outlierChi2); + } + + // Get the fitted track parameter + const auto& boundParam = traj->trackParameters(trackTip); + const auto& parameter = boundParam.parameters(); + const auto& covariance = *boundParam.covariance(); + + auto pars = track_parameters->create(); + pars.setType(0); // type: track head --> 0 + pars.setLoc({static_cast(parameter[Acts::eBoundLoc0]), + static_cast(parameter[Acts::eBoundLoc1])}); + pars.setTheta(static_cast(parameter[Acts::eBoundTheta])); + pars.setPhi(static_cast(parameter[Acts::eBoundPhi])); + pars.setQOverP(static_cast(parameter[Acts::eBoundQOverP])); + pars.setTime(static_cast(parameter[Acts::eBoundTime])); +#if EDM4EIC_VERSION_MAJOR >= 5 + edm4eic::Cov6f cov; + for (size_t i = 0; const auto& [a, x] : edm4eic_indexed_units) { + for (size_t j = 0; const auto& [b, y] : edm4eic_indexed_units) { + // FIXME why not pars.getCovariance()(i,j) = covariance(a,b) / x / y; + cov(i, j) = covariance(a, b) / x / y; } + } + pars.setCovariance(cov); +#else + pars.setCharge(static_cast(boundParam.charge())); + pars.setLocError({static_cast(covariance(Acts::eBoundLoc0, Acts::eBoundLoc0)), + static_cast(covariance(Acts::eBoundLoc1, Acts::eBoundLoc1)), + static_cast(covariance(Acts::eBoundLoc0, Acts::eBoundLoc1))}); + pars.setMomentumError({static_cast(covariance(Acts::eBoundTheta, Acts::eBoundTheta)), + static_cast(covariance(Acts::eBoundPhi, Acts::eBoundPhi)), + static_cast(covariance(Acts::eBoundQOverP, Acts::eBoundQOverP)), + static_cast(covariance(Acts::eBoundTheta, Acts::eBoundPhi)), + static_cast(covariance(Acts::eBoundTheta, Acts::eBoundQOverP)), + static_cast(covariance(Acts::eBoundPhi, Acts::eBoundQOverP))}); + pars.setTimeError(sqrt(static_cast(covariance(Acts::eBoundTime, Acts::eBoundTime)))); +#endif - // last entry: move vectors - acts_trajectories.push_back(new ActsExamples::Trajectories( - constTracks.trackStateContainer(), - std::move(tips), std::move(parameters))); + trajectory.addToTrackParameters(pars); +// Fill tracks +#if EDM4EIC_VERSION_MAJOR >= 5 + auto track = tracks->create(); + track.setType( // Flag that defines the type of track + pars.getType()); + track.setPosition( // Track 3-position at the vertex + edm4hep::Vector3f()); + track.setMomentum( // Track 3-momentum at the vertex [GeV] + edm4hep::Vector3f()); + track.setPositionMomentumCovariance( // Covariance matrix in basis [x,y,z,px,py,pz] + edm4eic::Cov6f()); + track.setTime( // Track time at the vertex [ns] + static_cast(parameter[Acts::eBoundTime])); + track.setTimeError( // Error on the track vertex time + sqrt(static_cast(covariance(Acts::eBoundTime, Acts::eBoundTime)))); + track.setCharge( // Particle charge + std::copysign(1., parameter[Acts::eBoundQOverP])); + track.setChi2(trajectoryState.chi2Sum); // Total chi2 + track.setNdf(trajectoryState.NDF); // Number of degrees of freedom + track.setPdg( // PDG particle ID hypothesis + boundParam.particleHypothesis().absolutePdg()); + track.setTrajectory(trajectory); // Trajectory of this track +#endif - // Loop over trajectories - for (const auto* traj : acts_trajectories) { - // The trajectory entry indices and the multiTrajectory - const auto& trackTips = traj->tips(); - const auto& mj = traj->multiTrajectory(); - if (trackTips.empty()) { - m_log->warn("Empty multiTrajectory."); - continue; - } + // save measurement2d to good measurements or outliers according to srclink index + // fix me: ideally, this should be integrated into multitrajectoryhelper + // fix me: should say "OutlierMeasurements" instead of "OutlierHits" etc + mj.visitBackwards(trackTip, [&](const auto& state) { + auto geoID = state.referenceSurface().geometryId().value(); + auto typeFlags = state.typeFlags(); - // Loop over all trajectories in a multiTrajectory - // FIXME: we only retain the first trackTips entry - for (auto trackTip : decltype(trackTips){trackTips.front()}) { - // Collect the trajectory summary info - auto trajectoryState = - Acts::MultiTrajectoryHelpers::trajectoryState(mj, trackTip); - - // Check if the reco track has fitted track parameters - if (not traj->hasTrackParameters(trackTip)) { - m_log->warn( - "No fitted track parameters for trajectory with entry index = {}", - trackTip); - continue; - } + // find the associated hit (2D measurement) with state sourcelink index + // fix me: calibrated or not? + if (state.hasUncalibratedSourceLink()) { - // Create trajectory - auto trajectory = trajectories->create(); - #if EDM4EIC_VERSION_MAJOR < 5 - trajectory.setChi2(trajectoryState.chi2Sum); - trajectory.setNdf(trajectoryState.NDF); - #endif - trajectory.setNMeasurements(trajectoryState.nMeasurements); - trajectory.setNStates(trajectoryState.nStates); - trajectory.setNOutliers(trajectoryState.nOutliers); - trajectory.setNHoles(trajectoryState.nHoles); - trajectory.setNSharedHits(trajectoryState.nSharedHits); - - m_log->debug("trajectory state, measurement, outlier, hole: {} {} {} {}", - trajectoryState.nStates, - trajectoryState.nMeasurements, - trajectoryState.nOutliers, - trajectoryState.nHoles); - - for (const auto& measurementChi2 : trajectoryState.measurementChi2) { - trajectory.addToMeasurementChi2(measurementChi2); - } + std::size_t srclink_index = state.getUncalibratedSourceLink() + .template get() + .index(); - for (const auto& outlierChi2 : trajectoryState.outlierChi2) { - trajectory.addToOutlierChi2(outlierChi2); - } + // no hit on this state/surface, skip + if (typeFlags.test(Acts::TrackStateFlag::HoleFlag)) { + m_log->debug("No hit found on geo id={}", geoID); - // Get the fitted track parameter - const auto& boundParam = traj->trackParameters(trackTip); - const auto& parameter = boundParam.parameters(); - const auto& covariance = *boundParam.covariance(); - - auto pars = track_parameters->create(); - pars.setType(0); // type: track head --> 0 - pars.setLoc({ - static_cast(parameter[Acts::eBoundLoc0]), - static_cast(parameter[Acts::eBoundLoc1]) - }); - pars.setTheta(static_cast(parameter[Acts::eBoundTheta])); - pars.setPhi(static_cast(parameter[Acts::eBoundPhi])); - pars.setQOverP(static_cast(parameter[Acts::eBoundQOverP])); - pars.setTime(static_cast(parameter[Acts::eBoundTime])); - #if EDM4EIC_VERSION_MAJOR >= 5 - edm4eic::Cov6f cov; - for (size_t i = 0; const auto& [a, x] : edm4eic_indexed_units) { - for (size_t j = 0; const auto& [b, y] : edm4eic_indexed_units) { - // FIXME why not pars.getCovariance()(i,j) = covariance(a,b) / x / y; - cov(i,j) = covariance(a,b) / x / y; - } - } - pars.setCovariance(cov); - #else - pars.setCharge(static_cast(boundParam.charge())); - pars.setLocError({ - static_cast(covariance(Acts::eBoundLoc0, Acts::eBoundLoc0)), - static_cast(covariance(Acts::eBoundLoc1, Acts::eBoundLoc1)), - static_cast(covariance(Acts::eBoundLoc0, Acts::eBoundLoc1)) - }); - pars.setMomentumError({ - static_cast(covariance(Acts::eBoundTheta, Acts::eBoundTheta)), - static_cast(covariance(Acts::eBoundPhi, Acts::eBoundPhi)), - static_cast(covariance(Acts::eBoundQOverP, Acts::eBoundQOverP)), - static_cast(covariance(Acts::eBoundTheta, Acts::eBoundPhi)), - static_cast(covariance(Acts::eBoundTheta, Acts::eBoundQOverP)), - static_cast(covariance(Acts::eBoundPhi, Acts::eBoundQOverP)) - }); - pars.setTimeError(sqrt(static_cast(covariance(Acts::eBoundTime, Acts::eBoundTime)))); - #endif - - trajectory.addToTrackParameters(pars); - - // Fill tracks - #if EDM4EIC_VERSION_MAJOR >= 5 - auto track = tracks->create(); - track.setType( // Flag that defines the type of track - pars.getType() - ); - track.setPosition( // Track 3-position at the vertex - edm4hep::Vector3f() - ); - track.setMomentum( // Track 3-momentum at the vertex [GeV] - edm4hep::Vector3f() - ); - track.setPositionMomentumCovariance( // Covariance matrix in basis [x,y,z,px,py,pz] - edm4eic::Cov6f() - ); - track.setTime( // Track time at the vertex [ns] - static_cast(parameter[Acts::eBoundTime]) - ); - track.setTimeError( // Error on the track vertex time - sqrt(static_cast(covariance(Acts::eBoundTime, Acts::eBoundTime))) - ); - track.setCharge( // Particle charge - std::copysign(1., parameter[Acts::eBoundQOverP]) - ); - track.setChi2(trajectoryState.chi2Sum); // Total chi2 - track.setNdf(trajectoryState.NDF); // Number of degrees of freedom - track.setPdg( // PDG particle ID hypothesis - boundParam.particleHypothesis().absolutePdg() - ); - track.setTrajectory(trajectory); // Trajectory of this track - #endif - - // save measurement2d to good measurements or outliers according to srclink index - // fix me: ideally, this should be integrated into multitrajectoryhelper - // fix me: should say "OutlierMeasurements" instead of "OutlierHits" etc - mj.visitBackwards(trackTip, [&](const auto& state) { - - auto geoID = state.referenceSurface().geometryId().value(); - auto typeFlags = state.typeFlags(); - - // find the associated hit (2D measurement) with state sourcelink index - // fix me: calibrated or not? - if (state.hasUncalibratedSourceLink()) { - - std::size_t srclink_index = state.getUncalibratedSourceLink().template get().index(); - - // no hit on this state/surface, skip - if (typeFlags.test(Acts::TrackStateFlag::HoleFlag)) { - m_log->debug("No hit found on geo id={}", geoID); - - } else { - auto meas2D = meas2Ds[srclink_index]; - if (typeFlags.test(Acts::TrackStateFlag::MeasurementFlag)) { - #if EDM4EIC_VERSION_MAJOR >= 5 - track.addToMeasurements(meas2D); - trajectory.addToMeasurements_deprecated(meas2D); - #else + } else { + auto meas2D = meas2Ds[srclink_index]; + if (typeFlags.test(Acts::TrackStateFlag::MeasurementFlag)) { +#if EDM4EIC_VERSION_MAJOR >= 5 + track.addToMeasurements(meas2D); + trajectory.addToMeasurements_deprecated(meas2D); +#else trajectory.addToMeasurementHits(meas2D); - #endif - m_log->debug("Measurement on geo id={}, index={}, loc={},{}", - geoID, srclink_index, meas2D.getLoc().a, meas2D.getLoc().b); - - } - else if (typeFlags.test(Acts::TrackStateFlag::OutlierFlag)) { - #if EDM4EIC_VERSION_MAJOR >= 5 - trajectory.addToOutliers_deprecated(meas2D); - #else - trajectory.addToOutlierHits(meas2D); - #endif - m_log->debug("Outlier on geo id={}, index={}, loc={},{}", - geoID, srclink_index, meas2D.getLoc().a, meas2D.getLoc().b); - - } - } - } - - }); +#endif + m_log->debug("Measurement on geo id={}, index={}, loc={},{}", geoID, srclink_index, + meas2D.getLoc().a, meas2D.getLoc().b); + } else if (typeFlags.test(Acts::TrackStateFlag::OutlierFlag)) { +#if EDM4EIC_VERSION_MAJOR >= 5 + trajectory.addToOutliers_deprecated(meas2D); +#else + trajectory.addToOutlierHits(meas2D); +#endif + m_log->debug("Outlier on geo id={}, index={}, loc={},{}", geoID, srclink_index, + meas2D.getLoc().a, meas2D.getLoc().b); + } } } - - return std::make_tuple(std::move(trajectories), std::move(track_parameters), std::move(tracks), std::move(acts_trajectories), std::move(constTracks_v)); + }); } + } + + return std::make_tuple(std::move(trajectories), std::move(track_parameters), std::move(tracks), + std::move(acts_trajectories), std::move(constTracks_v)); +} } // namespace eicrecon diff --git a/src/algorithms/tracking/CKFTracking.h b/src/algorithms/tracking/CKFTracking.h index 3b9b847eb9..94ead1454b 100644 --- a/src/algorithms/tracking/CKFTracking.h +++ b/src/algorithms/tracking/CKFTracking.h @@ -38,65 +38,62 @@ namespace eicrecon { * \ingroup tracking */ - class CKFTracking: public WithPodConfig { - public: - /// Track finder function that takes input measurements, initial trackstate - /// and track finder options and returns some track-finder-specific result. - using TrackFinderOptions = - Acts::CombinatorialKalmanFilterOptions; - using TrackFinderResult = - Acts::Result>; - - /// Find function that takes the above parameters - /// @note This is separated into a virtual interface to keep compilation units - /// small - class CKFTrackingFunction { - public: - virtual ~CKFTrackingFunction() = default; - - virtual TrackFinderResult operator()(const ActsExamples::TrackParameters&, - const TrackFinderOptions&, - ActsExamples::TrackContainer&) const = 0; - }; - - /// Create the track finder function implementation. - /// The magnetic field is intentionally given by-value since the variantresults - /// contains shared_ptr anyways. - static std::shared_ptr makeCKFTrackingFunction( - std::shared_ptr trackingGeometry, - std::shared_ptr magneticField, - const Acts::Logger& logger); - - CKFTracking(); - - void init(std::shared_ptr geo_svc, std::shared_ptr log); - - std::tuple< - std::unique_ptr, - std::unique_ptr, - std::unique_ptr, - std::vector, - std::vector - > - process(const edm4eic::Measurement2DCollection& meas2Ds, - const edm4eic::TrackParametersCollection &init_trk_params); - - private: - std::shared_ptr m_log; - std::shared_ptr m_acts_logger{nullptr}; - std::shared_ptr m_trackFinderFunc; - std::shared_ptr m_geoSvc; - - std::shared_ptr m_BField = nullptr; - Acts::GeometryContext m_geoctx; - Acts::CalibrationContext m_calibctx; - Acts::MagneticFieldContext m_fieldctx; - - Acts::MeasurementSelector::Config m_sourcelinkSelectorCfg; - - /// Private access to the logging instance - const Acts::Logger& logger() const { return *m_acts_logger; } - }; - -} // namespace eicrecon::Reco +class CKFTracking : public WithPodConfig { +public: + /// Track finder function that takes input measurements, initial trackstate + /// and track finder options and returns some track-finder-specific result. + using TrackFinderOptions = + Acts::CombinatorialKalmanFilterOptions; + using TrackFinderResult = Acts::Result>; + + /// Find function that takes the above parameters + /// @note This is separated into a virtual interface to keep compilation units + /// small + class CKFTrackingFunction { + public: + virtual ~CKFTrackingFunction() = default; + + virtual TrackFinderResult operator()(const ActsExamples::TrackParameters&, + const TrackFinderOptions&, + ActsExamples::TrackContainer&) const = 0; + }; + + /// Create the track finder function implementation. + /// The magnetic field is intentionally given by-value since the variantresults + /// contains shared_ptr anyways. + static std::shared_ptr + makeCKFTrackingFunction(std::shared_ptr trackingGeometry, + std::shared_ptr magneticField, + const Acts::Logger& logger); + + CKFTracking(); + + void init(std::shared_ptr geo_svc, + std::shared_ptr log); + + std::tuple, + std::unique_ptr, + std::unique_ptr, std::vector, + std::vector> + process(const edm4eic::Measurement2DCollection& meas2Ds, + const edm4eic::TrackParametersCollection& init_trk_params); + +private: + std::shared_ptr m_log; + std::shared_ptr m_acts_logger{nullptr}; + std::shared_ptr m_trackFinderFunc; + std::shared_ptr m_geoSvc; + + std::shared_ptr m_BField = nullptr; + Acts::GeometryContext m_geoctx; + Acts::CalibrationContext m_calibctx; + Acts::MagneticFieldContext m_fieldctx; + + Acts::MeasurementSelector::Config m_sourcelinkSelectorCfg; + + /// Private access to the logging instance + const Acts::Logger& logger() const { return *m_acts_logger; } +}; + +} // namespace eicrecon diff --git a/src/algorithms/tracking/CKFTrackingConfig.h b/src/algorithms/tracking/CKFTrackingConfig.h index 9332cf2205..08192192c2 100644 --- a/src/algorithms/tracking/CKFTrackingConfig.h +++ b/src/algorithms/tracking/CKFTrackingConfig.h @@ -7,9 +7,9 @@ #include namespace eicrecon { - struct CKFTrackingConfig { - std::vector etaBins = {}; // {this, "etaBins", {}}; - std::vector chi2CutOff = {15.}; //{this, "chi2CutOff", {15.}}; - std::vector numMeasurementsCutOff = {10}; //{this, "numMeasurementsCutOff", {10}}; - }; -} +struct CKFTrackingConfig { + std::vector etaBins = {}; // {this, "etaBins", {}}; + std::vector chi2CutOff = {15.}; //{this, "chi2CutOff", {15.}}; + std::vector numMeasurementsCutOff = {10}; //{this, "numMeasurementsCutOff", {10}}; +}; +} // namespace eicrecon diff --git a/src/algorithms/tracking/CKFTrackingFunction.cc b/src/algorithms/tracking/CKFTrackingFunction.cc index 5e748ff5b9..e7a6e2fb90 100644 --- a/src/algorithms/tracking/CKFTrackingFunction.cc +++ b/src/algorithms/tracking/CKFTrackingFunction.cc @@ -29,62 +29,56 @@ #include "ActsExamples/EventData/Track.hpp" #include "CKFTracking.h" -namespace eicrecon{ +namespace eicrecon { - using Updater = Acts::GainMatrixUpdater; - using Smoother = Acts::GainMatrixSmoother; +using Updater = Acts::GainMatrixUpdater; +using Smoother = Acts::GainMatrixSmoother; - using Stepper = Acts::EigenStepper<>; - using Navigator = Acts::Navigator; - using Propagator = Acts::Propagator; +using Stepper = Acts::EigenStepper<>; +using Navigator = Acts::Navigator; +using Propagator = Acts::Propagator; - using CKF = - Acts::CombinatorialKalmanFilter; +using CKF = Acts::CombinatorialKalmanFilter; - using TrackContainer = - Acts::TrackContainer; +using TrackContainer = + Acts::TrackContainer; - /** Finder implementation . +/** Finder implementation . * * \ingroup track */ - struct CKFTrackingFunctionImpl - : public eicrecon::CKFTracking::CKFTrackingFunction { - CKF trackFinder; - - CKFTrackingFunctionImpl(CKF&& f) : trackFinder(std::move(f)) {} - - eicrecon::CKFTracking::TrackFinderResult operator()( - const ActsExamples::TrackParameters& initialParameters, - const eicrecon::CKFTracking::TrackFinderOptions& options, - TrackContainer& tracks) const override { - return trackFinder.findTracks(initialParameters, options, tracks); - }; +struct CKFTrackingFunctionImpl : public eicrecon::CKFTracking::CKFTrackingFunction { + CKF trackFinder; + + CKFTrackingFunctionImpl(CKF&& f) : trackFinder(std::move(f)) {} + + eicrecon::CKFTracking::TrackFinderResult + operator()(const ActsExamples::TrackParameters& initialParameters, + const eicrecon::CKFTracking::TrackFinderOptions& options, + TrackContainer& tracks) const override { + return trackFinder.findTracks(initialParameters, options, tracks); }; +}; -} // namespace +} // namespace eicrecon namespace eicrecon { - std::shared_ptr - CKFTracking::makeCKFTrackingFunction( - std::shared_ptr trackingGeometry, - std::shared_ptr magneticField, - const Acts::Logger& logger) - { - Stepper stepper(std::move(magneticField)); - Navigator::Config cfg{trackingGeometry}; - cfg.resolvePassive = false; - cfg.resolveMaterial = true; - cfg.resolveSensitive = true; - Navigator navigator(cfg); - - Propagator propagator(std::move(stepper), std::move(navigator)); - CKF trackFinder(std::move(propagator), logger.cloneWithSuffix("CKF")); - - // build the track finder functions. owns the track finder object. - return std::make_shared(std::move(trackFinder)); - } - -} // namespace eicrecon::Reco +std::shared_ptr CKFTracking::makeCKFTrackingFunction( + std::shared_ptr trackingGeometry, + std::shared_ptr magneticField, const Acts::Logger& logger) { + Stepper stepper(std::move(magneticField)); + Navigator::Config cfg{trackingGeometry}; + cfg.resolvePassive = false; + cfg.resolveMaterial = true; + cfg.resolveSensitive = true; + Navigator navigator(cfg); + + Propagator propagator(std::move(stepper), std::move(navigator)); + CKF trackFinder(std::move(propagator), logger.cloneWithSuffix("CKF")); + + // build the track finder functions. owns the track finder object. + return std::make_shared(std::move(trackFinder)); +} + +} // namespace eicrecon diff --git a/src/algorithms/tracking/DD4hepBField.cc b/src/algorithms/tracking/DD4hepBField.cc index f8f7a1ffa2..468bcac327 100644 --- a/src/algorithms/tracking/DD4hepBField.cc +++ b/src/algorithms/tracking/DD4hepBField.cc @@ -15,35 +15,32 @@ namespace eicrecon::BField { - Acts::Result DD4hepBField::getField(const Acts::Vector3& position, - Acts::MagneticFieldProvider::Cache& /*cache*/) const - { - dd4hep::Position pos( - position[0] * (dd4hep::mm / Acts::UnitConstants::mm), - position[1] * (dd4hep::mm / Acts::UnitConstants::mm), - position[2] * (dd4hep::mm / Acts::UnitConstants::mm)); - - auto fieldObj = m_det->field(); - auto field = fieldObj.magneticField(pos) * (Acts::UnitConstants::T / dd4hep::tesla); - - // FIXME Acts doesn't seem to like exact zero components - if (field.x() * field.y() * field.z() == 0) { - static dd4hep::Direction epsilon{ - std::numeric_limits::epsilon(), - std::numeric_limits::epsilon(), - std::numeric_limits::epsilon() - }; - field += epsilon; - } - - return Acts::Result::success({field.x(), field.y(), field.z()}); +Acts::Result +DD4hepBField::getField(const Acts::Vector3& position, + Acts::MagneticFieldProvider::Cache& /*cache*/) const { + dd4hep::Position pos(position[0] * (dd4hep::mm / Acts::UnitConstants::mm), + position[1] * (dd4hep::mm / Acts::UnitConstants::mm), + position[2] * (dd4hep::mm / Acts::UnitConstants::mm)); + + auto fieldObj = m_det->field(); + auto field = fieldObj.magneticField(pos) * (Acts::UnitConstants::T / dd4hep::tesla); + + // FIXME Acts doesn't seem to like exact zero components + if (field.x() * field.y() * field.z() == 0) { + static dd4hep::Direction epsilon{std::numeric_limits::epsilon(), + std::numeric_limits::epsilon(), + std::numeric_limits::epsilon()}; + field += epsilon; } - Acts::Result DD4hepBField::getFieldGradient(const Acts::Vector3& position, - Acts::ActsMatrix<3, 3>& /*derivative*/, - Acts::MagneticFieldProvider::Cache& cache) const - { - return this->getField(position, cache); - } + return Acts::Result::success({field.x(), field.y(), field.z()}); +} + +Acts::Result +DD4hepBField::getFieldGradient(const Acts::Vector3& position, + Acts::ActsMatrix<3, 3>& /*derivative*/, + Acts::MagneticFieldProvider::Cache& cache) const { + return this->getField(position, cache); +} } // namespace eicrecon::BField diff --git a/src/algorithms/tracking/DD4hepBField.h b/src/algorithms/tracking/DD4hepBField.h index 257666c6af..c2ba2b8937 100644 --- a/src/algorithms/tracking/DD4hepBField.h +++ b/src/algorithms/tracking/DD4hepBField.h @@ -17,42 +17,39 @@ #include #include - - - namespace eicrecon::BField { - ///// The Context to be handed around - //struct ScalableBFieldContext { - // double scalor = 1.; - //}; +///// The Context to be handed around +//struct ScalableBFieldContext { +// double scalor = 1.; +//}; - /** Use the dd4hep magnetic field in acts. +/** Use the dd4hep magnetic field in acts. * * \ingroup magnets * \ingroup magsvc */ - class DD4hepBField final : public Acts::MagneticFieldProvider { - public: - gsl::not_null m_det; +class DD4hepBField final : public Acts::MagneticFieldProvider { +public: + gsl::not_null m_det; - public: - struct Cache { - Cache(const Acts::MagneticFieldContext& /*mcfg*/) { } - }; +public: + struct Cache { + Cache(const Acts::MagneticFieldContext& /*mcfg*/) {} + }; - Acts::MagneticFieldProvider::Cache makeCache(const Acts::MagneticFieldContext& mctx) const override - { - return Acts::MagneticFieldProvider::Cache::make(mctx); - } + Acts::MagneticFieldProvider::Cache + makeCache(const Acts::MagneticFieldContext& mctx) const override { + return Acts::MagneticFieldProvider::Cache::make(mctx); + } - /** construct constant magnetic field from field vector. + /** construct constant magnetic field from field vector. * * @param [in] DD4hep detector instance */ - explicit DD4hepBField(gsl::not_null det) : m_det(det) {} + explicit DD4hepBField(gsl::not_null det) : m_det(det) {} - /** retrieve magnetic field value. + /** retrieve magnetic field value. * * @param [in] position global position * @param [in] cache Cache object (is ignored) @@ -61,9 +58,10 @@ namespace eicrecon::BField { * @note The @p position is ignored and only kept as argument to provide * a consistent interface with other magnetic field services. */ - Acts::Result getField(const Acts::Vector3& position, Acts::MagneticFieldProvider::Cache& cache) const override; + Acts::Result getField(const Acts::Vector3& position, + Acts::MagneticFieldProvider::Cache& cache) const override; - /** @brief retrieve magnetic field value & its gradient + /** @brief retrieve magnetic field value & its gradient * * @param [in] position global position * @param [out] derivative gradient of magnetic field vector as (3x3) @@ -76,12 +74,11 @@ namespace eicrecon::BField { * @note currently the derivative is not calculated * @todo return derivative */ - Acts::Result getFieldGradient(const Acts::Vector3& position, Acts::ActsMatrix<3, 3>& /*derivative*/, - Acts::MagneticFieldProvider::Cache& cache) const override; - }; - - using BFieldVariant = std::variant>; - + Acts::Result + getFieldGradient(const Acts::Vector3& position, Acts::ActsMatrix<3, 3>& /*derivative*/, + Acts::MagneticFieldProvider::Cache& cache) const override; +}; +using BFieldVariant = std::variant>; } // namespace eicrecon::BField diff --git a/src/algorithms/tracking/IterativeVertexFinder.cc b/src/algorithms/tracking/IterativeVertexFinder.cc index 8885559a3a..d4719a4c9f 100644 --- a/src/algorithms/tracking/IterativeVertexFinder.cc +++ b/src/algorithms/tracking/IterativeVertexFinder.cc @@ -70,8 +70,8 @@ std::unique_ptr eicrecon::IterativeVertexFinder::prod Acts::EigenStepper<> stepper(m_BField); // Set up propagator with void navigator - auto propagator = std::make_shared( - stepper, Acts::detail::VoidNavigator{}, logger().cloneWithSuffix("Prop")); + auto propagator = std::make_shared(stepper, Acts::detail::VoidNavigator{}, + logger().cloneWithSuffix("Prop")); Acts::PropagatorOptions opts(m_geoctx, m_fieldctx); // Setup the vertex fitter @@ -86,15 +86,15 @@ std::unique_ptr eicrecon::IterativeVertexFinder::prod VertexSeeder::Config seederCfg(ipEst); VertexSeeder seeder(seederCfg); // Set up the actual vertex finder - VertexFinder::Config finderCfg(std::move(vertexFitter), std::move(linearizer), - std::move(seeder), std::move(ipEst)); + VertexFinder::Config finderCfg(std::move(vertexFitter), std::move(linearizer), std::move(seeder), + std::move(ipEst)); finderCfg.maxVertices = m_cfg.maxVertices; finderCfg.reassignTracksAfterFirstFit = m_cfg.reassignTracksAfterFirstFit; - #if Acts_VERSION_MAJOR >= 31 +#if Acts_VERSION_MAJOR >= 31 VertexFinder finder(std::move(finderCfg)); - #else +#else VertexFinder finder(finderCfg); - #endif +#endif VertexFinder::State state(*m_BField, m_fieldctx); VertexFinderOptions finderOpts(m_geoctx, m_fieldctx); @@ -119,37 +119,35 @@ std::unique_ptr eicrecon::IterativeVertexFinder::prod for (const auto& vtx : vertices) { #if EDM4EIC_VERSION_MAJOR >= 5 - edm4eic::Cov4f cov(vtx.fullCovariance()(0,0), vtx.fullCovariance()(1,1), vtx.fullCovariance()(2,2), vtx.fullCovariance()(3,3), - vtx.fullCovariance()(0,1), vtx.fullCovariance()(0,2), vtx.fullCovariance()(0,3), - vtx.fullCovariance()(1,2), vtx.fullCovariance()(1,3), - vtx.fullCovariance()(2,3)); + edm4eic::Cov4f cov(vtx.fullCovariance()(0, 0), vtx.fullCovariance()(1, 1), + vtx.fullCovariance()(2, 2), vtx.fullCovariance()(3, 3), + vtx.fullCovariance()(0, 1), vtx.fullCovariance()(0, 2), + vtx.fullCovariance()(0, 3), vtx.fullCovariance()(1, 2), + vtx.fullCovariance()(1, 3), vtx.fullCovariance()(2, 3)); auto eicvertex = outputVertices->create(); - eicvertex.setType(1); // boolean flag if vertex is primary vertex of event - eicvertex.setChi2((float)vtx.fitQuality().first); // chi2 - eicvertex.setNdf((float)vtx.fitQuality().second); // ndf + eicvertex.setType(1); // boolean flag if vertex is primary vertex of event + eicvertex.setChi2((float)vtx.fitQuality().first); // chi2 + eicvertex.setNdf((float)vtx.fitQuality().second); // ndf eicvertex.setPosition({ - (float)vtx.position().x(), - (float)vtx.position().y(), - (float)vtx.position().z(), - (float)vtx.time(), - }); // vtxposition - eicvertex.setPositionError(cov); // covariance + (float)vtx.position().x(), + (float)vtx.position().y(), + (float)vtx.position().z(), + (float)vtx.time(), + }); // vtxposition + eicvertex.setPositionError(cov); // covariance #else edm4eic::Cov3f cov(vtx.covariance()(0, 0), vtx.covariance()(1, 1), vtx.covariance()(2, 2), vtx.covariance()(0, 1), vtx.covariance()(0, 2), vtx.covariance()(1, 2)); auto eicvertex = outputVertices->create(); - eicvertex.setPrimary(1); // boolean flag if vertex is primary vertex of event + eicvertex.setPrimary(1); // boolean flag if vertex is primary vertex of event eicvertex.setChi2((float)vtx.fitQuality().first); // chi2 eicvertex.setProbability((float)vtx.fitQuality().second); // ndf - eicvertex.setPosition({ - (float)vtx.position().x(), - (float)vtx.position().y(), - (float)vtx.position().z() - }); // vtxposition - eicvertex.setPositionError(cov); // covariance - eicvertex.setAlgorithmType(1); // algorithmtype - eicvertex.setTime((float)vtx.time()); // time + eicvertex.setPosition({(float)vtx.position().x(), (float)vtx.position().y(), + (float)vtx.position().z()}); // vtxposition + eicvertex.setPositionError(cov); // covariance + eicvertex.setAlgorithmType(1); // algorithmtype + eicvertex.setTime((float)vtx.time()); // time #endif } diff --git a/src/algorithms/tracking/IterativeVertexFinderConfig.h b/src/algorithms/tracking/IterativeVertexFinderConfig.h index 2a3cf77afc..a7f63afd85 100644 --- a/src/algorithms/tracking/IterativeVertexFinderConfig.h +++ b/src/algorithms/tracking/IterativeVertexFinderConfig.h @@ -3,7 +3,7 @@ namespace eicrecon { struct IterativeVertexFinderConfig { - int maxVertices = 10; + int maxVertices = 10; bool reassignTracksAfterFirstFit = true; }; diff --git a/src/algorithms/tracking/OrthogonalTrackSeedingConfig.h b/src/algorithms/tracking/OrthogonalTrackSeedingConfig.h index 755e5fa17d..2a5494cf49 100644 --- a/src/algorithms/tracking/OrthogonalTrackSeedingConfig.h +++ b/src/algorithms/tracking/OrthogonalTrackSeedingConfig.h @@ -10,82 +10,92 @@ namespace eicrecon { - struct OrthogonalTrackSeedingConfig { +struct OrthogonalTrackSeedingConfig { - ////////////////////////////////////////////////////////////////////////// - /// SEED FINDER GENERAL PARAMETERS - float rMax = 440. * Acts::UnitConstants::mm; // max r to look for hits to compose seeds - float rMin = 33. * Acts::UnitConstants::mm; // min r to look for hits to compose seeds - float zMax = 1700. * Acts::UnitConstants::mm; // max z to look for hits to compose seeds - float zMin = -1500. * Acts::UnitConstants::mm; // min z to look for hits to compose seeds - float deltaRMinTopSP = 10. * Acts::UnitConstants::mm; // Min distance in r between middle and top SP in one seed - float deltaRMaxTopSP = 200. * Acts::UnitConstants::mm; // Max distance in r between middle and top SP in one seed - float deltaRMinBottomSP = 10. * Acts::UnitConstants::mm; // Min distance in r between middle and bottom SP in one seed - float deltaRMaxBottomSP = 200. * Acts::UnitConstants::mm; // Max distance in r between middle and bottom SP in one seed - float collisionRegionMin = -250 * Acts::UnitConstants::mm; // Min z for primary vertex - float collisionRegionMax = 250 * Acts::UnitConstants::mm; // Max z for primary vertex + ////////////////////////////////////////////////////////////////////////// + /// SEED FINDER GENERAL PARAMETERS + float rMax = 440. * Acts::UnitConstants::mm; // max r to look for hits to compose seeds + float rMin = 33. * Acts::UnitConstants::mm; // min r to look for hits to compose seeds + float zMax = 1700. * Acts::UnitConstants::mm; // max z to look for hits to compose seeds + float zMin = -1500. * Acts::UnitConstants::mm; // min z to look for hits to compose seeds + float deltaRMinTopSP = + 10. * Acts::UnitConstants::mm; // Min distance in r between middle and top SP in one seed + float deltaRMaxTopSP = + 200. * Acts::UnitConstants::mm; // Max distance in r between middle and top SP in one seed + float deltaRMinBottomSP = + 10. * Acts::UnitConstants::mm; // Min distance in r between middle and bottom SP in one seed + float deltaRMaxBottomSP = + 200. * Acts::UnitConstants::mm; // Max distance in r between middle and bottom SP in one seed + float collisionRegionMin = -250 * Acts::UnitConstants::mm; // Min z for primary vertex + float collisionRegionMax = 250 * Acts::UnitConstants::mm; // Max z for primary vertex - unsigned int maxSeedsPerSpM = 0; // max number of seeds a single middle sp can belong to - 1 - float cotThetaMax = 1.0 / tan(2. * atan(exp(-4.0))); // Cotangent of max theta angle (based on eta) + unsigned int maxSeedsPerSpM = 0; // max number of seeds a single middle sp can belong to - 1 + float cotThetaMax = + 1.0 / tan(2. * atan(exp(-4.0))); // Cotangent of max theta angle (based on eta) - float sigmaScattering = 5; // How many standard devs of scattering angles to consider - float radLengthPerSeed = 0.1; // Average radiation lengths of material on the length of a seed - float minPt = (100. * Acts::UnitConstants::MeV) / cotThetaMax; // MeV (in Acts units of GeV) - minimum transverse momentum - float bFieldInZ = 1.7 * Acts::UnitConstants::T; // T (in Acts units of GeV/[e*mm]) - Magnetic field strength - float beamPosX = 0; // x offset for beam position - float beamPosY = 0; // y offset for beam position - float impactMax = 3. * Acts::UnitConstants::mm; // Maximum transverse PCA allowed - float bFieldMin = 0.1 * Acts::UnitConstants::T; // T (in Acts units of GeV/[e*mm]) - Minimum Magnetic field strength - float rMinMiddle = 20. * Acts::UnitConstants::mm; // Middle spacepoint must fall between these two radii - float rMaxMiddle = 400. * Acts::UnitConstants::mm; + float sigmaScattering = 5; // How many standard devs of scattering angles to consider + float radLengthPerSeed = 0.1; // Average radiation lengths of material on the length of a seed + float minPt = (100. * Acts::UnitConstants::MeV) / + cotThetaMax; // MeV (in Acts units of GeV) - minimum transverse momentum + float bFieldInZ = + 1.7 * Acts::UnitConstants::T; // T (in Acts units of GeV/[e*mm]) - Magnetic field strength + float beamPosX = 0; // x offset for beam position + float beamPosY = 0; // y offset for beam position + float impactMax = 3. * Acts::UnitConstants::mm; // Maximum transverse PCA allowed + float bFieldMin = + 0.1 * + Acts::UnitConstants::T; // T (in Acts units of GeV/[e*mm]) - Minimum Magnetic field strength + float rMinMiddle = + 20. * Acts::UnitConstants::mm; // Middle spacepoint must fall between these two radii + float rMaxMiddle = 400. * Acts::UnitConstants::mm; - ////////////////////////////////////////////////////////////////////////// - /// SEED FILTER GENERAL PARAMETERS - /// The parameters below control the process of filtering out seeds before - /// sending them off to track reconstruction. These parameters first correspond - /// to global settings (more loose) followed by more strict cuts for the central - /// and forward/backward regions separately. + ////////////////////////////////////////////////////////////////////////// + /// SEED FILTER GENERAL PARAMETERS + /// The parameters below control the process of filtering out seeds before + /// sending them off to track reconstruction. These parameters first correspond + /// to global settings (more loose) followed by more strict cuts for the central + /// and forward/backward regions separately. - float maxSeedsPerSpM_filter = 0; // max number of seeds a single middle sp can belong to - 1 - float deltaRMin = 5* Acts::UnitConstants::mm; - bool seedConfirmation = false; - float deltaInvHelixDiameter = 0.00003 * 1. / Acts::UnitConstants::mm; - float impactWeightFactor = 1.; - float zOriginWeightFactor = 1.; - float compatSeedWeight = 200.; - size_t compatSeedLimit = 2; - float seedWeightIncrement = 0; + float maxSeedsPerSpM_filter = 0; // max number of seeds a single middle sp can belong to - 1 + float deltaRMin = 5 * Acts::UnitConstants::mm; + bool seedConfirmation = false; + float deltaInvHelixDiameter = 0.00003 * 1. / Acts::UnitConstants::mm; + float impactWeightFactor = 1.; + float zOriginWeightFactor = 1.; + float compatSeedWeight = 200.; + size_t compatSeedLimit = 2; + float seedWeightIncrement = 0; - /////////////////////////////////////// - /// CENTRAL SEED FILTER PARAMETERS - float zMinSeedConfCentral = -250 * Acts::UnitConstants::mm; - float zMaxSeedConfCentral = 250 * Acts::UnitConstants::mm; - float rMaxSeedConfCentral = 140 * Acts::UnitConstants::mm; - size_t nTopForLargeRCentral = 1; - size_t nTopForSmallRCentral = 2; - float seedConfMinBottomRadiusCentral = 60.0 * Acts::UnitConstants::mm; - float seedConfMaxZOriginCentral = 150.0 * Acts::UnitConstants::mm; - float minImpactSeedConfCentral = 1.0 * Acts::UnitConstants::mm; + /////////////////////////////////////// + /// CENTRAL SEED FILTER PARAMETERS + float zMinSeedConfCentral = -250 * Acts::UnitConstants::mm; + float zMaxSeedConfCentral = 250 * Acts::UnitConstants::mm; + float rMaxSeedConfCentral = 140 * Acts::UnitConstants::mm; + size_t nTopForLargeRCentral = 1; + size_t nTopForSmallRCentral = 2; + float seedConfMinBottomRadiusCentral = 60.0 * Acts::UnitConstants::mm; + float seedConfMaxZOriginCentral = 150.0 * Acts::UnitConstants::mm; + float minImpactSeedConfCentral = 1.0 * Acts::UnitConstants::mm; - /////////////////////////////////////// - /// FORWARD / BACKWARD SEED FILTER PARAMETERS - float zMinSeedConfForward = -3000 * Acts::UnitConstants::mm; - float zMaxSeedConfForward = 3000 * Acts::UnitConstants::mm; - float rMaxSeedConfForward = 140 * Acts::UnitConstants::mm; - size_t nTopForLargeRForward = 1; - size_t nTopForSmallRForward = 2; - float seedConfMinBottomRadiusForward = 60.0 * Acts::UnitConstants::mm; - float seedConfMaxZOriginForward = 150.0 * Acts::UnitConstants::mm; - float minImpactSeedConfForward = 1.0 * Acts::UnitConstants::mm; + /////////////////////////////////////// + /// FORWARD / BACKWARD SEED FILTER PARAMETERS + float zMinSeedConfForward = -3000 * Acts::UnitConstants::mm; + float zMaxSeedConfForward = 3000 * Acts::UnitConstants::mm; + float rMaxSeedConfForward = 140 * Acts::UnitConstants::mm; + size_t nTopForLargeRForward = 1; + size_t nTopForSmallRForward = 2; + float seedConfMinBottomRadiusForward = 60.0 * Acts::UnitConstants::mm; + float seedConfMaxZOriginForward = 150.0 * Acts::UnitConstants::mm; + float minImpactSeedConfForward = 1.0 * Acts::UnitConstants::mm; - ////////////////////////////////////// - ///Seed Covariance Error Matrix - float locaError = 1.5 * Acts::UnitConstants::mm; //Error on Loc a - float locbError = 1.5 * Acts::UnitConstants::mm; //Error on Loc b - float phiError = 0.02 * Acts::UnitConstants::rad; //Error on phi - float thetaError = 0.002 * Acts::UnitConstants::rad; //Error on theta - float qOverPError = 0.025 / Acts::UnitConstants::GeV; //Error on q over p - float timeError = 0.1 * Acts::UnitConstants::mm; //Error on time - // Note: Acts native time units are mm: https://acts.readthedocs.io/en/latest/core/definitions/units.html - }; -} + ////////////////////////////////////// + ///Seed Covariance Error Matrix + float locaError = 1.5 * Acts::UnitConstants::mm; //Error on Loc a + float locbError = 1.5 * Acts::UnitConstants::mm; //Error on Loc b + float phiError = 0.02 * Acts::UnitConstants::rad; //Error on phi + float thetaError = 0.002 * Acts::UnitConstants::rad; //Error on theta + float qOverPError = 0.025 / Acts::UnitConstants::GeV; //Error on q over p + float timeError = 0.1 * Acts::UnitConstants::mm; //Error on time + // Note: Acts native time units are mm: https://acts.readthedocs.io/en/latest/core/definitions/units.html +}; +} // namespace eicrecon diff --git a/src/algorithms/tracking/SpacePoint.h b/src/algorithms/tracking/SpacePoint.h index c5401bc60a..f67e1cf83f 100644 --- a/src/algorithms/tracking/SpacePoint.h +++ b/src/algorithms/tracking/SpacePoint.h @@ -6,33 +6,28 @@ #include "ActsGeometryProvider.h" namespace eicrecon { -class SpacePoint : public edm4eic::TrackerHit -{ - public: - const Acts::Surface *m_surface = nullptr; - - SpacePoint(const TrackerHit& hit) : TrackerHit(hit) {} - - void setSurface(std::shared_ptr m_geoSvc) - { - const auto its = m_geoSvc->surfaceMap().find(getCellID()); - if (its == m_geoSvc->surfaceMap().end()) { - m_surface = nullptr; - } - else { - m_surface = its->second; - } +class SpacePoint : public edm4eic::TrackerHit { +public: + const Acts::Surface* m_surface = nullptr; + + SpacePoint(const TrackerHit& hit) : TrackerHit(hit) {} + + void setSurface(std::shared_ptr m_geoSvc) { + const auto its = m_geoSvc->surfaceMap().find(getCellID()); + if (its == m_geoSvc->surfaceMap().end()) { + m_surface = nullptr; + } else { + m_surface = its->second; } + } float x() const { return getPosition()[0]; } float y() const { return getPosition()[1]; } float z() const { return getPosition()[2]; } float r() const { return std::hypot(x(), y()); } - float varianceR() const - { - return (std::pow(x(), 2) * getPositionError().xx + - std::pow(y(), 2) * getPositionError().yy) / - (std::pow(x(), 2) + std::pow(y(), 2)); + float varianceR() const { + return (std::pow(x(), 2) * getPositionError().xx + std::pow(y(), 2) * getPositionError().yy) / + (std::pow(x(), 2) + std::pow(y(), 2)); } float varianceZ() const { return getPositionError().zz; } @@ -40,24 +35,17 @@ class SpacePoint : public edm4eic::TrackerHit if (m_surface == nullptr) { return false; } - return m_surface->isOnSurface(Acts::GeometryContext(), {x(), y(), z()}, - {0, 0, 0}); + return m_surface->isOnSurface(Acts::GeometryContext(), {x(), y(), z()}, {0, 0, 0}); } }; -inline bool operator==(SpacePoint a, SpacePoint b) -{ - return (a.getObjectID() == b.getObjectID()); -} -static bool spCompare(SpacePoint r, SpacePoint s) -{ - return - std::hypot(r.x(), r.y(), r.z()) < - std::hypot(s.x(), s.y(), s.z()); +inline bool operator==(SpacePoint a, SpacePoint b) { return (a.getObjectID() == b.getObjectID()); } +static bool spCompare(SpacePoint r, SpacePoint s) { + return std::hypot(r.x(), r.y(), r.z()) < std::hypot(s.x(), s.y(), s.z()); } using SpacePointPtr = std::unique_ptr; /// Container of sim seed using SeedContainer = std::vector>; -} +} // namespace eicrecon diff --git a/src/algorithms/tracking/TrackParamTruthInit.cc b/src/algorithms/tracking/TrackParamTruthInit.cc index 3d59f00544..ed87e13f89 100644 --- a/src/algorithms/tracking/TrackParamTruthInit.cc +++ b/src/algorithms/tracking/TrackParamTruthInit.cc @@ -28,137 +28,138 @@ #include "extensions/spdlog/SpdlogFormatters.h" // IWYU pragma: keep +void eicrecon::TrackParamTruthInit::init(std::shared_ptr geo_svc, + const std::shared_ptr logger) { + m_log = logger; + m_geoSvc = geo_svc; -void eicrecon::TrackParamTruthInit::init(std::shared_ptr geo_svc, const std::shared_ptr logger) { - m_log = logger; - m_geoSvc = geo_svc; - - // TODO make a service? - m_pdg_db = std::make_shared(); + // TODO make a service? + m_pdg_db = std::make_shared(); } std::unique_ptr eicrecon::TrackParamTruthInit::produce(const edm4hep::MCParticleCollection* mcparticles) { - // MCParticles uses numerical values in its specified units, - // while m_cfg is in the DD4hep unit system - - // Create output collection - auto track_parameters = std::make_unique(); - - // Loop over input particles - for (const auto& mcparticle: *mcparticles) { - - // require generatorStatus == 1 for stable generated particles in HepMC3 and DDSim gun - if (mcparticle.getGeneratorStatus() != 1 ) { - m_log->trace("ignoring particle with generatorStatus = {}", mcparticle.getGeneratorStatus()); - continue; - } - - // require close to interaction vertex - auto v = mcparticle.getVertex(); - if (abs(v.x) * dd4hep::mm > m_cfg.maxVertexX || - abs(v.y) * dd4hep::mm > m_cfg.maxVertexY || - abs(v.z) * dd4hep::mm > m_cfg.maxVertexZ) { - m_log->trace("ignoring particle with vs = {} [mm]", v); - continue; - } - - // require minimum momentum - const auto& p = mcparticle.getMomentum(); - const auto pmag = std::hypot(p.x, p.y, p.z); - if (pmag * dd4hep::GeV < m_cfg.minMomentum) { - m_log->trace("ignoring particle with p = {} GeV ", pmag); - continue; - } - - // require minimum pseudorapidity - const auto phi = std::atan2(p.y, p.x); - const auto theta = std::atan2(std::hypot(p.x, p.y), p.z); - const auto eta = -std::log(std::tan(theta/2)); - if (eta > m_cfg.maxEtaForward || eta < -std::abs(m_cfg.maxEtaBackward)) { - m_log->trace("ignoring particle with Eta = {}", eta); - continue; - } - - // get the particle charge - // note that we cannot trust the mcparticles charge, as DD4hep - // sets this value to zero! let's lookup by PDGID instead - //const double charge = m_pidSvc->particle(mcparticle.getPDG()).charge; - const auto pdg = mcparticle.getPDG(); - const auto* particle = m_pdg_db->GetParticle(pdg); - if (particle == nullptr) { - m_log->debug("particle with PDG {} not in TDatabasePDG", pdg); - continue; - } - double charge = std::copysign(1.0,particle->Charge()); - if (abs(charge) < std::numeric_limits::epsilon()) { - m_log->trace("ignoring neutral particle"); - continue; - } - - // modify initial momentum to avoid bleeding truth to results when fit fails - const auto pinit = pmag * (1.0 + m_cfg.momentumSmear * m_normDist(generator)); - - // define line surface for local position values - auto perigee = Acts::Surface::makeShared(Acts::Vector3(0,0,0)); - - // track particle back to transverse point-of-closest approach - // with respect to the defined line surface - auto linesurface_parameter = -(v.x*p.x + v.y*p.y)/(p.x*p.x + p.y*p.y); - - auto xpca = v.x + linesurface_parameter*p.x; - auto ypca = v.y + linesurface_parameter*p.y; - auto zpca = v.z + linesurface_parameter*p.z; - - Acts::Vector3 global(xpca, ypca, zpca); - Acts::Vector3 direction(sin(theta)*cos(phi), sin(theta)*sin(phi), cos(theta)); - - // convert from global to local coordinates using the defined line surface - auto local = perigee->globalToLocal(m_geoSvc->getActsGeometryContext(), global, direction); - - if(!local.ok()) - { - m_log->error("skipping the track because globaltoLocal function failed"); - continue; - } - - Acts::Vector2 localpos = local.value(); - - // Insert into edm4eic::TrackParameters, which uses numerical values in its specified units - auto track_parameter = track_parameters->create(); - track_parameter.setType(-1); // type --> seed(-1) - track_parameter.setLoc({static_cast(localpos(0)), static_cast(localpos(1))}); // 2d location on surface [mm] - track_parameter.setPhi(phi); // phi [rad] - track_parameter.setTheta(theta); // theta [rad] - track_parameter.setQOverP(charge / (pinit / dd4hep::GeV)); // Q/p [e/GeV] - track_parameter.setTime(mcparticle.getTime()); // time [ns] - #if EDM4EIC_VERSION_MAJOR >= 5 - edm4eic::Cov6f cov; - cov(0,0) = 1.0; // loc0 - cov(1,1) = 1.0; // loc1 - cov(2,2) = 0.05; // phi - cov(3,3) = 0.01; // theta - cov(4,4) = 0.1; // qOverP - cov(5,5) = 10e9; // time - track_parameter.setCovariance(cov); - #else - track_parameter.setCharge(charge); // charge - track_parameter.setLocError({1.0, 1.0}); // sqrt(variance) of location [mm] - track_parameter.setMomentumError({0.01, 0.05, 0.1}); // sqrt(variance) on theta, phi, q/p [rad, rad, e/GeV] - track_parameter.setTimeError(10e9); // error on time [ns] - #endif - - // Debug output - if (m_log->level() <= spdlog::level::debug) { - m_log->debug("Invoke track finding seeded by truth particle with:"); - m_log->debug(" p = {} GeV (smeared to {} GeV)", pmag / dd4hep::GeV, pinit / dd4hep::GeV); - m_log->debug(" q = {}", charge); - m_log->debug(" q/p = {} e/GeV (smeared to {} e/GeV)", charge / (pmag / dd4hep::GeV), charge / (pinit / dd4hep::GeV)); - m_log->debug(" theta = {}", theta); - m_log->debug(" phi = {}", phi); - } + // MCParticles uses numerical values in its specified units, + // while m_cfg is in the DD4hep unit system + + // Create output collection + auto track_parameters = std::make_unique(); + + // Loop over input particles + for (const auto& mcparticle : *mcparticles) { + + // require generatorStatus == 1 for stable generated particles in HepMC3 and DDSim gun + if (mcparticle.getGeneratorStatus() != 1) { + m_log->trace("ignoring particle with generatorStatus = {}", mcparticle.getGeneratorStatus()); + continue; + } + + // require close to interaction vertex + auto v = mcparticle.getVertex(); + if (abs(v.x) * dd4hep::mm > m_cfg.maxVertexX || abs(v.y) * dd4hep::mm > m_cfg.maxVertexY || + abs(v.z) * dd4hep::mm > m_cfg.maxVertexZ) { + m_log->trace("ignoring particle with vs = {} [mm]", v); + continue; + } + + // require minimum momentum + const auto& p = mcparticle.getMomentum(); + const auto pmag = std::hypot(p.x, p.y, p.z); + if (pmag * dd4hep::GeV < m_cfg.minMomentum) { + m_log->trace("ignoring particle with p = {} GeV ", pmag); + continue; + } + + // require minimum pseudorapidity + const auto phi = std::atan2(p.y, p.x); + const auto theta = std::atan2(std::hypot(p.x, p.y), p.z); + const auto eta = -std::log(std::tan(theta / 2)); + if (eta > m_cfg.maxEtaForward || eta < -std::abs(m_cfg.maxEtaBackward)) { + m_log->trace("ignoring particle with Eta = {}", eta); + continue; + } + + // get the particle charge + // note that we cannot trust the mcparticles charge, as DD4hep + // sets this value to zero! let's lookup by PDGID instead + //const double charge = m_pidSvc->particle(mcparticle.getPDG()).charge; + const auto pdg = mcparticle.getPDG(); + const auto* particle = m_pdg_db->GetParticle(pdg); + if (particle == nullptr) { + m_log->debug("particle with PDG {} not in TDatabasePDG", pdg); + continue; + } + double charge = std::copysign(1.0, particle->Charge()); + if (abs(charge) < std::numeric_limits::epsilon()) { + m_log->trace("ignoring neutral particle"); + continue; } - return std::move(track_parameters); + // modify initial momentum to avoid bleeding truth to results when fit fails + const auto pinit = pmag * (1.0 + m_cfg.momentumSmear * m_normDist(generator)); + + // define line surface for local position values + auto perigee = Acts::Surface::makeShared(Acts::Vector3(0, 0, 0)); + + // track particle back to transverse point-of-closest approach + // with respect to the defined line surface + auto linesurface_parameter = -(v.x * p.x + v.y * p.y) / (p.x * p.x + p.y * p.y); + + auto xpca = v.x + linesurface_parameter * p.x; + auto ypca = v.y + linesurface_parameter * p.y; + auto zpca = v.z + linesurface_parameter * p.z; + + Acts::Vector3 global(xpca, ypca, zpca); + Acts::Vector3 direction(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta)); + + // convert from global to local coordinates using the defined line surface + auto local = perigee->globalToLocal(m_geoSvc->getActsGeometryContext(), global, direction); + + if (!local.ok()) { + m_log->error("skipping the track because globaltoLocal function failed"); + continue; + } + + Acts::Vector2 localpos = local.value(); + + // Insert into edm4eic::TrackParameters, which uses numerical values in its specified units + auto track_parameter = track_parameters->create(); + track_parameter.setType(-1); // type --> seed(-1) + track_parameter.setLoc({static_cast(localpos(0)), + static_cast(localpos(1))}); // 2d location on surface [mm] + track_parameter.setPhi(phi); // phi [rad] + track_parameter.setTheta(theta); // theta [rad] + track_parameter.setQOverP(charge / (pinit / dd4hep::GeV)); // Q/p [e/GeV] + track_parameter.setTime(mcparticle.getTime()); // time [ns] +#if EDM4EIC_VERSION_MAJOR >= 5 + edm4eic::Cov6f cov; + cov(0, 0) = 1.0; // loc0 + cov(1, 1) = 1.0; // loc1 + cov(2, 2) = 0.05; // phi + cov(3, 3) = 0.01; // theta + cov(4, 4) = 0.1; // qOverP + cov(5, 5) = 10e9; // time + track_parameter.setCovariance(cov); +#else + track_parameter.setCharge(charge); // charge + track_parameter.setLocError({1.0, 1.0}); // sqrt(variance) of location [mm] + track_parameter.setMomentumError( + {0.01, 0.05, 0.1}); // sqrt(variance) on theta, phi, q/p [rad, rad, e/GeV] + track_parameter.setTimeError(10e9); // error on time [ns] +#endif + + // Debug output + if (m_log->level() <= spdlog::level::debug) { + m_log->debug("Invoke track finding seeded by truth particle with:"); + m_log->debug(" p = {} GeV (smeared to {} GeV)", pmag / dd4hep::GeV, + pinit / dd4hep::GeV); + m_log->debug(" q = {}", charge); + m_log->debug(" q/p = {} e/GeV (smeared to {} e/GeV)", charge / (pmag / dd4hep::GeV), + charge / (pinit / dd4hep::GeV)); + m_log->debug(" theta = {}", theta); + m_log->debug(" phi = {}", phi); + } + } + return std::move(track_parameters); } diff --git a/src/algorithms/tracking/TrackParamTruthInit.h b/src/algorithms/tracking/TrackParamTruthInit.h index 7f9de2c0e9..fc6d8e8e82 100644 --- a/src/algorithms/tracking/TrackParamTruthInit.h +++ b/src/algorithms/tracking/TrackParamTruthInit.h @@ -16,23 +16,22 @@ #include "algorithms/interfaces/WithPodConfig.h" namespace eicrecon { - class TrackParamTruthInit: public WithPodConfig { +class TrackParamTruthInit : public WithPodConfig { - public: +public: + void init(std::shared_ptr geo_svc, + const std::shared_ptr logger); - void init(std::shared_ptr geo_svc, const std::shared_ptr logger); + std::unique_ptr + produce(const edm4hep::MCParticleCollection* parts); - std::unique_ptr - produce(const edm4hep::MCParticleCollection* parts); +private: + std::shared_ptr m_log; + std::shared_ptr m_pdg_db; + std::shared_ptr m_geoSvc; - private: - std::shared_ptr m_log; - std::shared_ptr m_pdg_db; - std::shared_ptr m_geoSvc; - - std::default_random_engine generator; // TODO: need something more appropriate here - std::uniform_int_distribution m_uniformIntDist{-1, 1}; // defaults to min=-1, max=1 - std::normal_distribution m_normDist; - - }; -} // namespace eicrecon + std::default_random_engine generator; // TODO: need something more appropriate here + std::uniform_int_distribution m_uniformIntDist{-1, 1}; // defaults to min=-1, max=1 + std::normal_distribution m_normDist; +}; +} // namespace eicrecon diff --git a/src/algorithms/tracking/TrackParamTruthInitConfig.h b/src/algorithms/tracking/TrackParamTruthInitConfig.h index d09c479b8e..09ae8ec69a 100644 --- a/src/algorithms/tracking/TrackParamTruthInitConfig.h +++ b/src/algorithms/tracking/TrackParamTruthInitConfig.h @@ -8,12 +8,11 @@ struct TrackParamTruthInitConfig { - double maxVertexX = 80 * dd4hep::mm; - double maxVertexY = 80 * dd4hep::mm; - double maxVertexZ = 200 * dd4hep::mm; - double minMomentum = 100 * dd4hep::MeV; - double maxEtaForward = 6.0; - double maxEtaBackward = 4.1; - double momentumSmear = 0.1; - + double maxVertexX = 80 * dd4hep::mm; + double maxVertexY = 80 * dd4hep::mm; + double maxVertexZ = 200 * dd4hep::mm; + double minMomentum = 100 * dd4hep::MeV; + double maxEtaForward = 6.0; + double maxEtaBackward = 4.1; + double momentumSmear = 0.1; }; diff --git a/src/algorithms/tracking/TrackProjector.cc b/src/algorithms/tracking/TrackProjector.cc index 68eb0859cf..a2596b3eb2 100644 --- a/src/algorithms/tracking/TrackProjector.cc +++ b/src/algorithms/tracking/TrackProjector.cc @@ -25,188 +25,164 @@ #include "extensions/spdlog/SpdlogFormatters.h" // IWYU pragma: keep #if FMT_VERSION >= 90000 -template<> struct fmt::formatter : fmt::ostream_formatter {}; +template <> struct fmt::formatter : fmt::ostream_formatter {}; #endif // FMT_VERSION >= 90000 namespace eicrecon { - void - TrackProjector::init(std::shared_ptr geo_svc, std::shared_ptr logger) { - m_log = logger; - m_geo_provider = geo_svc; +void TrackProjector::init(std::shared_ptr geo_svc, + std::shared_ptr logger) { + m_log = logger; + m_geo_provider = geo_svc; +} + +std::unique_ptr +TrackProjector::execute(std::vector trajectories) { + + // create output collections + auto track_segments = std::make_unique(); + m_log->debug("Track projector event process. Num of input trajectories: {}", + std::size(trajectories)); + + // Loop over the trajectories + for (const auto& traj : trajectories) { + // Get the entry index for the single trajectory + // The trajectory entry indices and the multiTrajectory + const auto& mj = traj->multiTrajectory(); + const auto& trackTips = traj->tips(); + m_log->debug("------ Trajectory ------"); + m_log->debug(" Num of elements in trackTips {}", trackTips.size()); + + // Skip empty + if (trackTips.empty()) { + m_log->debug(" Empty multiTrajectory."); + continue; } - - - std::unique_ptr TrackProjector::execute(std::vector trajectories) { - - // create output collections - auto track_segments = std::make_unique(); - m_log->debug("Track projector event process. Num of input trajectories: {}", std::size(trajectories)); - - // Loop over the trajectories - for (const auto &traj: trajectories) { - // Get the entry index for the single trajectory - // The trajectory entry indices and the multiTrajectory - const auto &mj = traj->multiTrajectory(); - const auto &trackTips = traj->tips(); - m_log->debug("------ Trajectory ------"); - m_log->debug(" Num of elements in trackTips {}", trackTips.size()); - - // Skip empty - if (trackTips.empty()) { - m_log->debug(" Empty multiTrajectory."); - continue; - } - const auto &trackTip = trackTips.front(); - - // Collect the trajectory summary info - auto trajState = Acts::MultiTrajectoryHelpers::trajectoryState(mj, trackTip); - int m_nMeasurements = trajState.nMeasurements; - int m_nStates = trajState.nStates; - int m_nCalibrated = 0; - m_log->debug(" Num measurement in trajectory {}", m_nMeasurements); - m_log->debug(" Num state in trajectory {}", m_nStates); - - auto track_segment = track_segments->create(); - - // visit the track points - mj.visitBackwards(trackTip, [&](auto &&trackstate) { - // get volume info - auto geoID = trackstate.referenceSurface().geometryId(); - auto volume = geoID.volume(); - auto layer = geoID.layer(); - - if (trackstate.hasCalibrated()) { - m_nCalibrated++; - } - - // get track state parameters and their covariances - const auto ¶meter = trackstate.predicted(); - const auto &covariance = trackstate.predictedCovariance(); - - // convert local to global - auto global = trackstate.referenceSurface().localToGlobal( - m_geo_provider->getActsGeometryContext(), - {parameter[Acts::eBoundLoc0], parameter[Acts::eBoundLoc1]}, - Acts::makeDirectionFromPhiTheta( - parameter[Acts::eBoundPhi], - parameter[Acts::eBoundTheta] - ) - ); - auto jacobian = trackstate.referenceSurface().boundToFreeJacobian( - m_geo_provider->getActsGeometryContext(), - parameter - ); - auto free_covariance = jacobian * covariance * jacobian.transpose(); - - // global position - const decltype(edm4eic::TrackPoint::position) position{ - static_cast(global.x()), - static_cast(global.y()), - static_cast(global.z()) - }; - - // local position - const decltype(edm4eic::TrackParametersData::loc) loc{ - static_cast(parameter[Acts::eBoundLoc0]), - static_cast(parameter[Acts::eBoundLoc1]) - }; - const edm4eic::Cov2f locError{ - static_cast(covariance(Acts::eBoundLoc0, Acts::eBoundLoc0)), - static_cast(covariance(Acts::eBoundLoc1, Acts::eBoundLoc1)), - static_cast(covariance(Acts::eBoundLoc0, Acts::eBoundLoc1)) - }; - const decltype(edm4eic::TrackPoint::positionError) positionError{ - static_cast(free_covariance(Acts::eFreePos0, Acts::eFreePos0)), - static_cast(free_covariance(Acts::eFreePos1, Acts::eFreePos1)), - static_cast(free_covariance(Acts::eFreePos2, Acts::eFreePos2)), - static_cast(free_covariance(Acts::eFreePos0, Acts::eFreePos1)), - static_cast(free_covariance(Acts::eFreePos0, Acts::eFreePos2)), - static_cast(free_covariance(Acts::eFreePos1, Acts::eFreePos2)), - }; - - // momentum - const decltype(edm4eic::TrackPoint::momentum) momentum = edm4hep::utils::sphericalToVector( - static_cast(1.0 / std::abs(parameter[Acts::eBoundQOverP])), - static_cast(parameter[Acts::eBoundTheta]), - static_cast(parameter[Acts::eBoundPhi]) - ); - const decltype(edm4eic::TrackPoint::momentumError) momentumError{ - static_cast(covariance(Acts::eBoundTheta, Acts::eBoundTheta)), - static_cast(covariance(Acts::eBoundPhi, Acts::eBoundPhi)), - static_cast(covariance(Acts::eBoundQOverP, Acts::eBoundQOverP)), - static_cast(covariance(Acts::eBoundTheta, Acts::eBoundPhi)), - static_cast(covariance(Acts::eBoundTheta, Acts::eBoundQOverP)), - static_cast(covariance(Acts::eBoundPhi, Acts::eBoundQOverP)) - }; - const float time{static_cast(parameter(Acts::eBoundTime))}; - const float timeError{sqrt(static_cast(covariance(Acts::eBoundTime, Acts::eBoundTime)))}; - const float theta(parameter[Acts::eBoundTheta]); - const float phi(parameter[Acts::eBoundPhi]); - const decltype(edm4eic::TrackPoint::directionError) directionError{ - static_cast(covariance(Acts::eBoundTheta, Acts::eBoundTheta)), - static_cast(covariance(Acts::eBoundPhi, Acts::eBoundPhi)), - static_cast(covariance(Acts::eBoundTheta, Acts::eBoundPhi)) - }; - const float pathLength = static_cast(trackstate.pathLength()); - const float pathLengthError = 0; - - uint64_t surface = trackstate.referenceSurface().geometryId().value(); - uint32_t system = 0; - - // Store track point - track_segment.addToPoints({ - surface, - system, - position, - positionError, - momentum, - momentumError, - time, - timeError, - theta, - phi, - directionError, - pathLength, - pathLengthError - }); - - - m_log->debug(" ******************************"); - m_log->debug(" position: {}", position); - m_log->debug(" positionError: {}", positionError); - m_log->debug(" momentum: {}", momentum); - m_log->debug(" momentumError: {}", momentumError); - m_log->debug(" time: {}", time); - m_log->debug(" timeError: {}", timeError); - m_log->debug(" theta: {}", theta); - m_log->debug(" phi: {}", phi); - m_log->debug(" directionError: {}", directionError); - m_log->debug(" pathLength: {}", pathLength); - m_log->debug(" pathLengthError: {}", pathLengthError); - m_log->debug(" geoID = {}", geoID); - m_log->debug(" volume = {}, layer = {}", volume, layer); - m_log->debug(" pathlength = {}", pathLength); - m_log->debug(" hasCalibrated = {}", trackstate.hasCalibrated()); - m_log->debug(" ******************************"); - - // Local position on the reference surface. - //m_log->debug("parameter[eBoundLoc0] = {}", parameter[Acts::eBoundLoc0]); - //m_log->debug("parameter[eBoundLoc1] = {}", parameter[Acts::eBoundLoc1]); - //m_log->debug("parameter[eBoundPhi] = {}", parameter[Acts::eBoundPhi]); - //m_log->debug("parameter[eBoundTheta] = {}", parameter[Acts::eBoundTheta]); - //m_log->debug("parameter[eBoundQOverP] = {}", parameter[Acts::eBoundQOverP]); - //m_log->debug("parameter[eBoundTime] = {}", parameter[Acts::eBoundTime]); - //m_log->debug("predicted variables: {}", trackstate.predicted()); - }); - - m_log->debug(" Num calibrated state in trajectory {}", m_nCalibrated); - m_log->debug("------ end of trajectory process ------"); - } - - m_log->debug("END OF Track projector event process"); - return std::move(track_segments); - } - - -} // namespace eicrecon::Reco + const auto& trackTip = trackTips.front(); + + // Collect the trajectory summary info + auto trajState = Acts::MultiTrajectoryHelpers::trajectoryState(mj, trackTip); + int m_nMeasurements = trajState.nMeasurements; + int m_nStates = trajState.nStates; + int m_nCalibrated = 0; + m_log->debug(" Num measurement in trajectory {}", m_nMeasurements); + m_log->debug(" Num state in trajectory {}", m_nStates); + + auto track_segment = track_segments->create(); + + // visit the track points + mj.visitBackwards(trackTip, [&](auto&& trackstate) { + // get volume info + auto geoID = trackstate.referenceSurface().geometryId(); + auto volume = geoID.volume(); + auto layer = geoID.layer(); + + if (trackstate.hasCalibrated()) { + m_nCalibrated++; + } + + // get track state parameters and their covariances + const auto& parameter = trackstate.predicted(); + const auto& covariance = trackstate.predictedCovariance(); + + // convert local to global + auto global = trackstate.referenceSurface().localToGlobal( + m_geo_provider->getActsGeometryContext(), + {parameter[Acts::eBoundLoc0], parameter[Acts::eBoundLoc1]}, + Acts::makeDirectionFromPhiTheta(parameter[Acts::eBoundPhi], + parameter[Acts::eBoundTheta])); + auto jacobian = trackstate.referenceSurface().boundToFreeJacobian( + m_geo_provider->getActsGeometryContext(), parameter); + auto free_covariance = jacobian * covariance * jacobian.transpose(); + + // global position + const decltype(edm4eic::TrackPoint::position) position{static_cast(global.x()), + static_cast(global.y()), + static_cast(global.z())}; + + // local position + const decltype(edm4eic::TrackParametersData::loc) loc{ + static_cast(parameter[Acts::eBoundLoc0]), + static_cast(parameter[Acts::eBoundLoc1])}; + const edm4eic::Cov2f locError{ + static_cast(covariance(Acts::eBoundLoc0, Acts::eBoundLoc0)), + static_cast(covariance(Acts::eBoundLoc1, Acts::eBoundLoc1)), + static_cast(covariance(Acts::eBoundLoc0, Acts::eBoundLoc1))}; + const decltype(edm4eic::TrackPoint::positionError) positionError{ + static_cast(free_covariance(Acts::eFreePos0, Acts::eFreePos0)), + static_cast(free_covariance(Acts::eFreePos1, Acts::eFreePos1)), + static_cast(free_covariance(Acts::eFreePos2, Acts::eFreePos2)), + static_cast(free_covariance(Acts::eFreePos0, Acts::eFreePos1)), + static_cast(free_covariance(Acts::eFreePos0, Acts::eFreePos2)), + static_cast(free_covariance(Acts::eFreePos1, Acts::eFreePos2)), + }; + + // momentum + const decltype(edm4eic::TrackPoint::momentum) momentum = edm4hep::utils::sphericalToVector( + static_cast(1.0 / std::abs(parameter[Acts::eBoundQOverP])), + static_cast(parameter[Acts::eBoundTheta]), + static_cast(parameter[Acts::eBoundPhi])); + const decltype(edm4eic::TrackPoint::momentumError) momentumError{ + static_cast(covariance(Acts::eBoundTheta, Acts::eBoundTheta)), + static_cast(covariance(Acts::eBoundPhi, Acts::eBoundPhi)), + static_cast(covariance(Acts::eBoundQOverP, Acts::eBoundQOverP)), + static_cast(covariance(Acts::eBoundTheta, Acts::eBoundPhi)), + static_cast(covariance(Acts::eBoundTheta, Acts::eBoundQOverP)), + static_cast(covariance(Acts::eBoundPhi, Acts::eBoundQOverP))}; + const float time{static_cast(parameter(Acts::eBoundTime))}; + const float timeError{ + sqrt(static_cast(covariance(Acts::eBoundTime, Acts::eBoundTime)))}; + const float theta(parameter[Acts::eBoundTheta]); + const float phi(parameter[Acts::eBoundPhi]); + const decltype(edm4eic::TrackPoint::directionError) directionError{ + static_cast(covariance(Acts::eBoundTheta, Acts::eBoundTheta)), + static_cast(covariance(Acts::eBoundPhi, Acts::eBoundPhi)), + static_cast(covariance(Acts::eBoundTheta, Acts::eBoundPhi))}; + const float pathLength = static_cast(trackstate.pathLength()); + const float pathLengthError = 0; + + uint64_t surface = trackstate.referenceSurface().geometryId().value(); + uint32_t system = 0; + + // Store track point + track_segment.addToPoints({surface, system, position, positionError, momentum, momentumError, + time, timeError, theta, phi, directionError, pathLength, + pathLengthError}); + + m_log->debug(" ******************************"); + m_log->debug(" position: {}", position); + m_log->debug(" positionError: {}", positionError); + m_log->debug(" momentum: {}", momentum); + m_log->debug(" momentumError: {}", momentumError); + m_log->debug(" time: {}", time); + m_log->debug(" timeError: {}", timeError); + m_log->debug(" theta: {}", theta); + m_log->debug(" phi: {}", phi); + m_log->debug(" directionError: {}", directionError); + m_log->debug(" pathLength: {}", pathLength); + m_log->debug(" pathLengthError: {}", pathLengthError); + m_log->debug(" geoID = {}", geoID); + m_log->debug(" volume = {}, layer = {}", volume, layer); + m_log->debug(" pathlength = {}", pathLength); + m_log->debug(" hasCalibrated = {}", trackstate.hasCalibrated()); + m_log->debug(" ******************************"); + + // Local position on the reference surface. + //m_log->debug("parameter[eBoundLoc0] = {}", parameter[Acts::eBoundLoc0]); + //m_log->debug("parameter[eBoundLoc1] = {}", parameter[Acts::eBoundLoc1]); + //m_log->debug("parameter[eBoundPhi] = {}", parameter[Acts::eBoundPhi]); + //m_log->debug("parameter[eBoundTheta] = {}", parameter[Acts::eBoundTheta]); + //m_log->debug("parameter[eBoundQOverP] = {}", parameter[Acts::eBoundQOverP]); + //m_log->debug("parameter[eBoundTime] = {}", parameter[Acts::eBoundTime]); + //m_log->debug("predicted variables: {}", trackstate.predicted()); + }); + + m_log->debug(" Num calibrated state in trajectory {}", m_nCalibrated); + m_log->debug("------ end of trajectory process ------"); + } + + m_log->debug("END OF Track projector event process"); + return std::move(track_segments); +} + +} // namespace eicrecon diff --git a/src/algorithms/tracking/TrackProjector.h b/src/algorithms/tracking/TrackProjector.h index d1aa9fa5d2..5809fe1656 100644 --- a/src/algorithms/tracking/TrackProjector.h +++ b/src/algorithms/tracking/TrackProjector.h @@ -13,27 +13,24 @@ #include "ActsGeometryProvider.h" #include "algorithms/interfaces/WithPodConfig.h" - namespace eicrecon { - /** Extract the particles form fit trajectories. +/** Extract the particles form fit trajectories. * * \ingroup tracking */ - class TrackProjector { - - public: - - void init(std::shared_ptr geo_svc, std::shared_ptr logger); - - std::unique_ptr execute(std::vector trajectories); - - private: - std::shared_ptr m_geo_provider; - std::shared_ptr m_log; +class TrackProjector { - }; +public: + void init(std::shared_ptr geo_svc, + std::shared_ptr logger); + std::unique_ptr + execute(std::vector trajectories); +private: + std::shared_ptr m_geo_provider; + std::shared_ptr m_log; +}; -} // eicrecon +} // namespace eicrecon diff --git a/src/algorithms/tracking/TrackPropagation.cc b/src/algorithms/tracking/TrackPropagation.cc index 12f8cdff9e..9c7257f347 100644 --- a/src/algorithms/tracking/TrackPropagation.cc +++ b/src/algorithms/tracking/TrackPropagation.cc @@ -46,276 +46,276 @@ namespace eicrecon { -template -struct multilambda : L... { +template struct multilambda : L... { using L::operator()...; - constexpr multilambda(L...lambda) : L(std::move(lambda))... {} + constexpr multilambda(L... lambda) : L(std::move(lambda))... {} }; void TrackPropagation::init(const dd4hep::Detector* detector, std::shared_ptr geo_svc, std::shared_ptr logger) { - m_geoSvc = geo_svc; - m_log = logger; + m_geoSvc = geo_svc; + m_log = logger; - std::map system_id_layers; + std::map system_id_layers; - multilambda _toDouble = { + multilambda _toDouble = { [](const std::string& v) { return dd4hep::_toDouble(v); }, - [](const double& v) { return v; }, - }; - - for (auto& surface_variant: m_cfg.surfaces) { - if (std::holds_alternative(surface_variant)) { - CylinderSurfaceConfig surface = std::get(surface_variant); - const double rmin = std::visit(_toDouble, surface.rmin) / dd4hep::mm * Acts::UnitConstants::mm; - const double zmin = std::visit(_toDouble, surface.zmin) / dd4hep::mm * Acts::UnitConstants::mm; - const double zmax = std::visit(_toDouble, surface.zmax) / dd4hep::mm * Acts::UnitConstants::mm; - const uint32_t system_id = detector->constant(surface.id); - auto bounds = std::make_shared(rmin, (zmax-zmin)/2); - auto t = Acts::Translation3(Acts::Vector3(0, 0, (zmax+zmin)/2)); - auto tf = Acts::Transform3(t); - auto acts_surface = Acts::Surface::makeShared(tf, bounds); - acts_surface->assignGeometryId(Acts::GeometryIdentifier().setExtra(system_id).setLayer(++system_id_layers[system_id])); - m_target_surface_list.push_back(acts_surface); - } - if (std::holds_alternative(surface_variant)) { - DiscSurfaceConfig surface = std::get(surface_variant); - const double zmin = std::visit(_toDouble, surface.zmin) / dd4hep::mm * Acts::UnitConstants::mm; - const double rmin = std::visit(_toDouble, surface.rmin) / dd4hep::mm * Acts::UnitConstants::mm; - const double rmax = std::visit(_toDouble, surface.rmax) / dd4hep::mm * Acts::UnitConstants::mm; - const uint32_t system_id = detector->constant(surface.id); - auto bounds = std::make_shared(rmin, rmax); - auto t = Acts::Translation3(Acts::Vector3(0, 0, zmin)); - auto tf = Acts::Transform3(t); - auto acts_surface = Acts::Surface::makeShared(tf, bounds); - acts_surface->assignGeometryId(Acts::GeometryIdentifier().setExtra(system_id).setLayer(++system_id_layers[system_id])); - m_target_surface_list.push_back(acts_surface); - } + [](const double& v) { return v; }, + }; + + for (auto& surface_variant : m_cfg.surfaces) { + if (std::holds_alternative(surface_variant)) { + CylinderSurfaceConfig surface = std::get(surface_variant); + const double rmin = + std::visit(_toDouble, surface.rmin) / dd4hep::mm * Acts::UnitConstants::mm; + const double zmin = + std::visit(_toDouble, surface.zmin) / dd4hep::mm * Acts::UnitConstants::mm; + const double zmax = + std::visit(_toDouble, surface.zmax) / dd4hep::mm * Acts::UnitConstants::mm; + const uint32_t system_id = detector->constant(surface.id); + auto bounds = std::make_shared(rmin, (zmax - zmin) / 2); + auto t = Acts::Translation3(Acts::Vector3(0, 0, (zmax + zmin) / 2)); + auto tf = Acts::Transform3(t); + auto acts_surface = Acts::Surface::makeShared(tf, bounds); + acts_surface->assignGeometryId( + Acts::GeometryIdentifier().setExtra(system_id).setLayer(++system_id_layers[system_id])); + m_target_surface_list.push_back(acts_surface); } + if (std::holds_alternative(surface_variant)) { + DiscSurfaceConfig surface = std::get(surface_variant); + const double zmin = + std::visit(_toDouble, surface.zmin) / dd4hep::mm * Acts::UnitConstants::mm; + const double rmin = + std::visit(_toDouble, surface.rmin) / dd4hep::mm * Acts::UnitConstants::mm; + const double rmax = + std::visit(_toDouble, surface.rmax) / dd4hep::mm * Acts::UnitConstants::mm; + const uint32_t system_id = detector->constant(surface.id); + auto bounds = std::make_shared(rmin, rmax); + auto t = Acts::Translation3(Acts::Vector3(0, 0, zmin)); + auto tf = Acts::Transform3(t); + auto acts_surface = Acts::Surface::makeShared(tf, bounds); + acts_surface->assignGeometryId( + Acts::GeometryIdentifier().setExtra(system_id).setLayer(++system_id_layers[system_id])); + m_target_surface_list.push_back(acts_surface); + } + } - m_log->trace("Initialized"); + m_log->trace("Initialized"); } - - - std::unique_ptr TrackPropagation::propagateToSurfaceList( - std::vector trajectories, - std::vector> targetSurfaces, - std::shared_ptr filterSurface, - std::function trackPointCut, - bool stopIfTrackPointCutFailed - ) const - { - // logging - m_log->trace("Propagate trajectories: --------------------"); - m_log->trace("number of trajectories: {}",trajectories.size()); - - // start output collection - auto track_segments = std::make_unique(); - - // loop over input trajectories - for(const auto& traj : trajectories) { - - // check if this trajectory can be propagated to `filterSurface` - if(filterSurface) { - try { - if(!propagate(traj, filterSurface)) { - m_log->trace("<> Skip this trajectory, since it cannot be propagated to filterSurface"); - continue; - } - } catch(std::exception &e) { - m_log->warn("<> Exception in TrackPropagation::propagateToSurfaceList: {}; skip this TrackPoint and surface", e.what()); - continue; - } +std::unique_ptr TrackPropagation::propagateToSurfaceList( + std::vector trajectories, + std::vector> targetSurfaces, + std::shared_ptr filterSurface, + std::function trackPointCut, bool stopIfTrackPointCutFailed) const { + // logging + m_log->trace("Propagate trajectories: --------------------"); + m_log->trace("number of trajectories: {}", trajectories.size()); + + // start output collection + auto track_segments = std::make_unique(); + + // loop over input trajectories + for (const auto& traj : trajectories) { + + // check if this trajectory can be propagated to `filterSurface` + if (filterSurface) { + try { + if (!propagate(traj, filterSurface)) { + m_log->trace("<> Skip this trajectory, since it cannot be propagated to filterSurface"); + continue; } - - // start a mutable TrackSegment - auto track_segment = track_segments->create(); - decltype(edm4eic::TrackSegmentData::length) length = 0; - decltype(edm4eic::TrackSegmentData::lengthError) length_error = 0; - - // loop over projection-target surfaces - for(const auto& targetSurf : targetSurfaces) { - - // project the trajectory `traj` to this surface - std::unique_ptr point; - try { - point = propagate(traj, targetSurf); - } catch(std::exception &e) { - m_log->warn("<> Exception in TrackPropagation::propagateToSurfaceList: {}; skip this TrackPoint and surface", e.what()); - continue; - } - if(!point) { - m_log->trace("<> Failed to propagate trajectory to this plane"); - continue; - } - - // logging - m_log->trace("<> trajectory: x=( {:>10.2f} {:>10.2f} {:>10.2f} )", - point->position.x, point->position.y, point->position.z); - m_log->trace(" p=( {:>10.2f} {:>10.2f} {:>10.2f} )", - point->momentum.x, point->momentum.y, point->momentum.z); - - // track point cut - if(!trackPointCut(*point)) { - m_log->trace(" => REJECTED by trackPointCut"); - if(stopIfTrackPointCutFailed) - break; - continue; - } - - // update the `TrackSegment` length - // FIXME: `length` and `length_error` are currently not used by any callers, and may not be correctly calculated here - if(track_segment.points_size()>0) { - auto pos0 = point->position; - auto pos1 = std::prev(track_segment.points_end())->position; - auto dist = edm4hep::utils::magnitude(pos0-pos1); - length += dist; - m_log->trace(" dist to previous point: {}", dist); - } - - // add the `TrackPoint` to the `TrackSegment` - track_segment.addToPoints(*point); - - } // end `targetSurfaces` loop - - // set final length and length error - track_segment.setLength(length); - track_segment.setLengthError(length_error); - - } // end loop over input trajectories - - return track_segments; + } catch (std::exception& e) { + m_log->warn("<> Exception in TrackPropagation::propagateToSurfaceList: {}; skip this " + "TrackPoint and surface", + e.what()); + continue; + } } + // start a mutable TrackSegment + auto track_segment = track_segments->create(); + decltype(edm4eic::TrackSegmentData::length) length = 0; + decltype(edm4eic::TrackSegmentData::lengthError) length_error = 0; + + // loop over projection-target surfaces + for (const auto& targetSurf : targetSurfaces) { + + // project the trajectory `traj` to this surface + std::unique_ptr point; + try { + point = propagate(traj, targetSurf); + } catch (std::exception& e) { + m_log->warn("<> Exception in TrackPropagation::propagateToSurfaceList: {}; skip this " + "TrackPoint and surface", + e.what()); + continue; + } + if (!point) { + m_log->trace("<> Failed to propagate trajectory to this plane"); + continue; + } + // logging + m_log->trace("<> trajectory: x=( {:>10.2f} {:>10.2f} {:>10.2f} )", point->position.x, + point->position.y, point->position.z); + m_log->trace(" p=( {:>10.2f} {:>10.2f} {:>10.2f} )", point->momentum.x, + point->momentum.y, point->momentum.z); + + // track point cut + if (!trackPointCut(*point)) { + m_log->trace(" => REJECTED by trackPointCut"); + if (stopIfTrackPointCutFailed) + break; + continue; + } - std::unique_ptr TrackPropagation::propagate(const ActsExamples::Trajectories *traj, - const std::shared_ptr &targetSurf) const { - // Get the entry index for the single trajectory - // The trajectory entry indices and the multiTrajectory - const auto &mj = traj->multiTrajectory(); - const auto &trackTips = traj->tips(); - - m_log->trace(" Number of elements in trackTips {}", trackTips.size()); - - // Skip empty - if (trackTips.empty()) { - m_log->trace(" Empty multiTrajectory."); - return nullptr; - } - const auto &trackTip = trackTips.front(); - - // Collect the trajectory summary info - auto trajState = Acts::MultiTrajectoryHelpers::trajectoryState(mj, trackTip); - int m_nMeasurements = trajState.nMeasurements; - int m_nStates = trajState.nStates; - - m_log->trace(" Num measurement in trajectory: {}", m_nMeasurements); - m_log->trace(" Num states in trajectory : {}", m_nStates); - - - - //================================================= - //Track projection - //Reference sPHENIX code: https://github.com/sPHENIX-Collaboration/coresoftware/blob/335e6da4ccacc8374cada993485fe81d82e74a4f/offline/packages/trackreco/PHActsTrackProjection.h - //================================================= - const auto &initial_bound_parameters = traj->trackParameters(trackTip); - + // update the `TrackSegment` length + // FIXME: `length` and `length_error` are currently not used by any callers, and may not be correctly calculated here + if (track_segment.points_size() > 0) { + auto pos0 = point->position; + auto pos1 = std::prev(track_segment.points_end())->position; + auto dist = edm4hep::utils::magnitude(pos0 - pos1); + length += dist; + m_log->trace(" dist to previous point: {}", dist); + } - m_log->trace(" TrackPropagation. Propagating to surface # {}", typeid(targetSurf->type()).name()); + // add the `TrackPoint` to the `TrackSegment` + track_segment.addToPoints(*point); - std::shared_ptr trackingGeometry = m_geoSvc->trackingGeometry(); - std::shared_ptr magneticField = m_geoSvc->getFieldProvider(); - using Stepper = Acts::EigenStepper<>; - using Propagator = Acts::Propagator; - Stepper stepper(magneticField); - Propagator propagator(stepper); + } // end `targetSurfaces` loop - ACTS_LOCAL_LOGGER(eicrecon::getSpdlogLogger("PROP", m_log)); + // set final length and length error + track_segment.setLength(length); + track_segment.setLengthError(length_error); - Acts::PropagatorOptions<> options(m_geoContext, m_fieldContext); + } // end loop over input trajectories - auto result = propagator.propagate(initial_bound_parameters, *targetSurf, options); + return track_segments; +} - // check propagation result - if (!result.ok()) { - m_log->trace(" propagation failed (!result.ok())"); - return nullptr; - } - m_log->trace(" propagation result is OK"); - - // Pulling results to convenient variables - auto trackStateParams = *((*result).endParameters); - const auto ¶meter = trackStateParams.parameters(); - const auto &covariance = *trackStateParams.covariance(); - - // Path length - const float pathLength = (*result).pathLength; - const float pathLengthError = 0; - m_log->trace(" path len = {}", pathLength); - - // Position: - auto projectionPos = trackStateParams.position(m_geoContext); - const decltype(edm4eic::TrackPoint::position) position{ - static_cast(projectionPos(0)), - static_cast(projectionPos(1)), - static_cast(projectionPos(2)) - }; - const decltype(edm4eic::TrackPoint::positionError) positionError{0, 0, 0}; - m_log->trace(" pos x = {}", position.x); - m_log->trace(" pos y = {}", position.y); - m_log->trace(" pos z = {}", position.z); - - // Momentum - const decltype(edm4eic::TrackPoint::momentum) momentum = edm4hep::utils::sphericalToVector( - static_cast(1.0 / std::abs(parameter[Acts::eBoundQOverP])), - static_cast(parameter[Acts::eBoundTheta]), - static_cast(parameter[Acts::eBoundPhi]) - ); - const decltype(edm4eic::TrackPoint::momentumError) momentumError{ - static_cast(covariance(Acts::eBoundTheta, Acts::eBoundTheta)), - static_cast(covariance(Acts::eBoundPhi, Acts::eBoundPhi)), - static_cast(covariance(Acts::eBoundQOverP, Acts::eBoundQOverP)), - static_cast(covariance(Acts::eBoundTheta, Acts::eBoundPhi)), - static_cast(covariance(Acts::eBoundTheta, Acts::eBoundQOverP)), - static_cast(covariance(Acts::eBoundPhi, Acts::eBoundQOverP)) - }; - - // time - const float time{static_cast(parameter(Acts::eBoundTime))}; - const float timeError{sqrt(static_cast(covariance(Acts::eBoundTime, Acts::eBoundTime)))}; - - // Direction - const float theta(parameter[Acts::eBoundTheta]); - const float phi(parameter[Acts::eBoundPhi]); - const decltype(edm4eic::TrackPoint::directionError) directionError{ - static_cast(covariance(Acts::eBoundTheta, Acts::eBoundTheta)), - static_cast(covariance(Acts::eBoundPhi, Acts::eBoundPhi)), - static_cast(covariance(Acts::eBoundTheta, Acts::eBoundPhi)) - }; - - - // >oO debug print - m_log->trace(" loc 0 = {:.4f}", parameter[Acts::eBoundLoc0]); - m_log->trace(" loc 1 = {:.4f}", parameter[Acts::eBoundLoc1]); - m_log->trace(" phi = {:.4f}", parameter[Acts::eBoundPhi]); - m_log->trace(" theta = {:.4f}", parameter[Acts::eBoundTheta]); - m_log->trace(" q/p = {:.4f}", parameter[Acts::eBoundQOverP]); - m_log->trace(" p = {:.4f}", 1.0 / parameter[Acts::eBoundQOverP]); - m_log->trace(" err phi = {:.4f}", sqrt(covariance(Acts::eBoundPhi, Acts::eBoundPhi))); - m_log->trace(" err th = {:.4f}", sqrt(covariance(Acts::eBoundTheta, Acts::eBoundTheta))); - m_log->trace(" err q/p = {:.4f}", sqrt(covariance(Acts::eBoundQOverP, Acts::eBoundQOverP))); - m_log->trace(" chi2 = {:.4f}", trajState.chi2Sum); - m_log->trace(" loc err = {:.4f}", static_cast(covariance(Acts::eBoundLoc0, Acts::eBoundLoc0))); - m_log->trace(" loc err = {:.4f}", static_cast(covariance(Acts::eBoundLoc1, Acts::eBoundLoc1))); - m_log->trace(" loc err = {:.4f}", static_cast(covariance(Acts::eBoundLoc0, Acts::eBoundLoc1))); - - uint64_t surface = targetSurf->geometryId().value(); - uint32_t system = 0; // default value...will be set in TrackPropagation factory - - /* +std::unique_ptr +TrackPropagation::propagate(const ActsExamples::Trajectories* traj, + const std::shared_ptr& targetSurf) const { + // Get the entry index for the single trajectory + // The trajectory entry indices and the multiTrajectory + const auto& mj = traj->multiTrajectory(); + const auto& trackTips = traj->tips(); + + m_log->trace(" Number of elements in trackTips {}", trackTips.size()); + + // Skip empty + if (trackTips.empty()) { + m_log->trace(" Empty multiTrajectory."); + return nullptr; + } + const auto& trackTip = trackTips.front(); + + // Collect the trajectory summary info + auto trajState = Acts::MultiTrajectoryHelpers::trajectoryState(mj, trackTip); + int m_nMeasurements = trajState.nMeasurements; + int m_nStates = trajState.nStates; + + m_log->trace(" Num measurement in trajectory: {}", m_nMeasurements); + m_log->trace(" Num states in trajectory : {}", m_nStates); + + //================================================= + //Track projection + //Reference sPHENIX code: https://github.com/sPHENIX-Collaboration/coresoftware/blob/335e6da4ccacc8374cada993485fe81d82e74a4f/offline/packages/trackreco/PHActsTrackProjection.h + //================================================= + const auto& initial_bound_parameters = traj->trackParameters(trackTip); + + m_log->trace(" TrackPropagation. Propagating to surface # {}", + typeid(targetSurf->type()).name()); + + std::shared_ptr trackingGeometry = m_geoSvc->trackingGeometry(); + std::shared_ptr magneticField = m_geoSvc->getFieldProvider(); + using Stepper = Acts::EigenStepper<>; + using Propagator = Acts::Propagator; + Stepper stepper(magneticField); + Propagator propagator(stepper); + + ACTS_LOCAL_LOGGER(eicrecon::getSpdlogLogger("PROP", m_log)); + + Acts::PropagatorOptions<> options(m_geoContext, m_fieldContext); + + auto result = propagator.propagate(initial_bound_parameters, *targetSurf, options); + + // check propagation result + if (!result.ok()) { + m_log->trace(" propagation failed (!result.ok())"); + return nullptr; + } + m_log->trace(" propagation result is OK"); + + // Pulling results to convenient variables + auto trackStateParams = *((*result).endParameters); + const auto& parameter = trackStateParams.parameters(); + const auto& covariance = *trackStateParams.covariance(); + + // Path length + const float pathLength = (*result).pathLength; + const float pathLengthError = 0; + m_log->trace(" path len = {}", pathLength); + + // Position: + auto projectionPos = trackStateParams.position(m_geoContext); + const decltype(edm4eic::TrackPoint::position) position{static_cast(projectionPos(0)), + static_cast(projectionPos(1)), + static_cast(projectionPos(2))}; + const decltype(edm4eic::TrackPoint::positionError) positionError{0, 0, 0}; + m_log->trace(" pos x = {}", position.x); + m_log->trace(" pos y = {}", position.y); + m_log->trace(" pos z = {}", position.z); + + // Momentum + const decltype(edm4eic::TrackPoint::momentum) momentum = edm4hep::utils::sphericalToVector( + static_cast(1.0 / std::abs(parameter[Acts::eBoundQOverP])), + static_cast(parameter[Acts::eBoundTheta]), + static_cast(parameter[Acts::eBoundPhi])); + const decltype(edm4eic::TrackPoint::momentumError) momentumError{ + static_cast(covariance(Acts::eBoundTheta, Acts::eBoundTheta)), + static_cast(covariance(Acts::eBoundPhi, Acts::eBoundPhi)), + static_cast(covariance(Acts::eBoundQOverP, Acts::eBoundQOverP)), + static_cast(covariance(Acts::eBoundTheta, Acts::eBoundPhi)), + static_cast(covariance(Acts::eBoundTheta, Acts::eBoundQOverP)), + static_cast(covariance(Acts::eBoundPhi, Acts::eBoundQOverP))}; + + // time + const float time{static_cast(parameter(Acts::eBoundTime))}; + const float timeError{sqrt(static_cast(covariance(Acts::eBoundTime, Acts::eBoundTime)))}; + + // Direction + const float theta(parameter[Acts::eBoundTheta]); + const float phi(parameter[Acts::eBoundPhi]); + const decltype(edm4eic::TrackPoint::directionError) directionError{ + static_cast(covariance(Acts::eBoundTheta, Acts::eBoundTheta)), + static_cast(covariance(Acts::eBoundPhi, Acts::eBoundPhi)), + static_cast(covariance(Acts::eBoundTheta, Acts::eBoundPhi))}; + + // >oO debug print + m_log->trace(" loc 0 = {:.4f}", parameter[Acts::eBoundLoc0]); + m_log->trace(" loc 1 = {:.4f}", parameter[Acts::eBoundLoc1]); + m_log->trace(" phi = {:.4f}", parameter[Acts::eBoundPhi]); + m_log->trace(" theta = {:.4f}", parameter[Acts::eBoundTheta]); + m_log->trace(" q/p = {:.4f}", parameter[Acts::eBoundQOverP]); + m_log->trace(" p = {:.4f}", 1.0 / parameter[Acts::eBoundQOverP]); + m_log->trace(" err phi = {:.4f}", sqrt(covariance(Acts::eBoundPhi, Acts::eBoundPhi))); + m_log->trace(" err th = {:.4f}", sqrt(covariance(Acts::eBoundTheta, Acts::eBoundTheta))); + m_log->trace(" err q/p = {:.4f}", sqrt(covariance(Acts::eBoundQOverP, Acts::eBoundQOverP))); + m_log->trace(" chi2 = {:.4f}", trajState.chi2Sum); + m_log->trace(" loc err = {:.4f}", + static_cast(covariance(Acts::eBoundLoc0, Acts::eBoundLoc0))); + m_log->trace(" loc err = {:.4f}", + static_cast(covariance(Acts::eBoundLoc1, Acts::eBoundLoc1))); + m_log->trace(" loc err = {:.4f}", + static_cast(covariance(Acts::eBoundLoc0, Acts::eBoundLoc1))); + + uint64_t surface = targetSurf->geometryId().value(); + uint32_t system = 0; // default value...will be set in TrackPropagation factory + + /* ::edm4hep::Vector3f position{}; ///< Position of the trajectory point [mm] ::edm4eic::Cov3f positionError{}; ///< Error on the position ::edm4hep::Vector3f momentum{}; ///< 3-momentum at the point [GeV] @@ -328,21 +328,9 @@ void TrackPropagation::init(const dd4hep::Detector* detector, float pathlength{}; ///< Pathlength from the origin to this point float pathlengthError{}; ///< Error on the pathlenght */ - return std::make_unique(edm4eic::TrackPoint{ - surface, - system, - position, - positionError, - momentum, - momentumError, - time, - timeError, - theta, - phi, - directionError, - pathLength, - pathLengthError - }); - } + return std::make_unique( + edm4eic::TrackPoint{surface, system, position, positionError, momentum, momentumError, time, + timeError, theta, phi, directionError, pathLength, pathLengthError}); +} } // namespace eicrecon diff --git a/src/algorithms/tracking/TrackPropagation.h b/src/algorithms/tracking/TrackPropagation.h index f39ac1b482..515d59a763 100644 --- a/src/algorithms/tracking/TrackPropagation.h +++ b/src/algorithms/tracking/TrackPropagation.h @@ -26,44 +26,47 @@ namespace eicrecon { - using ActsTrackPropagationResult = Acts::Result>; +using ActsTrackPropagationResult = Acts::Result>; - /** Extract the particles form fit trajectories. +/** Extract the particles form fit trajectories. * * \ingroup tracking */ - class TrackPropagation: public eicrecon::WithPodConfig { - - - public: - - /** Initialize algorithm */ - void init(const dd4hep::Detector* detector, std::shared_ptr geo_svc, std::shared_ptr logger); - - void process( - const std::tuple, const std::vector> input, - const std::tuple output) const { - - const auto [acts_trajectories, acts_tracks] = input; - auto [propagated_tracks] = output; - - for (auto traj: acts_trajectories) { - edm4eic::MutableTrackSegment this_propagated_track; - for(auto& surf : m_target_surface_list) { - auto prop_point = propagate(traj, surf); - if(!prop_point) continue; - prop_point->surface = surf->geometryId().layer(); - prop_point->system = surf->geometryId().extra(); - this_propagated_track.addToPoints(*prop_point); - } - propagated_tracks->push_back(this_propagated_track); - } - } - - /** Propagates a single trajectory to a given surface */ - std::unique_ptr propagate(const ActsExamples::Trajectories *, const std::shared_ptr& targetSurf) const; - - /** Propagates a collection of trajectories to a list of surfaces, and returns the full `TrackSegment`; +class TrackPropagation : public eicrecon::WithPodConfig { + +public: + /** Initialize algorithm */ + void init(const dd4hep::Detector* detector, std::shared_ptr geo_svc, + std::shared_ptr logger); + + void process(const std::tuple, + const std::vector> + input, + const std::tuple output) const { + + const auto [acts_trajectories, acts_tracks] = input; + auto [propagated_tracks] = output; + + for (auto traj : acts_trajectories) { + edm4eic::MutableTrackSegment this_propagated_track; + for (auto& surf : m_target_surface_list) { + auto prop_point = propagate(traj, surf); + if (!prop_point) + continue; + prop_point->surface = surf->geometryId().layer(); + prop_point->system = surf->geometryId().extra(); + this_propagated_track.addToPoints(*prop_point); + } + propagated_tracks->push_back(this_propagated_track); + } + } + + /** Propagates a single trajectory to a given surface */ + std::unique_ptr + propagate(const ActsExamples::Trajectories*, + const std::shared_ptr& targetSurf) const; + + /** Propagates a collection of trajectories to a list of surfaces, and returns the full `TrackSegment`; * @param trajectories the input collection of trajectories * @param targetSurfaces the list of surfaces to propagate to * @param filterSurface if defined, do not propagate to any surfaces unless successful propagation to this filterSurface @@ -71,21 +74,20 @@ namespace eicrecon { * @param stopIfTrackPointCutFailed if true, stop propagating a trajectory when trackPointCut returns false * @return the resulting collection of propagated tracks */ - std::unique_ptr propagateToSurfaceList( - std::vector trajectories, - std::vector> targetSurfaces, - std::shared_ptr filterSurface = nullptr, - std::function trackPointCut = [] (edm4eic::TrackPoint p) { return true; }, - bool stopIfTrackPointCutFailed = false - ) const; - - private: - - Acts::GeometryContext m_geoContext; - Acts::MagneticFieldContext m_fieldContext; - std::shared_ptr m_geoSvc; - std::shared_ptr m_log; - - std::vector> m_target_surface_list; - }; + std::unique_ptr propagateToSurfaceList( + std::vector trajectories, + std::vector> targetSurfaces, + std::shared_ptr filterSurface = nullptr, + std::function trackPointCut = + [](edm4eic::TrackPoint p) { return true; }, + bool stopIfTrackPointCutFailed = false) const; + +private: + Acts::GeometryContext m_geoContext; + Acts::MagneticFieldContext m_fieldContext; + std::shared_ptr m_geoSvc; + std::shared_ptr m_log; + + std::vector> m_target_surface_list; +}; } // namespace eicrecon diff --git a/src/algorithms/tracking/TrackPropagationConfig.h b/src/algorithms/tracking/TrackPropagationConfig.h index f5b0a4f918..673f797e50 100644 --- a/src/algorithms/tracking/TrackPropagationConfig.h +++ b/src/algorithms/tracking/TrackPropagationConfig.h @@ -7,22 +7,22 @@ namespace eicrecon { - struct CylinderSurfaceConfig { - std::string id; - std::variant rmin; - std::variant zmin; - std::variant zmax; - }; +struct CylinderSurfaceConfig { + std::string id; + std::variant rmin; + std::variant zmin; + std::variant zmax; +}; - struct DiscSurfaceConfig { - std::string id; - std::variant zmin; - std::variant rmin; - std::variant rmax; - }; +struct DiscSurfaceConfig { + std::string id; + std::variant zmin; + std::variant rmin; + std::variant rmax; +}; - struct TrackPropagationConfig { - std::vector> surfaces; - }; +struct TrackPropagationConfig { + std::vector> surfaces; +}; -} // eicrecon +} // namespace eicrecon diff --git a/src/algorithms/tracking/TrackSeeding.cc b/src/algorithms/tracking/TrackSeeding.cc index 4fc96eb848..9c24253a22 100644 --- a/src/algorithms/tracking/TrackSeeding.cc +++ b/src/algorithms/tracking/TrackSeeding.cc @@ -32,252 +32,238 @@ #include #endif -namespace -{ - //! convenience square method - template - inline constexpr T square( const T& x ) { return x*x; } -} +namespace { +//! convenience square method +template inline constexpr T square(const T& x) { return x * x; } +} // namespace -void eicrecon::TrackSeeding::init(std::shared_ptr geo_svc, std::shared_ptr log) { +void eicrecon::TrackSeeding::init(std::shared_ptr geo_svc, + std::shared_ptr log) { - m_log = log; + m_log = log; - m_geoSvc = geo_svc; + m_geoSvc = geo_svc; - m_BField = std::dynamic_pointer_cast(m_geoSvc->getFieldProvider()); - m_fieldctx = eicrecon::BField::BFieldVariant(m_BField); + m_BField = + std::dynamic_pointer_cast(m_geoSvc->getFieldProvider()); + m_fieldctx = eicrecon::BField::BFieldVariant(m_BField); - configure(); + configure(); } void eicrecon::TrackSeeding::configure() { - // Filter parameters - m_seedFilterConfig.maxSeedsPerSpM = m_cfg.maxSeedsPerSpM_filter; - m_seedFilterConfig.deltaRMin = m_cfg.deltaRMin; - m_seedFilterConfig.seedConfirmation = m_cfg.seedConfirmation; - m_seedFilterConfig.deltaInvHelixDiameter = m_cfg.deltaInvHelixDiameter; - m_seedFilterConfig.impactWeightFactor = m_cfg.impactWeightFactor; - m_seedFilterConfig.zOriginWeightFactor = m_cfg.zOriginWeightFactor; - m_seedFilterConfig.compatSeedWeight = m_cfg.compatSeedWeight; - m_seedFilterConfig.compatSeedLimit = m_cfg.compatSeedLimit; - m_seedFilterConfig.seedWeightIncrement = m_cfg.seedWeightIncrement; - - m_seedFilterConfig.centralSeedConfirmationRange = Acts::SeedConfirmationRangeConfig{ - m_cfg.zMinSeedConfCentral, - m_cfg.zMaxSeedConfCentral, - m_cfg.rMaxSeedConfCentral, - m_cfg.nTopForLargeRCentral, - m_cfg.nTopForSmallRCentral, - m_cfg.seedConfMinBottomRadiusCentral, - m_cfg.seedConfMaxZOriginCentral, - m_cfg.minImpactSeedConfCentral - }; - - m_seedFilterConfig.forwardSeedConfirmationRange = Acts::SeedConfirmationRangeConfig{ - m_cfg.zMinSeedConfForward, - m_cfg.zMaxSeedConfForward, - m_cfg.rMaxSeedConfForward, - m_cfg.nTopForLargeRForward, - m_cfg.nTopForSmallRForward, - m_cfg.seedConfMinBottomRadiusForward, - m_cfg.seedConfMaxZOriginForward, - m_cfg.minImpactSeedConfForward - }; - - m_seedFilterConfig = m_seedFilterConfig.toInternalUnits(); - - // Finder parameters - m_seedFinderConfig.seedFilter = std::make_unique>(Acts::SeedFilter(m_seedFilterConfig)); - m_seedFinderConfig.rMax = m_cfg.rMax; - m_seedFinderConfig.deltaRMinTopSP = m_cfg.deltaRMinTopSP; - m_seedFinderConfig.deltaRMaxTopSP = m_cfg.deltaRMaxTopSP; - m_seedFinderConfig.deltaRMinBottomSP = m_cfg.deltaRMinBottomSP; - m_seedFinderConfig.deltaRMaxBottomSP = m_cfg.deltaRMaxBottomSP; - m_seedFinderConfig.collisionRegionMin = m_cfg.collisionRegionMin; - m_seedFinderConfig.collisionRegionMax = m_cfg.collisionRegionMax; - m_seedFinderConfig.zMin = m_cfg.zMin; - m_seedFinderConfig.zMax = m_cfg.zMax; - m_seedFinderConfig.maxSeedsPerSpM = m_cfg.maxSeedsPerSpM; - m_seedFinderConfig.cotThetaMax = m_cfg.cotThetaMax; - m_seedFinderConfig.sigmaScattering = m_cfg.sigmaScattering; - m_seedFinderConfig.radLengthPerSeed = m_cfg.radLengthPerSeed; - m_seedFinderConfig.minPt = m_cfg.minPt; - m_seedFinderConfig.impactMax = m_cfg.impactMax; - m_seedFinderConfig.rMinMiddle = m_cfg.rMinMiddle; - m_seedFinderConfig.rMaxMiddle = m_cfg.rMaxMiddle; - - m_seedFinderOptions.beamPos = Acts::Vector2(m_cfg.beamPosX, m_cfg.beamPosY); - m_seedFinderOptions.bFieldInZ = m_cfg.bFieldInZ; - - m_seedFinderConfig = - m_seedFinderConfig.toInternalUnits().calculateDerivedQuantities(); - m_seedFinderOptions = + // Filter parameters + m_seedFilterConfig.maxSeedsPerSpM = m_cfg.maxSeedsPerSpM_filter; + m_seedFilterConfig.deltaRMin = m_cfg.deltaRMin; + m_seedFilterConfig.seedConfirmation = m_cfg.seedConfirmation; + m_seedFilterConfig.deltaInvHelixDiameter = m_cfg.deltaInvHelixDiameter; + m_seedFilterConfig.impactWeightFactor = m_cfg.impactWeightFactor; + m_seedFilterConfig.zOriginWeightFactor = m_cfg.zOriginWeightFactor; + m_seedFilterConfig.compatSeedWeight = m_cfg.compatSeedWeight; + m_seedFilterConfig.compatSeedLimit = m_cfg.compatSeedLimit; + m_seedFilterConfig.seedWeightIncrement = m_cfg.seedWeightIncrement; + + m_seedFilterConfig.centralSeedConfirmationRange = Acts::SeedConfirmationRangeConfig{ + m_cfg.zMinSeedConfCentral, m_cfg.zMaxSeedConfCentral, + m_cfg.rMaxSeedConfCentral, m_cfg.nTopForLargeRCentral, + m_cfg.nTopForSmallRCentral, m_cfg.seedConfMinBottomRadiusCentral, + m_cfg.seedConfMaxZOriginCentral, m_cfg.minImpactSeedConfCentral}; + + m_seedFilterConfig.forwardSeedConfirmationRange = Acts::SeedConfirmationRangeConfig{ + m_cfg.zMinSeedConfForward, m_cfg.zMaxSeedConfForward, + m_cfg.rMaxSeedConfForward, m_cfg.nTopForLargeRForward, + m_cfg.nTopForSmallRForward, m_cfg.seedConfMinBottomRadiusForward, + m_cfg.seedConfMaxZOriginForward, m_cfg.minImpactSeedConfForward}; + + m_seedFilterConfig = m_seedFilterConfig.toInternalUnits(); + + // Finder parameters + m_seedFinderConfig.seedFilter = std::make_unique>( + Acts::SeedFilter(m_seedFilterConfig)); + m_seedFinderConfig.rMax = m_cfg.rMax; + m_seedFinderConfig.deltaRMinTopSP = m_cfg.deltaRMinTopSP; + m_seedFinderConfig.deltaRMaxTopSP = m_cfg.deltaRMaxTopSP; + m_seedFinderConfig.deltaRMinBottomSP = m_cfg.deltaRMinBottomSP; + m_seedFinderConfig.deltaRMaxBottomSP = m_cfg.deltaRMaxBottomSP; + m_seedFinderConfig.collisionRegionMin = m_cfg.collisionRegionMin; + m_seedFinderConfig.collisionRegionMax = m_cfg.collisionRegionMax; + m_seedFinderConfig.zMin = m_cfg.zMin; + m_seedFinderConfig.zMax = m_cfg.zMax; + m_seedFinderConfig.maxSeedsPerSpM = m_cfg.maxSeedsPerSpM; + m_seedFinderConfig.cotThetaMax = m_cfg.cotThetaMax; + m_seedFinderConfig.sigmaScattering = m_cfg.sigmaScattering; + m_seedFinderConfig.radLengthPerSeed = m_cfg.radLengthPerSeed; + m_seedFinderConfig.minPt = m_cfg.minPt; + m_seedFinderConfig.impactMax = m_cfg.impactMax; + m_seedFinderConfig.rMinMiddle = m_cfg.rMinMiddle; + m_seedFinderConfig.rMaxMiddle = m_cfg.rMaxMiddle; + + m_seedFinderOptions.beamPos = Acts::Vector2(m_cfg.beamPosX, m_cfg.beamPosY); + m_seedFinderOptions.bFieldInZ = m_cfg.bFieldInZ; + + m_seedFinderConfig = m_seedFinderConfig.toInternalUnits().calculateDerivedQuantities(); + m_seedFinderOptions = m_seedFinderOptions.toInternalUnits().calculateDerivedQuantities(m_seedFinderConfig); - } -std::unique_ptr eicrecon::TrackSeeding::produce(const edm4eic::TrackerHitCollection& trk_hits) { +std::unique_ptr +eicrecon::TrackSeeding::produce(const edm4eic::TrackerHitCollection& trk_hits) { std::vector spacePoints = getSpacePoints(trk_hits); - Acts::SeedFinderOrthogonal finder(m_seedFinderConfig); // FIXME move into class scope + Acts::SeedFinderOrthogonal finder( + m_seedFinderConfig); // FIXME move into class scope - std::function( - const eicrecon::SpacePoint *sp)> - create_coordinates = [](const eicrecon::SpacePoint *sp) { + std::function(const eicrecon::SpacePoint* sp)> + create_coordinates = [](const eicrecon::SpacePoint* sp) { Acts::Vector3 position(sp->x(), sp->y(), sp->z()); Acts::Vector2 variance(sp->varianceR(), sp->varianceZ()); return std::make_pair(position, variance); }; - eicrecon::SeedContainer seeds = finder.createSeeds(m_seedFinderOptions, spacePoints, create_coordinates); + eicrecon::SeedContainer seeds = + finder.createSeeds(m_seedFinderOptions, spacePoints, create_coordinates); std::unique_ptr trackparams = makeTrackParams(seeds); - for (auto& sp: spacePoints) { + for (auto& sp : spacePoints) { delete sp; } return std::move(trackparams); } -std::vector eicrecon::TrackSeeding::getSpacePoints(const edm4eic::TrackerHitCollection& trk_hits) -{ +std::vector +eicrecon::TrackSeeding::getSpacePoints(const edm4eic::TrackerHitCollection& trk_hits) { std::vector spacepoints; - for(const auto hit : trk_hits) - { - const eicrecon::SpacePoint* sp = new SpacePoint(hit); - spacepoints.push_back(sp); - } + for (const auto hit : trk_hits) { + const eicrecon::SpacePoint* sp = new SpacePoint(hit); + spacepoints.push_back(sp); + } return spacepoints; } -std::unique_ptr eicrecon::TrackSeeding::makeTrackParams(SeedContainer& seeds) -{ +std::unique_ptr +eicrecon::TrackSeeding::makeTrackParams(SeedContainer& seeds) { auto trackparams = std::make_unique(); - for(auto& seed : seeds) - { - std::vector> xyHitPositions; - std::vector> rzHitPositions; - for(const auto& spptr : seed.sp()) - { - xyHitPositions.emplace_back(spptr->x(), spptr->y()); - rzHitPositions.emplace_back(spptr->r(), spptr->z()); - } - - auto RX0Y0 = circleFit(xyHitPositions); - float R = std::get<0>(RX0Y0); - float X0 = std::get<1>(RX0Y0); - float Y0 = std::get<2>(RX0Y0); - if (!(std::isfinite(R) && - std::isfinite(std::abs(X0)) && - std::isfinite(std::abs(Y0)))) { - // avoid float overflow for hits on a line - continue; - } - if ( std::hypot(X0,Y0) < std::numeric_limits::epsilon() || - !std::isfinite(std::hypot(X0,Y0)) ) { - //Avoid center of circle at origin, where there is no point-of-closest approach - //Also, avoid float overfloat on circle center - continue; - } - - auto slopeZ0 = lineFit(rzHitPositions); - const auto xypos = findPCA(RX0Y0); - - - //Determine charge - int charge = determineCharge(xyHitPositions, xypos, RX0Y0); - - float theta = atan(1./std::get<0>(slopeZ0)); - // normalize to 0(Acts::Vector3(0,0,0)); - Acts::Vector3 global(xypos.first, xypos.second, z0); - - //Compute local position at PCA - Acts::Vector2 localpos; - Acts::Vector3 direction(sin(theta)*cos(phi), sin(theta)*sin(phi), cos(theta)); - - auto local = perigee->globalToLocal(m_geoSvc->getActsGeometryContext(), - global, - direction); - - if(!local.ok()) - { - continue; - } - - localpos = local.value(); - - auto trackparam = trackparams->create(); - trackparam.setType(-1); // type --> seed(-1) - trackparam.setLoc({static_cast(localpos(0)), static_cast(localpos(1))}); // 2d location on surface - trackparam.setPhi(static_cast(phi)); // phi [rad] - trackparam.setTheta(theta); //theta [rad] - trackparam.setQOverP(qOverP); // Q/p [e/GeV] - trackparam.setTime(10); // time in ns - #if EDM4EIC_VERSION_MAJOR >= 5 - edm4eic::Cov6f cov; - cov(0,0) = m_cfg.locaError / Acts::UnitConstants::mm; // loc0 - cov(1,1) = m_cfg.locbError / Acts::UnitConstants::mm; // loc1 - cov(2,2) = m_cfg.phiError / Acts::UnitConstants::rad; // phi - cov(3,3) = m_cfg.thetaError / Acts::UnitConstants::rad; // theta - cov(4,4) = m_cfg.qOverPError * Acts::UnitConstants::GeV; // qOverP - cov(5,5) = m_cfg.timeError / Acts::UnitConstants::ns; // time - trackparam.setCovariance(cov); - #else - trackparam.setCharge(static_cast(charge)); // charge - trackparam.setLocError({m_cfg.locaError, m_cfg.locbError}); //covariance of location - trackparam.setMomentumError({m_cfg.thetaError, m_cfg.phiError, m_cfg.qOverPError}); // covariance on theta/phi/q/p - trackparam.setTimeError(m_cfg.timeError); // error on time - #endif + for (auto& seed : seeds) { + std::vector> xyHitPositions; + std::vector> rzHitPositions; + for (const auto& spptr : seed.sp()) { + xyHitPositions.emplace_back(spptr->x(), spptr->y()); + rzHitPositions.emplace_back(spptr->r(), spptr->z()); + } + + auto RX0Y0 = circleFit(xyHitPositions); + float R = std::get<0>(RX0Y0); + float X0 = std::get<1>(RX0Y0); + float Y0 = std::get<2>(RX0Y0); + if (!(std::isfinite(R) && std::isfinite(std::abs(X0)) && std::isfinite(std::abs(Y0)))) { + // avoid float overflow for hits on a line + continue; + } + if (std::hypot(X0, Y0) < std::numeric_limits::epsilon() || + !std::isfinite(std::hypot(X0, Y0))) { + //Avoid center of circle at origin, where there is no point-of-closest approach + //Also, avoid float overfloat on circle center + continue; + } + + auto slopeZ0 = lineFit(rzHitPositions); + const auto xypos = findPCA(RX0Y0); + + //Determine charge + int charge = determineCharge(xyHitPositions, xypos, RX0Y0); + + float theta = atan(1. / std::get<0>(slopeZ0)); + // normalize to 0(Acts::Vector3(0, 0, 0)); + Acts::Vector3 global(xypos.first, xypos.second, z0); + + //Compute local position at PCA + Acts::Vector2 localpos; + Acts::Vector3 direction(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta)); + + auto local = perigee->globalToLocal(m_geoSvc->getActsGeometryContext(), global, direction); + + if (!local.ok()) { + continue; } + localpos = local.value(); + + auto trackparam = trackparams->create(); + trackparam.setType(-1); // type --> seed(-1) + trackparam.setLoc({static_cast(localpos(0)), + static_cast(localpos(1))}); // 2d location on surface + trackparam.setPhi(static_cast(phi)); // phi [rad] + trackparam.setTheta(theta); //theta [rad] + trackparam.setQOverP(qOverP); // Q/p [e/GeV] + trackparam.setTime(10); // time in ns +#if EDM4EIC_VERSION_MAJOR >= 5 + edm4eic::Cov6f cov; + cov(0, 0) = m_cfg.locaError / Acts::UnitConstants::mm; // loc0 + cov(1, 1) = m_cfg.locbError / Acts::UnitConstants::mm; // loc1 + cov(2, 2) = m_cfg.phiError / Acts::UnitConstants::rad; // phi + cov(3, 3) = m_cfg.thetaError / Acts::UnitConstants::rad; // theta + cov(4, 4) = m_cfg.qOverPError * Acts::UnitConstants::GeV; // qOverP + cov(5, 5) = m_cfg.timeError / Acts::UnitConstants::ns; // time + trackparam.setCovariance(cov); +#else + trackparam.setCharge(static_cast(charge)); // charge + trackparam.setLocError({m_cfg.locaError, m_cfg.locbError}); //covariance of location + trackparam.setMomentumError( + {m_cfg.thetaError, m_cfg.phiError, m_cfg.qOverPError}); // covariance on theta/phi/q/p + trackparam.setTimeError(m_cfg.timeError); // error on time +#endif + } + return std::move(trackparams); } -std::pair eicrecon::TrackSeeding::findPCA(std::tuple& circleParams) const -{ - const float R = std::get<0>(circleParams); +std::pair +eicrecon::TrackSeeding::findPCA(std::tuple& circleParams) const { + const float R = std::get<0>(circleParams); const float X0 = std::get<1>(circleParams); const float Y0 = std::get<2>(circleParams); const double R0 = std::hypot(X0, Y0); //Calculate point on circle closest to origin - const double xmin = X0 * (1. - R/R0); - const double ymin = Y0 * (1. - R/R0); + const double xmin = X0 * (1. - R / R0); + const double ymin = Y0 * (1. - R / R0); - return std::make_pair(xmin,ymin); + return std::make_pair(xmin, ymin); } -int eicrecon::TrackSeeding::determineCharge(std::vector>& positions, const std::pair& PCA, std::tuple& RX0Y0) const -{ +int eicrecon::TrackSeeding::determineCharge(std::vector>& positions, + const std::pair& PCA, + std::tuple& RX0Y0) const { const auto& firstpos = positions.at(0); - auto hit_x = firstpos.first; - auto hit_y = firstpos.second; + auto hit_x = firstpos.first; + auto hit_y = firstpos.second; auto xpos = PCA.first; auto ypos = PCA.second; @@ -285,9 +271,9 @@ int eicrecon::TrackSeeding::determineCharge(std::vector>& float X0 = std::get<1>(RX0Y0); float Y0 = std::get<2>(RX0Y0); - Acts::Vector3 B_z(0,0,1); - Acts::Vector3 radial(X0-xpos, Y0-ypos, 0); - Acts::Vector3 hit(hit_x-xpos, hit_y-ypos, 0); + Acts::Vector3 B_z(0, 0, 1); + Acts::Vector3 radial(X0 - xpos, Y0 - ypos, 0); + Acts::Vector3 hit(hit_x - xpos, hit_y - ypos, 0); auto cross = radial.cross(hit); @@ -296,8 +282,7 @@ int eicrecon::TrackSeeding::determineCharge(std::vector>& return copysign(1., -dot); } - - /** +/** * Circle fit to a given set of data points (in 2D) * This is an algebraic fit, due to Taubin, based on the journal article * G. Taubin, "Estimation Of Planar Curves, Surfaces And Nonplanar @@ -309,15 +294,14 @@ int eicrecon::TrackSeeding::determineCharge(std::vector>& * It provides a very good initial guess for a subsequent geometric fit. * Nikolai Chernov (September 2012) */ -std::tuple eicrecon::TrackSeeding::circleFit(std::vector>& positions) const -{ +std::tuple +eicrecon::TrackSeeding::circleFit(std::vector>& positions) const { // Compute x- and y- sample means - double meanX = 0; - double meanY = 0; + double meanX = 0; + double meanY = 0; double weight = 0; - for( const auto& [x,y] : positions) - { + for (const auto& [x, y] : positions) { meanX += x; meanY += y; ++weight; @@ -334,18 +318,17 @@ std::tuple eicrecon::TrackSeeding::circleFit(std::vector=std::abs(y)) break; - - x = xnew; y = ynew; - + for (int iter = 0; iter < iter_max; ++iter) { + const double Dy = A1 + x * (A22 + A33 * x); + const double xnew = x - y / Dy; + if ((xnew == x) || (!std::isfinite(xnew))) + break; + + const double ynew = A0 + xnew * (A1 + xnew * (A2 + xnew * A3)); + if (std::abs(ynew) >= std::abs(y)) + break; + + x = xnew; + y = ynew; } // computing parameters of the fitting circle - const double DET = std::pow(x,2) - x*Mz + Cov_xy; - const double Xcenter = (Mxz*(Myy - x) - Myz*Mxy)/DET/2; - const double Ycenter = (Myz*(Mxx - x) - Mxz*Mxy)/DET/2; + const double DET = std::pow(x, 2) - x * Mz + Cov_xy; + const double Xcenter = (Mxz * (Myy - x) - Myz * Mxy) / DET / 2; + const double Ycenter = (Myz * (Mxx - x) - Mxz * Mxy) / DET / 2; // assembling the output float X0 = Xcenter + meanX; float Y0 = Ycenter + meanY; - float R = std::sqrt( std::pow(Xcenter,2) + std::pow(Ycenter,2) + Mz); - return std::make_tuple( R, X0, Y0 ); + float R = std::sqrt(std::pow(Xcenter, 2) + std::pow(Ycenter, 2) + Mz); + return std::make_tuple(R, X0, Y0); } -std::tuple eicrecon::TrackSeeding::lineFit(std::vector>& positions) const -{ - double xsum=0; - double x2sum=0; - double ysum=0; - double xysum=0; - for( const auto& [r,z]:positions ) - { - xsum=xsum+r; //calculate sigma(xi) - ysum=ysum+z; //calculate sigma(yi) - x2sum=x2sum+std::pow(r,2); //calculate sigma(x^2i) - xysum=xysum+r*z; //calculate sigma(xi*yi) +std::tuple +eicrecon::TrackSeeding::lineFit(std::vector>& positions) const { + double xsum = 0; + double x2sum = 0; + double ysum = 0; + double xysum = 0; + for (const auto& [r, z] : positions) { + xsum = xsum + r; //calculate sigma(xi) + ysum = ysum + z; //calculate sigma(yi) + x2sum = x2sum + std::pow(r, 2); //calculate sigma(x^2i) + xysum = xysum + r * z; //calculate sigma(xi*yi) } - const auto npts = positions.size(); - const double denominator = (x2sum*npts-std::pow(xsum,2)); - const float a= (xysum*npts-xsum*ysum)/denominator; //calculate slope - const float b= (x2sum*ysum-xsum*xysum)/denominator; //calculate intercept - return std::make_tuple( a, b ); + const auto npts = positions.size(); + const double denominator = (x2sum * npts - std::pow(xsum, 2)); + const float a = (xysum * npts - xsum * ysum) / denominator; //calculate slope + const float b = (x2sum * ysum - xsum * xysum) / denominator; //calculate intercept + return std::make_tuple(a, b); } diff --git a/src/algorithms/tracking/TrackSeeding.h b/src/algorithms/tracking/TrackSeeding.h index 2f0b8d885b..ede20edc70 100644 --- a/src/algorithms/tracking/TrackSeeding.h +++ b/src/algorithms/tracking/TrackSeeding.h @@ -23,33 +23,36 @@ #include "SpacePoint.h" #include "algorithms/interfaces/WithPodConfig.h" - namespace eicrecon { - class TrackSeeding: - public eicrecon::WithPodConfig { - public: - void init(std::shared_ptr geo_svc, std::shared_ptr log); - std::unique_ptr produce(const edm4eic::TrackerHitCollection& trk_hits); - - private: - void configure(); - - std::shared_ptr m_log; - std::shared_ptr m_geoSvc; - - std::shared_ptr m_BField = nullptr; - Acts::MagneticFieldContext m_fieldctx; - - Acts::SeedFilterConfig m_seedFilterConfig; - Acts::SeedFinderOptions m_seedFinderOptions; - Acts::SeedFinderOrthogonalConfig m_seedFinderConfig; - - int determineCharge(std::vector>& positions, const std::pair& PCA, std::tuple& RX0Y0) const; - std::pair findPCA(std::tuple& circleParams) const; - std::vector getSpacePoints(const edm4eic::TrackerHitCollection& trk_hits); - std::unique_ptr makeTrackParams(SeedContainer& seeds); - - std::tuple circleFit(std::vector>& positions) const; - std::tuple lineFit(std::vector>& positions) const; - }; -} +class TrackSeeding : public eicrecon::WithPodConfig { +public: + void init(std::shared_ptr geo_svc, + std::shared_ptr log); + std::unique_ptr + produce(const edm4eic::TrackerHitCollection& trk_hits); + +private: + void configure(); + + std::shared_ptr m_log; + std::shared_ptr m_geoSvc; + + std::shared_ptr m_BField = nullptr; + Acts::MagneticFieldContext m_fieldctx; + + Acts::SeedFilterConfig m_seedFilterConfig; + Acts::SeedFinderOptions m_seedFinderOptions; + Acts::SeedFinderOrthogonalConfig m_seedFinderConfig; + + int determineCharge(std::vector>& positions, + const std::pair& PCA, + std::tuple& RX0Y0) const; + std::pair findPCA(std::tuple& circleParams) const; + std::vector + getSpacePoints(const edm4eic::TrackerHitCollection& trk_hits); + std::unique_ptr makeTrackParams(SeedContainer& seeds); + + std::tuple circleFit(std::vector>& positions) const; + std::tuple lineFit(std::vector>& positions) const; +}; +} // namespace eicrecon diff --git a/src/algorithms/tracking/TrackerHitReconstruction.cc b/src/algorithms/tracking/TrackerHitReconstruction.cc index 155ba7d35f..a814a7481b 100644 --- a/src/algorithms/tracking/TrackerHitReconstruction.cc +++ b/src/algorithms/tracking/TrackerHitReconstruction.cc @@ -18,67 +18,71 @@ namespace eicrecon { namespace { - inline double get_resolution(const double pixel_size) { - constexpr const double sqrt_12 = 3.4641016151; - return pixel_size / sqrt_12; - } - inline double get_variance(const double pixel_size) { - const double res = get_resolution(pixel_size); - return res * res; - } + inline double get_resolution(const double pixel_size) { + constexpr const double sqrt_12 = 3.4641016151; + return pixel_size / sqrt_12; + } + inline double get_variance(const double pixel_size) { + const double res = get_resolution(pixel_size); + return res * res; + } } // namespace -void TrackerHitReconstruction::init(const dd4hep::rec::CellIDPositionConverter* converter, std::shared_ptr& logger) { +void TrackerHitReconstruction::init(const dd4hep::rec::CellIDPositionConverter* converter, + std::shared_ptr& logger) { - m_log = logger; + m_log = logger; - m_converter = converter; + m_converter = converter; } -std::unique_ptr TrackerHitReconstruction::process(const edm4eic::RawTrackerHitCollection& raw_hits) { - using dd4hep::mm; - - auto rec_hits { std::make_unique() }; - - for (const auto& raw_hit : raw_hits) { - - auto id = raw_hit.getCellID(); - - // Get position and dimension - auto pos = m_converter->position(id); - auto dim = m_converter->cellDimensions(id); - - // >oO trace - if(m_log->level() == spdlog::level::trace) { - m_log->trace("position x={:.2f} y={:.2f} z={:.2f} [mm]: ", pos.x()/ mm, pos.y()/ mm, pos.z()/ mm); - m_log->trace("dimension size: {}", dim.size()); - for (size_t j = 0; j < std::size(dim); ++j) { - m_log->trace(" - dimension {:<5} size: {:.2}", j, dim[j]); - } - } - - // Note about variance: - // The variance is used to obtain a diagonal covariance matrix. - // Note that the covariance matrix is written in DD4hep surface coordinates, - // *NOT* global position coordinates. This implies that: - // - XY segmentation: xx -> sigma_x, yy-> sigma_y, zz -> 0, tt -> 0 - // - XZ segmentation: xx -> sigma_x, yy-> sigma_z, zz -> 0, tt -> 0 - // - XYZ segmentation: xx -> sigma_x, yy-> sigma_y, zz -> sigma_z, tt -> 0 - // This is properly in line with how we get the local coordinates for the hit - // in the TrackerSourceLinker. - rec_hits->create( - raw_hit.getCellID(), // Raw DD4hep cell ID - edm4hep::Vector3f{static_cast(pos.x() / mm), static_cast(pos.y() / mm), static_cast(pos.z() / mm)}, // mm - edm4eic::CovDiag3f{get_variance(dim[0] / mm), get_variance(dim[1] / mm), // variance (see note above) - std::size(dim) > 2 ? get_variance(dim[2] / mm) : 0.}, - static_cast((double)(raw_hit.getTimeStamp()) / 1000.0), // ns - m_cfg.timeResolution, // in ns - static_cast(raw_hit.getCharge() / 1.0e6), // Collected energy (GeV) - 0.0F); // Error on the energy +std::unique_ptr +TrackerHitReconstruction::process(const edm4eic::RawTrackerHitCollection& raw_hits) { + using dd4hep::mm; + + auto rec_hits{std::make_unique()}; + + for (const auto& raw_hit : raw_hits) { + + auto id = raw_hit.getCellID(); + + // Get position and dimension + auto pos = m_converter->position(id); + auto dim = m_converter->cellDimensions(id); + // >oO trace + if (m_log->level() == spdlog::level::trace) { + m_log->trace("position x={:.2f} y={:.2f} z={:.2f} [mm]: ", pos.x() / mm, pos.y() / mm, + pos.z() / mm); + m_log->trace("dimension size: {}", dim.size()); + for (size_t j = 0; j < std::size(dim); ++j) { + m_log->trace(" - dimension {:<5} size: {:.2}", j, dim[j]); + } } - return std::move(rec_hits); + // Note about variance: + // The variance is used to obtain a diagonal covariance matrix. + // Note that the covariance matrix is written in DD4hep surface coordinates, + // *NOT* global position coordinates. This implies that: + // - XY segmentation: xx -> sigma_x, yy-> sigma_y, zz -> 0, tt -> 0 + // - XZ segmentation: xx -> sigma_x, yy-> sigma_z, zz -> 0, tt -> 0 + // - XYZ segmentation: xx -> sigma_x, yy-> sigma_y, zz -> sigma_z, tt -> 0 + // This is properly in line with how we get the local coordinates for the hit + // in the TrackerSourceLinker. + rec_hits->create(raw_hit.getCellID(), // Raw DD4hep cell ID + edm4hep::Vector3f{static_cast(pos.x() / mm), + static_cast(pos.y() / mm), + static_cast(pos.z() / mm)}, // mm + edm4eic::CovDiag3f{get_variance(dim[0] / mm), + get_variance(dim[1] / mm), // variance (see note above) + std::size(dim) > 2 ? get_variance(dim[2] / mm) : 0.}, + static_cast((double)(raw_hit.getTimeStamp()) / 1000.0), // ns + m_cfg.timeResolution, // in ns + static_cast(raw_hit.getCharge() / 1.0e6), // Collected energy (GeV) + 0.0F); // Error on the energy + } + + return std::move(rec_hits); } } // namespace eicrecon diff --git a/src/algorithms/tracking/TrackerHitReconstruction.h b/src/algorithms/tracking/TrackerHitReconstruction.h index e6b67e2d6f..138cd33f2f 100644 --- a/src/algorithms/tracking/TrackerHitReconstruction.h +++ b/src/algorithms/tracking/TrackerHitReconstruction.h @@ -14,26 +14,32 @@ namespace eicrecon { - /** +/** * Produces edm4eic::TrackerHit with geometric info from edm4eic::RawTrackerHit */ - class TrackerHitReconstruction : public WithPodConfig { - - public: - /// Once in a lifetime initialization - void init(const dd4hep::rec::CellIDPositionConverter* converter, std::shared_ptr& logger); - - /// Processes RawTrackerHit and produces a TrackerHit - std::unique_ptr process(const edm4eic::RawTrackerHitCollection& raw_hits); - - /// Set a configuration - eicrecon::TrackerHitReconstructionConfig& applyConfig(eicrecon::TrackerHitReconstructionConfig& cfg) {m_cfg = cfg; return m_cfg;} - - private: - /** algorithm logger */ - std::shared_ptr m_log; - - /// Cell ID position converter - const dd4hep::rec::CellIDPositionConverter* m_converter; - }; -} +class TrackerHitReconstruction : public WithPodConfig { + +public: + /// Once in a lifetime initialization + void init(const dd4hep::rec::CellIDPositionConverter* converter, + std::shared_ptr& logger); + + /// Processes RawTrackerHit and produces a TrackerHit + std::unique_ptr + process(const edm4eic::RawTrackerHitCollection& raw_hits); + + /// Set a configuration + eicrecon::TrackerHitReconstructionConfig& + applyConfig(eicrecon::TrackerHitReconstructionConfig& cfg) { + m_cfg = cfg; + return m_cfg; + } + +private: + /** algorithm logger */ + std::shared_ptr m_log; + + /// Cell ID position converter + const dd4hep::rec::CellIDPositionConverter* m_converter; +}; +} // namespace eicrecon diff --git a/src/algorithms/tracking/TrackerHitReconstructionConfig.h b/src/algorithms/tracking/TrackerHitReconstructionConfig.h index 35d81adbe4..c903611564 100644 --- a/src/algorithms/tracking/TrackerHitReconstructionConfig.h +++ b/src/algorithms/tracking/TrackerHitReconstructionConfig.h @@ -4,7 +4,7 @@ #pragma once namespace eicrecon { - struct TrackerHitReconstructionConfig { - float timeResolution = 10; - }; -} +struct TrackerHitReconstructionConfig { + float timeResolution = 10; +}; +} // namespace eicrecon diff --git a/src/algorithms/tracking/TrackerMeasurementFromHits.cc b/src/algorithms/tracking/TrackerMeasurementFromHits.cc index af8d7dfb75..261b7ddb6e 100644 --- a/src/algorithms/tracking/TrackerMeasurementFromHits.cc +++ b/src/algorithms/tracking/TrackerMeasurementFromHits.cc @@ -27,111 +27,123 @@ #include #include - namespace eicrecon { - - void TrackerMeasurementFromHits::init(const dd4hep::Detector* detector, - const dd4hep::rec::CellIDPositionConverter* converter, - std::shared_ptr acts_context, - std::shared_ptr logger) { - m_dd4hepGeo = detector; - m_converter = converter; - m_log = logger; - m_acts_context = std::move(acts_context); - m_detid_b0tracker = m_dd4hepGeo->constant("B0Tracker_Station_1_ID"); +void TrackerMeasurementFromHits::init(const dd4hep::Detector* detector, + const dd4hep::rec::CellIDPositionConverter* converter, + std::shared_ptr acts_context, + std::shared_ptr logger) { + m_dd4hepGeo = detector; + m_converter = converter; + m_log = logger; + m_acts_context = std::move(acts_context); + m_detid_b0tracker = m_dd4hepGeo->constant("B0Tracker_Station_1_ID"); } +std::unique_ptr +TrackerMeasurementFromHits::produce(const edm4eic::TrackerHitCollection& trk_hits) { + constexpr double mm_acts = Acts::UnitConstants::mm; + constexpr double mm_conv = mm_acts / dd4hep::mm; // = 1/0.1 + + // output collections + auto meas2Ds = std::make_unique(); + + // To do: add clustering to allow forming one measurement from several hits. + // For now, one hit = one measurement. + for (const auto hit : trk_hits) { + + Acts::SquareMatrix2 cov = Acts::SquareMatrix2::Zero(); + cov(0, 0) = hit.getPositionError().xx * mm_acts * mm_acts; // note mm = 1 (Acts) + cov(1, 1) = hit.getPositionError().yy * mm_acts * mm_acts; + cov(0, 1) = cov(1, 0) = 0.0; + + const auto* vol_ctx = m_converter->findContext(hit.getCellID()); + auto vol_id = vol_ctx->identifier; + + auto surfaceMap = m_acts_context->surfaceMap(); + + // m_log->trace("Hit preparation information: {}", hit_index); + m_log->trace(" System id: {}, Cell id: {}", hit.getCellID() & 0xFF, hit.getCellID()); + m_log->trace(" cov matrix: {:>12.2e} {:>12.2e}", cov(0, 0), cov(0, 1)); + m_log->trace(" {:>12.2e} {:>12.2e}", cov(1, 0), cov(1, 1)); + m_log->trace(" surfaceMap size: {}", surfaceMap.size()); - std::unique_ptr TrackerMeasurementFromHits::produce(const edm4eic::TrackerHitCollection& trk_hits) { - constexpr double mm_acts = Acts::UnitConstants::mm; - constexpr double mm_conv = mm_acts / dd4hep::mm; // = 1/0.1 - - // output collections - auto meas2Ds = std::make_unique(); - - // To do: add clustering to allow forming one measurement from several hits. - // For now, one hit = one measurement. - for (const auto hit: trk_hits) { - - Acts::SquareMatrix2 cov = Acts::SquareMatrix2::Zero(); - cov(0, 0) = hit.getPositionError().xx * mm_acts * mm_acts; // note mm = 1 (Acts) - cov(1, 1) = hit.getPositionError().yy * mm_acts * mm_acts; - cov(0, 1) = cov(1, 0) = 0.0; - - const auto* vol_ctx = m_converter->findContext(hit.getCellID()); - auto vol_id = vol_ctx->identifier; - - auto surfaceMap = m_acts_context->surfaceMap(); - - // m_log->trace("Hit preparation information: {}", hit_index); - m_log->trace(" System id: {}, Cell id: {}", hit.getCellID() &0xFF, hit.getCellID()); - m_log->trace(" cov matrix: {:>12.2e} {:>12.2e}", cov(0,0), cov(0,1)); - m_log->trace(" {:>12.2e} {:>12.2e}", cov(1,0), cov(1,1)); - m_log->trace(" surfaceMap size: {}", surfaceMap.size()); - - const auto is = surfaceMap.find(vol_id); - if (is == m_acts_context->surfaceMap().end()) { - m_log->warn(" WARNING: vol_id ({}) not found in m_surfaces.", vol_id ); - continue; - } - const Acts::Surface* surface = is->second; - // variable surf_center not used anywhere; - - const auto& hit_pos = hit.getPosition(); // 3d position - - Acts::Vector2 loc = Acts::Vector2::Zero(); - Acts::Vector2 pos; - auto hit_det = hit.getCellID()&0xFF; - auto onSurfaceTolerance = 0.1*Acts::UnitConstants::um; // By default, ACTS uses 0.1 micron as the on surface tolerance - if (hit_det==m_detid_b0tracker){ - onSurfaceTolerance = 1*Acts::UnitConstants::um; // FIXME Ugly hack for testing B0. Should be a way to increase this tolerance in geometry. - } - - try { - // transform global position into local coordinates - // geometry context contains nothing here - pos = surface->globalToLocal( - Acts::GeometryContext(), - {hit_pos.x, hit_pos.y, hit_pos.z}, - {0, 0, 0}, onSurfaceTolerance).value(); - - loc[Acts::eBoundLoc0] = pos[0]; - loc[Acts::eBoundLoc1] = pos[1]; - } - catch(std::exception &ex) { - m_log->warn("Can't convert globalToLocal for hit: vol_id={} det_id={} CellID={} x={} y={} z={}", - vol_id, hit.getCellID()&0xFF, hit.getCellID(), hit_pos.x, hit_pos.y, hit_pos.z); - continue; - } - - if (m_log->level() <= spdlog::level::trace) { - auto volman = m_acts_context->dd4hepDetector()->volumeManager(); - auto alignment = volman.lookupDetElement(vol_id).nominal(); - auto local_position = (alignment.worldToLocal({hit_pos.x / mm_conv, hit_pos.y / mm_conv, hit_pos.z / mm_conv})) * mm_conv; - double surf_center_x = surface->center(Acts::GeometryContext()).transpose()[0]; - double surf_center_y = surface->center(Acts::GeometryContext()).transpose()[1]; - double surf_center_z = surface->center(Acts::GeometryContext()).transpose()[2]; - m_log->trace(" hit position : {:>10.2f} {:>10.2f} {:>10.2f}", hit_pos.x, hit_pos.y, hit_pos.z); - m_log->trace(" local position : {:>10.2f} {:>10.2f} {:>10.2f}", local_position.x(), local_position.y(), local_position.z()); - m_log->trace(" surface center : {:>10.2f} {:>10.2f} {:>10.2f}", surf_center_x, surf_center_y, surf_center_z); - m_log->trace(" acts local center: {:>10.2f} {:>10.2f}", pos.transpose()[0], pos.transpose()[1]); - m_log->trace(" acts loc pos : {:>10.2f} {:>10.2f}", loc[Acts::eBoundLoc0], loc[Acts::eBoundLoc1]); - } - - - auto meas2D = meas2Ds->create(); - meas2D.setSurface(surface->geometryId().value()); // Surface for bound coordinates (geometryID) - meas2D.setLoc({static_cast(pos[0]),static_cast(pos[1])}); // 2D location on surface - meas2D.setTime(hit.getTime()); // Measurement time - // fixme: no off-diagonal terms. cov(0,1) = cov(1,0)?? - meas2D.setCovariance({cov(0,0),cov(1,1),hit.getTimeError(),cov(0,1)}); // Covariance on location and time - meas2D.addToWeights(1.0); // Weight for each of the hits, mirrors hits array - meas2D.addToHits(hit); - } - - m_log->debug("All hits processed. Hits size: {} measurements->size: {}", trk_hits.size(), meas2Ds->size()); - - return std::move(meas2Ds); + const auto is = surfaceMap.find(vol_id); + if (is == m_acts_context->surfaceMap().end()) { + m_log->warn(" WARNING: vol_id ({}) not found in m_surfaces.", vol_id); + continue; } + const Acts::Surface* surface = is->second; + // variable surf_center not used anywhere; + + const auto& hit_pos = hit.getPosition(); // 3d position + + Acts::Vector2 loc = Acts::Vector2::Zero(); + Acts::Vector2 pos; + auto hit_det = hit.getCellID() & 0xFF; + auto onSurfaceTolerance = + 0.1 * + Acts::UnitConstants::um; // By default, ACTS uses 0.1 micron as the on surface tolerance + if (hit_det == m_detid_b0tracker) { + onSurfaceTolerance = + 1 * + Acts::UnitConstants:: + um; // FIXME Ugly hack for testing B0. Should be a way to increase this tolerance in geometry. + } + + try { + // transform global position into local coordinates + // geometry context contains nothing here + pos = surface + ->globalToLocal(Acts::GeometryContext(), {hit_pos.x, hit_pos.y, hit_pos.z}, + {0, 0, 0}, onSurfaceTolerance) + .value(); + + loc[Acts::eBoundLoc0] = pos[0]; + loc[Acts::eBoundLoc1] = pos[1]; + } catch (std::exception& ex) { + m_log->warn( + "Can't convert globalToLocal for hit: vol_id={} det_id={} CellID={} x={} y={} z={}", + vol_id, hit.getCellID() & 0xFF, hit.getCellID(), hit_pos.x, hit_pos.y, hit_pos.z); + continue; + } + + if (m_log->level() <= spdlog::level::trace) { + auto volman = m_acts_context->dd4hepDetector()->volumeManager(); + auto alignment = volman.lookupDetElement(vol_id).nominal(); + auto local_position = (alignment.worldToLocal( + {hit_pos.x / mm_conv, hit_pos.y / mm_conv, hit_pos.z / mm_conv})) * + mm_conv; + double surf_center_x = surface->center(Acts::GeometryContext()).transpose()[0]; + double surf_center_y = surface->center(Acts::GeometryContext()).transpose()[1]; + double surf_center_z = surface->center(Acts::GeometryContext()).transpose()[2]; + m_log->trace(" hit position : {:>10.2f} {:>10.2f} {:>10.2f}", hit_pos.x, hit_pos.y, + hit_pos.z); + m_log->trace(" local position : {:>10.2f} {:>10.2f} {:>10.2f}", local_position.x(), + local_position.y(), local_position.z()); + m_log->trace(" surface center : {:>10.2f} {:>10.2f} {:>10.2f}", surf_center_x, + surf_center_y, surf_center_z); + m_log->trace(" acts local center: {:>10.2f} {:>10.2f}", pos.transpose()[0], + pos.transpose()[1]); + m_log->trace(" acts loc pos : {:>10.2f} {:>10.2f}", loc[Acts::eBoundLoc0], + loc[Acts::eBoundLoc1]); + } + + auto meas2D = meas2Ds->create(); + meas2D.setSurface(surface->geometryId().value()); // Surface for bound coordinates (geometryID) + meas2D.setLoc( + {static_cast(pos[0]), static_cast(pos[1])}); // 2D location on surface + meas2D.setTime(hit.getTime()); // Measurement time + // fixme: no off-diagonal terms. cov(0,1) = cov(1,0)?? + meas2D.setCovariance( + {cov(0, 0), cov(1, 1), hit.getTimeError(), cov(0, 1)}); // Covariance on location and time + meas2D.addToWeights(1.0); // Weight for each of the hits, mirrors hits array + meas2D.addToHits(hit); + } + + m_log->debug("All hits processed. Hits size: {} measurements->size: {}", trk_hits.size(), + meas2Ds->size()); + + return std::move(meas2Ds); +} } // namespace eicrecon diff --git a/src/algorithms/tracking/TrackerMeasurementFromHits.h b/src/algorithms/tracking/TrackerMeasurementFromHits.h index 5c7de0275a..e25ff8d56a 100644 --- a/src/algorithms/tracking/TrackerMeasurementFromHits.h +++ b/src/algorithms/tracking/TrackerMeasurementFromHits.h @@ -18,26 +18,26 @@ namespace eicrecon { - class TrackerMeasurementFromHits { - public: - void init(const dd4hep::Detector* detector, - const dd4hep::rec::CellIDPositionConverter* converter, - std::shared_ptr acts_context, - std::shared_ptr logger); +class TrackerMeasurementFromHits { +public: + void init(const dd4hep::Detector* detector, const dd4hep::rec::CellIDPositionConverter* converter, + std::shared_ptr acts_context, + std::shared_ptr logger); - std::unique_ptr produce(const edm4eic::TrackerHitCollection& trk_hits); + std::unique_ptr + produce(const edm4eic::TrackerHitCollection& trk_hits); - private: - std::shared_ptr m_log; +private: + std::shared_ptr m_log; - /// Geometry and Cell ID position converter - const dd4hep::Detector* m_dd4hepGeo; - const dd4hep::rec::CellIDPositionConverter* m_converter; + /// Geometry and Cell ID position converter + const dd4hep::Detector* m_dd4hepGeo; + const dd4hep::rec::CellIDPositionConverter* m_converter; - std::shared_ptr m_acts_context; + std::shared_ptr m_acts_context; - /// Detector-specific information - int m_detid_b0tracker; - }; + /// Detector-specific information + int m_detid_b0tracker; +}; -} +} // namespace eicrecon diff --git a/src/benchmarks/detectors/EcalBarrelScFiCheck/EcalBarrelScFiCheck.cc b/src/benchmarks/detectors/EcalBarrelScFiCheck/EcalBarrelScFiCheck.cc index 4b95373a25..f430586252 100644 --- a/src/benchmarks/detectors/EcalBarrelScFiCheck/EcalBarrelScFiCheck.cc +++ b/src/benchmarks/detectors/EcalBarrelScFiCheck/EcalBarrelScFiCheck.cc @@ -4,8 +4,8 @@ // The following just makes this a JANA plugin extern "C" { - void InitPlugin(JApplication *app) { - InitJANAPlugin(app); - app->Add(new EcalBarrelScFiCheckProcessor); - } +void InitPlugin(JApplication* app) { + InitJANAPlugin(app); + app->Add(new EcalBarrelScFiCheckProcessor); +} } diff --git a/src/benchmarks/detectors/EcalBarrelScFiCheck/EcalBarrelScFiCheckProcessor.cc b/src/benchmarks/detectors/EcalBarrelScFiCheck/EcalBarrelScFiCheckProcessor.cc index 88234a2428..4cc1bd815b 100644 --- a/src/benchmarks/detectors/EcalBarrelScFiCheck/EcalBarrelScFiCheckProcessor.cc +++ b/src/benchmarks/detectors/EcalBarrelScFiCheck/EcalBarrelScFiCheckProcessor.cc @@ -21,78 +21,106 @@ //------------------------------------------- // InitWithGlobalRootLock //------------------------------------------- -void EcalBarrelScFiCheckProcessor::InitWithGlobalRootLock(){ - - auto rootfile_svc = GetApplication()->GetService(); - auto rootfile = rootfile_svc->GetHistFile(); - rootfile->mkdir("EcalBarrelScFi")->cd(); - - hist1D["EcalBarrelScFiHits_hits_per_event"] = new TH1I("EcalBarrelScFiHits_hits_per_event", "EcalBarrelScFi Simulated hit Nhits/event;Nhits", 300, 0.0, 3000); - hist2D["EcalBarrelScFiHits_occupancy"] = new TH2I("EcalBarrelScFiHits_occupancy", "EcalBarrelScFi Simulated hit occupancy;column;row", 70, -700.0, 700.0, 70, -700.0, 700.0); - hist1D["EcalBarrelScFiHits_hit_energy"] = new TH1D("EcalBarrelScFiHits_hit_energy", "EcalBarrelScFi Simulated hit energy;GeV", 1000, 0.0, 2.0); - - hist1D["EcalBarrelScFiRawHits_hits_per_event"] = new TH1I("EcalBarrelScFiRawHits_hits_per_event", "EcalBarrelScFi Simulated digitized hit Nhits/event;Nhits", 300, 0.0, 3000); - hist1D["EcalBarrelScFiRawHits_amplitude"] = new TH1D("EcalBarrelScFiRawHits_amplitude", "EcalBarrelScFi Simulated digitized hit amplitude;amplitude", 1000, 0.0, 8200.0); - hist1D["EcalBarrelScFiRawHits_timestamp"] = new TH1I("EcalBarrelScFiRawHits_timestamp", "EcalBarrelScFi Simulated digitized hit timestamp;timestamp", 1024, 0.0, 8191.0); - - hist1D["EcalBarrelScFiRecHits_hits_per_event"] = new TH1I("EcalBarrelScFiRecHits_hits_per_event", "EcalBarrelScFi Reconstructed hit Nhits/event;Nhits", 300, 0.0, 3000); - hist1D["EcalBarrelScFiRecHits_hit_energy"] = new TH1D("EcalBarrelScFiRecHits_hit_energy", "EcalBarrelScFi Reconstructed hit energy;MeV", 1000, 0.0, 100.0); - hist2D["EcalBarrelScFiRecHits_xy"] = new TH2D("EcalBarrelScFiRecHits_xy", "EcalBarrelScFi Reconstructed hit Y vs. X (energy weighted);x;y", 128, -1100.0, 1100.0, 128, -1100.0, 1100.0); - hist1D["EcalBarrelScFiRecHits_z"] = new TH1D("EcalBarrelScFiRecHits_z", "EcalBarrelScFi Reconstructed hit Z;z", 400, -3000.0, 1600.0); - hist1D["EcalBarrelScFiRecHits_time"] = new TH1D("EcalBarrelScFiRecHits_time", "EcalBarrelScFi Reconstructed hit time;time", 1000, -10.0, 2000.0); - - hist1D["EcalBarrelScFiProtoClusters_clusters_per_event"] = new TH1I("EcalBarrelScFiProtoClusters_clusters_per_event", "EcalBarrelScFi Protoclusters Nclusters/event;Nclusters", 61, -0.5, 60.5); - hist1D["EcalBarrelScFiProtoClusters_hits_per_cluster"] = new TH1I("EcalBarrelScFiProtoClusters_hits_per_cluster", "EcalBarrelScFi Protoclusters Nhits/cluster;Nhits", 101, -0.5, 100.5); - - // Set some draw options - hist2D["EcalBarrelScFiHits_occupancy"]->SetOption("colz"); - hist2D["EcalBarrelScFiRecHits_xy"]->SetOption("colz"); +void EcalBarrelScFiCheckProcessor::InitWithGlobalRootLock() { + + auto rootfile_svc = GetApplication()->GetService(); + auto rootfile = rootfile_svc->GetHistFile(); + rootfile->mkdir("EcalBarrelScFi")->cd(); + + hist1D["EcalBarrelScFiHits_hits_per_event"] = + new TH1I("EcalBarrelScFiHits_hits_per_event", + "EcalBarrelScFi Simulated hit Nhits/event;Nhits", 300, 0.0, 3000); + hist2D["EcalBarrelScFiHits_occupancy"] = + new TH2I("EcalBarrelScFiHits_occupancy", "EcalBarrelScFi Simulated hit occupancy;column;row", + 70, -700.0, 700.0, 70, -700.0, 700.0); + hist1D["EcalBarrelScFiHits_hit_energy"] = new TH1D( + "EcalBarrelScFiHits_hit_energy", "EcalBarrelScFi Simulated hit energy;GeV", 1000, 0.0, 2.0); + + hist1D["EcalBarrelScFiRawHits_hits_per_event"] = + new TH1I("EcalBarrelScFiRawHits_hits_per_event", + "EcalBarrelScFi Simulated digitized hit Nhits/event;Nhits", 300, 0.0, 3000); + hist1D["EcalBarrelScFiRawHits_amplitude"] = + new TH1D("EcalBarrelScFiRawHits_amplitude", + "EcalBarrelScFi Simulated digitized hit amplitude;amplitude", 1000, 0.0, 8200.0); + hist1D["EcalBarrelScFiRawHits_timestamp"] = + new TH1I("EcalBarrelScFiRawHits_timestamp", + "EcalBarrelScFi Simulated digitized hit timestamp;timestamp", 1024, 0.0, 8191.0); + + hist1D["EcalBarrelScFiRecHits_hits_per_event"] = + new TH1I("EcalBarrelScFiRecHits_hits_per_event", + "EcalBarrelScFi Reconstructed hit Nhits/event;Nhits", 300, 0.0, 3000); + hist1D["EcalBarrelScFiRecHits_hit_energy"] = + new TH1D("EcalBarrelScFiRecHits_hit_energy", "EcalBarrelScFi Reconstructed hit energy;MeV", + 1000, 0.0, 100.0); + hist2D["EcalBarrelScFiRecHits_xy"] = new TH2D( + "EcalBarrelScFiRecHits_xy", "EcalBarrelScFi Reconstructed hit Y vs. X (energy weighted);x;y", + 128, -1100.0, 1100.0, 128, -1100.0, 1100.0); + hist1D["EcalBarrelScFiRecHits_z"] = new TH1D( + "EcalBarrelScFiRecHits_z", "EcalBarrelScFi Reconstructed hit Z;z", 400, -3000.0, 1600.0); + hist1D["EcalBarrelScFiRecHits_time"] = + new TH1D("EcalBarrelScFiRecHits_time", "EcalBarrelScFi Reconstructed hit time;time", 1000, + -10.0, 2000.0); + + hist1D["EcalBarrelScFiProtoClusters_clusters_per_event"] = + new TH1I("EcalBarrelScFiProtoClusters_clusters_per_event", + "EcalBarrelScFi Protoclusters Nclusters/event;Nclusters", 61, -0.5, 60.5); + hist1D["EcalBarrelScFiProtoClusters_hits_per_cluster"] = + new TH1I("EcalBarrelScFiProtoClusters_hits_per_cluster", + "EcalBarrelScFi Protoclusters Nhits/cluster;Nhits", 101, -0.5, 100.5); + + // Set some draw options + hist2D["EcalBarrelScFiHits_occupancy"]->SetOption("colz"); + hist2D["EcalBarrelScFiRecHits_xy"]->SetOption("colz"); } //------------------------------------------- // ProcessSequential //------------------------------------------- void EcalBarrelScFiCheckProcessor::ProcessSequential(const std::shared_ptr& event) { - const auto &EcalBarrelScFiHits = *(event->GetCollection("EcalBarrelScFiHits")); - const auto &EcalBarrelScFiRawHits = *(event->GetCollection("EcalBarrelScFiRawHits")); - const auto &EcalBarrelScFiRecHits = *(event->GetCollection("EcalBarrelScFiRecHits")); - const auto &EcalBarrelScFiProtoClusters = *(event->GetCollection("EcalBarrelScFiProtoClusters")); - - // Fill histograms here - - // EcalBarrelScFiHits - hist1D["EcalBarrelScFiHits_hits_per_event"]->Fill(EcalBarrelScFiHits.size()); - for( auto hit : EcalBarrelScFiHits ){ - auto row = floor(hit.getPosition().y); - auto col = floor(hit.getPosition().x); - hist2D["EcalBarrelScFiHits_occupancy"]->Fill(row, col); - - hist1D["EcalBarrelScFiHits_hit_energy"]->Fill(hit.getEnergy()); - } - - // EcalBarrelScFiRawHits - hist1D["EcalBarrelScFiRawHits_hits_per_event"]->Fill(EcalBarrelScFiRawHits.size()); - for( auto hit : EcalBarrelScFiRawHits ){ - hist1D["EcalBarrelScFiRawHits_amplitude"]->Fill( hit.getAmplitude() ); - hist1D["EcalBarrelScFiRawHits_timestamp"]->Fill( hit.getTimeStamp() ); - } - - // EcalBarrelScFiRecHits - hist1D["EcalBarrelScFiRecHits_hits_per_event"]->Fill(EcalBarrelScFiRecHits.size()); - for( auto hit : EcalBarrelScFiRecHits ){ - auto &pos = hit.getPosition(); - hist1D["EcalBarrelScFiRecHits_hit_energy"]->Fill(hit.getEnergy() / dd4hep::MeV); - hist2D["EcalBarrelScFiRecHits_xy"]->Fill( pos.x, pos.y, hit.getEnergy() ); - hist1D["EcalBarrelScFiRecHits_z"]->Fill(pos.z); - hist1D["EcalBarrelScFiRecHits_time"]->Fill( hit.getTime() ); - } - - - // EcalBarrelScFiProtoClusters - hist1D["EcalBarrelScFiProtoClusters_clusters_per_event"]->Fill(EcalBarrelScFiProtoClusters.size()); - for (auto proto : EcalBarrelScFiProtoClusters ){ - hist1D["EcalBarrelScFiProtoClusters_hits_per_cluster"]->Fill( proto.getHits().size() ); - } + const auto& EcalBarrelScFiHits = + *(event->GetCollection("EcalBarrelScFiHits")); + const auto& EcalBarrelScFiRawHits = + *(event->GetCollection("EcalBarrelScFiRawHits")); + const auto& EcalBarrelScFiRecHits = + *(event->GetCollection("EcalBarrelScFiRecHits")); + const auto& EcalBarrelScFiProtoClusters = + *(event->GetCollection("EcalBarrelScFiProtoClusters")); + + // Fill histograms here + + // EcalBarrelScFiHits + hist1D["EcalBarrelScFiHits_hits_per_event"]->Fill(EcalBarrelScFiHits.size()); + for (auto hit : EcalBarrelScFiHits) { + auto row = floor(hit.getPosition().y); + auto col = floor(hit.getPosition().x); + hist2D["EcalBarrelScFiHits_occupancy"]->Fill(row, col); + + hist1D["EcalBarrelScFiHits_hit_energy"]->Fill(hit.getEnergy()); + } + + // EcalBarrelScFiRawHits + hist1D["EcalBarrelScFiRawHits_hits_per_event"]->Fill(EcalBarrelScFiRawHits.size()); + for (auto hit : EcalBarrelScFiRawHits) { + hist1D["EcalBarrelScFiRawHits_amplitude"]->Fill(hit.getAmplitude()); + hist1D["EcalBarrelScFiRawHits_timestamp"]->Fill(hit.getTimeStamp()); + } + + // EcalBarrelScFiRecHits + hist1D["EcalBarrelScFiRecHits_hits_per_event"]->Fill(EcalBarrelScFiRecHits.size()); + for (auto hit : EcalBarrelScFiRecHits) { + auto& pos = hit.getPosition(); + hist1D["EcalBarrelScFiRecHits_hit_energy"]->Fill(hit.getEnergy() / dd4hep::MeV); + hist2D["EcalBarrelScFiRecHits_xy"]->Fill(pos.x, pos.y, hit.getEnergy()); + hist1D["EcalBarrelScFiRecHits_z"]->Fill(pos.z); + hist1D["EcalBarrelScFiRecHits_time"]->Fill(hit.getTime()); + } + + // EcalBarrelScFiProtoClusters + hist1D["EcalBarrelScFiProtoClusters_clusters_per_event"]->Fill( + EcalBarrelScFiProtoClusters.size()); + for (auto proto : EcalBarrelScFiProtoClusters) { + hist1D["EcalBarrelScFiProtoClusters_hits_per_cluster"]->Fill(proto.getHits().size()); + } } //------------------------------------------- @@ -100,6 +128,5 @@ void EcalBarrelScFiCheckProcessor::ProcessSequential(const std::shared_ptr #include -class EcalBarrelScFiCheckProcessor: public JEventProcessorSequentialRoot { +class EcalBarrelScFiCheckProcessor : public JEventProcessorSequentialRoot { private: - - // Declare histogram and tree pointers - std::map hist1D; - std::map hist2D; + // Declare histogram and tree pointers + std::map hist1D; + std::map hist2D; public: - EcalBarrelScFiCheckProcessor() { SetTypeName(NAME_OF_THIS); } + EcalBarrelScFiCheckProcessor() { SetTypeName(NAME_OF_THIS); } - void InitWithGlobalRootLock() override; - void ProcessSequential(const std::shared_ptr& event) override; - void FinishWithGlobalRootLock() override; + void InitWithGlobalRootLock() override; + void ProcessSequential(const std::shared_ptr& event) override; + void FinishWithGlobalRootLock() override; }; diff --git a/src/benchmarks/reconstruction/TRACKINGcheck/TRACKINGcheck.cc b/src/benchmarks/reconstruction/TRACKINGcheck/TRACKINGcheck.cc index aa7f0e6cad..59322d4e96 100644 --- a/src/benchmarks/reconstruction/TRACKINGcheck/TRACKINGcheck.cc +++ b/src/benchmarks/reconstruction/TRACKINGcheck/TRACKINGcheck.cc @@ -4,8 +4,8 @@ // The following just makes this a JANA plugin extern "C" { - void InitPlugin(JApplication *app) { - InitJANAPlugin(app); - app->Add(new TRACKINGcheckProcessor); - } +void InitPlugin(JApplication* app) { + InitJANAPlugin(app); + app->Add(new TRACKINGcheckProcessor); +} } diff --git a/src/benchmarks/reconstruction/TRACKINGcheck/TRACKINGcheckProcessor.cc b/src/benchmarks/reconstruction/TRACKINGcheck/TRACKINGcheckProcessor.cc index c2cb9afb8e..052b7e651f 100644 --- a/src/benchmarks/reconstruction/TRACKINGcheck/TRACKINGcheckProcessor.cc +++ b/src/benchmarks/reconstruction/TRACKINGcheck/TRACKINGcheckProcessor.cc @@ -15,45 +15,52 @@ //------------------------------------------- // InitWithGlobalRootLock //------------------------------------------- -void TRACKINGcheckProcessor::InitWithGlobalRootLock(){ - - auto rootfile_svc = GetApplication()->GetService(); - auto *rootfile = rootfile_svc->GetHistFile(); - rootfile->mkdir("TRACKING")->cd(); - - hist1D["Trajectories_trajectories_per_event"] = new TH1I("Trajectories_trajectories_per_event", "TRACKING Reconstructed trajectories/event;Ntrajectories", 201, -0.5, 200.5); - hist1D["Trajectories_time"] = new TH1D("Trajectories_time", "TRACKING reconstructed particle time;time (ns)", 200, -100.0, 100.0); - hist2D["Trajectories_xy"] = new TH2D("Trajectories_xy", "TRACKING reconstructed position Y vs. X;x;y", 100, -1000.0, 1000.0, 100, -1000., 1000.0); - hist1D["Trajectories_z"] = new TH1D("Trajectories_z", "TRACKING reconstructed position Z;z", 200, -50.0, 50.0); - - // Set some draw options - hist2D["Trajectories_xy"]->SetOption("colz"); +void TRACKINGcheckProcessor::InitWithGlobalRootLock() { + + auto rootfile_svc = GetApplication()->GetService(); + auto* rootfile = rootfile_svc->GetHistFile(); + rootfile->mkdir("TRACKING")->cd(); + + hist1D["Trajectories_trajectories_per_event"] = + new TH1I("Trajectories_trajectories_per_event", + "TRACKING Reconstructed trajectories/event;Ntrajectories", 201, -0.5, 200.5); + hist1D["Trajectories_time"] = new TH1D( + "Trajectories_time", "TRACKING reconstructed particle time;time (ns)", 200, -100.0, 100.0); + hist2D["Trajectories_xy"] = + new TH2D("Trajectories_xy", "TRACKING reconstructed position Y vs. X;x;y", 100, -1000.0, + 1000.0, 100, -1000., 1000.0); + hist1D["Trajectories_z"] = + new TH1D("Trajectories_z", "TRACKING reconstructed position Z;z", 200, -50.0, 50.0); + + // Set some draw options + hist2D["Trajectories_xy"]->SetOption("colz"); } //------------------------------------------- // ProcessSequential //------------------------------------------- void TRACKINGcheckProcessor::ProcessSequential(const std::shared_ptr& event) { - auto Trajectories = event->Get("CentralCKFActsTrajectories"); + auto Trajectories = event->Get("CentralCKFActsTrajectories"); - // Fill histograms here + // Fill histograms here - // Trajectories - hist1D["Trajectories_trajectories_per_event"]->Fill(Trajectories.size()); + // Trajectories + hist1D["Trajectories_trajectories_per_event"]->Fill(Trajectories.size()); - for( const auto *traj : Trajectories ){ - for( auto entryIndex : traj->tips() ){ - if( ! traj->hasTrackParameters( entryIndex) ) continue; - auto trackparams = traj->trackParameters( entryIndex ); + for (const auto* traj : Trajectories) { + for (auto entryIndex : traj->tips()) { + if (!traj->hasTrackParameters(entryIndex)) + continue; + auto trackparams = traj->trackParameters(entryIndex); - auto pos = trackparams.position(Acts::GeometryContext()); - auto t = trackparams.time(); + auto pos = trackparams.position(Acts::GeometryContext()); + auto t = trackparams.time(); - hist1D["Trajectories_time"]->Fill( t ); - hist2D["Trajectories_xy"]->Fill( pos.x(), pos.y()); - hist1D["Trajectories_z"]->Fill( pos.z() ); - } + hist1D["Trajectories_time"]->Fill(t); + hist2D["Trajectories_xy"]->Fill(pos.x(), pos.y()); + hist1D["Trajectories_z"]->Fill(pos.z()); } + } } //------------------------------------------- @@ -61,6 +68,5 @@ void TRACKINGcheckProcessor::ProcessSequential(const std::shared_ptr #include - -class TRACKINGcheckProcessor: public JEventProcessorSequentialRoot { +class TRACKINGcheckProcessor : public JEventProcessorSequentialRoot { private: - - // Containers for histograms - std::map hist1D; - std::map hist2D; + // Containers for histograms + std::map hist1D; + std::map hist2D; public: - TRACKINGcheckProcessor() { SetTypeName(NAME_OF_THIS); } + TRACKINGcheckProcessor() { SetTypeName(NAME_OF_THIS); } - void InitWithGlobalRootLock() override; - void ProcessSequential(const std::shared_ptr& event) override; - void FinishWithGlobalRootLock() override; + void InitWithGlobalRootLock() override; + void ProcessSequential(const std::shared_ptr& event) override; + void FinishWithGlobalRootLock() override; }; diff --git a/src/benchmarks/reconstruction/TRACKINGcheck/macros/TRACKINGcheck.C b/src/benchmarks/reconstruction/TRACKINGcheck/macros/TRACKINGcheck.C index b462ad2a52..95d25b66dd 100644 --- a/src/benchmarks/reconstruction/TRACKINGcheck/macros/TRACKINGcheck.C +++ b/src/benchmarks/reconstruction/TRACKINGcheck/macros/TRACKINGcheck.C @@ -1,82 +1,84 @@ -void EEMCcheck(void) -{ - auto fil = new TFile("eicrecon.root"); - - auto EcalEndcapNhits_hits_per_event = (TH1I*)fil->Get("EEMC/EcalEndcapNhits_hits_per_event"); - auto EcalEndcapNhits_occupancy = (TH2I*)fil->Get("EEMC/EcalEndcapNhits_occupancy"); - auto EcalEndcapNhits_hit_energy = (TH1D*)fil->Get("EEMC/EcalEndcapNhits_hit_energy"); - - auto EcalEndcapNRawhits_hits_per_event = (TH1I*)fil->Get("EEMC/EcalEndcapNRawhits_hits_per_event"); - auto EcalEndcapNRawhits_amplitude = (TH1D*)fil->Get("EEMC/EcalEndcapNRawhits_amplitude"); - auto EcalEndcapNRawhits_timestamp = (TH1I*)fil->Get("EEMC/EcalEndcapNRawhits_timestamp"); - - auto EcalEndcapNRechits_hits_per_event = (TH1I*)fil->Get("EEMC/EcalEndcapNRechits_hits_per_event"); - auto EcalEndcapNRecHits_hit_energy = (TH1D*)fil->Get("EEMC/EcalEndcapNRecHits_hit_energy"); - auto EcalEndcapNRecHits_xy = (TH2D*)fil->Get("EEMC/EcalEndcapNRecHits_xy"); - auto EcalEndcapNRecHits_z = (TH1D*)fil->Get("EEMC/EcalEndcapNRecHits_z"); - auto EcalEndcapNRecHits_time = (TH1D*)fil->Get("EEMC/EcalEndcapNRecHits_time"); - - auto EcalEndcapNIslandProtoClusters_clusters_per_event = (TH1I*)fil->Get("EEMC/EcalEndcapNIslandProtoClusters_clusters_per_event"); - auto EcalEndcapNIslandProtoClusters_hits_per_cluster = (TH1I*)fil->Get("EEMC/EcalEndcapNIslandProtoClusters_hits_per_cluster"); - - - auto c1 = new TCanvas("c1", "", 1700, 1000); - c1->Divide(4,4); - - //---------------- EcalEndcapNhits - c1->cd(1); - gPad->SetLogy(); - EcalEndcapNhits_hits_per_event->Draw(); - - c1->cd(2); - EcalEndcapNhits_occupancy->Draw(); - - c1->cd(3); - gPad->SetLogy(); - EcalEndcapNhits_hit_energy->Draw(); - - //---------------- EcalEndcapNRawhits - c1->cd(5); - gPad->SetLogy(); - EcalEndcapNRawhits_hits_per_event->Draw(); - - c1->cd(6); - gPad->SetLogy(); - EcalEndcapNRawhits_amplitude->Draw(); - - c1->cd(7); - EcalEndcapNRawhits_timestamp->Draw(); - - //---------------- EcalEndcapNRecHits - c1->cd(9); - gPad->SetLogy(); - EcalEndcapNRechits_hits_per_event->Draw(); - - c1->cd(10); - EcalEndcapNRecHits_xy->Draw(); - - c1->cd(11); - EcalEndcapNRecHits_z->Draw(); - - c1->cd(12); - gPad->SetLogy(); - EcalEndcapNRecHits_time->Draw(); - - c1->cd(8); - gPad->SetLogy(); - EcalEndcapNRecHits_hit_energy->Draw(); - - //---------------- EcalEndcapNIslandProtoClusters - c1->cd(13); - gPad->SetLogy(); - EcalEndcapNIslandProtoClusters_clusters_per_event->Draw(); - - c1->cd(14); - gPad->SetLogy(); - EcalEndcapNIslandProtoClusters_hits_per_cluster->Draw(); - - c1->SaveAs("EEMCcheck.pdf"); - c1->SaveAs("EEMCcheck.png"); +void EEMCcheck(void) { + auto fil = new TFile("eicrecon.root"); + + auto EcalEndcapNhits_hits_per_event = (TH1I*)fil->Get("EEMC/EcalEndcapNhits_hits_per_event"); + auto EcalEndcapNhits_occupancy = (TH2I*)fil->Get("EEMC/EcalEndcapNhits_occupancy"); + auto EcalEndcapNhits_hit_energy = (TH1D*)fil->Get("EEMC/EcalEndcapNhits_hit_energy"); + + auto EcalEndcapNRawhits_hits_per_event = + (TH1I*)fil->Get("EEMC/EcalEndcapNRawhits_hits_per_event"); + auto EcalEndcapNRawhits_amplitude = (TH1D*)fil->Get("EEMC/EcalEndcapNRawhits_amplitude"); + auto EcalEndcapNRawhits_timestamp = (TH1I*)fil->Get("EEMC/EcalEndcapNRawhits_timestamp"); + + auto EcalEndcapNRechits_hits_per_event = + (TH1I*)fil->Get("EEMC/EcalEndcapNRechits_hits_per_event"); + auto EcalEndcapNRecHits_hit_energy = (TH1D*)fil->Get("EEMC/EcalEndcapNRecHits_hit_energy"); + auto EcalEndcapNRecHits_xy = (TH2D*)fil->Get("EEMC/EcalEndcapNRecHits_xy"); + auto EcalEndcapNRecHits_z = (TH1D*)fil->Get("EEMC/EcalEndcapNRecHits_z"); + auto EcalEndcapNRecHits_time = (TH1D*)fil->Get("EEMC/EcalEndcapNRecHits_time"); + + auto EcalEndcapNIslandProtoClusters_clusters_per_event = + (TH1I*)fil->Get("EEMC/EcalEndcapNIslandProtoClusters_clusters_per_event"); + auto EcalEndcapNIslandProtoClusters_hits_per_cluster = + (TH1I*)fil->Get("EEMC/EcalEndcapNIslandProtoClusters_hits_per_cluster"); + + auto c1 = new TCanvas("c1", "", 1700, 1000); + c1->Divide(4, 4); + + //---------------- EcalEndcapNhits + c1->cd(1); + gPad->SetLogy(); + EcalEndcapNhits_hits_per_event->Draw(); + + c1->cd(2); + EcalEndcapNhits_occupancy->Draw(); + + c1->cd(3); + gPad->SetLogy(); + EcalEndcapNhits_hit_energy->Draw(); + + //---------------- EcalEndcapNRawhits + c1->cd(5); + gPad->SetLogy(); + EcalEndcapNRawhits_hits_per_event->Draw(); + + c1->cd(6); + gPad->SetLogy(); + EcalEndcapNRawhits_amplitude->Draw(); + + c1->cd(7); + EcalEndcapNRawhits_timestamp->Draw(); + + //---------------- EcalEndcapNRecHits + c1->cd(9); + gPad->SetLogy(); + EcalEndcapNRechits_hits_per_event->Draw(); + + c1->cd(10); + EcalEndcapNRecHits_xy->Draw(); + + c1->cd(11); + EcalEndcapNRecHits_z->Draw(); + + c1->cd(12); + gPad->SetLogy(); + EcalEndcapNRecHits_time->Draw(); + + c1->cd(8); + gPad->SetLogy(); + EcalEndcapNRecHits_hit_energy->Draw(); + + //---------------- EcalEndcapNIslandProtoClusters + c1->cd(13); + gPad->SetLogy(); + EcalEndcapNIslandProtoClusters_clusters_per_event->Draw(); + + c1->cd(14); + gPad->SetLogy(); + EcalEndcapNIslandProtoClusters_hits_per_cluster->Draw(); + + c1->SaveAs("EEMCcheck.pdf"); + c1->SaveAs("EEMCcheck.png"); } diff --git a/src/benchmarks/reconstruction/femc_studies/femc_studies.cc b/src/benchmarks/reconstruction/femc_studies/femc_studies.cc index e2e8fa7721..47b47b6e02 100644 --- a/src/benchmarks/reconstruction/femc_studies/femc_studies.cc +++ b/src/benchmarks/reconstruction/femc_studies/femc_studies.cc @@ -4,8 +4,8 @@ // The following just makes this a JANA plugin extern "C" { - void InitPlugin(JApplication* app) { - InitJANAPlugin(app); - app->Add(new femc_studiesProcessor()); - } +void InitPlugin(JApplication* app) { + InitJANAPlugin(app); + app->Add(new femc_studiesProcessor()); +} } diff --git a/src/benchmarks/reconstruction/femc_studies/femc_studiesProcessor.cc b/src/benchmarks/reconstruction/femc_studies/femc_studiesProcessor.cc index 92de31be61..5e04c6d94e 100644 --- a/src/benchmarks/reconstruction/femc_studies/femc_studiesProcessor.cc +++ b/src/benchmarks/reconstruction/femc_studies/femc_studiesProcessor.cc @@ -38,7 +38,6 @@ #include "services/log/Log_service.h" #include "services/rootfile/RootFile_service.h" - //******************************************************************************************// // InitWithGlobalRootLock //******************************************************************************************// @@ -49,7 +48,7 @@ void femc_studiesProcessor::Init() { // =============================================================================================== // Get JANA application and seup general variables // =============================================================================================== - auto *app = GetApplication(); + auto* app = GetApplication(); std::string log_level_str = "info"; m_log = app->GetService()->logger(plugin_name); @@ -66,7 +65,7 @@ void femc_studiesProcessor::Init() { // Get TDirectory for histograms root file auto globalRootLock = app->GetService(); globalRootLock->acquire_write_lock(); - auto *file = root_file_service->GetHistFile(); + auto* file = root_file_service->GetHistFile(); globalRootLock->release_lock(); // =============================================================================================== @@ -77,19 +76,22 @@ void femc_studiesProcessor::Init() { // =============================================================================================== // Simulations hists // =============================================================================================== - hMCEnergyVsEta = new TH2D("hMCEnergyVsEta", "; E (GeV); #eta", 1500, 0., 150., 500, 0, 5); + hMCEnergyVsEta = new TH2D("hMCEnergyVsEta", "; E (GeV); #eta", 1500, 0., 150., 500, 0, 5); hMCEnergyVsEta->SetDirectory(m_dir_main); // =============================================================================================== // Sum cell clusters rec histos // =============================================================================================== - hClusterEcalib_E_eta = new TH3D("hClusterEcalib_E_eta", "; E_{MC} (GeV); E_{rec,rec hit}/E_{MC}; #eta", - 1500, 0., 150.0, 200, 0., 2.0, 50, 0, 5); - hClusterNCells_E_eta = new TH3D("hClusterNCells_E_eta", "; E_{MC} (GeV); N_{cells}; #eta", - 1500, 0., 150.0, 500, -0.5, 499.5, 50, 0, 5); - hClusterEcalib_E_phi = new TH3D("hClusterEcalib_E_phi", "; E_{MC} (GeV); E_{rec,rec hit}/E_{MC}; #varphi (rad)", - 1500, 0., 150.0, 200, 0., 2.0, 360 , -TMath::Pi(), TMath::Pi()); - hPosCaloHitsXY = new TH2D("hPosCaloHitsXY", "; X (cm); Y (cm)", 400, -400., 400., 400, -400., 400.); + hClusterEcalib_E_eta = + new TH3D("hClusterEcalib_E_eta", "; E_{MC} (GeV); E_{rec,rec hit}/E_{MC}; #eta", 1500, 0., + 150.0, 200, 0., 2.0, 50, 0, 5); + hClusterNCells_E_eta = new TH3D("hClusterNCells_E_eta", "; E_{MC} (GeV); N_{cells}; #eta", 1500, + 0., 150.0, 500, -0.5, 499.5, 50, 0, 5); + hClusterEcalib_E_phi = + new TH3D("hClusterEcalib_E_phi", "; E_{MC} (GeV); E_{rec,rec hit}/E_{MC}; #varphi (rad)", + 1500, 0., 150.0, 200, 0., 2.0, 360, -TMath::Pi(), TMath::Pi()); + hPosCaloHitsXY = + new TH2D("hPosCaloHitsXY", "; X (cm); Y (cm)", 400, -400., 400., 400, -400., 400.); hClusterEcalib_E_eta->SetDirectory(m_dir_main); hClusterNCells_E_eta->SetDirectory(m_dir_main); hClusterEcalib_E_phi->SetDirectory(m_dir_main); @@ -98,16 +100,23 @@ void femc_studiesProcessor::Init() { // =============================================================================================== // Sum cell clusters sim histos // =============================================================================================== - hClusterESimcalib_E_eta = new TH3D("hClusterESimcalib_E_eta", "; E_{MC} (GeV); E_{rec,sim hit}/E_{MC}; #eta" , - 1500, 0., 150.0, 200, 0., 2.0, 50, 0, 5); - hClusterSimNCells_E_eta = new TH3D("hClusterSimNCells_E_eta", "; E_{MC} (GeV); N_{cells, sim}; #eta", - 1500, 0., 150.0, 500, -0.5, 499.5, 50, 0, 5); - hClusterESimcalib_E_phi = new TH3D("hClusterESimcalib_E_phi", "; E_{MC} (GeV); E_{rec,sim hit}/E_{MC}; #varphi (rad)" , - 1500, 0., 150.0, 200, 0., 2.0, 360 , -TMath::Pi(), TMath::Pi()); - hCellESim_layerX = new TH2D("hCellESim_layerX", "; #cell ID X; E_{rec,sim hit} (GeV)" , 500, -0.5, 499.5, 5000, 0, 1); - hCellESim_layerY = new TH2D("hCellESim_layerY", "; #cell ID Y; E_{rec,sim hit} (GeV)" , 500, -0.5, 499.5, 5000, 0, 1); - hCellTSim_layerX = new TH2D("hCellTSim_layerX", "; #cell ID X; t_{rec,sim hit} (GeV)" , 500, -0.5, 499.5, 5000, 0, 1000); - hPosCaloSimHitsXY = new TH2D("hPosCaloSimHitsXY", "; X (cm); Y (cm)", 400, -400., 400., 400, -400., 400.); + hClusterESimcalib_E_eta = + new TH3D("hClusterESimcalib_E_eta", "; E_{MC} (GeV); E_{rec,sim hit}/E_{MC}; #eta", 1500, 0., + 150.0, 200, 0., 2.0, 50, 0, 5); + hClusterSimNCells_E_eta = + new TH3D("hClusterSimNCells_E_eta", "; E_{MC} (GeV); N_{cells, sim}; #eta", 1500, 0., 150.0, + 500, -0.5, 499.5, 50, 0, 5); + hClusterESimcalib_E_phi = + new TH3D("hClusterESimcalib_E_phi", "; E_{MC} (GeV); E_{rec,sim hit}/E_{MC}; #varphi (rad)", + 1500, 0., 150.0, 200, 0., 2.0, 360, -TMath::Pi(), TMath::Pi()); + hCellESim_layerX = new TH2D("hCellESim_layerX", "; #cell ID X; E_{rec,sim hit} (GeV)", 500, -0.5, + 499.5, 5000, 0, 1); + hCellESim_layerY = new TH2D("hCellESim_layerY", "; #cell ID Y; E_{rec,sim hit} (GeV)", 500, -0.5, + 499.5, 5000, 0, 1); + hCellTSim_layerX = new TH2D("hCellTSim_layerX", "; #cell ID X; t_{rec,sim hit} (GeV)", 500, -0.5, + 499.5, 5000, 0, 1000); + hPosCaloSimHitsXY = + new TH2D("hPosCaloSimHitsXY", "; X (cm); Y (cm)", 400, -400., 400., 400, -400., 400.); hClusterESimcalib_E_eta->SetDirectory(m_dir_main); hClusterSimNCells_E_eta->SetDirectory(m_dir_main); hClusterESimcalib_E_phi->SetDirectory(m_dir_main); @@ -119,15 +128,18 @@ void femc_studiesProcessor::Init() { // =============================================================================================== // rec cluster MA clusters histos // =============================================================================================== - hRecClusterEcalib_E_eta = new TH3D("hRecClusterEcalib_E_eta", "; E_{MC} (GeV); E_{rec,rec clus}/E_{MC}; #eta", - 1500, 0., 150.0, 200, 0., 2.0, 50, 0, 5); - hRecNClusters_E_eta = new TH3D("hRecNClusters_E_eta", "; E_{MC} (GeV); N_{rec cl.}; #eta", - 1500, 0., 150.0, 10, -0.5, 9.5, 50, 0, 5); + hRecClusterEcalib_E_eta = + new TH3D("hRecClusterEcalib_E_eta", "; E_{MC} (GeV); E_{rec,rec clus}/E_{MC}; #eta", 1500, 0., + 150.0, 200, 0., 2.0, 50, 0, 5); + hRecNClusters_E_eta = new TH3D("hRecNClusters_E_eta", "; E_{MC} (GeV); N_{rec cl.}; #eta", 1500, + 0., 150.0, 10, -0.5, 9.5, 50, 0, 5); // rec cluster highest - hRecClusterEcalib_Ehigh_eta = new TH3D("hRecClusterEcalib_Ehigh_eta", "; E_{MC} (GeV); E_{rec,rec clus high.}/E_{MC}; #eta", - 1500, 0., 150.0, 200, 0., 2.0, 50, 0, 5); - hRecClusterNCells_Ehigh_eta = new TH3D("hRecClusterNCells_Ehigh_eta", "; E_{MC} (GeV); N_{cells, rec cl., high.}; #eta", - 1500, 0., 150.0, 500, -0.5, 499.5, 50, 0, 5); + hRecClusterEcalib_Ehigh_eta = + new TH3D("hRecClusterEcalib_Ehigh_eta", "; E_{MC} (GeV); E_{rec,rec clus high.}/E_{MC}; #eta", + 1500, 0., 150.0, 200, 0., 2.0, 50, 0, 5); + hRecClusterNCells_Ehigh_eta = + new TH3D("hRecClusterNCells_Ehigh_eta", "; E_{MC} (GeV); N_{cells, rec cl., high.}; #eta", + 1500, 0., 150.0, 500, -0.5, 499.5, 50, 0, 5); hRecClusterEcalib_E_eta->SetDirectory(m_dir_main); hRecNClusters_E_eta->SetDirectory(m_dir_main); hRecClusterEcalib_Ehigh_eta->SetDirectory(m_dir_main); @@ -136,15 +148,18 @@ void femc_studiesProcessor::Init() { // =============================================================================================== // rec cluster framework Island clusters histos // =============================================================================================== - hRecFClusterEcalib_E_eta = new TH3D("hRecFClusterEcalib_E_eta", "; E_{MC} (GeV); E_{rec,island clus}/E_{MC}; #eta", - 1500, 0., 150.0, 200, 0., 2.0, 50, 0, 5); - hRecFNClusters_E_eta = new TH3D("hRecFNClusters_E_eta", "; E_{MC} (GeV); N_{rec f. cl.}; #eta", - 1500, 0., 150.0, 10, -0.5, 9.5, 50, 0, 5); + hRecFClusterEcalib_E_eta = + new TH3D("hRecFClusterEcalib_E_eta", "; E_{MC} (GeV); E_{rec,island clus}/E_{MC}; #eta", 1500, + 0., 150.0, 200, 0., 2.0, 50, 0, 5); + hRecFNClusters_E_eta = new TH3D("hRecFNClusters_E_eta", "; E_{MC} (GeV); N_{rec f. cl.}; #eta", + 1500, 0., 150.0, 10, -0.5, 9.5, 50, 0, 5); // rec cluster framework highest - hRecFClusterEcalib_Ehigh_eta = new TH3D("hRecFClusterEcalib_Ehigh_eta", "; E_{MC} (GeV); E_{rec,island clus high.}/E_{MC}; #eta", - 1500, 0., 150.0, 200, 0., 2.0, 50, 0, 5); - hRecFClusterNCells_Ehigh_eta = new TH3D("hRecFClusterNCells_Ehigh_eta", "; E_{MC} (GeV); N_{cells, rec f. cl., high.}; #eta", - 1500, 0., 150.0, 500, -0.5, 499.5, 50, 0, 5); + hRecFClusterEcalib_Ehigh_eta = new TH3D("hRecFClusterEcalib_Ehigh_eta", + "; E_{MC} (GeV); E_{rec,island clus high.}/E_{MC}; #eta", + 1500, 0., 150.0, 200, 0., 2.0, 50, 0, 5); + hRecFClusterNCells_Ehigh_eta = + new TH3D("hRecFClusterNCells_Ehigh_eta", "; E_{MC} (GeV); N_{cells, rec f. cl., high.}; #eta", + 1500, 0., 150.0, 500, -0.5, 499.5, 50, 0, 5); hRecFClusterEcalib_E_eta->SetDirectory(m_dir_main); hRecFNClusters_E_eta->SetDirectory(m_dir_main); hRecFClusterEcalib_Ehigh_eta->SetDirectory(m_dir_main); @@ -153,23 +168,23 @@ void femc_studiesProcessor::Init() { // =============================================================================================== // Sampling fraction // =============================================================================================== - hSamplingFractionEta = new TH2D("hSamplingFractionEta", "; #eta; f", 400, 1., 5., 500, 0., 0.2); + hSamplingFractionEta = new TH2D("hSamplingFractionEta", "; #eta; f", 400, 1., 5., 500, 0., 0.2); hSamplingFractionEta->SetDirectory(m_dir_main); // =============================================================================================== // Tree for clusterizer studies // =============================================================================================== - if (enableTree){ - event_tree = new TTree("event_tree", "event_tree"); + if (enableTree) { + event_tree = new TTree("event_tree", "event_tree"); event_tree->SetDirectory(m_dir_main); - t_fEMC_towers_cellE = new float[maxNTowers]; - t_fEMC_towers_cellT = new float[maxNTowers]; - t_fEMC_towers_cellIDx = new short[maxNTowers]; - t_fEMC_towers_cellIDy = new short[maxNTowers]; - t_fEMC_towers_clusterIDA = new short[maxNTowers]; - t_fEMC_towers_clusterIDB = new short[maxNTowers]; - t_fEMC_towers_cellTrueID = new int[maxNTowers]; + t_fEMC_towers_cellE = new float[maxNTowers]; + t_fEMC_towers_cellT = new float[maxNTowers]; + t_fEMC_towers_cellIDx = new short[maxNTowers]; + t_fEMC_towers_cellIDy = new short[maxNTowers]; + t_fEMC_towers_clusterIDA = new short[maxNTowers]; + t_fEMC_towers_clusterIDB = new short[maxNTowers]; + t_fEMC_towers_cellTrueID = new int[maxNTowers]; // towers FEMC event_tree->Branch("tower_FEMC_N", &t_fEMC_towers_N, "tower_FEMC_N/I"); @@ -177,21 +192,24 @@ void femc_studiesProcessor::Init() { event_tree->Branch("tower_FEMC_T", t_fEMC_towers_cellT, "tower_FEMC_T[tower_FEMC_N]/F"); event_tree->Branch("tower_FEMC_ix", t_fEMC_towers_cellIDx, "tower_FEMC_ix[tower_FEMC_N]/S"); event_tree->Branch("tower_FEMC_iy", t_fEMC_towers_cellIDy, "tower_FEMC_iy[tower_FEMC_N]/S"); - event_tree->Branch("tower_FEMC_clusIDA", t_fEMC_towers_clusterIDA, "tower_FEMC_clusIDA[tower_FEMC_N]/S"); - event_tree->Branch("tower_FEMC_clusIDB", t_fEMC_towers_clusterIDB, "tower_FEMC_clusIDB[tower_FEMC_N]/S"); - event_tree->Branch("tower_FEMC_trueID", t_fEMC_towers_cellTrueID, "tower_FEMC_trueID[tower_FEMC_N]/I"); + event_tree->Branch("tower_FEMC_clusIDA", t_fEMC_towers_clusterIDA, + "tower_FEMC_clusIDA[tower_FEMC_N]/S"); + event_tree->Branch("tower_FEMC_clusIDB", t_fEMC_towers_clusterIDB, + "tower_FEMC_clusIDB[tower_FEMC_N]/S"); + event_tree->Branch("tower_FEMC_trueID", t_fEMC_towers_cellTrueID, + "tower_FEMC_trueID[tower_FEMC_N]/I"); } // =============================================================================================== // Tree for cluster studies // =============================================================================================== - if (enableTreeCluster){ - cluster_tree = new TTree("cluster_tree", "cluster_tree"); + if (enableTreeCluster) { + cluster_tree = new TTree("cluster_tree", "cluster_tree"); cluster_tree->SetDirectory(m_dir_main); - t_mc_E = new float[maxNMC]; - t_mc_Phi = new float[maxNMC]; - t_mc_Eta = new float[maxNMC]; + t_mc_E = new float[maxNMC]; + t_mc_Phi = new float[maxNMC]; + t_mc_Eta = new float[maxNMC]; t_fEMC_cluster_E = new float[maxNCluster]; t_fEMC_cluster_NCells = new int[maxNCluster]; t_fEMC_cluster_Phi = new float[maxNCluster]; @@ -205,9 +223,12 @@ void femc_studiesProcessor::Init() { // clusters FECal cluster_tree->Branch("cluster_FEMC_N", &t_fEMC_clusters_N, "cluster_FEMC_N/I"); cluster_tree->Branch("cluster_FEMC_E", t_fEMC_cluster_E, "cluster_FEMC_E[cluster_FEMC_N]/F"); - cluster_tree->Branch("cluster_FEMC_Ncells", t_fEMC_cluster_NCells, "cluster_FEMC_Ncells[cluster_FEMC_N]/I"); - cluster_tree->Branch("cluster_FEMC_Eta", t_fEMC_cluster_Eta, "cluster_FEMC_Eta[cluster_FEMC_N]/F"); - cluster_tree->Branch("cluster_FEMC_Phi", t_fEMC_cluster_Phi, "cluster_FEMC_Phi[cluster_FEMC_N]/F"); + cluster_tree->Branch("cluster_FEMC_Ncells", t_fEMC_cluster_NCells, + "cluster_FEMC_Ncells[cluster_FEMC_N]/I"); + cluster_tree->Branch("cluster_FEMC_Eta", t_fEMC_cluster_Eta, + "cluster_FEMC_Eta[cluster_FEMC_N]/F"); + cluster_tree->Branch("cluster_FEMC_Phi", t_fEMC_cluster_Phi, + "cluster_FEMC_Phi[cluster_FEMC_N]/F"); } std::cout << __PRETTY_FUNCTION__ << " " << __LINE__ << std::endl; @@ -215,31 +236,30 @@ void femc_studiesProcessor::Init() { std::cout << "--------------------------\nID specification:\n"; try { m_decoder = detector->readout("EcalEndcapPHits").idSpec().decoder(); - std::cout << "1st: "<< m_decoder << std::endl; + std::cout << "1st: " << m_decoder << std::endl; std::cout << "full list: " << " " << m_decoder->fieldDescription() << std::endl; } catch (...) { - std::cout <<"2nd: " << m_decoder << std::endl; - m_log->error("readoutClass not in the output"); - throw std::runtime_error("readoutClass not in the output."); + std::cout << "2nd: " << m_decoder << std::endl; + m_log->error("readoutClass not in the output"); + throw std::runtime_error("readoutClass not in the output."); } - } //******************************************************************************************// // ProcessSequential //******************************************************************************************// void femc_studiesProcessor::Process(const std::shared_ptr& event) { -// void femc_studiesProcessor::ProcessSequential(const std::shared_ptr& event) { + // void femc_studiesProcessor::ProcessSequential(const std::shared_ptr& event) { // =============================================================================================== // process MC particles // =============================================================================================== - const auto &mcParticles = *(event->GetCollection("MCParticles")); - double mceta = 0; - double mcphi = 0; - double mcp = 0; - double mcenergy = 0; - int iMC = 0; + const auto& mcParticles = *(event->GetCollection("MCParticles")); + double mceta = 0; + double mcphi = 0; + double mcp = 0; + double mcenergy = 0; + int iMC = 0; for (const auto mcparticle : mcParticles) { if (mcparticle.getGeneratorStatus() != 1) continue; @@ -252,11 +272,12 @@ void femc_studiesProcessor::Process(const std::shared_ptr& event) mcphi = atan2(mom.y, mom.x); // determine mc momentum mcp = sqrt(mom.x * mom.x + mom.y * mom.y + mom.z * mom.z); - m_log->trace("MC particle:{} \t {} \t {} \t totmom: {} phi {} eta {}", mom.x, mom.y, mom.z, mcp, mcphi, mceta); - hMCEnergyVsEta->Fill(mcp,mceta); + m_log->trace("MC particle:{} \t {} \t {} \t totmom: {} phi {} eta {}", mom.x, mom.y, mom.z, mcp, + mcphi, mceta); + hMCEnergyVsEta->Fill(mcp, mceta); - if (enableTreeCluster){ - if (iMC < maxNMC){ + if (enableTreeCluster) { + if (iMC < maxNMC) { t_mc_E[iMC] = mcenergy; t_mc_Phi[iMC] = mcphi; t_mc_Eta[iMC] = mceta; @@ -264,38 +285,40 @@ void femc_studiesProcessor::Process(const std::shared_ptr& event) } iMC++; } - if (enableTreeCluster) t_mc_N = iMC; + if (enableTreeCluster) + t_mc_N = iMC; // =============================================================================================== // process sim hits // =============================================================================================== std::vector input_tower_sim; - int nCaloHitsSim = 0; - float sumActiveCaloEnergy = 0; + int nCaloHitsSim = 0; + float sumActiveCaloEnergy = 0; float sumPassiveCaloEnergy = 0; - const auto &simHits = *(event->GetCollection(nameSimHits)); + const auto& simHits = *(event->GetCollection(nameSimHits)); for (const auto caloHit : simHits) { float x = caloHit.getPosition().x / 10.; float y = caloHit.getPosition().y / 10.; float z = caloHit.getPosition().z / 10.; uint64_t cellID = caloHit.getCellID(); float energy = caloHit.getEnergy(); - double time = std::numeric_limits::max(); + double time = std::numeric_limits::max(); for (const auto& c : caloHit.getContributions()) { - if (c.getTime() <= time) { - time = c.getTime(); - } + if (c.getTime() <= time) { + time = c.getTime(); + } } - auto detector_layer_x = floor((x+246)/2.5); - auto detector_layer_y = floor((y+246)/2.5); + auto detector_layer_x = floor((x + 246) / 2.5); + auto detector_layer_y = floor((y + 246) / 2.5); auto detector_passive = 0; - if(detector_passive == 0) { + if (detector_passive == 0) { sumActiveCaloEnergy += energy; } else { sumPassiveCaloEnergy += energy; } - if (detector_passive > 0) continue; + if (detector_passive > 0) + continue; // calc cell IDs int cellIDx = detector_layer_x; int cellIDy = detector_layer_y; @@ -318,16 +341,16 @@ void femc_studiesProcessor::Process(const std::shared_ptr& event) } if (!found) { towersStrct tempstructT; - tempstructT.energy = energy; - tempstructT.time = time; - tempstructT.posx = x; - tempstructT.posy = y; - tempstructT.posz = z; - tempstructT.cellID = cellID; - tempstructT.cellIDx = cellIDx; - tempstructT.cellIDy = cellIDy; - tempstructT.cellIDz = cellIDz; - tempstructT.tower_trueID = 0; //TODO how to get trueID? + tempstructT.energy = energy; + tempstructT.time = time; + tempstructT.posx = x; + tempstructT.posy = y; + tempstructT.posz = z; + tempstructT.cellID = cellID; + tempstructT.cellIDx = cellIDx; + tempstructT.cellIDy = cellIDy; + tempstructT.cellIDz = cellIDz; + tempstructT.tower_trueID = 0; //TODO how to get trueID? input_tower_sim.push_back(tempstructT); } } @@ -335,8 +358,8 @@ void femc_studiesProcessor::Process(const std::shared_ptr& event) // =============================================================================================== // read rec hits & fill structs // =============================================================================================== - const auto &recHits = *(event->GetCollection(nameRecHits)); - int nCaloHitsRec = 0; + const auto& recHits = *(event->GetCollection(nameRecHits)); + int nCaloHitsRec = 0; std::vector input_tower_rec; std::vector input_tower_recSav; // process rec hits @@ -349,9 +372,10 @@ void femc_studiesProcessor::Process(const std::shared_ptr& event) float time = caloHit.getTime(); auto detector_passive = 0; - auto detector_layer_x = floor((x+246)/2.5); - auto detector_layer_y = floor((y+246)/2.5); - if (detector_passive > 0) continue; + auto detector_layer_x = floor((x + 246) / 2.5); + auto detector_layer_y = floor((y + 246) / 2.5); + if (detector_passive > 0) + continue; // calc cell IDs int cellIDx = detector_layer_x; @@ -372,26 +396,28 @@ void femc_studiesProcessor::Process(const std::shared_ptr& event) } if (!found) { towersStrct tempstructT; - tempstructT.energy = energy; - tempstructT.time = time; - tempstructT.posx = x; - tempstructT.posy = y; - tempstructT.posz = z; - tempstructT.cellID = cellID; - tempstructT.cellIDx = cellIDx; - tempstructT.cellIDy = cellIDy; - tempstructT.tower_trueID = 0; //TODO how to get trueID? + tempstructT.energy = energy; + tempstructT.time = time; + tempstructT.posx = x; + tempstructT.posy = y; + tempstructT.posz = z; + tempstructT.cellID = cellID; + tempstructT.cellIDx = cellIDx; + tempstructT.cellIDy = cellIDy; + tempstructT.tower_trueID = 0; //TODO how to get trueID? input_tower_rec.push_back(tempstructT); input_tower_recSav.push_back(tempstructT); } } m_log->trace("FEMC mod: nCaloHits sim {}\t rec {}", nCaloHitsSim, nCaloHitsRec); - if (nCaloHitsRec > 0) nEventsWithCaloHits++; + if (nCaloHitsRec > 0) + nEventsWithCaloHits++; // =============================================================================================== // sort tower arrays // =============================================================================================== - hSamplingFractionEta->Fill(mceta, sumActiveCaloEnergy / (sumActiveCaloEnergy+sumPassiveCaloEnergy)); + hSamplingFractionEta->Fill(mceta, + sumActiveCaloEnergy / (sumActiveCaloEnergy + sumPassiveCaloEnergy)); std::sort(input_tower_rec.begin(), input_tower_rec.end(), &acompare); std::sort(input_tower_recSav.begin(), input_tower_recSav.end(), &acompare); std::sort(input_tower_sim.begin(), input_tower_sim.end(), &acompare); @@ -411,34 +437,35 @@ void femc_studiesProcessor::Process(const std::shared_ptr& event) // sim hits double tot_energySimHit = 0; for (auto& tower : input_tower_sim) { - tower.energy = tower.energy/samplingFraction; // calibrate + tower.energy = tower.energy / samplingFraction; // calibrate tot_energySimHit += tower.energy; } - m_log->trace("Mc E: {} \t eta: {} \t sim E rec: {}\t rec E rec: {}", mcenergy, mceta, tot_energySimHit, tot_energyRecHit); + m_log->trace("Mc E: {} \t eta: {} \t sim E rec: {}\t rec E rec: {}", mcenergy, mceta, + tot_energySimHit, tot_energyRecHit); // =============================================================================================== // Fill summed hits histos // =============================================================================================== // rec hits hClusterNCells_E_eta->Fill(mcenergy, nCaloHitsRec, mceta); - hClusterEcalib_E_eta->Fill(mcenergy, tot_energyRecHit/mcenergy, mceta); - hClusterEcalib_E_phi->Fill(mcenergy, tot_energyRecHit/mcenergy, mcphi); + hClusterEcalib_E_eta->Fill(mcenergy, tot_energyRecHit / mcenergy, mceta); + hClusterEcalib_E_phi->Fill(mcenergy, tot_energyRecHit / mcenergy, mcphi); // sim hits hClusterSimNCells_E_eta->Fill(mcenergy, nCaloHitsSim, mceta); - hClusterESimcalib_E_eta->Fill(mcenergy, tot_energySimHit/mcenergy, mceta); - hClusterESimcalib_E_phi->Fill(mcenergy, tot_energySimHit/mcenergy, mcphi); + hClusterESimcalib_E_eta->Fill(mcenergy, tot_energySimHit / mcenergy, mceta); + hClusterESimcalib_E_phi->Fill(mcenergy, tot_energySimHit / mcenergy, mcphi); // =============================================================================================== // MA clusterization // =============================================================================================== - int removedCells = 0; - float minAggE = 0.001; - float seedE = 0.20; + int removedCells = 0; + float minAggE = 0.001; + float seedE = 0.20; - if (!input_tower_rec.empty()){ + if (!input_tower_rec.empty()) { // clean up rec array for clusterization - while (input_tower_rec.at(input_tower_rec.size()-1).energy < minAggE ){ + while (input_tower_rec.at(input_tower_rec.size() - 1).energy < minAggE) { input_tower_rec.pop_back(); removedCells++; } @@ -449,30 +476,39 @@ void femc_studiesProcessor::Process(const std::shared_ptr& event) std::vector clusters_calo; // vector of towers within the currently found cluster std::vector cluster_towers; - while (!input_tower_rec.empty() ) { + while (!input_tower_rec.empty()) { cluster_towers.clear(); clustersStrct tempstructC; // always start with highest energetic tower - if(input_tower_rec.at(0).energy > seedE){ - m_log->trace("seed: {}\t {} \t {}", input_tower_rec.at(0).energy, input_tower_rec.at(0).cellIDx, input_tower_rec.at(0).cellIDy ); + if (input_tower_rec.at(0).energy > seedE) { + m_log->trace("seed: {}\t {} \t {}", input_tower_rec.at(0).energy, + input_tower_rec.at(0).cellIDx, input_tower_rec.at(0).cellIDy); tempstructC = findMACluster(seedE, minAggE, input_tower_rec, cluster_towers, 0.1); // determine remaining cluster properties from its towers - float* showershape_eta_phi = CalculateM02andWeightedPosition(cluster_towers, tempstructC.cluster_E, 4.5); - tempstructC.cluster_M02 = showershape_eta_phi[0]; - tempstructC.cluster_M20 = showershape_eta_phi[1]; - tempstructC.cluster_Eta = showershape_eta_phi[2]; - tempstructC.cluster_Phi = showershape_eta_phi[3]; - tempstructC.cluster_X = showershape_eta_phi[4]; - tempstructC.cluster_Y = showershape_eta_phi[5]; - tempstructC.cluster_Z = showershape_eta_phi[6]; + float* showershape_eta_phi = + CalculateM02andWeightedPosition(cluster_towers, tempstructC.cluster_E, 4.5); + tempstructC.cluster_M02 = showershape_eta_phi[0]; + tempstructC.cluster_M20 = showershape_eta_phi[1]; + tempstructC.cluster_Eta = showershape_eta_phi[2]; + tempstructC.cluster_Phi = showershape_eta_phi[3]; + tempstructC.cluster_X = showershape_eta_phi[4]; + tempstructC.cluster_Y = showershape_eta_phi[5]; + tempstructC.cluster_Z = showershape_eta_phi[6]; tempstructC.cluster_towers = cluster_towers; - m_log->trace("---------> \t {} \tcluster with E = {} \tEta: {} \tPhi: {} \tX: {} \tY: {} \tZ: {} \tntowers: {} \ttrueID: {}", nclusters, tempstructC.cluster_E, tempstructC.cluster_Eta, tempstructC.cluster_Phi, tempstructC.cluster_X, tempstructC.cluster_Y, tempstructC.cluster_Z, tempstructC.cluster_NTowers, tempstructC.cluster_trueID ); + m_log->trace("---------> \t {} \tcluster with E = {} \tEta: {} \tPhi: {} \tX: {} \tY: {} " + "\tZ: {} \tntowers: {} \ttrueID: {}", + nclusters, tempstructC.cluster_E, tempstructC.cluster_Eta, + tempstructC.cluster_Phi, tempstructC.cluster_X, tempstructC.cluster_Y, + tempstructC.cluster_Z, tempstructC.cluster_NTowers, + tempstructC.cluster_trueID); clusters_calo.push_back(tempstructC); nclusters++; } else { - m_log->trace("remaining: {} largest: {} \t {} \t {} \t {}", (int)input_tower_rec.size(), input_tower_rec.at(0).energy, input_tower_rec.at(0).cellIDx, input_tower_rec.at(0).cellIDy, input_tower_rec.at(0).cellIDz); + m_log->trace("remaining: {} largest: {} \t {} \t {} \t {}", (int)input_tower_rec.size(), + input_tower_rec.at(0).energy, input_tower_rec.at(0).cellIDx, + input_tower_rec.at(0).cellIDy, input_tower_rec.at(0).cellIDz); input_tower_rec.clear(); } } @@ -481,20 +517,21 @@ void femc_studiesProcessor::Process(const std::shared_ptr& event) // --------------------------- Fill LFHCal MA clusters in tree and hists ------------------------- // ----------------------------------------------------------------------------------------------- std::sort(clusters_calo.begin(), clusters_calo.end(), &acompareCl); - m_log->info("-----> found {} clusters" , clusters_calo.size()); + m_log->info("-----> found {} clusters", clusters_calo.size()); hRecNClusters_E_eta->Fill(mcenergy, clusters_calo.size(), mceta); int iCl = 0; for (const auto cluster : clusters_calo) { - if (iCl < maxNCluster && enableTreeCluster){ - t_fEMC_cluster_E[iCl] = (float)cluster.cluster_E; - t_fEMC_cluster_NCells[iCl] = (int)cluster.cluster_NTowers; - t_fEMC_cluster_Eta[iCl] = (float)cluster.cluster_Eta; - t_fEMC_cluster_Phi[iCl] = (float)cluster.cluster_Phi; + if (iCl < maxNCluster && enableTreeCluster) { + t_fEMC_cluster_E[iCl] = (float)cluster.cluster_E; + t_fEMC_cluster_NCells[iCl] = (int)cluster.cluster_NTowers; + t_fEMC_cluster_Eta[iCl] = (float)cluster.cluster_Eta; + t_fEMC_cluster_Phi[iCl] = (float)cluster.cluster_Phi; } - hRecClusterEcalib_E_eta->Fill(mcenergy, cluster.cluster_E/mcenergy, mceta); - for (const auto cluster_tower : cluster.cluster_towers){ + hRecClusterEcalib_E_eta->Fill(mcenergy, cluster.cluster_E / mcenergy, mceta); + for (const auto cluster_tower : cluster.cluster_towers) { int pSav = 0; - while(cluster_tower.cellID != input_tower_recSav.at(pSav).cellID && pSav < (int)input_tower_recSav.size() ) { + while (cluster_tower.cellID != input_tower_recSav.at(pSav).cellID && + pSav < (int)input_tower_recSav.size()) { pSav++; } if (cluster_tower.cellID == input_tower_recSav.at(pSav).cellID) { @@ -502,45 +539,47 @@ void femc_studiesProcessor::Process(const std::shared_ptr& event) } } - if (iCl == 0){ - hRecClusterEcalib_Ehigh_eta->Fill(mcenergy, cluster.cluster_E/mcenergy, mceta); + if (iCl == 0) { + hRecClusterEcalib_Ehigh_eta->Fill(mcenergy, cluster.cluster_E / mcenergy, mceta); hRecClusterNCells_Ehigh_eta->Fill(mcenergy, cluster.cluster_NTowers, mceta); } iCl++; m_log->trace("MA cluster {}:\t {} \t {}", iCl, cluster.cluster_E, cluster.cluster_NTowers); } - if (iCl < maxNCluster && enableTreeCluster) t_fEMC_clusters_N = (int)iCl; + if (iCl < maxNCluster && enableTreeCluster) + t_fEMC_clusters_N = (int)iCl; clusters_calo.clear(); } else { hRecNClusters_E_eta->Fill(mcenergy, 0., mceta); - if (enableTreeCluster) t_fEMC_clusters_N = 0; + if (enableTreeCluster) + t_fEMC_clusters_N = 0; } // =============================================================================================== // ------------------------------- Fill LFHCAl Island clusters in hists -------------------------- // =============================================================================================== - int iClF = 0; - float highestEFr = 0; - int iClFHigh = 0; + int iClF = 0; + float highestEFr = 0; + int iClFHigh = 0; - const auto &fecalClustersF = *(event->GetCollection(nameClusters)); + const auto& fecalClustersF = *(event->GetCollection(nameClusters)); for (const auto cluster : fecalClustersF) { - if (cluster.getEnergy() > highestEFr){ - iClFHigh = iClF; - highestEFr = cluster.getEnergy(); + if (cluster.getEnergy() > highestEFr) { + iClFHigh = iClF; + highestEFr = cluster.getEnergy(); } - hRecFClusterEcalib_E_eta->Fill(mcenergy, cluster.getEnergy()/mcenergy, mceta); + hRecFClusterEcalib_E_eta->Fill(mcenergy, cluster.getEnergy() / mcenergy, mceta); m_log->trace("Island cluster {}:\t {} \t {}", iClF, cluster.getEnergy(), cluster.getNhits()); iClF++; } hRecFNClusters_E_eta->Fill(mcenergy, iClF, mceta); // fill hists for highest Island cluster - iClF = 0; + iClF = 0; for (const auto cluster : fecalClustersF) { - if (iClF == iClFHigh){ - hRecFClusterEcalib_Ehigh_eta->Fill(mcenergy, cluster.getEnergy()/mcenergy, mceta); + if (iClF == iClFHigh) { + hRecFClusterEcalib_Ehigh_eta->Fill(mcenergy, cluster.getEnergy() / mcenergy, mceta); hRecFClusterNCells_Ehigh_eta->Fill(mcenergy, cluster.getNhits(), mceta); } iClF++; @@ -549,10 +588,13 @@ void femc_studiesProcessor::Process(const std::shared_ptr& event) // =============================================================================================== // Write clusterizer tree & clean-up variables // =============================================================================================== - if (enableTree){ + if (enableTree) { t_fEMC_towers_N = (int)input_tower_recSav.size(); - for (int iCell = 0; iCell < (int)input_tower_recSav.size(); iCell++){ - m_log->trace("{} \t {} \t {} \t {} \t {}", input_tower_recSav.at(iCell).cellIDx, input_tower_recSav.at(iCell).cellIDy , input_tower_recSav.at(iCell).energy, input_tower_recSav.at(iCell).tower_clusterIDA, input_tower_recSav.at(iCell).tower_clusterIDB ); + for (int iCell = 0; iCell < (int)input_tower_recSav.size(); iCell++) { + m_log->trace("{} \t {} \t {} \t {} \t {}", input_tower_recSav.at(iCell).cellIDx, + input_tower_recSav.at(iCell).cellIDy, input_tower_recSav.at(iCell).energy, + input_tower_recSav.at(iCell).tower_clusterIDA, + input_tower_recSav.at(iCell).tower_clusterIDB); t_fEMC_towers_cellE[iCell] = (float)input_tower_recSav.at(iCell).energy; t_fEMC_towers_cellT[iCell] = (float)input_tower_recSav.at(iCell).time; @@ -566,48 +608,47 @@ void femc_studiesProcessor::Process(const std::shared_ptr& event) event_tree->Fill(); t_fEMC_towers_N = 0; - for (Int_t itow = 0; itow < maxNTowers; itow++){ - t_fEMC_towers_cellE[itow] = 0; - t_fEMC_towers_cellT[itow] = 0; - t_fEMC_towers_cellIDx[itow] = 0; - t_fEMC_towers_cellIDy[itow] = 0; - t_fEMC_towers_clusterIDA[itow] = 0; - t_fEMC_towers_clusterIDB[itow] = 0; - t_fEMC_towers_cellTrueID[itow] = 0; + for (Int_t itow = 0; itow < maxNTowers; itow++) { + t_fEMC_towers_cellE[itow] = 0; + t_fEMC_towers_cellT[itow] = 0; + t_fEMC_towers_cellIDx[itow] = 0; + t_fEMC_towers_cellIDy[itow] = 0; + t_fEMC_towers_clusterIDA[itow] = 0; + t_fEMC_towers_clusterIDB[itow] = 0; + t_fEMC_towers_cellTrueID[itow] = 0; } } // =============================================================================================== // Write cluster tree & clean-up variables // =============================================================================================== - if (enableTreeCluster){ + if (enableTreeCluster) { cluster_tree->Fill(); - t_mc_N = 0; - t_fEMC_clusters_N = 0; - t_fEMC_clusters_N = 0; - for (Int_t iMC = 0; iMC < maxNMC; iMC++){ - t_mc_E[iMC] = 0; - t_mc_Phi[iMC] = 0; - t_mc_Eta[iMC] = 0; + t_mc_N = 0; + t_fEMC_clusters_N = 0; + t_fEMC_clusters_N = 0; + for (Int_t iMC = 0; iMC < maxNMC; iMC++) { + t_mc_E[iMC] = 0; + t_mc_Phi[iMC] = 0; + t_mc_Eta[iMC] = 0; } - for (Int_t iCl = 0; iCl < maxNCluster; iCl++){ - t_fEMC_cluster_E[iCl] = 0; - t_fEMC_cluster_NCells[iCl] = 0; - t_fEMC_cluster_Eta[iCl] = 0; - t_fEMC_cluster_Phi[iCl] = 0; + for (Int_t iCl = 0; iCl < maxNCluster; iCl++) { + t_fEMC_cluster_E[iCl] = 0; + t_fEMC_cluster_NCells[iCl] = 0; + t_fEMC_cluster_Eta[iCl] = 0; + t_fEMC_cluster_Phi[iCl] = 0; } } - } - //******************************************************************************************// // FinishWithGlobalRootLock //******************************************************************************************// void femc_studiesProcessor::Finish() { - std::cout << "------> FEMC " << nEventsWithCaloHits << " with calo info present"<< std::endl; - if (enableTreeCluster) cluster_tree->Write(); + std::cout << "------> FEMC " << nEventsWithCaloHits << " with calo info present" << std::endl; + if (enableTreeCluster) + cluster_tree->Write(); // Do any final calculations here. if (enableTree) { diff --git a/src/benchmarks/reconstruction/femc_studies/femc_studiesProcessor.h b/src/benchmarks/reconstruction/femc_studies/femc_studiesProcessor.h index 7522dbd477..e37fc2fb9c 100644 --- a/src/benchmarks/reconstruction/femc_studies/femc_studiesProcessor.h +++ b/src/benchmarks/reconstruction/femc_studies/femc_studiesProcessor.h @@ -16,74 +16,73 @@ #include #include -class femc_studiesProcessor: public JEventProcessor { +class femc_studiesProcessor : public JEventProcessor { public: - femc_studiesProcessor() { SetTypeName(NAME_OF_THIS); } + femc_studiesProcessor() { SetTypeName(NAME_OF_THIS); } - void Init() override; -// void InitWithGlobalRootLock() override; - void Process(const std::shared_ptr& event) override; -// void ProcessSequential(const std::shared_ptr& event) override; -// void FinishWithGlobalRootLock() override; - void Finish() override; - TDirectory *m_dir_main; - // Declare histogram and tree pointers here. e.g. - TH2D* hMCEnergyVsEta; - TH3D* hClusterEcalib_E_eta; - TH3D* hClusterNCells_E_eta; - TH3D* hClusterEcalib_E_phi; - TH2D* hPosCaloHitsXY; - TH3D* hClusterESimcalib_E_eta; - TH3D* hClusterSimNCells_E_eta; - TH3D* hClusterESimcalib_E_phi; - TH2D* hCellESim_layerX; - TH2D* hCellESim_layerY; - TH2D* hCellTSim_layerX; - TH2D* hPosCaloSimHitsXY; - TH3D* hRecClusterEcalib_E_eta; - TH3D* hRecNClusters_E_eta; - TH3D* hRecClusterEcalib_Ehigh_eta; - TH3D* hRecClusterNCells_Ehigh_eta; - TH3D* hRecFClusterEcalib_E_eta; - TH3D* hRecFNClusters_E_eta; - TH3D* hRecFClusterEcalib_Ehigh_eta; - TH3D* hRecFClusterNCells_Ehigh_eta; - TH2D* hSamplingFractionEta; + void Init() override; + // void InitWithGlobalRootLock() override; + void Process(const std::shared_ptr& event) override; + // void ProcessSequential(const std::shared_ptr& event) override; + // void FinishWithGlobalRootLock() override; + void Finish() override; + TDirectory* m_dir_main; + // Declare histogram and tree pointers here. e.g. + TH2D* hMCEnergyVsEta; + TH3D* hClusterEcalib_E_eta; + TH3D* hClusterNCells_E_eta; + TH3D* hClusterEcalib_E_phi; + TH2D* hPosCaloHitsXY; + TH3D* hClusterESimcalib_E_eta; + TH3D* hClusterSimNCells_E_eta; + TH3D* hClusterESimcalib_E_phi; + TH2D* hCellESim_layerX; + TH2D* hCellESim_layerY; + TH2D* hCellTSim_layerX; + TH2D* hPosCaloSimHitsXY; + TH3D* hRecClusterEcalib_E_eta; + TH3D* hRecNClusters_E_eta; + TH3D* hRecClusterEcalib_Ehigh_eta; + TH3D* hRecClusterNCells_Ehigh_eta; + TH3D* hRecFClusterEcalib_E_eta; + TH3D* hRecFNClusters_E_eta; + TH3D* hRecFClusterEcalib_Ehigh_eta; + TH3D* hRecFClusterNCells_Ehigh_eta; + TH2D* hSamplingFractionEta; - bool enableTree = false; - TTree* event_tree; - const int maxNTowers = 65000; - int t_fEMC_towers_N; - short* t_fEMC_towers_cellIDx; - short* t_fEMC_towers_cellIDy; - short* t_fEMC_towers_clusterIDA; - short* t_fEMC_towers_clusterIDB; - float* t_fEMC_towers_cellE; - float* t_fEMC_towers_cellT; - int* t_fEMC_towers_cellTrueID; + bool enableTree = false; + TTree* event_tree; + const int maxNTowers = 65000; + int t_fEMC_towers_N; + short* t_fEMC_towers_cellIDx; + short* t_fEMC_towers_cellIDy; + short* t_fEMC_towers_clusterIDA; + short* t_fEMC_towers_clusterIDB; + float* t_fEMC_towers_cellE; + float* t_fEMC_towers_cellT; + int* t_fEMC_towers_cellTrueID; - bool enableTreeCluster = false; - TTree* cluster_tree; - const int maxNCluster = 50; - const int maxNMC = 50; - int t_mc_N; - float* t_mc_E; - float* t_mc_Phi; - float* t_mc_Eta; - int t_fEMC_clusters_N; - float* t_fEMC_cluster_E; - int* t_fEMC_cluster_NCells; - float* t_fEMC_cluster_Phi; - float* t_fEMC_cluster_Eta; - - int nEventsWithCaloHits = 0; - std::shared_ptr m_log; - dd4hep::DDSegmentation::BitFieldCoder* m_decoder; - std::string nameSimHits = "EcalEndcapPHits"; - std::string nameRecHits = "EcalEndcapPRecHits"; - std::string nameClusters = "EcalEndcapPClusters"; - std::string nameProtoClusters = "EcalEndcapPIslandProtoClusters"; - short iLx; - short iLy; + bool enableTreeCluster = false; + TTree* cluster_tree; + const int maxNCluster = 50; + const int maxNMC = 50; + int t_mc_N; + float* t_mc_E; + float* t_mc_Phi; + float* t_mc_Eta; + int t_fEMC_clusters_N; + float* t_fEMC_cluster_E; + int* t_fEMC_cluster_NCells; + float* t_fEMC_cluster_Phi; + float* t_fEMC_cluster_Eta; + int nEventsWithCaloHits = 0; + std::shared_ptr m_log; + dd4hep::DDSegmentation::BitFieldCoder* m_decoder; + std::string nameSimHits = "EcalEndcapPHits"; + std::string nameRecHits = "EcalEndcapPRecHits"; + std::string nameClusters = "EcalEndcapPClusters"; + std::string nameProtoClusters = "EcalEndcapPIslandProtoClusters"; + short iLx; + short iLy; }; diff --git a/src/benchmarks/reconstruction/lfhcal_studies/clusterizer_MA.h b/src/benchmarks/reconstruction/lfhcal_studies/clusterizer_MA.h index bbef61f5f9..df6d2ffac9 100644 --- a/src/benchmarks/reconstruction/lfhcal_studies/clusterizer_MA.h +++ b/src/benchmarks/reconstruction/lfhcal_studies/clusterizer_MA.h @@ -7,8 +7,20 @@ #include #include -struct towersStrct{ - towersStrct(): energy(0), time (0), posx(0), posy(0), posz(0), cellID(0), cellIDx(-1), cellIDy(-1), cellIDz(-1), tower_trueID(-10000), tower_clusterIDA(-1), tower_clusterIDB(-1) {} +struct towersStrct { + towersStrct() + : energy(0) + , time(0) + , posx(0) + , posy(0) + , posz(0) + , cellID(0) + , cellIDx(-1) + , cellIDy(-1) + , cellIDz(-1) + , tower_trueID(-10000) + , tower_clusterIDA(-1) + , tower_clusterIDB(-1) {} float energy; float time; float posx; @@ -21,12 +33,24 @@ struct towersStrct{ int tower_trueID; int tower_clusterIDA; int tower_clusterIDB; -} ; +}; bool acompare(towersStrct lhs, towersStrct rhs) { return lhs.energy > rhs.energy; } -struct clustersStrct{ - clustersStrct(): cluster_E(0.), cluster_seed(0.), cluster_Eta(-10.), cluster_Phi(-10.), cluster_X(0.) , cluster_Y(0.), cluster_Z(0.), cluster_M02(0.), cluster_M20(0.), cluster_NTowers(0), cluster_trueID(-10000), cluster_NtrueID(0) {} +struct clustersStrct { + clustersStrct() + : cluster_E(0.) + , cluster_seed(0.) + , cluster_Eta(-10.) + , cluster_Phi(-10.) + , cluster_X(0.) + , cluster_Y(0.) + , cluster_Z(0.) + , cluster_M02(0.) + , cluster_M20(0.) + , cluster_NTowers(0) + , cluster_trueID(-10000) + , cluster_NtrueID(0) {} float cluster_E; float cluster_seed; float cluster_Eta; @@ -40,7 +64,7 @@ struct clustersStrct{ int cluster_trueID; int cluster_NtrueID; std::vector cluster_towers; -} ; +}; bool acompareCl(clustersStrct lhs, clustersStrct rhs) { return lhs.cluster_E > rhs.cluster_E; } @@ -50,62 +74,64 @@ bool acompareCl(clustersStrct lhs, clustersStrct rhs) { return lhs.cluster_E > r //**************************************************************************************************************// //**************************************************************************************************************// clustersStrct findMACluster( - float seed, // minimum seed energy - float agg, // minimum aggregation energy - std::vector &input_towers_temp, // temporary full tower array - std::vector &cluster_towers_temp, // towers associated to cluster -// std::vector clslabels_temp // MC labels in cluster - float aggMargin = 1.0 // aggregation margin - ){ + float seed, // minimum seed energy + float agg, // minimum aggregation energy + std::vector& input_towers_temp, // temporary full tower array + std::vector& cluster_towers_temp, // towers associated to cluster + // std::vector clslabels_temp // MC labels in cluster + float aggMargin = 1.0 // aggregation margin +) { clustersStrct tempstructC; - if(input_towers_temp.at(0).energy > seed){ -// std::cout << "new cluster" << std::endl; + if (input_towers_temp.at(0).energy > seed) { + // std::cout << "new cluster" << std::endl; // fill seed cell information into current cluster tempstructC.cluster_E = input_towers_temp.at(0).energy; tempstructC.cluster_seed = input_towers_temp.at(0).energy; tempstructC.cluster_NTowers = 1; tempstructC.cluster_NtrueID = 1; - tempstructC.cluster_trueID = input_towers_temp.at(0).tower_trueID; // TODO save all MC labels? + tempstructC.cluster_trueID = input_towers_temp.at(0).tower_trueID; // TODO save all MC labels? cluster_towers_temp.push_back(input_towers_temp.at(0)); -// clslabels_temp.push_back(input_towers_temp.at(0).tower_trueID); -// std::cout << "seed: "<< input_towers_temp.at(0).cellIDx << "\t" << input_towers_temp.at(0).cellIDy -// << "\t" << input_towers_temp.at(0).cellIDz << "\t E:"<< tempstructC.cluster_E << std::endl; - + // clslabels_temp.push_back(input_towers_temp.at(0).tower_trueID); + // std::cout << "seed: "<< input_towers_temp.at(0).cellIDx << "\t" << input_towers_temp.at(0).cellIDy + // << "\t" << input_towers_temp.at(0).cellIDz << "\t E:"<< tempstructC.cluster_E << std::endl; // remove seed tower from sample input_towers_temp.erase(input_towers_temp.begin()); - for (int tit = 0; tit < (int)cluster_towers_temp.size(); tit++){ + for (int tit = 0; tit < (int)cluster_towers_temp.size(); tit++) { // Now go recursively to all neighbours and add them to the cluster if they fulfill the conditions int iEtaTwr = cluster_towers_temp.at(tit).cellIDx; int iPhiTwr = cluster_towers_temp.at(tit).cellIDy; int iLTwr = cluster_towers_temp.at(tit).cellIDz; - int refC = 0; - for (int ait = 0; ait < (int)input_towers_temp.size(); ait++){ + int refC = 0; + for (int ait = 0; ait < (int)input_towers_temp.size(); ait++) { int iEtaTwrAgg = input_towers_temp.at(ait).cellIDx; int iPhiTwrAgg = input_towers_temp.at(ait).cellIDy; int iLTwrAgg = input_towers_temp.at(ait).cellIDz; - int deltaL = TMath::Abs(iLTwrAgg-iLTwr) ; - int deltaPhi = TMath::Abs(iPhiTwrAgg-iPhiTwr) ; - int deltaEta = TMath::Abs(iEtaTwrAgg-iEtaTwr) ; - bool neighbor = (deltaL+deltaPhi+deltaEta == 1); - bool corner2D = (deltaL == 0 && deltaPhi == 1 && deltaEta == 1) || (deltaL == 1 && deltaPhi == 0 && deltaEta == 1) || (deltaL == 1 && deltaPhi == 1 && deltaEta == 0); -// first condition asks for V3-like neighbors, while second condition also checks diagonally attached towers - if(neighbor || corner2D ){ + int deltaL = TMath::Abs(iLTwrAgg - iLTwr); + int deltaPhi = TMath::Abs(iPhiTwrAgg - iPhiTwr); + int deltaEta = TMath::Abs(iEtaTwrAgg - iEtaTwr); + bool neighbor = (deltaL + deltaPhi + deltaEta == 1); + bool corner2D = (deltaL == 0 && deltaPhi == 1 && deltaEta == 1) || + (deltaL == 1 && deltaPhi == 0 && deltaEta == 1) || + (deltaL == 1 && deltaPhi == 1 && deltaEta == 0); + // first condition asks for V3-like neighbors, while second condition also checks diagonally attached towers + if (neighbor || corner2D) { // only aggregate towers with lower energy than current tower - if(input_towers_temp.at(ait).energy >= (cluster_towers_temp.at(tit).energy + aggMargin)) continue; - tempstructC.cluster_E+=input_towers_temp.at(ait).energy; + if (input_towers_temp.at(ait).energy >= (cluster_towers_temp.at(tit).energy + aggMargin)) + continue; + tempstructC.cluster_E += input_towers_temp.at(ait).energy; tempstructC.cluster_NTowers++; cluster_towers_temp.push_back(input_towers_temp.at(ait)); -// if(!(std::find(clslabels_temp.begin(), clslabels_temp.end(), input_towers_temp.at(ait).tower_trueID) != clslabels_temp.end())){ -// tempstructC.cluster_NtrueID++; -// clslabels_temp.push_back(input_towers_temp.at(ait).tower_trueID); -// } -// std::cout << "aggregated: "<< iEtaTwrAgg << "\t" << iPhiTwrAgg << "\t" << iLTwrAgg << "\t E:" << input_towers_temp.at(ait).energy << "\t reference: "<< refC << "\t"<< iEtaTwr << "\t" << iPhiTwr << "\t" << iLTwr << "\t cond.: \t"<< neighbor << "\t" << corner2D << "\t diffs: " << deltaEta << "\t" << deltaPhi << "\t" << deltaL<< std::endl; + // if(!(std::find(clslabels_temp.begin(), clslabels_temp.end(), input_towers_temp.at(ait).tower_trueID) != clslabels_temp.end())){ + // tempstructC.cluster_NtrueID++; + // clslabels_temp.push_back(input_towers_temp.at(ait).tower_trueID); + // } + // std::cout << "aggregated: "<< iEtaTwrAgg << "\t" << iPhiTwrAgg << "\t" << iLTwrAgg << "\t E:" << input_towers_temp.at(ait).energy << "\t reference: "<< refC << "\t"<< iEtaTwr << "\t" << iPhiTwr << "\t" << iLTwr << "\t cond.: \t"<< neighbor << "\t" << corner2D << "\t diffs: " << deltaEta << "\t" << deltaPhi << "\t" << deltaL<< std::endl; - input_towers_temp.erase(input_towers_temp.begin()+ait); + input_towers_temp.erase(input_towers_temp.begin() + ait); ait--; refC++; } @@ -115,76 +141,84 @@ clustersStrct findMACluster( return tempstructC; } - // ANCHOR function to determine shower shape -float * CalculateM02andWeightedPosition(std::vector cluster_towers, float cluster_E_calc, float weight0){ - static float returnVariables[8]; //0:M02, 1:M20, 2:eta, 3: phi - float w_tot = 0; - std::vector w_i; - TVector3 vecTwr; - TVector3 vecTwrTmp; - float zHC = 1; - float w_0 = weight0; - - vecTwr = {0.,0.,0.}; - //calculation of weights and weighted position vector - int Nweighted = 0; - for(int cellI=0; cellI<(int)cluster_towers.size(); cellI++){ - w_i.push_back(TMath::Max( (float)0, (float) (w_0 + TMath::Log(cluster_towers.at(cellI).energy/cluster_E_calc) ))); - w_tot += w_i.at(cellI); - if(w_i.at(cellI)>0){ - Nweighted++; - vecTwrTmp = TVector3(cluster_towers.at(cellI).posx, cluster_towers.at(cellI).posy, cluster_towers.at(cellI).posz ); - vecTwr += w_i.at(cellI)*vecTwrTmp; - } +float* CalculateM02andWeightedPosition(std::vector cluster_towers, + float cluster_E_calc, float weight0) { + static float returnVariables[8]; //0:M02, 1:M20, 2:eta, 3: phi + float w_tot = 0; + std::vector w_i; + TVector3 vecTwr; + TVector3 vecTwrTmp; + float zHC = 1; + float w_0 = weight0; + + vecTwr = {0., 0., 0.}; + //calculation of weights and weighted position vector + int Nweighted = 0; + for (int cellI = 0; cellI < (int)cluster_towers.size(); cellI++) { + w_i.push_back(TMath::Max( + (float)0, (float)(w_0 + TMath::Log(cluster_towers.at(cellI).energy / cluster_E_calc)))); + w_tot += w_i.at(cellI); + if (w_i.at(cellI) > 0) { + Nweighted++; + vecTwrTmp = TVector3(cluster_towers.at(cellI).posx, cluster_towers.at(cellI).posy, + cluster_towers.at(cellI).posz); + vecTwr += w_i.at(cellI) * vecTwrTmp; } - // correct Eta position for average shift in calo - returnVariables[2]= vecTwr.Eta(); - returnVariables[3]= vecTwr.Phi(); //(vecTwr.Phi()<0 ? vecTwr.Phi()+TMath::Pi() : vecTwr.Phi()-TMath::Pi()); - vecTwr*=1./w_tot; -// std::cout << "Cluster: X: "<< vecTwr.X() << "\t" << " Y: "<< vecTwr.Y() << "\t" << " Z: "<< vecTwr.Z() << std::endl; - returnVariables[4]=vecTwr.X(); - returnVariables[5]=vecTwr.Y(); - returnVariables[6]=vecTwr.Z(); - - //calculation of M02 - float delta_phi_phi[4] = {0}; - float delta_eta_eta[4] = {0}; - float delta_eta_phi[4] = {0}; - float dispersion = 0; - - for(int cellI=0; cellI<(int)cluster_towers.size(); cellI++){ - int iphi=cluster_towers.at(cellI).cellIDy; - int ieta=cluster_towers.at(cellI).cellIDx; - delta_phi_phi[1] += (w_i.at(cellI)*iphi*iphi)/w_tot; - delta_phi_phi[2] += (w_i.at(cellI)*iphi)/w_tot; - delta_phi_phi[3] += (w_i.at(cellI)*iphi)/w_tot; - - delta_eta_eta[1] += (w_i.at(cellI)*ieta*ieta)/w_tot; - delta_eta_eta[2] += (w_i.at(cellI)*ieta)/w_tot; - delta_eta_eta[3] += (w_i.at(cellI)*ieta)/w_tot; - - delta_eta_phi[1] += (w_i.at(cellI)*ieta*iphi)/w_tot; - delta_eta_phi[2] += (w_i.at(cellI)*iphi)/w_tot; - delta_eta_phi[3] += (w_i.at(cellI)*ieta)/w_tot; - - vecTwrTmp = TVector3(cluster_towers.at(cellI).posx, cluster_towers.at(cellI).posy, cluster_towers.at(cellI).posz ); - // scale cluster position to z-plane - vecTwr*=abs(vecTwrTmp.Z()/vecTwr.Z()); - float dx2 = pow(vecTwrTmp.X()-vecTwr.X(),2); - float dy2 = pow(vecTwrTmp.Y()-vecTwr.Y(),2); - float dz2 = pow(vecTwrTmp.Z()-vecTwr.Z(),2); - dispersion+= (w_i.at(cellI)*(dx2+dy2+dz2))/w_tot; - } - returnVariables[7]=dispersion; - delta_phi_phi[0] = delta_phi_phi[1] - (delta_phi_phi[2] * delta_phi_phi[3]); - delta_eta_eta[0] = delta_eta_eta[1] - (delta_eta_eta[2] * delta_eta_eta[3]); - delta_eta_phi[0] = delta_eta_phi[1] - (delta_eta_phi[2] * delta_eta_phi[3]); - - float calcM02 = 0.5 * ( delta_phi_phi[0] + delta_eta_eta[0] ) + TMath::Sqrt( 0.25 * TMath::Power( ( delta_phi_phi[0] - delta_eta_eta[0] ), 2 ) + TMath::Power( delta_eta_phi[0], 2 ) ); - float calcM20 = 0.5 * ( delta_phi_phi[0] + delta_eta_eta[0] ) - TMath::Sqrt( 0.25 * TMath::Power( ( delta_phi_phi[0] - delta_eta_eta[0] ), 2 ) + TMath::Power( delta_eta_phi[0], 2 ) ); -// std::cout << "M02_calc: " << calcM02 << "\t\t = 0.5 * ( " << delta_phi_phi[0] <<" + "<Add(new lfhcal_studiesProcessor()); - } +void InitPlugin(JApplication* app) { + InitJANAPlugin(app); + app->Add(new lfhcal_studiesProcessor()); +} } diff --git a/src/benchmarks/reconstruction/lfhcal_studies/lfhcal_studiesProcessor.cc b/src/benchmarks/reconstruction/lfhcal_studies/lfhcal_studiesProcessor.cc index d44794e557..4806227545 100644 --- a/src/benchmarks/reconstruction/lfhcal_studies/lfhcal_studiesProcessor.cc +++ b/src/benchmarks/reconstruction/lfhcal_studies/lfhcal_studiesProcessor.cc @@ -38,7 +38,6 @@ #include "services/log/Log_service.h" #include "services/rootfile/RootFile_service.h" - //******************************************************************************************// // InitWithGlobalRootLock //******************************************************************************************// @@ -49,7 +48,7 @@ void lfhcal_studiesProcessor::Init() { // =============================================================================================== // Get JANA application and seup general variables // =============================================================================================== - auto app = GetApplication(); + auto app = GetApplication(); std::string log_level_str = "info"; m_log = app->GetService()->logger(plugin_name); @@ -66,7 +65,7 @@ void lfhcal_studiesProcessor::Init() { // Get TDirectory for histograms root file auto globalRootLock = app->GetService(); globalRootLock->acquire_write_lock(); - auto *file = root_file_service->GetHistFile(); + auto* file = root_file_service->GetHistFile(); globalRootLock->release_lock(); // =============================================================================================== @@ -77,21 +76,26 @@ void lfhcal_studiesProcessor::Init() { // =============================================================================================== // Simulations hists // =============================================================================================== - hMCEnergyVsEta = new TH2D("hMCEnergyVsEta", "; E (GeV); #eta", 1500, 0., 150., 500, 0, 5); + hMCEnergyVsEta = new TH2D("hMCEnergyVsEta", "; E (GeV); #eta", 1500, 0., 150., 500, 0, 5); hMCEnergyVsEta->SetDirectory(m_dir_main); // =============================================================================================== // Sum cell clusters rec histos // =============================================================================================== - hClusterEcalib_E_eta = new TH3D("hClusterEcalib_E_eta", "; E_{MC} (GeV); E_{rec,rec hit}/E_{MC}; #eta", - 1500, 0., 150.0, 200, 0., 2.0, 50, 0, 5); - hClusterNCells_E_eta = new TH3D("hClusterNCells_E_eta", "; E_{MC} (GeV); N_{cells}; #eta", - 1500, 0., 150.0, 500, -0.5, 499.5, 50, 0, 5); - hClusterEcalib_E_phi = new TH3D("hClusterEcalib_E_phi", "; E_{MC} (GeV); E_{rec,rec hit}/E_{MC}; #varphi (rad)", - 1500, 0., 150.0, 200, 0., 2.0, 360 , -TMath::Pi(), TMath::Pi()); - hPosCaloHitsXY = new TH2D("hPosCaloHitsXY", "; X (cm); Y (cm)", 400, -400., 400., 400, -400., 400.); - hPosCaloHitsZX = new TH2D("hPosCaloHitsZX", "; Z (cm); X (cm)", 200, 300., 500., 400, -400., 400.); - hPosCaloHitsZY = new TH2D("hPosCaloHitsZY", "; Z (cm); Y (cm)", 200, 300., 500., 400, -400., 400.); + hClusterEcalib_E_eta = + new TH3D("hClusterEcalib_E_eta", "; E_{MC} (GeV); E_{rec,rec hit}/E_{MC}; #eta", 1500, 0., + 150.0, 200, 0., 2.0, 50, 0, 5); + hClusterNCells_E_eta = new TH3D("hClusterNCells_E_eta", "; E_{MC} (GeV); N_{cells}; #eta", 1500, + 0., 150.0, 500, -0.5, 499.5, 50, 0, 5); + hClusterEcalib_E_phi = + new TH3D("hClusterEcalib_E_phi", "; E_{MC} (GeV); E_{rec,rec hit}/E_{MC}; #varphi (rad)", + 1500, 0., 150.0, 200, 0., 2.0, 360, -TMath::Pi(), TMath::Pi()); + hPosCaloHitsXY = + new TH2D("hPosCaloHitsXY", "; X (cm); Y (cm)", 400, -400., 400., 400, -400., 400.); + hPosCaloHitsZX = + new TH2D("hPosCaloHitsZX", "; Z (cm); X (cm)", 200, 300., 500., 400, -400., 400.); + hPosCaloHitsZY = + new TH2D("hPosCaloHitsZY", "; Z (cm); Y (cm)", 200, 300., 500., 400, -400., 400.); hClusterEcalib_E_eta->SetDirectory(m_dir_main); hClusterNCells_E_eta->SetDirectory(m_dir_main); hClusterEcalib_E_phi->SetDirectory(m_dir_main); @@ -102,19 +106,29 @@ void lfhcal_studiesProcessor::Init() { // =============================================================================================== // Sum cell clusters sim histos // =============================================================================================== - hClusterESimcalib_E_eta = new TH3D("hClusterESimcalib_E_eta", "; E_{MC} (GeV); E_{rec,sim hit}/E_{MC}; #eta" , - 1500, 0., 150.0, 200, 0., 2.0, 50, 0, 5); - hClusterSimNCells_E_eta = new TH3D("hClusterSimNCells_E_eta", "; E_{MC} (GeV); N_{cells, sim}; #eta", - 1500, 0., 150.0, 500, -0.5, 499.5, 50, 0, 5); - hClusterESimcalib_E_phi = new TH3D("hClusterESimcalib_E_phi", "; E_{MC} (GeV); E_{rec,sim hit}/E_{MC}; #varphi (rad)" , - 1500, 0., 150.0, 200, 0., 2.0, 360 , -TMath::Pi(), TMath::Pi()); - hCellESim_layerX = new TH2D("hCellESim_layerX", "; #cell ID X; E_{rec,sim hit} (GeV)" , 240, -0.5, 239.5, 5000, 0, 1); - hCellESim_layerY = new TH2D("hCellESim_layerY", "; #cell ID Y; E_{rec,sim hit} (GeV)" , 240, -0.5, 239.5, 5000, 0, 1); - hCellESim_layerZ = new TH2D("hCellESim_layerZ", "; #cell ID Z; E_{rec,sim hit} (GeV)" , 70, -0.5, 69.5, 5000, 0, 1); - hCellTSim_layerZ = new TH2D("hCellTSim_layerZ", "; #cell ID Z; t_{rec,sim hit} (GeV)" , 70, -0.5, 69.5, 5000, 0, 1000); - hPosCaloSimHitsXY = new TH2D("hPosCaloSimHitsXY", "; X (cm); Y (cm)", 400, -400., 400., 400, -400., 400.); - hPosCaloSimHitsZX = new TH2D("hPosCaloSimHitsZX", "; Z (cm); X (cm)", 200, 300., 500., 400, -400., 400.); - hPosCaloSimHitsZY = new TH2D("hPosCaloSimHitsZY", "; Z (cm); Y (cm)", 200, 300., 500., 400, -400., 400.); + hClusterESimcalib_E_eta = + new TH3D("hClusterESimcalib_E_eta", "; E_{MC} (GeV); E_{rec,sim hit}/E_{MC}; #eta", 1500, 0., + 150.0, 200, 0., 2.0, 50, 0, 5); + hClusterSimNCells_E_eta = + new TH3D("hClusterSimNCells_E_eta", "; E_{MC} (GeV); N_{cells, sim}; #eta", 1500, 0., 150.0, + 500, -0.5, 499.5, 50, 0, 5); + hClusterESimcalib_E_phi = + new TH3D("hClusterESimcalib_E_phi", "; E_{MC} (GeV); E_{rec,sim hit}/E_{MC}; #varphi (rad)", + 1500, 0., 150.0, 200, 0., 2.0, 360, -TMath::Pi(), TMath::Pi()); + hCellESim_layerX = new TH2D("hCellESim_layerX", "; #cell ID X; E_{rec,sim hit} (GeV)", 240, -0.5, + 239.5, 5000, 0, 1); + hCellESim_layerY = new TH2D("hCellESim_layerY", "; #cell ID Y; E_{rec,sim hit} (GeV)", 240, -0.5, + 239.5, 5000, 0, 1); + hCellESim_layerZ = new TH2D("hCellESim_layerZ", "; #cell ID Z; E_{rec,sim hit} (GeV)", 70, -0.5, + 69.5, 5000, 0, 1); + hCellTSim_layerZ = new TH2D("hCellTSim_layerZ", "; #cell ID Z; t_{rec,sim hit} (GeV)", 70, -0.5, + 69.5, 5000, 0, 1000); + hPosCaloSimHitsXY = + new TH2D("hPosCaloSimHitsXY", "; X (cm); Y (cm)", 400, -400., 400., 400, -400., 400.); + hPosCaloSimHitsZX = + new TH2D("hPosCaloSimHitsZX", "; Z (cm); X (cm)", 200, 300., 500., 400, -400., 400.); + hPosCaloSimHitsZY = + new TH2D("hPosCaloSimHitsZY", "; Z (cm); Y (cm)", 200, 300., 500., 400, -400., 400.); hClusterESimcalib_E_eta->SetDirectory(m_dir_main); hClusterSimNCells_E_eta->SetDirectory(m_dir_main); hClusterESimcalib_E_phi->SetDirectory(m_dir_main); @@ -129,15 +143,18 @@ void lfhcal_studiesProcessor::Init() { // =============================================================================================== // rec cluster MA clusters histos // =============================================================================================== - hRecClusterEcalib_E_eta = new TH3D("hRecClusterEcalib_E_eta", "; E_{MC} (GeV); E_{rec,rec clus}/E_{MC}; #eta", - 1500, 0., 150.0, 200, 0., 2.0, 50, 0, 5); - hRecNClusters_E_eta = new TH3D("hRecNClusters_E_eta", "; E_{MC} (GeV); N_{rec cl.}; #eta", - 1500, 0., 150.0, 10, -0.5, 9.5, 50, 0, 5); + hRecClusterEcalib_E_eta = + new TH3D("hRecClusterEcalib_E_eta", "; E_{MC} (GeV); E_{rec,rec clus}/E_{MC}; #eta", 1500, 0., + 150.0, 200, 0., 2.0, 50, 0, 5); + hRecNClusters_E_eta = new TH3D("hRecNClusters_E_eta", "; E_{MC} (GeV); N_{rec cl.}; #eta", 1500, + 0., 150.0, 10, -0.5, 9.5, 50, 0, 5); // rec cluster highest - hRecClusterEcalib_Ehigh_eta = new TH3D("hRecClusterEcalib_Ehigh_eta", "; E_{MC} (GeV); E_{rec,rec clus high.}/E_{MC}; #eta", - 1500, 0., 150.0, 200, 0., 2.0, 50, 0, 5); - hRecClusterNCells_Ehigh_eta = new TH3D("hRecClusterNCells_Ehigh_eta", "; E_{MC} (GeV); N_{cells, rec cl., high.}; #eta", - 1500, 0., 150.0, 500, -0.5, 499.5, 50, 0, 5); + hRecClusterEcalib_Ehigh_eta = + new TH3D("hRecClusterEcalib_Ehigh_eta", "; E_{MC} (GeV); E_{rec,rec clus high.}/E_{MC}; #eta", + 1500, 0., 150.0, 200, 0., 2.0, 50, 0, 5); + hRecClusterNCells_Ehigh_eta = + new TH3D("hRecClusterNCells_Ehigh_eta", "; E_{MC} (GeV); N_{cells, rec cl., high.}; #eta", + 1500, 0., 150.0, 500, -0.5, 499.5, 50, 0, 5); hRecClusterEcalib_E_eta->SetDirectory(m_dir_main); hRecNClusters_E_eta->SetDirectory(m_dir_main); hRecClusterEcalib_Ehigh_eta->SetDirectory(m_dir_main); @@ -146,15 +163,18 @@ void lfhcal_studiesProcessor::Init() { // =============================================================================================== // rec cluster framework Island clusters histos // =============================================================================================== - hRecFClusterEcalib_E_eta = new TH3D("hRecFClusterEcalib_E_eta", "; E_{MC} (GeV); E_{rec,island clus}/E_{MC}; #eta", - 1500, 0., 150.0, 200, 0., 2.0, 50, 0, 5); - hRecFNClusters_E_eta = new TH3D("hRecFNClusters_E_eta", "; E_{MC} (GeV); N_{rec f. cl.}; #eta", - 1500, 0., 150.0, 10, -0.5, 9.5, 50, 0, 5); + hRecFClusterEcalib_E_eta = + new TH3D("hRecFClusterEcalib_E_eta", "; E_{MC} (GeV); E_{rec,island clus}/E_{MC}; #eta", 1500, + 0., 150.0, 200, 0., 2.0, 50, 0, 5); + hRecFNClusters_E_eta = new TH3D("hRecFNClusters_E_eta", "; E_{MC} (GeV); N_{rec f. cl.}; #eta", + 1500, 0., 150.0, 10, -0.5, 9.5, 50, 0, 5); // rec cluster framework highest - hRecFClusterEcalib_Ehigh_eta = new TH3D("hRecFClusterEcalib_Ehigh_eta", "; E_{MC} (GeV); E_{rec,island clus high.}/E_{MC}; #eta", - 1500, 0., 150.0, 200, 0., 2.0, 50, 0, 5); - hRecFClusterNCells_Ehigh_eta = new TH3D("hRecFClusterNCells_Ehigh_eta", "; E_{MC} (GeV); N_{cells, rec f. cl., high.}; #eta", - 1500, 0., 150.0, 500, -0.5, 499.5, 50, 0, 5); + hRecFClusterEcalib_Ehigh_eta = new TH3D("hRecFClusterEcalib_Ehigh_eta", + "; E_{MC} (GeV); E_{rec,island clus high.}/E_{MC}; #eta", + 1500, 0., 150.0, 200, 0., 2.0, 50, 0, 5); + hRecFClusterNCells_Ehigh_eta = + new TH3D("hRecFClusterNCells_Ehigh_eta", "; E_{MC} (GeV); N_{cells, rec f. cl., high.}; #eta", + 1500, 0., 150.0, 500, -0.5, 499.5, 50, 0, 5); hRecFClusterEcalib_E_eta->SetDirectory(m_dir_main); hRecFNClusters_E_eta->SetDirectory(m_dir_main); hRecFClusterEcalib_Ehigh_eta->SetDirectory(m_dir_main); @@ -163,13 +183,17 @@ void lfhcal_studiesProcessor::Init() { // =============================================================================================== // FEcal rec cluster framework Island clusters histos // =============================================================================================== - hRecFEmClusterEcalib_E_eta = new TH3D("hRecFEmClusterEcalib_E_eta", "; E_{MC} (GeV); E_{Ecal, rec,island clus}/E_{MC}; #eta", - 1500, 0., 150.0, 200, 0., 2.0, 50, 0, 5); - hRecFEmNClusters_E_eta = new TH3D("hRecFEmNClusters_E_eta", "; E_{MC} (GeV); N_{Ecal, rec f. cl.}; #eta", - 1500, 0., 150.0, 10, -0.5, 9.5, 50, 0, 5); + hRecFEmClusterEcalib_E_eta = new TH3D("hRecFEmClusterEcalib_E_eta", + "; E_{MC} (GeV); E_{Ecal, rec,island clus}/E_{MC}; #eta", + 1500, 0., 150.0, 200, 0., 2.0, 50, 0, 5); + hRecFEmNClusters_E_eta = + new TH3D("hRecFEmNClusters_E_eta", "; E_{MC} (GeV); N_{Ecal, rec f. cl.}; #eta", 1500, 0., + 150.0, 10, -0.5, 9.5, 50, 0, 5); // rec cluster framework highest - hRecFEmClusterEcalib_Ehigh_eta = new TH3D("hRecFEmClusterEcalib_Ehigh_eta", "; E_{MC} (GeV); E_{Ecal, rec,island clus high.}/E_{MC}; #eta", - 1500, 0., 150.0, 200, 0., 2.0, 50, 0, 5); + hRecFEmClusterEcalib_Ehigh_eta = + new TH3D("hRecFEmClusterEcalib_Ehigh_eta", + "; E_{MC} (GeV); E_{Ecal, rec,island clus high.}/E_{MC}; #eta", 1500, 0., 150.0, 200, + 0., 2.0, 50, 0, 5); hRecFEmClusterEcalib_E_eta->SetDirectory(m_dir_main); hRecFEmNClusters_E_eta->SetDirectory(m_dir_main); hRecFEmClusterEcalib_Ehigh_eta->SetDirectory(m_dir_main); @@ -177,42 +201,48 @@ void lfhcal_studiesProcessor::Init() { // =============================================================================================== // Sampling fraction // =============================================================================================== - hSamplingFractionEta = new TH2D("hSamplingFractionEta", "; #eta; f", 400, 1., 5., 500, 0., 0.2); + hSamplingFractionEta = new TH2D("hSamplingFractionEta", "; #eta; f", 400, 1., 5., 500, 0., 0.2); hSamplingFractionEta->SetDirectory(m_dir_main); // =============================================================================================== // Tree for clusterizer studies // =============================================================================================== - if (enableTree){ - event_tree = new TTree("event_tree", "event_tree"); + if (enableTree) { + event_tree = new TTree("event_tree", "event_tree"); event_tree->SetDirectory(m_dir_main); - t_lFHCal_towers_cellE = new float[maxNTowers]; - t_lFHCal_towers_cellT = new float[maxNTowers]; - t_lFHCal_towers_cellIDx = new short[maxNTowers]; - t_lFHCal_towers_cellIDy = new short[maxNTowers]; - t_lFHCal_towers_cellIDz = new short[maxNTowers]; - t_lFHCal_towers_clusterIDA = new short[maxNTowers]; - t_lFHCal_towers_clusterIDB = new short[maxNTowers]; - t_lFHCal_towers_cellTrueID = new int[maxNTowers]; + t_lFHCal_towers_cellE = new float[maxNTowers]; + t_lFHCal_towers_cellT = new float[maxNTowers]; + t_lFHCal_towers_cellIDx = new short[maxNTowers]; + t_lFHCal_towers_cellIDy = new short[maxNTowers]; + t_lFHCal_towers_cellIDz = new short[maxNTowers]; + t_lFHCal_towers_clusterIDA = new short[maxNTowers]; + t_lFHCal_towers_clusterIDB = new short[maxNTowers]; + t_lFHCal_towers_cellTrueID = new int[maxNTowers]; // towers LFHCAL event_tree->Branch("tower_LFHCAL_N", &t_lFHCal_towers_N, "tower_LFHCAL_N/I"); event_tree->Branch("tower_LFHCAL_E", t_lFHCal_towers_cellE, "tower_LFHCAL_E[tower_LFHCAL_N]/F"); event_tree->Branch("tower_LFHCAL_T", t_lFHCal_towers_cellT, "tower_LFHCAL_T[tower_LFHCAL_N]/F"); - event_tree->Branch("tower_LFHCAL_ix", t_lFHCal_towers_cellIDx, "tower_LFHCAL_ix[tower_LFHCAL_N]/S"); - event_tree->Branch("tower_LFHCAL_iy", t_lFHCal_towers_cellIDy, "tower_LFHCAL_iy[tower_LFHCAL_N]/S"); - event_tree->Branch("tower_LFHCAL_iz", t_lFHCal_towers_cellIDz, "tower_LFHCAL_iz[tower_LFHCAL_N]/S"); - event_tree->Branch("tower_LFHCAL_clusIDA", t_lFHCal_towers_clusterIDA, "tower_LFHCAL_clusIDA[tower_LFHCAL_N]/S"); - event_tree->Branch("tower_LFHCAL_clusIDB", t_lFHCal_towers_clusterIDB, "tower_LFHCAL_clusIDB[tower_LFHCAL_N]/S"); - event_tree->Branch("tower_LFHCAL_trueID", t_lFHCal_towers_cellTrueID, "tower_LFHCAL_trueID[tower_LFHCAL_N]/I"); + event_tree->Branch("tower_LFHCAL_ix", t_lFHCal_towers_cellIDx, + "tower_LFHCAL_ix[tower_LFHCAL_N]/S"); + event_tree->Branch("tower_LFHCAL_iy", t_lFHCal_towers_cellIDy, + "tower_LFHCAL_iy[tower_LFHCAL_N]/S"); + event_tree->Branch("tower_LFHCAL_iz", t_lFHCal_towers_cellIDz, + "tower_LFHCAL_iz[tower_LFHCAL_N]/S"); + event_tree->Branch("tower_LFHCAL_clusIDA", t_lFHCal_towers_clusterIDA, + "tower_LFHCAL_clusIDA[tower_LFHCAL_N]/S"); + event_tree->Branch("tower_LFHCAL_clusIDB", t_lFHCal_towers_clusterIDB, + "tower_LFHCAL_clusIDB[tower_LFHCAL_N]/S"); + event_tree->Branch("tower_LFHCAL_trueID", t_lFHCal_towers_cellTrueID, + "tower_LFHCAL_trueID[tower_LFHCAL_N]/I"); } // =============================================================================================== // Tree for cluster studies // =============================================================================================== - if (enableTreeCluster){ - cluster_tree = new TTree("cluster_tree", "cluster_tree"); + if (enableTreeCluster) { + cluster_tree = new TTree("cluster_tree", "cluster_tree"); cluster_tree->SetDirectory(m_dir_main); t_mc_E = new float[maxNMC]; @@ -222,10 +252,10 @@ void lfhcal_studiesProcessor::Init() { t_lFHCal_cluster_NCells = new int[maxNCluster]; t_lFHCal_cluster_Phi = new float[maxNCluster]; t_lFHCal_cluster_Eta = new float[maxNCluster]; - t_fEMC_cluster_E = new float[maxNCluster]; - t_fEMC_cluster_NCells = new int[maxNCluster]; - t_fEMC_cluster_Eta = new float[maxNCluster]; - t_fEMC_cluster_Phi = new float[maxNCluster]; + t_fEMC_cluster_E = new float[maxNCluster]; + t_fEMC_cluster_NCells = new int[maxNCluster]; + t_fEMC_cluster_Eta = new float[maxNCluster]; + t_fEMC_cluster_Phi = new float[maxNCluster]; // MC particles cluster_tree->Branch("mc_N", &t_mc_N, "mc_N/I"); @@ -234,16 +264,23 @@ void lfhcal_studiesProcessor::Init() { cluster_tree->Branch("mc_Eta", t_mc_Eta, "mc_Eta[mc_N]/F"); // clusters LFHCAL cluster_tree->Branch("cluster_LFHCAL_N", &t_lFHCal_clusters_N, "cluster_LFHCAL_N/I"); - cluster_tree->Branch("cluster_LFHCAL_E", t_lFHCal_cluster_E, "cluster_LFHCAL_E[cluster_LFHCAL_N]/F"); - cluster_tree->Branch("cluster_LFHCAL_Ncells", t_lFHCal_cluster_NCells, "cluster_LFHCAL_Ncells[cluster_LFHCAL_N]/I"); - cluster_tree->Branch("cluster_LFHCAL_Eta", t_lFHCal_cluster_Eta, "cluster_LFHCAL_Eta[cluster_LFHCAL_N]/F"); - cluster_tree->Branch("cluster_LFHCAL_Phi", t_lFHCal_cluster_Phi, "cluster_LFHCAL_Phi[cluster_LFHCAL_N]/F"); + cluster_tree->Branch("cluster_LFHCAL_E", t_lFHCal_cluster_E, + "cluster_LFHCAL_E[cluster_LFHCAL_N]/F"); + cluster_tree->Branch("cluster_LFHCAL_Ncells", t_lFHCal_cluster_NCells, + "cluster_LFHCAL_Ncells[cluster_LFHCAL_N]/I"); + cluster_tree->Branch("cluster_LFHCAL_Eta", t_lFHCal_cluster_Eta, + "cluster_LFHCAL_Eta[cluster_LFHCAL_N]/F"); + cluster_tree->Branch("cluster_LFHCAL_Phi", t_lFHCal_cluster_Phi, + "cluster_LFHCAL_Phi[cluster_LFHCAL_N]/F"); // clusters FECal cluster_tree->Branch("cluster_FECAL_N", &t_fEMC_clusters_N, "cluster_FECAL_N/I"); cluster_tree->Branch("cluster_FECAL_E", t_fEMC_cluster_E, "cluster_FECAL_E[cluster_FECAL_N]/F"); - cluster_tree->Branch("cluster_FECAL_Ncells", t_fEMC_cluster_NCells, "cluster_FECAL_Ncells[cluster_FECAL_N]/I"); - cluster_tree->Branch("cluster_FECAL_Eta", t_fEMC_cluster_Eta, "cluster_FECAL_Eta[cluster_FECAL_N]/F"); - cluster_tree->Branch("cluster_FECAL_Phi", t_fEMC_cluster_Phi, "cluster_FECAL_Phi[cluster_FECAL_N]/F"); + cluster_tree->Branch("cluster_FECAL_Ncells", t_fEMC_cluster_NCells, + "cluster_FECAL_Ncells[cluster_FECAL_N]/I"); + cluster_tree->Branch("cluster_FECAL_Eta", t_fEMC_cluster_Eta, + "cluster_FECAL_Eta[cluster_FECAL_N]/F"); + cluster_tree->Branch("cluster_FECAL_Phi", t_fEMC_cluster_Phi, + "cluster_FECAL_Phi[cluster_FECAL_N]/F"); } std::cout << __PRETTY_FUNCTION__ << " " << __LINE__ << std::endl; @@ -251,35 +288,34 @@ void lfhcal_studiesProcessor::Init() { std::cout << "--------------------------\nID specification:\n"; try { m_decoder = detector->readout("LFHCALHits").idSpec().decoder(); - std::cout <<"1st: "<< m_decoder << std::endl; - iLx = m_decoder->index("towerx"); - iLy = m_decoder->index("towery"); - iLz = m_decoder->index("layerz"); + std::cout << "1st: " << m_decoder << std::endl; + iLx = m_decoder->index("towerx"); + iLy = m_decoder->index("towery"); + iLz = m_decoder->index("layerz"); iPassive = m_decoder->index("passive"); std::cout << "full list: " << " " << m_decoder->fieldDescription() << std::endl; } catch (...) { - std::cout <<"2nd: " << m_decoder << std::endl; - m_log->error("readoutClass not in the output"); - throw std::runtime_error("readoutClass not in the output."); + std::cout << "2nd: " << m_decoder << std::endl; + m_log->error("readoutClass not in the output"); + throw std::runtime_error("readoutClass not in the output."); } - } //******************************************************************************************// // ProcessSequential //******************************************************************************************// void lfhcal_studiesProcessor::Process(const std::shared_ptr& event) { -// void lfhcal_studiesProcessor::ProcessSequential(const std::shared_ptr& event) { + // void lfhcal_studiesProcessor::ProcessSequential(const std::shared_ptr& event) { // =============================================================================================== // process MC particles // =============================================================================================== - const auto &mcParticles = *(event->GetCollection("MCParticles")); - double mceta = 0; - double mcphi = 0; - double mcp = 0; - double mcenergy = 0; - int iMC = 0; + const auto& mcParticles = *(event->GetCollection("MCParticles")); + double mceta = 0; + double mcphi = 0; + double mcp = 0; + double mcenergy = 0; + int iMC = 0; for (auto mcparticle : mcParticles) { if (mcparticle.getGeneratorStatus() != 1) continue; @@ -292,11 +328,12 @@ void lfhcal_studiesProcessor::Process(const std::shared_ptr& event mcphi = atan2(mom.y, mom.x); // determine mc momentum mcp = sqrt(mom.x * mom.x + mom.y * mom.y + mom.z * mom.z); - m_log->trace("MC particle:{} \t {} \t {} \t totmom: {} phi {} eta {}", mom.x, mom.y, mom.z, mcp, mcphi, mceta); - hMCEnergyVsEta->Fill(mcp,mceta); + m_log->trace("MC particle:{} \t {} \t {} \t totmom: {} phi {} eta {}", mom.x, mom.y, mom.z, mcp, + mcphi, mceta); + hMCEnergyVsEta->Fill(mcp, mceta); - if (enableTreeCluster){ - if (iMC < maxNMC){ + if (enableTreeCluster) { + if (iMC < maxNMC) { t_mc_E[iMC] = mcenergy; t_mc_Phi[iMC] = mcphi; t_mc_Eta[iMC] = mceta; @@ -304,52 +341,54 @@ void lfhcal_studiesProcessor::Process(const std::shared_ptr& event } iMC++; } - if (enableTreeCluster) t_mc_N = iMC; + if (enableTreeCluster) + t_mc_N = iMC; // =============================================================================================== // process sim hits // =============================================================================================== std::vector input_tower_sim; - int nCaloHitsSim = 0; - float sumActiveCaloEnergy = 0; + int nCaloHitsSim = 0; + float sumActiveCaloEnergy = 0; float sumPassiveCaloEnergy = 0; - const auto &simHits = *(event->GetCollection(nameSimHits)); + const auto& simHits = *(event->GetCollection(nameSimHits)); for (const auto caloHit : simHits) { float x = caloHit.getPosition().x / 10.; float y = caloHit.getPosition().y / 10.; float z = caloHit.getPosition().z / 10.; uint64_t cellID = caloHit.getCellID(); float energy = caloHit.getEnergy(); - double time = std::numeric_limits::max(); + double time = std::numeric_limits::max(); for (const auto& c : caloHit.getContributions()) { - if (c.getTime() <= time) { - time = c.getTime(); - } + if (c.getTime() <= time) { + time = c.getTime(); + } } - auto detector_module_x = m_decoder->get(cellID, 1); - auto detector_module_y = m_decoder->get(cellID, 2); - auto detector_passive = m_decoder->get(cellID, iPassive); - auto detector_layer_x = m_decoder->get(cellID, iLx); - auto detector_layer_y = m_decoder->get(cellID, iLy); + auto detector_module_x = m_decoder->get(cellID, 1); + auto detector_module_y = m_decoder->get(cellID, 2); + auto detector_passive = m_decoder->get(cellID, iPassive); + auto detector_layer_x = m_decoder->get(cellID, iLx); + auto detector_layer_y = m_decoder->get(cellID, iLy); long detector_layer_rz = -1; if (isLFHCal) detector_layer_rz = m_decoder->get(cellID, 7); auto detector_layer_z = m_decoder->get(cellID, iLz); - if(detector_passive == 0) { + if (detector_passive == 0) { sumActiveCaloEnergy += energy; } else { sumPassiveCaloEnergy += energy; } - if (detector_passive > 0) continue; + if (detector_passive > 0) + continue; // calc cell IDs long cellIDx = -1; long cellIDy = -1; long cellIDz = -1; - if (isLFHCal){ - cellIDx = 54ll*2 - detector_module_x * 2 + detector_layer_x; - cellIDy = 54ll*2 - detector_module_y * 2 + detector_layer_y; - cellIDz = detector_layer_rz*10+detector_layer_z; + if (isLFHCal) { + cellIDx = 54ll * 2 - detector_module_x * 2 + detector_layer_x; + cellIDy = 54ll * 2 - detector_module_y * 2 + detector_layer_y; + cellIDz = detector_layer_rz * 10 + detector_layer_z; } nCaloHitsSim++; @@ -373,26 +412,25 @@ void lfhcal_studiesProcessor::Process(const std::shared_ptr& event } if (!found) { towersStrct tempstructT; - tempstructT.energy = energy; - tempstructT.time = time; - tempstructT.posx = x; - tempstructT.posy = y; - tempstructT.posz = z; - tempstructT.cellID = cellID; - tempstructT.cellIDx = cellIDx; - tempstructT.cellIDy = cellIDy; - tempstructT.cellIDz = cellIDz; - tempstructT.tower_trueID = 0; //TODO how to get trueID? + tempstructT.energy = energy; + tempstructT.time = time; + tempstructT.posx = x; + tempstructT.posy = y; + tempstructT.posz = z; + tempstructT.cellID = cellID; + tempstructT.cellIDx = cellIDx; + tempstructT.cellIDy = cellIDy; + tempstructT.cellIDz = cellIDz; + tempstructT.tower_trueID = 0; //TODO how to get trueID? input_tower_sim.push_back(tempstructT); } } - // =============================================================================================== // read rec hits & fill structs // =============================================================================================== - const auto &recHits = *(event->GetCollection(nameRecHits)); - int nCaloHitsRec = 0; + const auto& recHits = *(event->GetCollection(nameRecHits)); + int nCaloHitsRec = 0; std::vector input_tower_rec; std::vector input_tower_recSav; // process rec hits @@ -404,24 +442,25 @@ void lfhcal_studiesProcessor::Process(const std::shared_ptr& event float energy = caloHit.getEnergy(); float time = caloHit.getTime(); - auto detector_module_x = m_decoder->get(cellID, 1); - auto detector_module_y = m_decoder->get(cellID, 2); - auto detector_passive = m_decoder->get(cellID, iPassive); - auto detector_layer_x = m_decoder->get(cellID, iLx); - auto detector_layer_y = m_decoder->get(cellID, iLy); - int detector_layer_rz = -1; - if (isLFHCal){ - detector_layer_rz = m_decoder->get(cellID, 7); + auto detector_module_x = m_decoder->get(cellID, 1); + auto detector_module_y = m_decoder->get(cellID, 2); + auto detector_passive = m_decoder->get(cellID, iPassive); + auto detector_layer_x = m_decoder->get(cellID, iLx); + auto detector_layer_y = m_decoder->get(cellID, iLy); + int detector_layer_rz = -1; + if (isLFHCal) { + detector_layer_rz = m_decoder->get(cellID, 7); } - if (detector_passive > 0) continue; + if (detector_passive > 0) + continue; // calc cell IDs long cellIDx = -1; long cellIDy = -1; - if (isLFHCal){ - cellIDx = 54ll*2 - detector_module_x * 2 + detector_layer_x; - cellIDy = 54ll*2 - detector_module_y * 2 + detector_layer_y; + if (isLFHCal) { + cellIDx = 54ll * 2 - detector_module_x * 2 + detector_layer_x; + cellIDy = 54ll * 2 - detector_module_y * 2 + detector_layer_y; } hPosCaloHitsXY->Fill(x, y); @@ -441,29 +480,31 @@ void lfhcal_studiesProcessor::Process(const std::shared_ptr& event } if (!found) { towersStrct tempstructT; - tempstructT.energy = energy; - tempstructT.time = time; - tempstructT.posx = x; - tempstructT.posy = y; - tempstructT.posz = z; - tempstructT.cellID = cellID; - tempstructT.cellIDx = cellIDx; - tempstructT.cellIDy = cellIDy; + tempstructT.energy = energy; + tempstructT.time = time; + tempstructT.posx = x; + tempstructT.posy = y; + tempstructT.posz = z; + tempstructT.cellID = cellID; + tempstructT.cellIDx = cellIDx; + tempstructT.cellIDy = cellIDy; if (isLFHCal) - tempstructT.cellIDz = detector_layer_rz; - tempstructT.tower_trueID = 0; //TODO how to get trueID? + tempstructT.cellIDz = detector_layer_rz; + tempstructT.tower_trueID = 0; //TODO how to get trueID? input_tower_rec.push_back(tempstructT); input_tower_recSav.push_back(tempstructT); } } m_log->trace("LFHCal mod: nCaloHits sim {}\t rec {}", nCaloHitsSim, nCaloHitsRec); - if (nCaloHitsRec > 0) nEventsWithCaloHits++; + if (nCaloHitsRec > 0) + nEventsWithCaloHits++; // =============================================================================================== // sort tower arrays // =============================================================================================== - hSamplingFractionEta->Fill(mceta, sumActiveCaloEnergy / (sumActiveCaloEnergy+sumPassiveCaloEnergy)); + hSamplingFractionEta->Fill(mceta, + sumActiveCaloEnergy / (sumActiveCaloEnergy + sumPassiveCaloEnergy)); std::sort(input_tower_rec.begin(), input_tower_rec.end(), &acompare); std::sort(input_tower_recSav.begin(), input_tower_recSav.end(), &acompare); std::sort(input_tower_sim.begin(), input_tower_sim.end(), &acompare); @@ -486,36 +527,37 @@ void lfhcal_studiesProcessor::Process(const std::shared_ptr& event double tot_energySimHit = 0; for (auto& tower : input_tower_sim) { if (tower.cellIDz < minCellIDzDiffSamp) - tower.energy = tower.energy/samplingFractionW; // calibrate + tower.energy = tower.energy / samplingFractionW; // calibrate else - tower.energy = tower.energy/samplingFractionFe; // calibrate + tower.energy = tower.energy / samplingFractionFe; // calibrate tot_energySimHit += tower.energy; } - m_log->trace("Mc E: {} \t eta: {} \t sim E rec: {}\t rec E rec: {}", mcenergy, mceta, tot_energySimHit, tot_energyRecHit); + m_log->trace("Mc E: {} \t eta: {} \t sim E rec: {}\t rec E rec: {}", mcenergy, mceta, + tot_energySimHit, tot_energyRecHit); // =============================================================================================== // Fill summed hits histos // =============================================================================================== // rec hits hClusterNCells_E_eta->Fill(mcenergy, nCaloHitsRec, mceta); - hClusterEcalib_E_eta->Fill(mcenergy, tot_energyRecHit/mcenergy, mceta); - hClusterEcalib_E_phi->Fill(mcenergy, tot_energyRecHit/mcenergy, mcphi); + hClusterEcalib_E_eta->Fill(mcenergy, tot_energyRecHit / mcenergy, mceta); + hClusterEcalib_E_phi->Fill(mcenergy, tot_energyRecHit / mcenergy, mcphi); // sim hits hClusterSimNCells_E_eta->Fill(mcenergy, nCaloHitsSim, mceta); - hClusterESimcalib_E_eta->Fill(mcenergy, tot_energySimHit/mcenergy, mceta); - hClusterESimcalib_E_phi->Fill(mcenergy, tot_energySimHit/mcenergy, mcphi); + hClusterESimcalib_E_eta->Fill(mcenergy, tot_energySimHit / mcenergy, mceta); + hClusterESimcalib_E_phi->Fill(mcenergy, tot_energySimHit / mcenergy, mcphi); // =============================================================================================== // MA clusterization // =============================================================================================== - int removedCells = 0; - float minAggE = 0.001; - float seedE = 0.100; + int removedCells = 0; + float minAggE = 0.001; + float seedE = 0.100; - if (!input_tower_rec.empty()){ + if (!input_tower_rec.empty()) { // clean up rec array for clusterization - while (input_tower_rec.at(input_tower_rec.size()-1).energy < minAggE ){ + while (input_tower_rec.at(input_tower_rec.size() - 1).energy < minAggE) { input_tower_rec.pop_back(); removedCells++; } @@ -526,32 +568,42 @@ void lfhcal_studiesProcessor::Process(const std::shared_ptr& event std::vector clusters_calo; // vector of towers within the currently found cluster std::vector cluster_towers; - while (!input_tower_rec.empty() ) { + while (!input_tower_rec.empty()) { cluster_towers.clear(); clustersStrct tempstructC; // always start with highest energetic tower - if(input_tower_rec.at(0).energy > seedE){ - m_log->trace("seed: {}\t {} \t {}", input_tower_rec.at(0).energy, input_tower_rec.at(0).cellIDx, input_tower_rec.at(0).cellIDy, input_tower_rec.at(0).cellIDz); + if (input_tower_rec.at(0).energy > seedE) { + m_log->trace("seed: {}\t {} \t {}", input_tower_rec.at(0).energy, + input_tower_rec.at(0).cellIDx, input_tower_rec.at(0).cellIDy, + input_tower_rec.at(0).cellIDz); tempstructC = findMACluster(seedE, minAggE, input_tower_rec, cluster_towers); // determine remaining cluster properties from its towers - float* showershape_eta_phi = CalculateM02andWeightedPosition(cluster_towers, tempstructC.cluster_E, 4.5); - tempstructC.cluster_M02 = showershape_eta_phi[0]; - tempstructC.cluster_M20 = showershape_eta_phi[1]; - tempstructC.cluster_Eta = showershape_eta_phi[2]; - tempstructC.cluster_Phi = showershape_eta_phi[3]; - tempstructC.cluster_X = showershape_eta_phi[4]; - tempstructC.cluster_Y = showershape_eta_phi[5]; - tempstructC.cluster_Z = showershape_eta_phi[6]; + float* showershape_eta_phi = + CalculateM02andWeightedPosition(cluster_towers, tempstructC.cluster_E, 4.5); + tempstructC.cluster_M02 = showershape_eta_phi[0]; + tempstructC.cluster_M20 = showershape_eta_phi[1]; + tempstructC.cluster_Eta = showershape_eta_phi[2]; + tempstructC.cluster_Phi = showershape_eta_phi[3]; + tempstructC.cluster_X = showershape_eta_phi[4]; + tempstructC.cluster_Y = showershape_eta_phi[5]; + tempstructC.cluster_Z = showershape_eta_phi[6]; tempstructC.cluster_towers = cluster_towers; - m_log->trace("---------> \t {} \tcluster with E = {} \tEta: {} \tPhi: {} \tX: {} \tY: {} \tZ: {} \tntowers: {} \ttrueID: {}", nclusters, tempstructC.cluster_E, tempstructC.cluster_Eta, tempstructC.cluster_Phi, tempstructC.cluster_X, tempstructC.cluster_Y, tempstructC.cluster_Z, tempstructC.cluster_NTowers, tempstructC.cluster_trueID ); + m_log->trace("---------> \t {} \tcluster with E = {} \tEta: {} \tPhi: {} \tX: {} \tY: {} " + "\tZ: {} \tntowers: {} \ttrueID: {}", + nclusters, tempstructC.cluster_E, tempstructC.cluster_Eta, + tempstructC.cluster_Phi, tempstructC.cluster_X, tempstructC.cluster_Y, + tempstructC.cluster_Z, tempstructC.cluster_NTowers, + tempstructC.cluster_trueID); clusters_calo.push_back(tempstructC); clusters_calo.push_back(tempstructC); nclusters++; } else { - m_log->trace("remaining: {} largest: {} \t {} \t {} \t {}", (int)input_tower_rec.size(), input_tower_rec.at(0).energy, input_tower_rec.at(0).cellIDx, input_tower_rec.at(0).cellIDy, input_tower_rec.at(0).cellIDz); + m_log->trace("remaining: {} largest: {} \t {} \t {} \t {}", (int)input_tower_rec.size(), + input_tower_rec.at(0).energy, input_tower_rec.at(0).cellIDx, + input_tower_rec.at(0).cellIDy, input_tower_rec.at(0).cellIDz); input_tower_rec.clear(); } } @@ -560,106 +612,110 @@ void lfhcal_studiesProcessor::Process(const std::shared_ptr& event // --------------------------- Fill LFHCal MA clusters in tree and hists ------------------------- // ----------------------------------------------------------------------------------------------- std::sort(clusters_calo.begin(), clusters_calo.end(), &acompareCl); - m_log->info("-----> found {} clusters" , clusters_calo.size()); + m_log->info("-----> found {} clusters", clusters_calo.size()); hRecNClusters_E_eta->Fill(mcenergy, clusters_calo.size(), mceta); int iCl = 0; for (const auto cluster : clusters_calo) { - if (iCl < maxNCluster && enableTreeCluster){ - t_lFHCal_cluster_E[iCl] = (float)cluster.cluster_E; - t_lFHCal_cluster_NCells[iCl] = (int)cluster.cluster_NTowers; - t_lFHCal_cluster_Eta[iCl] = (float)cluster.cluster_Eta; - t_lFHCal_cluster_Phi[iCl] = (float)cluster.cluster_Phi; + if (iCl < maxNCluster && enableTreeCluster) { + t_lFHCal_cluster_E[iCl] = (float)cluster.cluster_E; + t_lFHCal_cluster_NCells[iCl] = (int)cluster.cluster_NTowers; + t_lFHCal_cluster_Eta[iCl] = (float)cluster.cluster_Eta; + t_lFHCal_cluster_Phi[iCl] = (float)cluster.cluster_Phi; } - hRecClusterEcalib_E_eta->Fill(mcenergy, cluster.cluster_E/mcenergy, mceta); - for (int iCell = 0; iCell < (int)cluster.cluster_towers.size(); iCell++){ + hRecClusterEcalib_E_eta->Fill(mcenergy, cluster.cluster_E / mcenergy, mceta); + for (int iCell = 0; iCell < (int)cluster.cluster_towers.size(); iCell++) { int pSav = 0; - while(cluster.cluster_towers.at(iCell).cellID != input_tower_recSav.at(pSav).cellID && pSav < (int)input_tower_recSav.size() ) pSav++; + while (cluster.cluster_towers.at(iCell).cellID != input_tower_recSav.at(pSav).cellID && + pSav < (int)input_tower_recSav.size()) + pSav++; if (cluster.cluster_towers.at(iCell).cellID == input_tower_recSav.at(pSav).cellID) input_tower_recSav.at(pSav).tower_clusterIDA = iCl; } - if (iCl == 0){ - hRecClusterEcalib_Ehigh_eta->Fill(mcenergy, cluster.cluster_E/mcenergy, mceta); + if (iCl == 0) { + hRecClusterEcalib_Ehigh_eta->Fill(mcenergy, cluster.cluster_E / mcenergy, mceta); hRecClusterNCells_Ehigh_eta->Fill(mcenergy, cluster.cluster_NTowers, mceta); } iCl++; m_log->trace("MA cluster {}:\t {} \t {}", iCl, cluster.cluster_E, cluster.cluster_NTowers); } - if (iCl < maxNCluster && enableTreeCluster) t_lFHCal_clusters_N = (int)iCl; + if (iCl < maxNCluster && enableTreeCluster) + t_lFHCal_clusters_N = (int)iCl; clusters_calo.clear(); } else { hRecNClusters_E_eta->Fill(mcenergy, 0., mceta); - if (enableTreeCluster) t_lFHCal_clusters_N = 0; + if (enableTreeCluster) + t_lFHCal_clusters_N = 0; } // =============================================================================================== // ------------------------------- Fill LFHCAl Island clusters in hists -------------------------- // =============================================================================================== - int iClF = 0; - float highestEFr = 0; - int iClFHigh = 0; + int iClF = 0; + float highestEFr = 0; + int iClFHigh = 0; - const auto &lfhcalClustersF = *(event->GetCollection(nameClusters)); + const auto& lfhcalClustersF = *(event->GetCollection(nameClusters)); for (const auto cluster : lfhcalClustersF) { - if (cluster.getEnergy() > highestEFr){ - iClFHigh = iClF; - highestEFr = cluster.getEnergy(); + if (cluster.getEnergy() > highestEFr) { + iClFHigh = iClF; + highestEFr = cluster.getEnergy(); } - hRecFClusterEcalib_E_eta->Fill(mcenergy, cluster.getEnergy()/mcenergy, mceta); + hRecFClusterEcalib_E_eta->Fill(mcenergy, cluster.getEnergy() / mcenergy, mceta); m_log->trace("Island cluster {}:\t {} \t {}", iClF, cluster.getEnergy(), cluster.getNhits()); iClF++; } hRecFNClusters_E_eta->Fill(mcenergy, iClF, mceta); // fill hists for highest Island cluster - iClF = 0; + iClF = 0; for (const auto cluster : lfhcalClustersF) { - if (iClF == iClFHigh){ - hRecFClusterEcalib_Ehigh_eta->Fill(mcenergy, cluster.getEnergy()/mcenergy, mceta); + if (iClF == iClFHigh) { + hRecFClusterEcalib_Ehigh_eta->Fill(mcenergy, cluster.getEnergy() / mcenergy, mceta); hRecFClusterNCells_Ehigh_eta->Fill(mcenergy, cluster.getNhits(), mceta); } iClF++; } - // =============================================================================================== // ------------------------------- Fill FECal Island clusters in hists -------------------------- // =============================================================================================== - int iECl = 0; - float highestEEmCl = 0; - int iEClHigh = 0; + int iECl = 0; + float highestEEmCl = 0; + int iEClHigh = 0; - if (enableECalCluster){ + if (enableECalCluster) { try { - const auto &fEMCClustersF = *(event->GetCollection("EcalEndcapPClusters")); - m_log->info("-----> found fEMCClustersF:" , fEMCClustersF.size()); + const auto& fEMCClustersF = *(event->GetCollection("EcalEndcapPClusters")); + m_log->info("-----> found fEMCClustersF:", fEMCClustersF.size()); for (const auto cluster : fEMCClustersF) { - if (iECl < maxNCluster && enableTreeCluster){ - t_fEMC_cluster_E[iECl] = (float)cluster.getEnergy(); - t_fEMC_cluster_NCells[iECl] = (int)cluster.getNhits(); - t_fEMC_cluster_Eta[iECl] = (-1.) * std::log(std::tan((float)cluster.getIntrinsicTheta() / 2.)); - t_fEMC_cluster_Phi[iECl] = (float)cluster.getIntrinsicPhi(); + if (iECl < maxNCluster && enableTreeCluster) { + t_fEMC_cluster_E[iECl] = (float)cluster.getEnergy(); + t_fEMC_cluster_NCells[iECl] = (int)cluster.getNhits(); + t_fEMC_cluster_Eta[iECl] = + (-1.) * std::log(std::tan((float)cluster.getIntrinsicTheta() / 2.)); + t_fEMC_cluster_Phi[iECl] = (float)cluster.getIntrinsicPhi(); } - if (cluster.getEnergy() > highestEEmCl){ - iEClHigh = iECl; - highestEEmCl = cluster.getEnergy(); + if (cluster.getEnergy() > highestEEmCl) { + iEClHigh = iECl; + highestEEmCl = cluster.getEnergy(); } - hRecFEmClusterEcalib_E_eta->Fill(mcenergy, cluster.getEnergy()/mcenergy, mceta); + hRecFEmClusterEcalib_E_eta->Fill(mcenergy, cluster.getEnergy() / mcenergy, mceta); iECl++; } - t_fEMC_clusters_N = iECl; + t_fEMC_clusters_N = iECl; hRecFEmNClusters_E_eta->Fill(mcenergy, iECl, mceta); // fill hists for highest Island cluster - iECl = 0; + iECl = 0; for (const auto cluster : fEMCClustersF) { - if (iECl == iEClHigh){ - hRecFEmClusterEcalib_Ehigh_eta->Fill(mcenergy, cluster.getEnergy()/mcenergy, mceta); + if (iECl == iEClHigh) { + hRecFEmClusterEcalib_Ehigh_eta->Fill(mcenergy, cluster.getEnergy() / mcenergy, mceta); } iECl++; } - } catch (...){ + } catch (...) { std::cout << "ECal clusters not in output" << std::endl; enableECalCluster = false; } @@ -667,10 +723,14 @@ void lfhcal_studiesProcessor::Process(const std::shared_ptr& event // =============================================================================================== // Write clusterizer tree & clean-up variables // =============================================================================================== - if (enableTree){ + if (enableTree) { t_lFHCal_towers_N = (int)input_tower_recSav.size(); - for (int iCell = 0; iCell < (int)input_tower_recSav.size(); iCell++){ - m_log->trace("{} \t {} \t {} \t {} \t {} \t {}", input_tower_recSav.at(iCell).cellIDx, input_tower_recSav.at(iCell).cellIDy, input_tower_recSav.at(iCell).cellIDz , input_tower_recSav.at(iCell).energy, input_tower_recSav.at(iCell).tower_clusterIDA, input_tower_recSav.at(iCell).tower_clusterIDB ); + for (int iCell = 0; iCell < (int)input_tower_recSav.size(); iCell++) { + m_log->trace("{} \t {} \t {} \t {} \t {} \t {}", input_tower_recSav.at(iCell).cellIDx, + input_tower_recSav.at(iCell).cellIDy, input_tower_recSav.at(iCell).cellIDz, + input_tower_recSav.at(iCell).energy, + input_tower_recSav.at(iCell).tower_clusterIDA, + input_tower_recSav.at(iCell).tower_clusterIDB); t_lFHCal_towers_cellE[iCell] = (float)input_tower_recSav.at(iCell).energy; t_lFHCal_towers_cellT[iCell] = (float)input_tower_recSav.at(iCell).time; @@ -685,51 +745,50 @@ void lfhcal_studiesProcessor::Process(const std::shared_ptr& event event_tree->Fill(); t_lFHCal_towers_N = 0; - for (Int_t itow = 0; itow < maxNTowers; itow++){ - t_lFHCal_towers_cellE[itow] = 0; - t_lFHCal_towers_cellT[itow] = 0; - t_lFHCal_towers_cellIDx[itow] = 0; - t_lFHCal_towers_cellIDy[itow] = 0; - t_lFHCal_towers_cellIDz[itow] = 0; - t_lFHCal_towers_clusterIDA[itow] = 0; - t_lFHCal_towers_clusterIDB[itow] = 0; - t_lFHCal_towers_cellTrueID[itow] = 0; + for (Int_t itow = 0; itow < maxNTowers; itow++) { + t_lFHCal_towers_cellE[itow] = 0; + t_lFHCal_towers_cellT[itow] = 0; + t_lFHCal_towers_cellIDx[itow] = 0; + t_lFHCal_towers_cellIDy[itow] = 0; + t_lFHCal_towers_cellIDz[itow] = 0; + t_lFHCal_towers_clusterIDA[itow] = 0; + t_lFHCal_towers_clusterIDB[itow] = 0; + t_lFHCal_towers_cellTrueID[itow] = 0; } } // =============================================================================================== // Write cluster tree & clean-up variables // =============================================================================================== - if (enableTreeCluster){ + if (enableTreeCluster) { cluster_tree->Fill(); - t_mc_N = 0; - t_lFHCal_clusters_N = 0; - t_fEMC_clusters_N = 0; - for (Int_t iMC = 0; iMC < maxNMC; iMC++){ - t_mc_E[iMC] = 0; - t_mc_Phi[iMC] = 0; - t_mc_Eta[iMC] = 0; + t_mc_N = 0; + t_lFHCal_clusters_N = 0; + t_fEMC_clusters_N = 0; + for (Int_t iMC = 0; iMC < maxNMC; iMC++) { + t_mc_E[iMC] = 0; + t_mc_Phi[iMC] = 0; + t_mc_Eta[iMC] = 0; } - for (Int_t iCl = 0; iCl < maxNCluster; iCl++){ - t_lFHCal_cluster_E[iCl] = 0; - t_lFHCal_cluster_NCells[iCl] = 0; - t_lFHCal_cluster_Eta[iCl] = 0; - t_lFHCal_cluster_Phi[iCl] = 0; + for (Int_t iCl = 0; iCl < maxNCluster; iCl++) { + t_lFHCal_cluster_E[iCl] = 0; + t_lFHCal_cluster_NCells[iCl] = 0; + t_lFHCal_cluster_Eta[iCl] = 0; + t_lFHCal_cluster_Phi[iCl] = 0; t_fEMC_cluster_E[iCl] = 0; t_fEMC_cluster_NCells[iCl] = 0; t_fEMC_cluster_Eta[iCl] = 0; t_fEMC_cluster_Phi[iCl] = 0; } } - } //******************************************************************************************// // Finish //******************************************************************************************// void lfhcal_studiesProcessor::Finish() { - std::cout << "------> LFHCal " << nEventsWithCaloHits << " with calo info present"<< std::endl; + std::cout << "------> LFHCal " << nEventsWithCaloHits << " with calo info present" << std::endl; // Do any final calculations here. if (enableTree) { diff --git a/src/benchmarks/reconstruction/lfhcal_studies/lfhcal_studiesProcessor.h b/src/benchmarks/reconstruction/lfhcal_studies/lfhcal_studiesProcessor.h index 27232ea3b0..4647469f48 100644 --- a/src/benchmarks/reconstruction/lfhcal_studies/lfhcal_studiesProcessor.h +++ b/src/benchmarks/reconstruction/lfhcal_studies/lfhcal_studiesProcessor.h @@ -16,93 +16,91 @@ #include #include -class lfhcal_studiesProcessor: public JEventProcessor { +class lfhcal_studiesProcessor : public JEventProcessor { public: - lfhcal_studiesProcessor() { SetTypeName(NAME_OF_THIS); } + lfhcal_studiesProcessor() { SetTypeName(NAME_OF_THIS); } - void Init() override; -// void InitWithGlobalRootLock() override; -// void ProcessSequential(const std::shared_ptr& event) override; - void Process(const std::shared_ptr& event) override; - void Finish() override; -// void FinishWithGlobalRootLock() override; - TDirectory *m_dir_main; - // Declare histogram and tree pointers here. e.g. - TH2D* hMCEnergyVsEta; - TH3D* hClusterEcalib_E_eta; - TH3D* hClusterNCells_E_eta; - TH3D* hClusterEcalib_E_phi; - TH2D* hPosCaloHitsXY; - TH2D* hPosCaloHitsZX; - TH2D* hPosCaloHitsZY; - TH3D* hClusterESimcalib_E_eta; - TH3D* hClusterSimNCells_E_eta; - TH3D* hClusterESimcalib_E_phi; - TH2D* hCellESim_layerZ; - TH2D* hCellESim_layerX; - TH2D* hCellESim_layerY; - TH2D* hCellTSim_layerZ; - TH2D* hPosCaloSimHitsXY; - TH2D* hPosCaloSimHitsZX; - TH2D* hPosCaloSimHitsZY; - TH3D* hRecClusterEcalib_E_eta; - TH3D* hRecNClusters_E_eta; - TH3D* hRecClusterEcalib_Ehigh_eta; - TH3D* hRecClusterNCells_Ehigh_eta; - TH3D* hRecFClusterEcalib_E_eta; - TH3D* hRecFNClusters_E_eta; - TH3D* hRecFClusterEcalib_Ehigh_eta; - TH3D* hRecFClusterNCells_Ehigh_eta; - TH3D* hRecFEmClusterEcalib_E_eta; - TH3D* hRecFEmNClusters_E_eta; - TH3D* hRecFEmClusterEcalib_Ehigh_eta; - TH2D* hSamplingFractionEta; + void Init() override; + // void InitWithGlobalRootLock() override; + // void ProcessSequential(const std::shared_ptr& event) override; + void Process(const std::shared_ptr& event) override; + void Finish() override; + // void FinishWithGlobalRootLock() override; + TDirectory* m_dir_main; + // Declare histogram and tree pointers here. e.g. + TH2D* hMCEnergyVsEta; + TH3D* hClusterEcalib_E_eta; + TH3D* hClusterNCells_E_eta; + TH3D* hClusterEcalib_E_phi; + TH2D* hPosCaloHitsXY; + TH2D* hPosCaloHitsZX; + TH2D* hPosCaloHitsZY; + TH3D* hClusterESimcalib_E_eta; + TH3D* hClusterSimNCells_E_eta; + TH3D* hClusterESimcalib_E_phi; + TH2D* hCellESim_layerZ; + TH2D* hCellESim_layerX; + TH2D* hCellESim_layerY; + TH2D* hCellTSim_layerZ; + TH2D* hPosCaloSimHitsXY; + TH2D* hPosCaloSimHitsZX; + TH2D* hPosCaloSimHitsZY; + TH3D* hRecClusterEcalib_E_eta; + TH3D* hRecNClusters_E_eta; + TH3D* hRecClusterEcalib_Ehigh_eta; + TH3D* hRecClusterNCells_Ehigh_eta; + TH3D* hRecFClusterEcalib_E_eta; + TH3D* hRecFNClusters_E_eta; + TH3D* hRecFClusterEcalib_Ehigh_eta; + TH3D* hRecFClusterNCells_Ehigh_eta; + TH3D* hRecFEmClusterEcalib_E_eta; + TH3D* hRecFEmNClusters_E_eta; + TH3D* hRecFEmClusterEcalib_Ehigh_eta; + TH2D* hSamplingFractionEta; - bool enableTree = true; - TTree* event_tree; - const int maxNTowers = 65000; - int t_lFHCal_towers_N; - short* t_lFHCal_towers_cellIDx; - short* t_lFHCal_towers_cellIDy; - short* t_lFHCal_towers_cellIDz; - short* t_lFHCal_towers_clusterIDA; - short* t_lFHCal_towers_clusterIDB; - float* t_lFHCal_towers_cellE; - float* t_lFHCal_towers_cellT; - int* t_lFHCal_towers_cellTrueID; + bool enableTree = true; + TTree* event_tree; + const int maxNTowers = 65000; + int t_lFHCal_towers_N; + short* t_lFHCal_towers_cellIDx; + short* t_lFHCal_towers_cellIDy; + short* t_lFHCal_towers_cellIDz; + short* t_lFHCal_towers_clusterIDA; + short* t_lFHCal_towers_clusterIDB; + float* t_lFHCal_towers_cellE; + float* t_lFHCal_towers_cellT; + int* t_lFHCal_towers_cellTrueID; - bool enableTreeCluster = true; - bool enableECalCluster = true; - TTree* cluster_tree; - const int maxNCluster = 50; - const int maxNMC = 50; - int t_mc_N; - float* t_mc_E; - float* t_mc_Phi; - float* t_mc_Eta; - int t_lFHCal_clusters_N; - float* t_lFHCal_cluster_E; - int* t_lFHCal_cluster_NCells; - float* t_lFHCal_cluster_Phi; - float* t_lFHCal_cluster_Eta; - int t_fEMC_clusters_N; - float* t_fEMC_cluster_E; - int* t_fEMC_cluster_NCells; - float* t_fEMC_cluster_Phi; - float* t_fEMC_cluster_Eta; - - - int nEventsWithCaloHits = 0; - bool isLFHCal = true; - std::shared_ptr m_log; - dd4hep::DDSegmentation::BitFieldCoder* m_decoder; - std::string nameSimHits = "LFHCALHits"; - std::string nameRecHits = "LFHCALRecHits"; - std::string nameClusters = "LFHCALClusters"; - std::string nameProtoClusters = "LFHCALIslandProtoClusters"; - short iPassive; - short iLx; - short iLy; - short iLz; + bool enableTreeCluster = true; + bool enableECalCluster = true; + TTree* cluster_tree; + const int maxNCluster = 50; + const int maxNMC = 50; + int t_mc_N; + float* t_mc_E; + float* t_mc_Phi; + float* t_mc_Eta; + int t_lFHCal_clusters_N; + float* t_lFHCal_cluster_E; + int* t_lFHCal_cluster_NCells; + float* t_lFHCal_cluster_Phi; + float* t_lFHCal_cluster_Eta; + int t_fEMC_clusters_N; + float* t_fEMC_cluster_E; + int* t_fEMC_cluster_NCells; + float* t_fEMC_cluster_Phi; + float* t_fEMC_cluster_Eta; + int nEventsWithCaloHits = 0; + bool isLFHCal = true; + std::shared_ptr m_log; + dd4hep::DDSegmentation::BitFieldCoder* m_decoder; + std::string nameSimHits = "LFHCALHits"; + std::string nameRecHits = "LFHCALRecHits"; + std::string nameClusters = "LFHCALClusters"; + std::string nameProtoClusters = "LFHCALIslandProtoClusters"; + short iPassive; + short iLx; + short iLy; + short iLz; }; diff --git a/src/benchmarks/reconstruction/tof_efficiency/TofEfficiency_processor.cc b/src/benchmarks/reconstruction/tof_efficiency/TofEfficiency_processor.cc index 4bb2de8720..451452d55c 100644 --- a/src/benchmarks/reconstruction/tof_efficiency/TofEfficiency_processor.cc +++ b/src/benchmarks/reconstruction/tof_efficiency/TofEfficiency_processor.cc @@ -18,116 +18,132 @@ //------------------------------------------- // InitWithGlobalRootLock //------------------------------------------- -void TofEfficiency_processor::InitWithGlobalRootLock(){ - std::string plugin_name=("tof_efficiency"); - - InitLogger(GetApplication(), plugin_name); - - // Get JANA application - auto *app = GetApplication(); - - // Ask service locator a file to write histograms to - auto root_file_service = app->GetService(); - - // Get TDirectory for histograms root file - auto globalRootLock = app->GetService(); - globalRootLock->acquire_write_lock(); - auto *file = root_file_service->GetHistFile(); - globalRootLock->release_lock(); - - // Create a directory for this plugin. And subdirectories for series of histograms - m_dir_main = file->mkdir(plugin_name.c_str()); - - auto phi_limit_min = 0; - auto phi_limit_max = 6.29; - auto z_limit_min = -1250; - auto z_limit_max = 1250; - auto r_limit_min = 50; - auto r_limit_max = 675; - - m_th2_btof_phiz = new TH2F("btof_phiz", "Hit position for Barrel TOF", 100, phi_limit_min, phi_limit_max, 100, z_limit_min, z_limit_max); - m_th2_ftof_rphi = new TH2F("ftof_rphi", "Hit position for Forward TOF", 100, r_limit_min, r_limit_max, 100, phi_limit_min, phi_limit_max); - m_th2_btof_phiz->SetDirectory(m_dir_main); - m_th2_ftof_rphi->SetDirectory(m_dir_main); - - m_tntuple_track = new TNtuple("track","track with tof","det:proj_x:proj_y:proj_z:proj_pathlength:tofhit_x:tofhit_y:tofhit_z:tofhit_t:tofhit_dca"); - m_tntuple_track->SetDirectory(m_dir_main); +void TofEfficiency_processor::InitWithGlobalRootLock() { + std::string plugin_name = ("tof_efficiency"); + + InitLogger(GetApplication(), plugin_name); + + // Get JANA application + auto* app = GetApplication(); + + // Ask service locator a file to write histograms to + auto root_file_service = app->GetService(); + + // Get TDirectory for histograms root file + auto globalRootLock = app->GetService(); + globalRootLock->acquire_write_lock(); + auto* file = root_file_service->GetHistFile(); + globalRootLock->release_lock(); + + // Create a directory for this plugin. And subdirectories for series of histograms + m_dir_main = file->mkdir(plugin_name.c_str()); + + auto phi_limit_min = 0; + auto phi_limit_max = 6.29; + auto z_limit_min = -1250; + auto z_limit_max = 1250; + auto r_limit_min = 50; + auto r_limit_max = 675; + + m_th2_btof_phiz = new TH2F("btof_phiz", "Hit position for Barrel TOF", 100, phi_limit_min, + phi_limit_max, 100, z_limit_min, z_limit_max); + m_th2_ftof_rphi = new TH2F("ftof_rphi", "Hit position for Forward TOF", 100, r_limit_min, + r_limit_max, 100, phi_limit_min, phi_limit_max); + m_th2_btof_phiz->SetDirectory(m_dir_main); + m_th2_ftof_rphi->SetDirectory(m_dir_main); + + m_tntuple_track = new TNtuple( + "track", "track with tof", + "det:proj_x:proj_y:proj_z:proj_pathlength:tofhit_x:tofhit_y:tofhit_z:tofhit_t:tofhit_dca"); + m_tntuple_track->SetDirectory(m_dir_main); } //------------------------------------------- // ProcessSequential //------------------------------------------- void TofEfficiency_processor::ProcessSequential(const std::shared_ptr& event) { - const auto &mcParticles = *(event->GetCollection("MCParticles")); - const auto &trackSegments = *(event->GetCollection("CentralTrackSegments")); - const auto &barrelHits = *(event->GetCollection("TOFBarrelRecHit")); - const auto &endcapHits = *(event->GetCollection("TOFEndcapRecHits")); - - // List TOF Barrel hits from barrel - logger()->trace("TOF barrel hits:"); - m_log->trace(" {:>10} {:>10} {:>10} {:>10}", "[x]", "[y]", "[z]", "[time]"); - for (const auto hit: barrelHits) { - const auto& pos = hit.getPosition(); - float r=sqrt(pos.x*pos.x+pos.y*pos.y); - float phi=acos(pos.x/r); if(pos.y<0) phi+=3.1415927; - m_th2_btof_phiz->Fill(phi, pos.z); - m_log->trace(" {:>10.2f} {:>10.2f} {:>10.2f} {:>10.4f}", pos.x, pos.y, pos.z, hit.getTime()); - } - - // List TOF endcap hits - logger()->trace("TOF endcap hits:"); - m_log->trace(" {:>10} {:>10} {:>10} {:>10}", "[x]", "[y]", "[z]", "[time]"); - for (const auto hit: endcapHits) { - const auto& pos = hit.getPosition(); - float r=sqrt(pos.x*pos.x+pos.y*pos.y); - float phi=acos(pos.x/r); if(pos.y<0) phi+=3.1415927; - m_th2_ftof_rphi->Fill(r, phi); - m_log->trace(" {:>10.2f} {:>10.2f} {:>10.2f} {:>10.4f}", pos.x, pos.y, pos.z, hit.getTime()); - } - - // Now go through reconstructed tracks points - logger()->trace("Going over tracks:"); - m_log->trace(" {:>10} {:>10} {:>10} {:>10}", "[x]", "[y]", "[z]", "[length]"); - for( const auto track_segment : trackSegments ){ - logger()->trace(" Track trajectory"); - - for(const auto point: track_segment.getPoints()) { - auto &pos = point.position; - m_log->trace(" {:>10.2f} {:>10.2f} {:>10.2f} {:>10.2f}", pos.x, pos.y, pos.z, point.pathlength); - - int det=IsTOFHit(pos.x, pos.y, pos.z); - float distance_closest=1e6; - float hit_x=-1000, hit_y=-1000, hit_z=-1000, hit_t=-1000; - float hit_px=-1000, hit_py=-1000, hit_pz=-1000, hit_e=-1000; - if(det==1) { - for (const auto hit: barrelHits) { - const auto& hitpos = hit.getPosition(); - float distance=sqrt((hitpos.x-pos.x)*(hitpos.x-pos.x)+(hitpos.y-pos.y)*(hitpos.y-pos.y)+(hitpos.z-pos.z)*(hitpos.z-pos.z)); - if(distanceFill(det, pos.x, pos.y, pos.z, point.pathlength, hit_x, hit_y, hit_z, hit_t, distance_closest); + const auto& mcParticles = *(event->GetCollection("MCParticles")); + const auto& trackSegments = + *(event->GetCollection("CentralTrackSegments")); + const auto& barrelHits = *(event->GetCollection("TOFBarrelRecHit")); + const auto& endcapHits = *(event->GetCollection("TOFEndcapRecHits")); + + // List TOF Barrel hits from barrel + logger()->trace("TOF barrel hits:"); + m_log->trace(" {:>10} {:>10} {:>10} {:>10}", "[x]", "[y]", "[z]", "[time]"); + for (const auto hit : barrelHits) { + const auto& pos = hit.getPosition(); + float r = sqrt(pos.x * pos.x + pos.y * pos.y); + float phi = acos(pos.x / r); + if (pos.y < 0) + phi += 3.1415927; + m_th2_btof_phiz->Fill(phi, pos.z); + m_log->trace(" {:>10.2f} {:>10.2f} {:>10.2f} {:>10.4f}", pos.x, pos.y, pos.z, hit.getTime()); + } + + // List TOF endcap hits + logger()->trace("TOF endcap hits:"); + m_log->trace(" {:>10} {:>10} {:>10} {:>10}", "[x]", "[y]", "[z]", "[time]"); + for (const auto hit : endcapHits) { + const auto& pos = hit.getPosition(); + float r = sqrt(pos.x * pos.x + pos.y * pos.y); + float phi = acos(pos.x / r); + if (pos.y < 0) + phi += 3.1415927; + m_th2_ftof_rphi->Fill(r, phi); + m_log->trace(" {:>10.2f} {:>10.2f} {:>10.2f} {:>10.4f}", pos.x, pos.y, pos.z, hit.getTime()); + } + + // Now go through reconstructed tracks points + logger()->trace("Going over tracks:"); + m_log->trace(" {:>10} {:>10} {:>10} {:>10}", "[x]", "[y]", "[z]", "[length]"); + for (const auto track_segment : trackSegments) { + logger()->trace(" Track trajectory"); + + for (const auto point : track_segment.getPoints()) { + auto& pos = point.position; + m_log->trace(" {:>10.2f} {:>10.2f} {:>10.2f} {:>10.2f}", pos.x, pos.y, pos.z, + point.pathlength); + + int det = IsTOFHit(pos.x, pos.y, pos.z); + float distance_closest = 1e6; + float hit_x = -1000, hit_y = -1000, hit_z = -1000, hit_t = -1000; + float hit_px = -1000, hit_py = -1000, hit_pz = -1000, hit_e = -1000; + if (det == 1) { + for (const auto hit : barrelHits) { + const auto& hitpos = hit.getPosition(); + float distance = sqrt((hitpos.x - pos.x) * (hitpos.x - pos.x) + + (hitpos.y - pos.y) * (hitpos.y - pos.y) + + (hitpos.z - pos.z) * (hitpos.z - pos.z)); + if (distance < distance_closest) { + distance_closest = distance; + hit_x = hitpos.x; + hit_y = hitpos.y; + hit_z = hitpos.z; + hit_t = hit.getTime(); + } + } + } + if (det == 2) { + for (const auto hit : endcapHits) { + const auto& hitpos = hit.getPosition(); + float distance = sqrt((hitpos.x - pos.x) * (hitpos.x - pos.x) + + (hitpos.y - pos.y) * (hitpos.y - pos.y) + + (hitpos.z - pos.z) * (hitpos.z - pos.z)); + if (distance < distance_closest) { + distance_closest = distance; + hit_x = hitpos.x; + hit_y = hitpos.y; + hit_z = hitpos.z; + hit_t = hit.getTime(); + } } + } + if (det != 0) + m_tntuple_track->Fill(det, pos.x, pos.y, pos.z, point.pathlength, hit_x, hit_y, hit_z, + hit_t, distance_closest); } + } } //------------------------------------------- @@ -135,24 +151,26 @@ void TofEfficiency_processor::ProcessSequential(const std::shared_ptrbtof_rmin&&rbtof_zmin&&zftof_rmin&&rftof_zmin&&z btof_rmin && r < btof_rmax && z > btof_zmin && z < btof_zmax) + return 1; + else if (r > ftof_rmin && r < ftof_rmax && z > ftof_zmin && z < ftof_zmax) + return 2; + else + return 0; } diff --git a/src/benchmarks/reconstruction/tof_efficiency/TofEfficiency_processor.h b/src/benchmarks/reconstruction/tof_efficiency/TofEfficiency_processor.h index 4205eba32b..d295be67ad 100644 --- a/src/benchmarks/reconstruction/tof_efficiency/TofEfficiency_processor.h +++ b/src/benchmarks/reconstruction/tof_efficiency/TofEfficiency_processor.h @@ -16,25 +16,24 @@ #include "extensions/spdlog/SpdlogMixin.h" -class TofEfficiency_processor: public JEventProcessorSequentialRoot, public eicrecon::SpdlogMixin { +class TofEfficiency_processor : public JEventProcessorSequentialRoot, public eicrecon::SpdlogMixin { private: - - // Containers for histograms - std::map m_1d_hists; - std::map m_2d_hists; + // Containers for histograms + std::map m_1d_hists; + std::map m_2d_hists; public: - TofEfficiency_processor() { SetTypeName(NAME_OF_THIS); } + TofEfficiency_processor() { SetTypeName(NAME_OF_THIS); } - void InitWithGlobalRootLock() override; - void ProcessSequential(const std::shared_ptr& event) override; - void FinishWithGlobalRootLock() override; + void InitWithGlobalRootLock() override; + void ProcessSequential(const std::shared_ptr& event) override; + void FinishWithGlobalRootLock() override; - int IsTOFHit(float x, float y, float z); + int IsTOFHit(float x, float y, float z); - TDirectory *m_dir_main; + TDirectory* m_dir_main; - TH2F * m_th2_btof_phiz; - TH2F * m_th2_ftof_rphi; - TNtuple * m_tntuple_track; + TH2F* m_th2_btof_phiz; + TH2F* m_th2_ftof_rphi; + TNtuple* m_tntuple_track; }; diff --git a/src/benchmarks/reconstruction/tof_efficiency/tof_efficiency.cc b/src/benchmarks/reconstruction/tof_efficiency/tof_efficiency.cc index 2b579d3573..315f80a8c2 100644 --- a/src/benchmarks/reconstruction/tof_efficiency/tof_efficiency.cc +++ b/src/benchmarks/reconstruction/tof_efficiency/tof_efficiency.cc @@ -8,8 +8,8 @@ #include "TofEfficiency_processor.h" extern "C" { - void InitPlugin(JApplication *app) { - InitJANAPlugin(app); - app->Add(new TofEfficiency_processor()); - } +void InitPlugin(JApplication* app) { + InitJANAPlugin(app); + app->Add(new TofEfficiency_processor()); +} } diff --git a/src/benchmarks/reconstruction/tracking_efficiency/TrackingEfficiency_processor.cc b/src/benchmarks/reconstruction/tracking_efficiency/TrackingEfficiency_processor.cc index ddae8e3909..4e446fdd69 100644 --- a/src/benchmarks/reconstruction/tracking_efficiency/TrackingEfficiency_processor.cc +++ b/src/benchmarks/reconstruction/tracking_efficiency/TrackingEfficiency_processor.cc @@ -30,168 +30,164 @@ //-------------------------------- // OccupancyAnalysis (Constructor) //-------------------------------- -TrackingEfficiency_processor::TrackingEfficiency_processor(JApplication *app) : - JEventProcessor(app) -{ -} +TrackingEfficiency_processor::TrackingEfficiency_processor(JApplication* app) + : JEventProcessor(app) {} //------------------ // Init //------------------ -void TrackingEfficiency_processor::Init() -{ - std::string plugin_name=("tracking_efficiency"); - - // Get JANA application - auto *app = GetApplication(); - - // Ask service locator a file to write histograms to - auto root_file_service = app->GetService(); - - // Get TDirectory for histograms root file - auto globalRootLock = app->GetService(); - globalRootLock->acquire_write_lock(); - auto *file = root_file_service->GetHistFile(); - globalRootLock->release_lock(); - - // Create a directory for this plugin. And subdirectories for series of histograms - m_dir_main = file->mkdir(plugin_name.c_str()); - - // Get log level from user parameter or default - std::string log_level_str = "info"; - m_log = app->GetService()->logger(plugin_name); - app->SetDefaultParameter(plugin_name + ":LogLevel", log_level_str, "LogLevel: trace, debug, info, warn, err, critical, off"); - m_log->set_level(eicrecon::ParseLogLevel(log_level_str)); +void TrackingEfficiency_processor::Init() { + std::string plugin_name = ("tracking_efficiency"); + + // Get JANA application + auto* app = GetApplication(); + + // Ask service locator a file to write histograms to + auto root_file_service = app->GetService(); + + // Get TDirectory for histograms root file + auto globalRootLock = app->GetService(); + globalRootLock->acquire_write_lock(); + auto* file = root_file_service->GetHistFile(); + globalRootLock->release_lock(); + + // Create a directory for this plugin. And subdirectories for series of histograms + m_dir_main = file->mkdir(plugin_name.c_str()); + + // Get log level from user parameter or default + std::string log_level_str = "info"; + m_log = app->GetService()->logger(plugin_name); + app->SetDefaultParameter(plugin_name + ":LogLevel", log_level_str, + "LogLevel: trace, debug, info, warn, err, critical, off"); + m_log->set_level(eicrecon::ParseLogLevel(log_level_str)); } - //------------------ // Process //------------------ -void TrackingEfficiency_processor::Process(const std::shared_ptr& event) -{ - using namespace ROOT; - - // EXAMPLE I - // This is access to for final result of the calculation/data transformation of central detector CFKTracking: - const auto reco_particles = event->Get("ReconstructedChargedParticles"); - - m_log->debug("Tracking reconstructed particles N={}: ", reco_particles.size()); - m_log->debug(" {:<5} {:>8} {:>8} {:>8} {:>8} {:>8}","[i]", "[px]", "[py]", "[pz]", "[P]", "[P*3]"); - - for(size_t i=0; i < reco_particles.size(); i++) { - auto& particle = *(reco_particles[i]); - - double px = particle.getMomentum().x; - double py = particle.getMomentum().y; - double pz = particle.getMomentum().z; - // ROOT::Math::PxPyPzM4D p4v(px, py, pz, particle.getMass()); - ROOT::Math::Cartesian3D p(px, py, pz); - m_log->debug(" {:<5} {:>8.2f} {:>8.2f} {:>8.2f} {:>8.2f} {:>8.2f}", i, px, py, pz, p.R(), p.R()*3); +void TrackingEfficiency_processor::Process(const std::shared_ptr& event) { + using namespace ROOT; + + // EXAMPLE I + // This is access to for final result of the calculation/data transformation of central detector CFKTracking: + const auto reco_particles = + event->Get("ReconstructedChargedParticles"); + + m_log->debug("Tracking reconstructed particles N={}: ", reco_particles.size()); + m_log->debug(" {:<5} {:>8} {:>8} {:>8} {:>8} {:>8}", "[i]", "[px]", "[py]", "[pz]", "[P]", + "[P*3]"); + + for (size_t i = 0; i < reco_particles.size(); i++) { + auto& particle = *(reco_particles[i]); + + double px = particle.getMomentum().x; + double py = particle.getMomentum().y; + double pz = particle.getMomentum().z; + // ROOT::Math::PxPyPzM4D p4v(px, py, pz, particle.getMass()); + ROOT::Math::Cartesian3D p(px, py, pz); + m_log->debug(" {:<5} {:>8.2f} {:>8.2f} {:>8.2f} {:>8.2f} {:>8.2f}", i, px, py, pz, p.R(), + p.R() * 3); + } + + // EXAMPLE II + // This gets access to more direct ACTS results from CFKTracking + auto acts_results = event->Get("CentralCKFActsTrajectories"); + m_log->debug("ACTS Trajectories( size: {} )", std::size(acts_results)); + m_log->debug("{:>10} {:>10} {:>10} {:>10} {:>10} {:>10} {:>12} {:>12} {:>12} {:>8}", "[loc 0]", + "[loc 1]", "[phi]", "[theta]", "[q/p]", "[p]", "[err phi]", "[err th]", "[err q/p]", + "[chi2]"); + + // Loop over the trajectories + for (const auto& traj : acts_results) { + + // Get the entry index for the single trajectory + // The trajectory entry indices and the multiTrajectory + const auto& mj = traj->multiTrajectory(); + const auto& trackTips = traj->tips(); + if (trackTips.empty()) { + m_log->debug("Empty multiTrajectory."); + continue; } - // EXAMPLE II - // This gets access to more direct ACTS results from CFKTracking - auto acts_results = event->Get("CentralCKFActsTrajectories"); - m_log->debug("ACTS Trajectories( size: {} )", std::size(acts_results)); - m_log->debug("{:>10} {:>10} {:>10} {:>10} {:>10} {:>10} {:>12} {:>12} {:>12} {:>8}", - "[loc 0]","[loc 1]", "[phi]", "[theta]", "[q/p]", "[p]", "[err phi]", "[err th]", "[err q/p]", "[chi2]" ); - - // Loop over the trajectories - for (const auto& traj : acts_results) { - - // Get the entry index for the single trajectory - // The trajectory entry indices and the multiTrajectory - const auto &mj = traj->multiTrajectory(); - const auto &trackTips = traj->tips(); - if (trackTips.empty()) { - m_log->debug("Empty multiTrajectory."); - continue; - } - - const auto &trackTip = trackTips.front(); - - // Collect the trajectory summary info - auto trajState = Acts::MultiTrajectoryHelpers::trajectoryState(mj, trackTip); - if (traj->hasTrackParameters(trackTip)) { - const auto &boundParam = traj->trackParameters(trackTip); - const auto ¶meter = boundParam.parameters(); - const auto &covariance = *boundParam.covariance(); - m_log->debug("{:>10.2f} {:>10.2f} {:>10.2f} {:>10.3f} {:>10.4f} {:>10.3f} {:>12.4e} {:>12.4e} {:>12.4e} {:>8.2f}", - parameter[Acts::eBoundLoc0], - parameter[Acts::eBoundLoc1], - parameter[Acts::eBoundPhi], - parameter[Acts::eBoundTheta], - parameter[Acts::eBoundQOverP], - 1.0 / parameter[Acts::eBoundQOverP], - sqrt(covariance(Acts::eBoundPhi, Acts::eBoundPhi)), - sqrt(covariance(Acts::eBoundTheta, Acts::eBoundTheta)), - sqrt(covariance(Acts::eBoundQOverP, Acts::eBoundQOverP)), - trajState.chi2Sum); - } - } - - - // EXAMPLE III - // Loop over MC particles - auto mc_particles = event->Get("MCParticles"); - m_log->debug("MC particles N={}: ", mc_particles.size()); - m_log->debug(" {:<5} {:<6} {:<7} {:>8} {:>8} {:>8} {:>8}","[i]", "status", "[PDG]", "[px]", "[py]", "[pz]", "[P]"); - for(size_t i=0; i < mc_particles.size(); i++) { - const auto *particle=mc_particles[i]; - - // GeneratorStatus() == 1 - stable particles from MC generator. 0 - might be added by Geant4 - if(particle->getGeneratorStatus() != 1) continue; - - double px = particle->getMomentum().x; - double py = particle->getMomentum().y; - double pz = particle->getMomentum().z; - ROOT::Math::PxPyPzM4D p4v(px, py, pz, particle->getMass()); - ROOT::Math::Cartesian3D p(px, py, pz); - if(p.R()<1) continue; - - m_log->debug(" {:<5} {:<6} {:<7} {:>8.2f} {:>8.2f} {:>8.2f} {:>8.2f}", i, particle->getGeneratorStatus(), particle->getPDG(), px, py, pz, p.R()); + const auto& trackTip = trackTips.front(); + + // Collect the trajectory summary info + auto trajState = Acts::MultiTrajectoryHelpers::trajectoryState(mj, trackTip); + if (traj->hasTrackParameters(trackTip)) { + const auto& boundParam = traj->trackParameters(trackTip); + const auto& parameter = boundParam.parameters(); + const auto& covariance = *boundParam.covariance(); + m_log->debug("{:>10.2f} {:>10.2f} {:>10.2f} {:>10.3f} {:>10.4f} {:>10.3f} {:>12.4e} " + "{:>12.4e} {:>12.4e} {:>8.2f}", + parameter[Acts::eBoundLoc0], parameter[Acts::eBoundLoc1], + parameter[Acts::eBoundPhi], parameter[Acts::eBoundTheta], + parameter[Acts::eBoundQOverP], 1.0 / parameter[Acts::eBoundQOverP], + sqrt(covariance(Acts::eBoundPhi, Acts::eBoundPhi)), + sqrt(covariance(Acts::eBoundTheta, Acts::eBoundTheta)), + sqrt(covariance(Acts::eBoundQOverP, Acts::eBoundQOverP)), trajState.chi2Sum); } + } + + // EXAMPLE III + // Loop over MC particles + auto mc_particles = event->Get("MCParticles"); + m_log->debug("MC particles N={}: ", mc_particles.size()); + m_log->debug(" {:<5} {:<6} {:<7} {:>8} {:>8} {:>8} {:>8}", "[i]", "status", "[PDG]", "[px]", + "[py]", "[pz]", "[P]"); + for (size_t i = 0; i < mc_particles.size(); i++) { + const auto* particle = mc_particles[i]; + + // GeneratorStatus() == 1 - stable particles from MC generator. 0 - might be added by Geant4 + if (particle->getGeneratorStatus() != 1) + continue; + + double px = particle->getMomentum().x; + double py = particle->getMomentum().y; + double pz = particle->getMomentum().z; + ROOT::Math::PxPyPzM4D p4v(px, py, pz, particle->getMass()); + ROOT::Math::Cartesian3D p(px, py, pz); + if (p.R() < 1) + continue; + + m_log->debug(" {:<5} {:<6} {:<7} {:>8.2f} {:>8.2f} {:>8.2f} {:>8.2f}", i, + particle->getGeneratorStatus(), particle->getPDG(), px, py, pz, p.R()); + } } - //------------------ // Finish //------------------ -void TrackingEfficiency_processor::Finish() -{ - fmt::print("OccupancyAnalysis::Finish() called\n"); - - - - // Next we want to create several pretty canvases (with histograms drawn on "same") - // But we don't want those canvases to pop up. So we set root to batch mode - // We will restore the mode afterwards - //bool save_is_batch = gROOT->IsBatch(); - //gROOT->SetBatch(true); - - // 3D hits distribution -// auto th3_by_det_canvas = new TCanvas("th3_by_det_cnv", "Occupancy of detectors"); -// dir_main->Append(th3_by_det_canvas); -// for (auto& kv : th3_by_detector->GetMap()) { -// auto th3_hist = kv.second; -// th3_hist->Draw("same"); -// } -// th3_by_det_canvas->GetPad(0)->BuildLegend(); -// -// // Hits Z by detector -// -// // Create pretty canvases -// auto z_by_det_canvas = new TCanvas("z_by_det_cnv", "Hit Z distribution by detector"); -// dir_main->Append(z_by_det_canvas); -// th1_hits_z->Draw("PLC PFC"); -// -// for (auto& kv : th1_z_by_detector->GetMap()) { -// auto hist = kv.second; -// hist->Draw("SAME PLC PFC"); -// hist->SetFillStyle(3001); -// } -// z_by_det_canvas->GetPad(0)->BuildLegend(); -// -// gROOT->SetBatch(save_is_batch); +void TrackingEfficiency_processor::Finish() { + fmt::print("OccupancyAnalysis::Finish() called\n"); + + // Next we want to create several pretty canvases (with histograms drawn on "same") + // But we don't want those canvases to pop up. So we set root to batch mode + // We will restore the mode afterwards + //bool save_is_batch = gROOT->IsBatch(); + //gROOT->SetBatch(true); + + // 3D hits distribution + // auto th3_by_det_canvas = new TCanvas("th3_by_det_cnv", "Occupancy of detectors"); + // dir_main->Append(th3_by_det_canvas); + // for (auto& kv : th3_by_detector->GetMap()) { + // auto th3_hist = kv.second; + // th3_hist->Draw("same"); + // } + // th3_by_det_canvas->GetPad(0)->BuildLegend(); + // + // // Hits Z by detector + // + // // Create pretty canvases + // auto z_by_det_canvas = new TCanvas("z_by_det_cnv", "Hit Z distribution by detector"); + // dir_main->Append(z_by_det_canvas); + // th1_hits_z->Draw("PLC PFC"); + // + // for (auto& kv : th1_z_by_detector->GetMap()) { + // auto hist = kv.second; + // hist->Draw("SAME PLC PFC"); + // hist->SetFillStyle(3001); + // } + // z_by_det_canvas->GetPad(0)->BuildLegend(); + // + // gROOT->SetBatch(save_is_batch); } diff --git a/src/benchmarks/reconstruction/tracking_efficiency/TrackingEfficiency_processor.h b/src/benchmarks/reconstruction/tracking_efficiency/TrackingEfficiency_processor.h index 86e7b225f4..1195269571 100644 --- a/src/benchmarks/reconstruction/tracking_efficiency/TrackingEfficiency_processor.h +++ b/src/benchmarks/reconstruction/tracking_efficiency/TrackingEfficiency_processor.h @@ -9,46 +9,44 @@ #include #include -class TrackingEfficiency_processor:public JEventProcessor -{ +class TrackingEfficiency_processor : public JEventProcessor { public: - explicit TrackingEfficiency_processor(JApplication *); - ~TrackingEfficiency_processor() override = default; - - //---------------------------- - // Init - // - // This is called once before the first call to the Process method - // below. You may, for example, want to open an output file here. - // Only one thread will call this. - void Init() override; - - //---------------------------- - // Process - // - // This is called for every event. Multiple threads may call this - // simultaneously. If you write something to an output file here - // then make sure to protect it with a mutex or similar mechanism. - // Minimize what is done while locked since that directly affects - // the multi-threaded performance. - void Process(const std::shared_ptr& event) override; - - //---------------------------- - // Finish - // - // This is called once after all events have been processed. You may, - // for example, want to close an output file here. - // Only one thread will call this. - void Finish() override; + explicit TrackingEfficiency_processor(JApplication*); + ~TrackingEfficiency_processor() override = default; + + //---------------------------- + // Init + // + // This is called once before the first call to the Process method + // below. You may, for example, want to open an output file here. + // Only one thread will call this. + void Init() override; + + //---------------------------- + // Process + // + // This is called for every event. Multiple threads may call this + // simultaneously. If you write something to an output file here + // then make sure to protect it with a mutex or similar mechanism. + // Minimize what is done while locked since that directly affects + // the multi-threaded performance. + void Process(const std::shared_ptr& event) override; + + //---------------------------- + // Finish + // + // This is called once after all events have been processed. You may, + // for example, want to close an output file here. + // Only one thread will call this. + void Finish() override; private: - - TDirectory* m_dir_main; /// Main TDirectory for this plugin 'occupancy_ana' - TH1F * m_th1_prt_pz; /// MC Particles pz - TH1F * m_th1_prt_energy; /// MC Particles total E - TH1F * m_th1_prt_theta; /// MC Particles theta angle - TH1F * m_th1_prt_phi; /// MC Particles phi angle - TH2F * m_th2_prt_pxy; /// MC Particles px,py - - std::shared_ptr m_log; + TDirectory* m_dir_main; /// Main TDirectory for this plugin 'occupancy_ana' + TH1F* m_th1_prt_pz; /// MC Particles pz + TH1F* m_th1_prt_energy; /// MC Particles total E + TH1F* m_th1_prt_theta; /// MC Particles theta angle + TH1F* m_th1_prt_phi; /// MC Particles phi angle + TH2F* m_th2_prt_pxy; /// MC Particles px,py + + std::shared_ptr m_log; }; diff --git a/src/benchmarks/reconstruction/tracking_efficiency/scripts/Plot_eta.C b/src/benchmarks/reconstruction/tracking_efficiency/scripts/Plot_eta.C index c94d14c1dd..4cb936986c 100644 --- a/src/benchmarks/reconstruction/tracking_efficiency/scripts/Plot_eta.C +++ b/src/benchmarks/reconstruction/tracking_efficiency/scripts/Plot_eta.C @@ -7,131 +7,157 @@ #include #include #include -#define mpi 0.139 // 1.864 GeV/c^2 - -void Plot_eta() -{ - - //==style of the plot==== - gStyle->SetPalette(1); - gStyle->SetOptTitle(0); - gStyle->SetTitleOffset(.85,"X");gStyle->SetTitleOffset(1.0,"Y"); - gStyle->SetTitleSize(.05,"X");gStyle->SetTitleSize(.05,"Y"); - gStyle->SetLabelSize(.04,"X");gStyle->SetLabelSize(.04,"Y"); - gStyle->SetHistLineWidth(2); - gStyle->SetOptFit(1); - gStyle->SetOptStat(0); - - - TFile *f = TFile::Open("sim.edm4hep.root"); - TTree *tree = (TTree*)f->Get("events"); - - // Timer Start +#define mpi 0.139 // 1.864 GeV/c^2 + +void Plot_eta() { + + //==style of the plot==== + gStyle->SetPalette(1); + gStyle->SetOptTitle(0); + gStyle->SetTitleOffset(.85, "X"); + gStyle->SetTitleOffset(1.0, "Y"); + gStyle->SetTitleSize(.05, "X"); + gStyle->SetTitleSize(.05, "Y"); + gStyle->SetLabelSize(.04, "X"); + gStyle->SetLabelSize(.04, "Y"); + gStyle->SetHistLineWidth(2); + gStyle->SetOptFit(1); + gStyle->SetOptStat(0); + + TFile* f = TFile::Open("sim.edm4hep.root"); + TTree* tree = (TTree*)f->Get("events"); + + // Timer Start TStopwatch timer; timer.Start(); - TCanvas * c1 = new TCanvas("c1","coutput",1400,1000); - c1->SetMargin(0.10, 0.05 ,0.1,0.05); - c1->SetGridx(); - - TH1D *hits_vtx_si = new TH1D("hits_vtx_si","hits_vtx_si",200,-4.,4.); - TH1D *hits_barrel_si = new TH1D("hits_barrel_si","hits_barrel_si",200,-4.,4.); // Barr1 - TH1D *hits_barrel_mpgd_in = new TH1D("hits_barrel_mpgd_in","hits_barrel_mpgd_in",200,-4.,4.); // BMT1 - TH1D *hits_barrel_tof = new TH1D("hits_barrel_tof","hits_barrel_tof",200,-4.,4.); - TH1D *hits_disks_si = new TH1D("hits_disks_si","hits_disks_si",200,-4.,4.); - TH1D *hits_endcap_tof = new TH1D("hits_endcap_tof","hits_endcap_tof",200,-4.,4.); - TH1D *hits_barrel_mpgd_out = new TH1D("hits_barrel_mpgd_out","hits_barrel_mpgd_out",200,-4.,4.); - TH1D *hits_fwd_mpgd = new TH1D("hits_fwd_mpgd","hits_fwd_mpgd",200,-4.,4.); - TH1D *hits_bwd_mpgd = new TH1D("hits_bwd_mpgd","hits_bwd_mpgd",200,-4.,4.); - TH1D *hits_b0tracker = new TH1D("hits_b0tracker","hits_b0tracker",200,-4.,4.); - - hits_vtx_si->GetXaxis()->SetTitle("#eta"); - hits_vtx_si->GetYaxis()->SetTitle("Entries (a.u.)"); - hits_vtx_si->GetXaxis()->CenterTitle(); - hits_vtx_si->GetYaxis()->CenterTitle(); + TCanvas* c1 = new TCanvas("c1", "coutput", 1400, 1000); + c1->SetMargin(0.10, 0.05, 0.1, 0.05); + c1->SetGridx(); + + TH1D* hits_vtx_si = new TH1D("hits_vtx_si", "hits_vtx_si", 200, -4., 4.); + TH1D* hits_barrel_si = new TH1D("hits_barrel_si", "hits_barrel_si", 200, -4., 4.); // Barr1 + TH1D* hits_barrel_mpgd_in = + new TH1D("hits_barrel_mpgd_in", "hits_barrel_mpgd_in", 200, -4., 4.); // BMT1 + TH1D* hits_barrel_tof = new TH1D("hits_barrel_tof", "hits_barrel_tof", 200, -4., 4.); + TH1D* hits_disks_si = new TH1D("hits_disks_si", "hits_disks_si", 200, -4., 4.); + TH1D* hits_endcap_tof = new TH1D("hits_endcap_tof", "hits_endcap_tof", 200, -4., 4.); + TH1D* hits_barrel_mpgd_out = + new TH1D("hits_barrel_mpgd_out", "hits_barrel_mpgd_out", 200, -4., 4.); + TH1D* hits_fwd_mpgd = new TH1D("hits_fwd_mpgd", "hits_fwd_mpgd", 200, -4., 4.); + TH1D* hits_bwd_mpgd = new TH1D("hits_bwd_mpgd", "hits_bwd_mpgd", 200, -4., 4.); + TH1D* hits_b0tracker = new TH1D("hits_b0tracker", "hits_b0tracker", 200, -4., 4.); + + hits_vtx_si->GetXaxis()->SetTitle("#eta"); + hits_vtx_si->GetYaxis()->SetTitle("Entries (a.u.)"); + hits_vtx_si->GetXaxis()->CenterTitle(); + hits_vtx_si->GetYaxis()->CenterTitle(); + + TString vtx_hits_eta = "-TMath::Log(TMath::Tan((TMath::ATan2(sqrt(VertexBarrelHits.position.x*" + "VertexBarrelHits.position.x+VertexBarrelHits.position.y*VertexBarrelHits." + "position.y),VertexBarrelHits.position.z))/2))>>hits_vtx_si"; + TString Barrel_hits_eta = "-TMath::Log(TMath::Tan((TMath::ATan2(sqrt(SiBarrelHits.position.x*" + "SiBarrelHits.position.x+SiBarrelHits.position.y*SiBarrelHits.position." + "y),SiBarrelHits.position.z))/2))>>hits_barrel_si"; + TString BMM_hits_eta = "-TMath::Log(TMath::Tan((TMath::ATan2(sqrt(MPGDBarrelHits.position.x*" + "MPGDBarrelHits.position.x+MPGDBarrelHits.position.y*MPGDBarrelHits." + "position.y),MPGDBarrelHits.position.z))/2))>>hits_barrel_mpgd_in"; + TString ToF_hits_eta = "-TMath::Log(TMath::Tan((TMath::ATan2(sqrt(TOFBarrelHits.position.x*" + "TOFBarrelHits.position.x+TOFBarrelHits.position.y*TOFBarrelHits.position." + "y),TOFBarrelHits.position.z))/2))>>hits_barrel_tof"; + TString ETracker_hits_eta = + "-TMath::Log(TMath::Tan((TMath::ATan2(sqrt(TrackerEndcapHits.position.x*TrackerEndcapHits." + "position.x+TrackerEndcapHits.position.y*TrackerEndcapHits.position.y),TrackerEndcapHits." + "position.z))/2))>>hits_disks_si"; + TString ETOF_hits_eta = "-TMath::Log(TMath::Tan((TMath::ATan2(sqrt(TOFEndcapHits.position.x*" + "TOFEndcapHits.position.x+TOFEndcapHits.position.y*TOFEndcapHits." + "position.y),TOFEndcapHits.position.z))/2))>>hits_endcap_tof"; + TString OutBMM_hits_eta = + "-TMath::Log(TMath::Tan((TMath::ATan2(sqrt(OuterMPGDBarrelHits.position.x*" + "OuterMPGDBarrelHits.position.x+OuterMPGDBarrelHits.position.y*OuterMPGDBarrelHits.position." + "y),OuterMPGDBarrelHits.position.z))/2))>>hits_barrel_mpgd_out"; + TString FwdMM_hits_eta = + "-TMath::Log(TMath::Tan((TMath::ATan2(sqrt(ForwardMPGDEndcapHits.position.x*" + "ForwardMPGDEndcapHits.position.x+ForwardMPGDEndcapHits.position.y*ForwardMPGDEndcapHits." + "position.y),ForwardMPGDEndcapHits.position.z))/2))>>hits_fwd_mpgd"; + TString BwdMM_hits_eta = + "-TMath::Log(TMath::Tan((TMath::ATan2(sqrt(BackwardMPGDEndcapHits.position.x*" + "BackwardMPGDEndcapHits.position.x+BackwardMPGDEndcapHits.position.y*BackwardMPGDEndcapHits." + "position.y),BackwardMPGDEndcapHits.position.z))/2))>>hits_bwd_mpgd"; + TString B0_hits_eta = "-TMath::Log(TMath::Tan((TMath::ATan2(sqrt(B0TrackerHits.position.x*" + "B0TrackerHits.position.x+B0TrackerHits.position.y*B0TrackerHits.position." + "y),B0TrackerHits.position.z))/2))>>hits_b0tracker"; + + tree->Draw(vtx_hits_eta.Data(), "VertexBarrelHits.position.y>0", "goff"); // Vtx layers + tree->Draw(Barrel_hits_eta.Data(), "SiBarrelHits.position.y>0 ", "goff"); // Barrel Si layers + tree->Draw(BMM_hits_eta.Data(), "MPGDBarrelHits.position.y>0 ", "goff"); // MPGD Barrel + tree->Draw(ToF_hits_eta.Data(), "TOFBarrelHits.position.y>0", "goff"); // TOF Hits + tree->Draw(ETracker_hits_eta.Data(), "TrackerEndcapHits.position.y>0", "goff"); // Tracker Endcap + tree->Draw(ETOF_hits_eta.Data(), "TOFEndcapHits.position.y>0", "goff"); // TOF Endcap + tree->Draw(OutBMM_hits_eta.Data(), "OuterMPGDBarrelHits.position.y>0", + "goff"); // Outer Barrel MPGD + tree->Draw(FwdMM_hits_eta.Data(), "ForwardMPGDEndcapHits.position.y>0", "goff"); // Forward MPGD + tree->Draw(BwdMM_hits_eta.Data(), "BackwardMPGDEndcapHits.position.y>0", "goff"); // Forward MPGD + tree->Draw(B0_hits_eta.Data(), "B0TrackerHits.position.y>0", "goff"); // B0 Tracker - TString vtx_hits_eta = "-TMath::Log(TMath::Tan((TMath::ATan2(sqrt(VertexBarrelHits.position.x*VertexBarrelHits.position.x+VertexBarrelHits.position.y*VertexBarrelHits.position.y),VertexBarrelHits.position.z))/2))>>hits_vtx_si"; - TString Barrel_hits_eta = "-TMath::Log(TMath::Tan((TMath::ATan2(sqrt(SiBarrelHits.position.x*SiBarrelHits.position.x+SiBarrelHits.position.y*SiBarrelHits.position.y),SiBarrelHits.position.z))/2))>>hits_barrel_si"; - TString BMM_hits_eta = "-TMath::Log(TMath::Tan((TMath::ATan2(sqrt(MPGDBarrelHits.position.x*MPGDBarrelHits.position.x+MPGDBarrelHits.position.y*MPGDBarrelHits.position.y),MPGDBarrelHits.position.z))/2))>>hits_barrel_mpgd_in"; - TString ToF_hits_eta = "-TMath::Log(TMath::Tan((TMath::ATan2(sqrt(TOFBarrelHits.position.x*TOFBarrelHits.position.x+TOFBarrelHits.position.y*TOFBarrelHits.position.y),TOFBarrelHits.position.z))/2))>>hits_barrel_tof"; - TString ETracker_hits_eta = "-TMath::Log(TMath::Tan((TMath::ATan2(sqrt(TrackerEndcapHits.position.x*TrackerEndcapHits.position.x+TrackerEndcapHits.position.y*TrackerEndcapHits.position.y),TrackerEndcapHits.position.z))/2))>>hits_disks_si"; - TString ETOF_hits_eta = "-TMath::Log(TMath::Tan((TMath::ATan2(sqrt(TOFEndcapHits.position.x*TOFEndcapHits.position.x+TOFEndcapHits.position.y*TOFEndcapHits.position.y),TOFEndcapHits.position.z))/2))>>hits_endcap_tof"; - TString OutBMM_hits_eta = "-TMath::Log(TMath::Tan((TMath::ATan2(sqrt(OuterMPGDBarrelHits.position.x*OuterMPGDBarrelHits.position.x+OuterMPGDBarrelHits.position.y*OuterMPGDBarrelHits.position.y),OuterMPGDBarrelHits.position.z))/2))>>hits_barrel_mpgd_out"; - TString FwdMM_hits_eta = "-TMath::Log(TMath::Tan((TMath::ATan2(sqrt(ForwardMPGDEndcapHits.position.x*ForwardMPGDEndcapHits.position.x+ForwardMPGDEndcapHits.position.y*ForwardMPGDEndcapHits.position.y),ForwardMPGDEndcapHits.position.z))/2))>>hits_fwd_mpgd"; - TString BwdMM_hits_eta = "-TMath::Log(TMath::Tan((TMath::ATan2(sqrt(BackwardMPGDEndcapHits.position.x*BackwardMPGDEndcapHits.position.x+BackwardMPGDEndcapHits.position.y*BackwardMPGDEndcapHits.position.y),BackwardMPGDEndcapHits.position.z))/2))>>hits_bwd_mpgd"; - TString B0_hits_eta = "-TMath::Log(TMath::Tan((TMath::ATan2(sqrt(B0TrackerHits.position.x*B0TrackerHits.position.x+B0TrackerHits.position.y*B0TrackerHits.position.y),B0TrackerHits.position.z))/2))>>hits_b0tracker"; - - tree->Draw(vtx_hits_eta.Data(),"VertexBarrelHits.position.y>0","goff"); // Vtx layers - tree->Draw(Barrel_hits_eta.Data(),"SiBarrelHits.position.y>0 ","goff"); // Barrel Si layers - tree->Draw(BMM_hits_eta.Data(),"MPGDBarrelHits.position.y>0 ","goff"); // MPGD Barrel - tree->Draw(ToF_hits_eta.Data(),"TOFBarrelHits.position.y>0","goff"); // TOF Hits - tree->Draw(ETracker_hits_eta.Data(),"TrackerEndcapHits.position.y>0","goff"); // Tracker Endcap - tree->Draw(ETOF_hits_eta.Data(),"TOFEndcapHits.position.y>0","goff"); // TOF Endcap - tree->Draw(OutBMM_hits_eta.Data(),"OuterMPGDBarrelHits.position.y>0","goff"); // Outer Barrel MPGD - tree->Draw(FwdMM_hits_eta.Data(),"ForwardMPGDEndcapHits.position.y>0","goff"); // Forward MPGD - tree->Draw(BwdMM_hits_eta.Data(),"BackwardMPGDEndcapHits.position.y>0","goff"); // Forward MPGD - tree->Draw(B0_hits_eta.Data(),"B0TrackerHits.position.y>0","goff"); // B0 Tracker - - c1->cd(); - c1->SetLogy(); - hits_vtx_si->Scale(1./hits_vtx_si->Integral()); - hits_barrel_si->Scale(1./hits_barrel_si->Integral()); - hits_barrel_mpgd_in->Scale(1./hits_barrel_mpgd_in->Integral()); - hits_barrel_tof->Scale(1./hits_barrel_tof->Integral()); - hits_disks_si->Scale(1./hits_disks_si->Integral()); - hits_endcap_tof->Scale(1./hits_endcap_tof->Integral()); - hits_barrel_mpgd_out->Scale(1./hits_barrel_mpgd_out->Integral()); - hits_fwd_mpgd->Scale(1./hits_fwd_mpgd->Integral()); - hits_bwd_mpgd->Scale(1./hits_bwd_mpgd->Integral()); - hits_b0tracker->Scale(1./hits_b0tracker->Integral()); - hits_vtx_si->SetLineColor(kBlue); - hits_barrel_si->SetLineColor(kMagenta); - hits_barrel_mpgd_in->SetLineColor(kRed); - hits_barrel_tof->SetLineColor(kBlack); - hits_disks_si->SetLineColor(kGreen); - hits_endcap_tof->SetLineColor(kCyan); - hits_barrel_mpgd_out->SetLineColor(kOrange); - hits_fwd_mpgd->SetLineColor(kAzure); - hits_bwd_mpgd->SetLineColor(kTeal); - hits_b0tracker->SetLineColor(kViolet); - - - hits_vtx_si->SetMaximum(0.2); - hits_vtx_si->GetXaxis()->SetRangeUser(-4.0,4.0); - hits_vtx_si->Draw("hist"); - hits_barrel_si->Draw("hist-same"); - hits_barrel_mpgd_in->Draw("hist-same"); - hits_barrel_tof->Draw("hist-same"); - hits_disks_si->Draw("hist-same"); - hits_endcap_tof->Draw("hist-same"); - hits_barrel_mpgd_out->Draw("hist-same"); - hits_fwd_mpgd->Draw("hist-same"); - hits_bwd_mpgd->Draw("hist-same"); - hits_b0tracker->Draw("hist-same"); - - TLegend *l1= new TLegend(0.11,0.75,0.70,0.94); + c1->cd(); + c1->SetLogy(); + hits_vtx_si->Scale(1. / hits_vtx_si->Integral()); + hits_barrel_si->Scale(1. / hits_barrel_si->Integral()); + hits_barrel_mpgd_in->Scale(1. / hits_barrel_mpgd_in->Integral()); + hits_barrel_tof->Scale(1. / hits_barrel_tof->Integral()); + hits_disks_si->Scale(1. / hits_disks_si->Integral()); + hits_endcap_tof->Scale(1. / hits_endcap_tof->Integral()); + hits_barrel_mpgd_out->Scale(1. / hits_barrel_mpgd_out->Integral()); + hits_fwd_mpgd->Scale(1. / hits_fwd_mpgd->Integral()); + hits_bwd_mpgd->Scale(1. / hits_bwd_mpgd->Integral()); + hits_b0tracker->Scale(1. / hits_b0tracker->Integral()); + hits_vtx_si->SetLineColor(kBlue); + hits_barrel_si->SetLineColor(kMagenta); + hits_barrel_mpgd_in->SetLineColor(kRed); + hits_barrel_tof->SetLineColor(kBlack); + hits_disks_si->SetLineColor(kGreen); + hits_endcap_tof->SetLineColor(kCyan); + hits_barrel_mpgd_out->SetLineColor(kOrange); + hits_fwd_mpgd->SetLineColor(kAzure); + hits_bwd_mpgd->SetLineColor(kTeal); + hits_b0tracker->SetLineColor(kViolet); + + hits_vtx_si->SetMaximum(0.2); + hits_vtx_si->GetXaxis()->SetRangeUser(-4.0, 4.0); + hits_vtx_si->Draw("hist"); + hits_barrel_si->Draw("hist-same"); + hits_barrel_mpgd_in->Draw("hist-same"); + hits_barrel_tof->Draw("hist-same"); + hits_disks_si->Draw("hist-same"); + hits_endcap_tof->Draw("hist-same"); + hits_barrel_mpgd_out->Draw("hist-same"); + hits_fwd_mpgd->Draw("hist-same"); + hits_bwd_mpgd->Draw("hist-same"); + hits_b0tracker->Draw("hist-same"); + + TLegend* l1 = new TLegend(0.11, 0.75, 0.70, 0.94); l1->SetNColumns(2); l1->SetTextSize(0.025); l1->SetBorderSize(0); - l1->AddEntry(hits_vtx_si,"VertexBarrelHits"); - l1->AddEntry(hits_barrel_si,"SiBarrelHits"); - l1->AddEntry(hits_barrel_mpgd_in,"MPGDBarrelHits"); - l1->AddEntry(hits_barrel_tof,"TOFBarrelHits"); - l1->AddEntry(hits_disks_si,"TrackerEndcapHits"); - l1->AddEntry(hits_endcap_tof,"TOFEndcapHits"); - l1->AddEntry(hits_barrel_mpgd_out,"OuterMPGDBarrelHits"); - l1->AddEntry(hits_fwd_mpgd,"ForwardMPGDEndcapHits"); - l1->AddEntry(hits_bwd_mpgd,"BackwardMPGDEndcapHits"); - l1->AddEntry(hits_b0tracker,"B0TrackerHits"); + l1->AddEntry(hits_vtx_si, "VertexBarrelHits"); + l1->AddEntry(hits_barrel_si, "SiBarrelHits"); + l1->AddEntry(hits_barrel_mpgd_in, "MPGDBarrelHits"); + l1->AddEntry(hits_barrel_tof, "TOFBarrelHits"); + l1->AddEntry(hits_disks_si, "TrackerEndcapHits"); + l1->AddEntry(hits_endcap_tof, "TOFEndcapHits"); + l1->AddEntry(hits_barrel_mpgd_out, "OuterMPGDBarrelHits"); + l1->AddEntry(hits_fwd_mpgd, "ForwardMPGDEndcapHits"); + l1->AddEntry(hits_bwd_mpgd, "BackwardMPGDEndcapHits"); + l1->AddEntry(hits_b0tracker, "B0TrackerHits"); l1->Draw("same"); c1->cd(); l1->Draw(); c1->SaveAs("eta_DD4HEP.png"); - // Timer Stop + // Timer Stop timer.Stop(); Double_t realtime = timer.RealTime(); - Double_t cputime = timer.CpuTime(); - printf("RealTime=%f seconds, CpuTime=%f seconds\n",realtime,cputime); - + Double_t cputime = timer.CpuTime(); + printf("RealTime=%f seconds, CpuTime=%f seconds\n", realtime, cputime); } diff --git a/src/benchmarks/reconstruction/tracking_efficiency/scripts/draw_Performance.C b/src/benchmarks/reconstruction/tracking_efficiency/scripts/draw_Performance.C index 1606569efa..78ecad12a8 100644 --- a/src/benchmarks/reconstruction/tracking_efficiency/scripts/draw_Performance.C +++ b/src/benchmarks/reconstruction/tracking_efficiency/scripts/draw_Performance.C @@ -8,152 +8,159 @@ #include #include -void draw_Performance(Int_t nevent=-1) -{ - -//==========Style of the plot============ - gStyle->SetPalette(1); - gStyle->SetOptTitle(1); - gStyle->SetTitleOffset(.85,"X");gStyle->SetTitleOffset(.85,"Y"); - gStyle->SetTitleSize(.04,"X");gStyle->SetTitleSize(.04,"Y"); - gStyle->SetLabelSize(.04,"X");gStyle->SetLabelSize(.04,"Y"); - gStyle->SetHistLineWidth(2); - gStyle->SetOptFit(1); - gStyle->SetOptStat(0); - -//=======Reading the root file DD4HEP=========== - TFile* file = new TFile("tracking_test_gun.edm4eic.root"); // Tree with tracks and hits - // Create the tree reader and its data containers - TTreeReader myReader("events", file); // name of tree and file - - TTreeReaderArray charge(myReader, "MCParticles.charge"); - TTreeReaderArray vx_mc(myReader, "MCParticles.vertex.x"); - TTreeReaderArray vy_mc(myReader, "MCParticles.vertex.y"); - TTreeReaderArray vz_mc(myReader, "MCParticles.vertex.z"); - TTreeReaderArray px_mc(myReader, "MCParticles.momentum.x"); - TTreeReaderArray py_mc(myReader, "MCParticles.momentum.y"); - TTreeReaderArray pz_mc(myReader, "MCParticles.momentum.z"); - TTreeReaderArray status(myReader, "MCParticles.generatorStatus"); - TTreeReaderArray pdg(myReader, "MCParticles.PDG"); - - TTreeReaderArray px_rec(myReader, "ReconstructedChargedParticles.momentum.x"); - TTreeReaderArray py_rec(myReader, "ReconstructedChargedParticles.momentum.y"); - TTreeReaderArray pz_rec(myReader, "ReconstructedChargedParticles.momentum.z"); - - const int ngraph = 7; - TCanvas * c[ngraph]; - for (int i =0; iSetMargin(0.09, 0.1 ,0.1,0.06); - } - - // X-Y Hits - - Int_t nbins = 200; - Double_t x= 4.0; - TH2D *hetavspmc = new TH2D("hetavspmc","hetavspmc",400,0.,40.,nbins,-x,x); - TH2D *hetavsprec = new TH2D("hetavsprec","hetavsprec",400,0.,40.,nbins,-x,x); - TH2D *heff_pnum = new TH2D("heff_pnum","heff_p",400,0.,40.,nbins,-x,x); - TH2D *heff_pden = new TH2D("heff_pden","heff_p",400,0.,40.,nbins,-x,x); - - TH2D *hetavsptmc = new TH2D("hetavsptmc","hetavsptmc",400,0.,40.,nbins,-x,x); - TH2D *hetavsptrec = new TH2D("hetavsptrec","hetavsptrec",400,0.,40.,nbins,-x,x); - TH2D *heff_ptnum = new TH2D("heff_ptnum","heff_p",400,0.,40.,nbins,-x,x); - TH2D *heff_ptden = new TH2D("heff_ptden","heff_p",400,0.,40.,nbins,-x,x); - - TH1D *hpresol = new TH1D("hpresol","hpresol",200,-0.5,0.5); - - hetavspmc->GetXaxis()->SetTitle("p_{mc} (GeV/c)"); - hetavspmc->GetYaxis()->SetTitle("#eta_{mc}"); - hetavspmc->GetXaxis()->CenterTitle(); - hetavspmc->GetYaxis()->CenterTitle(); - - hetavsptmc->GetXaxis()->SetTitle("pt_{mc} (GeV/c)"); - hetavsptmc->GetYaxis()->SetTitle("#eta_{mc}"); - hetavsptmc->GetXaxis()->CenterTitle(); - hetavsptmc->GetYaxis()->CenterTitle(); - - hetavsprec->GetXaxis()->SetTitle("p_{rec} (GeV/c)"); - hetavsprec->GetYaxis()->SetTitle("#eta_{rec}"); - hetavsprec->GetXaxis()->CenterTitle(); - hetavsprec->GetYaxis()->CenterTitle(); - - hetavsptrec->GetXaxis()->SetTitle("pt_{rec} (GeV/c)"); - hetavsptrec->GetYaxis()->SetTitle("#eta_{rec}"); - hetavsptrec->GetXaxis()->CenterTitle(); - hetavsptrec->GetYaxis()->CenterTitle(); - - hpresol->GetXaxis()->SetTitle("dp/p"); - hpresol->GetYaxis()->SetTitle("Entries (a.u.)"); - hpresol->GetXaxis()->CenterTitle(); - hpresol->GetYaxis()->CenterTitle(); - - -////////////////////////////////////////////////////////////////////// - int count = 0; - while (myReader.Next()) - { - if (nevent>0 && count>nevent) continue; - // cout<<"=====Event No. "<Fill(pmc,etamc); - hetavsptmc->Fill(ptmc,etamc); - heff_pden->Fill(pmc,etamc); - heff_ptden->Fill(ptmc,etamc); - if (px_rec.GetSize()==1){ - Double_t prec = sqrt(px_rec[iParticle]*px_rec[iParticle]+py_rec[iParticle]*py_rec[iParticle]+pz_rec[iParticle]*pz_rec[iParticle]); - Double_t ptrec = sqrt(px_rec[iParticle]*px_rec[iParticle]+py_rec[iParticle]*py_rec[iParticle]); - Double_t etarec = -1.0*TMath::Log(TMath::Tan((TMath::ACos(pz_rec[iParticle]/prec))/2)); - hetavsprec->Fill(prec,etarec); - hetavsptrec->Fill(ptrec,etarec); - hpresol->Fill((prec-pmc)/pmc); - heff_pnum->Fill(pmc,etamc); - heff_ptnum->Fill(ptmc,etamc); - } - } - } +void draw_Performance(Int_t nevent = -1) { + + //==========Style of the plot============ + gStyle->SetPalette(1); + gStyle->SetOptTitle(1); + gStyle->SetTitleOffset(.85, "X"); + gStyle->SetTitleOffset(.85, "Y"); + gStyle->SetTitleSize(.04, "X"); + gStyle->SetTitleSize(.04, "Y"); + gStyle->SetLabelSize(.04, "X"); + gStyle->SetLabelSize(.04, "Y"); + gStyle->SetHistLineWidth(2); + gStyle->SetOptFit(1); + gStyle->SetOptStat(0); + + //=======Reading the root file DD4HEP=========== + TFile* file = new TFile("tracking_test_gun.edm4eic.root"); // Tree with tracks and hits + // Create the tree reader and its data containers + TTreeReader myReader("events", file); // name of tree and file + + TTreeReaderArray charge(myReader, "MCParticles.charge"); + TTreeReaderArray vx_mc(myReader, "MCParticles.vertex.x"); + TTreeReaderArray vy_mc(myReader, "MCParticles.vertex.y"); + TTreeReaderArray vz_mc(myReader, "MCParticles.vertex.z"); + TTreeReaderArray px_mc(myReader, "MCParticles.momentum.x"); + TTreeReaderArray py_mc(myReader, "MCParticles.momentum.y"); + TTreeReaderArray pz_mc(myReader, "MCParticles.momentum.z"); + TTreeReaderArray status(myReader, "MCParticles.generatorStatus"); + TTreeReaderArray pdg(myReader, "MCParticles.PDG"); + + TTreeReaderArray px_rec(myReader, "ReconstructedChargedParticles.momentum.x"); + TTreeReaderArray py_rec(myReader, "ReconstructedChargedParticles.momentum.y"); + TTreeReaderArray pz_rec(myReader, "ReconstructedChargedParticles.momentum.z"); + + const int ngraph = 7; + TCanvas* c[ngraph]; + for (int i = 0; i < ngraph; ++i) { + c[i] = new TCanvas(Form("c%d", i), Form("c%d", i), 1200, 1000); + c[i]->SetMargin(0.09, 0.1, 0.1, 0.06); + } - count++; + // X-Y Hits + + Int_t nbins = 200; + Double_t x = 4.0; + TH2D* hetavspmc = new TH2D("hetavspmc", "hetavspmc", 400, 0., 40., nbins, -x, x); + TH2D* hetavsprec = new TH2D("hetavsprec", "hetavsprec", 400, 0., 40., nbins, -x, x); + TH2D* heff_pnum = new TH2D("heff_pnum", "heff_p", 400, 0., 40., nbins, -x, x); + TH2D* heff_pden = new TH2D("heff_pden", "heff_p", 400, 0., 40., nbins, -x, x); + + TH2D* hetavsptmc = new TH2D("hetavsptmc", "hetavsptmc", 400, 0., 40., nbins, -x, x); + TH2D* hetavsptrec = new TH2D("hetavsptrec", "hetavsptrec", 400, 0., 40., nbins, -x, x); + TH2D* heff_ptnum = new TH2D("heff_ptnum", "heff_p", 400, 0., 40., nbins, -x, x); + TH2D* heff_ptden = new TH2D("heff_ptden", "heff_p", 400, 0., 40., nbins, -x, x); + + TH1D* hpresol = new TH1D("hpresol", "hpresol", 200, -0.5, 0.5); + + hetavspmc->GetXaxis()->SetTitle("p_{mc} (GeV/c)"); + hetavspmc->GetYaxis()->SetTitle("#eta_{mc}"); + hetavspmc->GetXaxis()->CenterTitle(); + hetavspmc->GetYaxis()->CenterTitle(); + + hetavsptmc->GetXaxis()->SetTitle("pt_{mc} (GeV/c)"); + hetavsptmc->GetYaxis()->SetTitle("#eta_{mc}"); + hetavsptmc->GetXaxis()->CenterTitle(); + hetavsptmc->GetYaxis()->CenterTitle(); + + hetavsprec->GetXaxis()->SetTitle("p_{rec} (GeV/c)"); + hetavsprec->GetYaxis()->SetTitle("#eta_{rec}"); + hetavsprec->GetXaxis()->CenterTitle(); + hetavsprec->GetYaxis()->CenterTitle(); + + hetavsptrec->GetXaxis()->SetTitle("pt_{rec} (GeV/c)"); + hetavsptrec->GetYaxis()->SetTitle("#eta_{rec}"); + hetavsptrec->GetXaxis()->CenterTitle(); + hetavsptrec->GetYaxis()->CenterTitle(); + + hpresol->GetXaxis()->SetTitle("dp/p"); + hpresol->GetYaxis()->SetTitle("Entries (a.u.)"); + hpresol->GetXaxis()->CenterTitle(); + hpresol->GetYaxis()->CenterTitle(); + + ////////////////////////////////////////////////////////////////////// + int count = 0; + while (myReader.Next()) { + if (nevent > 0 && count > nevent) + continue; + // cout<<"=====Event No. "<Fill(pmc, etamc); + hetavsptmc->Fill(ptmc, etamc); + heff_pden->Fill(pmc, etamc); + heff_ptden->Fill(ptmc, etamc); + if (px_rec.GetSize() == 1) { + Double_t prec = + sqrt(px_rec[iParticle] * px_rec[iParticle] + py_rec[iParticle] * py_rec[iParticle] + + pz_rec[iParticle] * pz_rec[iParticle]); + Double_t ptrec = + sqrt(px_rec[iParticle] * px_rec[iParticle] + py_rec[iParticle] * py_rec[iParticle]); + Double_t etarec = + -1.0 * TMath::Log(TMath::Tan((TMath::ACos(pz_rec[iParticle] / prec)) / 2)); + hetavsprec->Fill(prec, etarec); + hetavsptrec->Fill(ptrec, etarec); + hpresol->Fill((prec - pmc) / pmc); + heff_pnum->Fill(pmc, etamc); + heff_ptnum->Fill(ptmc, etamc); + } + } + } + count++; } - heff_pnum->Divide(heff_pden); - heff_ptnum->Divide(heff_ptden); - heff_pnum->GetYaxis()->SetTitle("Acceptance"); - heff_pnum->GetXaxis()->SetTitle("p_mc"); - heff_pnum->GetZaxis()->SetRangeUser(0.,1.1); - - heff_ptnum->GetYaxis()->SetTitle("Acceptance"); - heff_ptnum->GetXaxis()->SetTitle("pt_mc"); - heff_ptnum->GetZaxis()->SetRangeUser(0.,1.1); - - c[0]->cd(); - hetavspmc->Draw("colz"); - c[0]->SaveAs("eta_mcvspmc.png"); - c[1]->cd(); - hetavsprec->Draw("colz"); - c[1]->SaveAs("eta_mcvsprec.png"); - c[2]->cd(); - hetavsptmc->Draw("colz"); - c[2]->SaveAs("eta_mcvsptmc.png"); - c[3]->cd(); - hetavsptrec->Draw("colz"); - c[3]->SaveAs("eta_mcvsptrec.png"); - c[4]->cd(); - hpresol->Draw("hist"); - c[4]->SaveAs("ptresol.png"); - c[5]->cd(); - heff_pnum->Draw("colz"); - c[5]->SaveAs("effvsp_2D.png"); - c[6]->cd(); - heff_ptnum->Draw("colz"); - c[6]->SaveAs("effvspt_2D.png"); - + heff_pnum->Divide(heff_pden); + heff_ptnum->Divide(heff_ptden); + heff_pnum->GetYaxis()->SetTitle("Acceptance"); + heff_pnum->GetXaxis()->SetTitle("p_mc"); + heff_pnum->GetZaxis()->SetRangeUser(0., 1.1); + + heff_ptnum->GetYaxis()->SetTitle("Acceptance"); + heff_ptnum->GetXaxis()->SetTitle("pt_mc"); + heff_ptnum->GetZaxis()->SetRangeUser(0., 1.1); + + c[0]->cd(); + hetavspmc->Draw("colz"); + c[0]->SaveAs("eta_mcvspmc.png"); + c[1]->cd(); + hetavsprec->Draw("colz"); + c[1]->SaveAs("eta_mcvsprec.png"); + c[2]->cd(); + hetavsptmc->Draw("colz"); + c[2]->SaveAs("eta_mcvsptmc.png"); + c[3]->cd(); + hetavsptrec->Draw("colz"); + c[3]->SaveAs("eta_mcvsptrec.png"); + c[4]->cd(); + hpresol->Draw("hist"); + c[4]->SaveAs("ptresol.png"); + c[5]->cd(); + heff_pnum->Draw("colz"); + c[5]->SaveAs("effvsp_2D.png"); + c[6]->cd(); + heff_ptnum->Draw("colz"); + c[6]->SaveAs("effvspt_2D.png"); } diff --git a/src/benchmarks/reconstruction/tracking_efficiency/scripts/draw_hits.C b/src/benchmarks/reconstruction/tracking_efficiency/scripts/draw_hits.C index e5628cc09b..f2dce2abbb 100644 --- a/src/benchmarks/reconstruction/tracking_efficiency/scripts/draw_hits.C +++ b/src/benchmarks/reconstruction/tracking_efficiency/scripts/draw_hits.C @@ -8,301 +8,372 @@ #include #include -void draw_hits() -{ - -//==========Style of the plot============ - gStyle->SetPalette(1); - gStyle->SetOptTitle(1); - gStyle->SetTitleOffset(.85,"X");gStyle->SetTitleOffset(.85,"Y"); - gStyle->SetTitleSize(.04,"X");gStyle->SetTitleSize(.04,"Y"); - gStyle->SetLabelSize(.04,"X");gStyle->SetLabelSize(.04,"Y"); - gStyle->SetHistLineWidth(2); - gStyle->SetOptFit(1); - gStyle->SetOptStat(0); - -//=======Reading the root file DD4HEP=========== - TFile *f = TFile::Open("sim.edm4hep.root"); - TTree *sim = (TTree*)f->Get("events"); - - // Timer Start +void draw_hits() { + + //==========Style of the plot============ + gStyle->SetPalette(1); + gStyle->SetOptTitle(1); + gStyle->SetTitleOffset(.85, "X"); + gStyle->SetTitleOffset(.85, "Y"); + gStyle->SetTitleSize(.04, "X"); + gStyle->SetTitleSize(.04, "Y"); + gStyle->SetLabelSize(.04, "X"); + gStyle->SetLabelSize(.04, "Y"); + gStyle->SetHistLineWidth(2); + gStyle->SetOptFit(1); + gStyle->SetOptStat(0); + + //=======Reading the root file DD4HEP=========== + TFile* f = TFile::Open("sim.edm4hep.root"); + TTree* sim = (TTree*)f->Get("events"); + + // Timer Start TStopwatch timer; timer.Start(); - TCanvas *c1 = new TCanvas("c1","c1",1200,1000); - c1->SetMargin(0.09, 0.03 ,0.1,0.06); + TCanvas* c1 = new TCanvas("c1", "c1", 1200, 1000); + c1->SetMargin(0.09, 0.03, 0.1, 0.06); - // X-Y Hits + // X-Y Hits Int_t nbins = 320; - Double_t x= 100., y = 100.; - TH2D *hitsxy_vtx_si = new TH2D("hitsxy_vtx_si","hitsxy_vtx_si",nbins,-x,x,nbins,-y,y); - TH2D *hitsxy_barrel_si = new TH2D("hitsxy_barrel_si","hitsxy_barrel_si",nbins,-x,x,nbins,-y,y); - TH2D *hitsxy_barrel_mm_in = new TH2D("hitsxy_barrel_mm_in","hitsxy_barrel_mm_in",nbins,-x,x,nbins,-y,y); - TH2D *hitsxy_barrel_tof = new TH2D("hitsxy_barrel_tof","hitsxy_barrel_tof",nbins,-x,x,nbins,-y,y); - TH2D *hitsxy_barrel_mm_out = new TH2D("hitsxy_barrel_mm_out","hitsxy_barrel_mm_out",nbins,-x,x,nbins,-y,y); - - TString si_vtx_hitsXY ="VertexBarrelHits.position.y*0.1:VertexBarrelHits.position.x*0.1>>hitsxy_vtx_si"; - TString si_barrel_hitsXY ="SiBarrelHits.position.y*0.1:SiBarrelHits.position.x*0.1>>hitsxy_barrel_si"; - TString barrel_mpgd_in_hitsXY ="MPGDBarrelHits.position.y*0.1:MPGDBarrelHits.position.x*0.1>>hitsxy_barrel_mm_in"; - TString tof_barrel_hitsXY ="TOFBarrelHits.position.y*0.1:TOFBarrelHits.position.x*0.1>>hitsxy_barrel_tof"; - TString barrel_mpgd_out_hitsXY ="OuterMPGDBarrelHits.position.y*0.1:OuterMPGDBarrelHits.position.x*0.1>>hitsxy_barrel_mm_out"; - - sim->Draw(si_vtx_hitsXY.Data(),"",""); // Multiply by 0.1 for cm - sim->Draw(si_barrel_hitsXY.Data(),"",""); - sim->Draw(barrel_mpgd_in_hitsXY.Data(),"",""); - sim->Draw(tof_barrel_hitsXY.Data(),"",""); - sim->Draw(barrel_mpgd_out_hitsXY.Data(),"",""); - - hitsxy_vtx_si->SetMarkerStyle(31); - hitsxy_vtx_si->SetTitle("Hit Points (XY)"); - hitsxy_vtx_si->SetMarkerColor(kBlack); - hitsxy_vtx_si->SetMarkerSize(0.1); - hitsxy_vtx_si->SetLineColor(kBlack); - hitsxy_vtx_si->GetXaxis()->SetTitle("X [cm]"); - hitsxy_vtx_si->GetYaxis()->SetTitle("Y [cm]"); - hitsxy_vtx_si->GetXaxis()->CenterTitle(); - hitsxy_vtx_si->GetYaxis()->CenterTitle(); + Double_t x = 100., y = 100.; + TH2D* hitsxy_vtx_si = new TH2D("hitsxy_vtx_si", "hitsxy_vtx_si", nbins, -x, x, nbins, -y, y); + TH2D* hitsxy_barrel_si = + new TH2D("hitsxy_barrel_si", "hitsxy_barrel_si", nbins, -x, x, nbins, -y, y); + TH2D* hitsxy_barrel_mm_in = + new TH2D("hitsxy_barrel_mm_in", "hitsxy_barrel_mm_in", nbins, -x, x, nbins, -y, y); + TH2D* hitsxy_barrel_tof = + new TH2D("hitsxy_barrel_tof", "hitsxy_barrel_tof", nbins, -x, x, nbins, -y, y); + TH2D* hitsxy_barrel_mm_out = + new TH2D("hitsxy_barrel_mm_out", "hitsxy_barrel_mm_out", nbins, -x, x, nbins, -y, y); + + TString si_vtx_hitsXY = + "VertexBarrelHits.position.y*0.1:VertexBarrelHits.position.x*0.1>>hitsxy_vtx_si"; + TString si_barrel_hitsXY = + "SiBarrelHits.position.y*0.1:SiBarrelHits.position.x*0.1>>hitsxy_barrel_si"; + TString barrel_mpgd_in_hitsXY = + "MPGDBarrelHits.position.y*0.1:MPGDBarrelHits.position.x*0.1>>hitsxy_barrel_mm_in"; + TString tof_barrel_hitsXY = + "TOFBarrelHits.position.y*0.1:TOFBarrelHits.position.x*0.1>>hitsxy_barrel_tof"; + TString barrel_mpgd_out_hitsXY = + "OuterMPGDBarrelHits.position.y*0.1:OuterMPGDBarrelHits.position.x*0.1>>hitsxy_barrel_mm_out"; + + sim->Draw(si_vtx_hitsXY.Data(), "", ""); // Multiply by 0.1 for cm + sim->Draw(si_barrel_hitsXY.Data(), "", ""); + sim->Draw(barrel_mpgd_in_hitsXY.Data(), "", ""); + sim->Draw(tof_barrel_hitsXY.Data(), "", ""); + sim->Draw(barrel_mpgd_out_hitsXY.Data(), "", ""); + + hitsxy_vtx_si->SetMarkerStyle(31); + hitsxy_vtx_si->SetTitle("Hit Points (XY)"); + hitsxy_vtx_si->SetMarkerColor(kBlack); + hitsxy_vtx_si->SetMarkerSize(0.1); + hitsxy_vtx_si->SetLineColor(kBlack); + hitsxy_vtx_si->GetXaxis()->SetTitle("X [cm]"); + hitsxy_vtx_si->GetYaxis()->SetTitle("Y [cm]"); + hitsxy_vtx_si->GetXaxis()->CenterTitle(); + hitsxy_vtx_si->GetYaxis()->CenterTitle(); hitsxy_barrel_si->SetMarkerStyle(20); - hitsxy_barrel_si->SetMarkerSize(0.1); - hitsxy_barrel_si->SetMarkerColor(kMagenta); - hitsxy_barrel_si->SetLineColor(kMagenta); + hitsxy_barrel_si->SetMarkerSize(0.1); + hitsxy_barrel_si->SetMarkerColor(kMagenta); + hitsxy_barrel_si->SetLineColor(kMagenta); hitsxy_barrel_mm_in->SetMarkerStyle(20); - hitsxy_barrel_mm_in->SetMarkerSize(0.1); - hitsxy_barrel_mm_in->SetMarkerColor(kBlue); - hitsxy_barrel_mm_in->SetLineColor(kBlue); + hitsxy_barrel_mm_in->SetMarkerSize(0.1); + hitsxy_barrel_mm_in->SetMarkerColor(kBlue); + hitsxy_barrel_mm_in->SetLineColor(kBlue); hitsxy_barrel_tof->SetMarkerStyle(20); - hitsxy_barrel_tof->SetMarkerSize(0.1); - hitsxy_barrel_tof->SetMarkerColor(kGreen); - hitsxy_barrel_tof->SetLineColor(kGreen);hitsxy_barrel_mm_out->SetMarkerStyle(20); - hitsxy_barrel_mm_out->SetMarkerSize(0.1); - hitsxy_barrel_mm_out->SetMarkerColor(kBlue-7); - hitsxy_barrel_mm_out->SetLineColor(kBlue-7); - c1->cd(); + hitsxy_barrel_tof->SetMarkerSize(0.1); + hitsxy_barrel_tof->SetMarkerColor(kGreen); + hitsxy_barrel_tof->SetLineColor(kGreen); + hitsxy_barrel_mm_out->SetMarkerStyle(20); + hitsxy_barrel_mm_out->SetMarkerSize(0.1); + hitsxy_barrel_mm_out->SetMarkerColor(kBlue - 7); + hitsxy_barrel_mm_out->SetLineColor(kBlue - 7); + c1->cd(); hitsxy_vtx_si->Draw(); hitsxy_barrel_si->Draw("same"); hitsxy_barrel_mm_in->Draw("same"); hitsxy_barrel_tof->Draw("same"); - hitsxy_barrel_mm_out->Draw("same"); - - TLegend *l= new TLegend(0.65,0.85,0.90,1.0); - l->SetTextSize(0.025); - l->SetBorderSize(0); - l->AddEntry(hitsxy_vtx_si,"VertexBarrelHits"); - l->AddEntry(hitsxy_barrel_si,"SiBarrelHits"); - l->AddEntry(hitsxy_barrel_mm_in,"MPGDBarrelHits"); - l->AddEntry(hitsxy_barrel_tof,"TOFBarrelHits"); - l->AddEntry(hitsxy_barrel_mm_out,"OuterMPGDBarrelHits"); - l->Draw(); - c1->SaveAs("hitsxy_dd4hep.png"); - - TCanvas *c2 = new TCanvas("c2","c2",1200,1000); - c2->SetMargin(0.09, 0.03 ,0.1,0.06); - // Y-Z Hits - Int_t nbinsx = 400, nbinsy=1800.; - x= 200.; y = 90.; - double xmin = -200.; - - TH2D *hitsrz_vtx_si = new TH2D("hitsrz_vtx_si","hitsrz_vtx_si",nbinsx,xmin,x,nbinsy,-y,y); - TH2D *hitsrz_barrel_si = new TH2D("hitsrz_barrel_si","hitsrz_barrel_si",nbinsx,-x,x,nbinsy,-y,y); - TH2D *hitsrz_barrel_mm_in = new TH2D("hitsrz_barrel_mm_in","hitsrz_barrel_mm_in",nbinsx,-x,x,nbinsy,-y,y); - TH2D *hitsrz_barrel_mm_out = new TH2D("hitsrz_barrel_mm_out","hitsrz_barrel_mm_out",nbinsx,-x,x,nbinsy,-y,y); - TH2D *hitsrz_barrel_tof = new TH2D("hitsrz_barrel_tof","hitsrz_barrel_tof",nbinsx,-x,x,nbinsy,-y,y); - TH2D *hitsrz_disks_si = new TH2D("hitsrz_disks_si","hitsrz_disks_si",nbinsx,-x,x,nbinsy,-y,y); - TH2D *hitsrz_endcap_tof = new TH2D("hitsrz_endcap_tof","hitsrz_endcap_tof",nbinsx,-x,x,nbinsy,-y,y); - TH2D *hitsrz_fwd_mpgd = new TH2D("hitsrz_fwd_mpgd","hitsrz_fwd_mpgd",nbinsx,-x,x,nbinsy,-y,y); - TH2D *hitsrz_bwd_mpgd = new TH2D("hitsrz_bwd_mpgd","hitsrz_bwd_mpgd",nbinsx,-x,x,nbinsy,-y,y); - - TH2D *hitsrz_vtx_si_1 = new TH2D("hitsrz_vtx_si_1","hitsrz_vtx_si_1",nbinsx,xmin,x,nbinsy,-y,y); - TH2D *hitsrz_barrel_si_1 = new TH2D("hitsrz_barrel_si_1","hitsrz_barrel_si_1",nbinsx,-x,x,nbinsy,-y,y); - TH2D *hitsrz_barrel_mm_in_1 = new TH2D("hitsrz_barrel_mm_in_1","hitsrz_barrel_mm_in_1",nbinsx,-x,x,nbinsy,-y,y); - TH2D *hitsrz_barrel_mm_out_1 = new TH2D("hitsrz_barrel_mm_out_1","hitsrz_barrel_mm_out_1",nbinsx,-x,x,nbinsy,-y,y); - TH2D *hitsrz_barrel_tof_1 = new TH2D("hitsrz_barrel_tof_1","hitsrz_barrel_tof_1",nbinsx,-x,x,nbinsy,-y,y); - TH2D *hitsrz_disks_si_1 = new TH2D("hitsrz_disks_si_1","hitsrz_disks_si_1",nbinsx,-x,x,nbinsy,-y,y); - TH2D *hitsrz_endcap_tof_1 = new TH2D("hitsrz_endcap_tof_1","hitsrz_endcap_tof_1",nbinsx,-x,x,nbinsy,-y,y); - TH2D *hitsrz_fwd_mpgd_1 = new TH2D("hitsrz_fwd_mpgd_1","hitsrz_fwd_mpgd_1",nbinsx,-x,x,nbinsy,-y,y); - TH2D *hitsrz_bwd_mpgd_1 = new TH2D("hitsrz_bwd_mpgd_1","hitsrz_bwd_mpgd_1",nbinsx,-x,x,nbinsy,-y,y); - - TString si_vtx_hitsrz_posR ="sqrt(VertexBarrelHits.position.x*VertexBarrelHits.position.x+VertexBarrelHits.position.y*VertexBarrelHits.position.y)*0.1:VertexBarrelHits.position.z*0.1>>hitsrz_vtx_si"; - - TString si_barrel_hitsrz_posR ="sqrt(SiBarrelHits.position.x*SiBarrelHits.position.x+SiBarrelHits.position.y*SiBarrelHits.position.y)*0.1:SiBarrelHits.position.z*0.1>>hitsrz_barrel_si"; - - TString barrel_mpgd_in_hitsrz_posR= "sqrt(MPGDBarrelHits.position.x*MPGDBarrelHits.position.x+MPGDBarrelHits.position.y*MPGDBarrelHits.position.y)*0.1:MPGDBarrelHits.position.z*0.1>>hitsrz_barrel_mm_in"; - - TString tof_barrel_hitsrz_posR ="sqrt(TOFBarrelHits.position.x*TOFBarrelHits.position.x+TOFBarrelHits.position.y*TOFBarrelHits.position.y)*0.1:TOFBarrelHits.position.z*0.1>>hitsrz_barrel_tof"; - - TString barrel_mpgd_out_hitsrz_posR ="sqrt(OuterMPGDBarrelHits.position.x*OuterMPGDBarrelHits.position.x+OuterMPGDBarrelHits.position.y*OuterMPGDBarrelHits.position.y)*0.1:OuterMPGDBarrelHits.position.z*0.1>>hitsrz_barrel_mm_out"; - - TString disks_si_hitsrz_posR ="sqrt(TrackerEndcapHits.position.x*TrackerEndcapHits.position.x+TrackerEndcapHits.position.y*TrackerEndcapHits.position.y)*0.1:TrackerEndcapHits.position.z*0.1>>hitsrz_disks_si"; - - TString endcap_tof_hitsrz_posR ="sqrt(TOFEndcapHits.position.x*TOFEndcapHits.position.x+TOFEndcapHits.position.y*TOFEndcapHits.position.y)*0.1:TOFEndcapHits.position.z*0.1>>hitsrz_endcap_tof"; - - TString fwd_mpgd_hitsrz_posR ="sqrt(ForwardMPGDEndcapHits.position.x*ForwardMPGDEndcapHits.position.x+ForwardMPGDEndcapHits.position.y*ForwardMPGDEndcapHits.position.y)*0.1:ForwardMPGDEndcapHits.position.z*0.1>>hitsrz_fwd_mpgd"; - - TString bwd_mpgd_hitsrz_posR ="sqrt(BackwardMPGDEndcapHits.position.x*BackwardMPGDEndcapHits.position.x+BackwardMPGDEndcapHits.position.y*BackwardMPGDEndcapHits.position.y)*0.1:BackwardMPGDEndcapHits.position.z*0.1>>hitsrz_bwd_mpgd"; - - - sim->Draw(si_vtx_hitsrz_posR.Data(),"VertexBarrelHits.position.y>0",""); // Multiply by 0.1 for cm - sim->Draw(si_barrel_hitsrz_posR.Data(),"SiBarrelHits.position.y>0",""); - sim->Draw(barrel_mpgd_in_hitsrz_posR.Data(),"MPGDBarrelHits.position.y>0",""); - sim->Draw(tof_barrel_hitsrz_posR.Data(),"TOFBarrelHits.position.y>0",""); - sim->Draw(disks_si_hitsrz_posR.Data(),"TrackerEndcapHits.position.y>0",""); - sim->Draw(endcap_tof_hitsrz_posR.Data(),"TOFEndcapHits.position.y>0",""); - sim->Draw(barrel_mpgd_out_hitsrz_posR.Data(),"OuterMPGDBarrelHits.position.y>0",""); - sim->Draw(fwd_mpgd_hitsrz_posR.Data(),"ForwardMPGDEndcapHits.position.y>0",""); - sim->Draw(bwd_mpgd_hitsrz_posR.Data(),"BackwardMPGDEndcapHits.position.y>0",""); - - TString si_vtx_hitsrz_negR ="-1.0*sqrt(VertexBarrelHits.position.x*VertexBarrelHits.position.x+VertexBarrelHits.position.y*VertexBarrelHits.position.y)*0.1:VertexBarrelHits.position.z*0.1>>hitsrz_vtx_si_1"; - - TString si_barrel_hitsrz_negR ="-1.0*sqrt(SiBarrelHits.position.x*SiBarrelHits.position.x+SiBarrelHits.position.y*SiBarrelHits.position.y)*0.1:SiBarrelHits.position.z*0.1>>hitsrz_barrel_si_1"; - - TString barrel_mpgd_in_hitsrz_negR= "-1.0*sqrt(MPGDBarrelHits.position.x*MPGDBarrelHits.position.x+MPGDBarrelHits.position.y*MPGDBarrelHits.position.y)*0.1:MPGDBarrelHits.position.z*0.1>>hitsrz_barrel_mm_in_1"; - - TString tof_barrel_hitsrz_negR ="-1.0*sqrt(TOFBarrelHits.position.x*TOFBarrelHits.position.x+TOFBarrelHits.position.y*TOFBarrelHits.position.y)*0.1:TOFBarrelHits.position.z*0.1>>hitsrz_barrel_tof_1"; - - TString barrel_mpgd_out_hitsrz_negR ="-1.0*sqrt(OuterMPGDBarrelHits.position.x*OuterMPGDBarrelHits.position.x+OuterMPGDBarrelHits.position.y*OuterMPGDBarrelHits.position.y)*0.1:OuterMPGDBarrelHits.position.z*0.1>>hitsrz_barrel_mm_out_1"; - - TString disks_si_hitsrz_negR ="-1.0*sqrt(TrackerEndcapHits.position.x*TrackerEndcapHits.position.x+TrackerEndcapHits.position.y*TrackerEndcapHits.position.y)*0.1:TrackerEndcapHits.position.z*0.1>>hitsrz_disks_si_1"; - - TString endcap_tof_hitsrz_negR ="-1.0*sqrt(TOFEndcapHits.position.x*TOFEndcapHits.position.x+TOFEndcapHits.position.y*TOFEndcapHits.position.y)*0.1:TOFEndcapHits.position.z*0.1>>hitsrz_endcap_tof_1"; - - TString fwd_mpgd_hitsrz_negR ="-1.0*sqrt(ForwardMPGDEndcapHits.position.x*ForwardMPGDEndcapHits.position.x+ForwardMPGDEndcapHits.position.y*ForwardMPGDEndcapHits.position.y)*0.1:ForwardMPGDEndcapHits.position.z*0.1>>hitsrz_fwd_mpgd_1"; - - TString bwd_mpgd_hitsrz_negR ="-1.0*sqrt(BackwardMPGDEndcapHits.position.x*BackwardMPGDEndcapHits.position.x+BackwardMPGDEndcapHits.position.y*BackwardMPGDEndcapHits.position.y)*0.1:BackwardMPGDEndcapHits.position.z*0.1>>hitsrz_bwd_mpgd_1"; - - sim->Draw(si_vtx_hitsrz_negR.Data(),"VertexBarrelHits.position.y<0",""); // Multiply by 0.1 for cm - sim->Draw(si_barrel_hitsrz_negR.Data(),"SiBarrelHits.position.y<0",""); - sim->Draw(barrel_mpgd_in_hitsrz_negR.Data(),"MPGDBarrelHits.position.y<0",""); - sim->Draw(tof_barrel_hitsrz_negR.Data(),"TOFBarrelHits.position.y<0",""); - sim->Draw(disks_si_hitsrz_negR.Data(),"TrackerEndcapHits.position.y<0",""); - sim->Draw(endcap_tof_hitsrz_negR.Data(),"TOFEndcapHits.position.y<0",""); - sim->Draw(barrel_mpgd_out_hitsrz_negR.Data(),"OuterMPGDBarrelHits.position.y<0",""); - sim->Draw(fwd_mpgd_hitsrz_negR.Data(),"ForwardMPGDEndcapHits.position.y<0",""); - sim->Draw(bwd_mpgd_hitsrz_negR.Data(),"BackwardMPGDEndcapHits.position.y<0",""); - - - hitsrz_vtx_si->SetMarkerStyle(31); - hitsrz_vtx_si->SetTitle(""); - hitsrz_vtx_si->SetMarkerSize(0.1); - hitsrz_vtx_si->SetLineColor(kBlack); - hitsrz_vtx_si->SetMarkerColor(kBlack); - hitsrz_vtx_si->GetXaxis()->SetTitle("Z [cm]"); - hitsrz_vtx_si->GetYaxis()->SetTitle("R [cm]"); - hitsrz_vtx_si->GetXaxis()->CenterTitle(); - hitsrz_vtx_si->GetYaxis()->CenterTitle(); - - hitsrz_vtx_si_1->SetMarkerSize(0.1); - hitsrz_vtx_si_1->SetLineColor(kBlack); - hitsrz_vtx_si_1->SetMarkerColor(kBlack); - - hitsrz_barrel_si->SetMarkerStyle(20); - hitsrz_barrel_si->SetMarkerSize(0.1); - hitsrz_barrel_si->SetMarkerColor(kMagenta); - hitsrz_barrel_si->SetLineColor(kMagenta); - - hitsrz_barrel_si_1->SetMarkerSize(0.1); - hitsrz_barrel_si_1->SetLineColor(kMagenta); - hitsrz_barrel_si_1->SetMarkerColor(kMagenta); - - hitsrz_barrel_mm_in->SetMarkerStyle(20); - hitsrz_barrel_mm_in->SetMarkerSize(0.1); - hitsrz_barrel_mm_in->SetLineColor(kBlue); - hitsrz_barrel_mm_in->SetMarkerColor(kBlue); - hitsrz_barrel_mm_in_1->SetMarkerSize(0.1); - hitsrz_barrel_mm_in_1->SetLineColor(kBlue); - hitsrz_barrel_mm_in_1->SetMarkerColor(kBlue); - - hitsrz_barrel_tof->SetMarkerStyle(20); - hitsrz_barrel_tof->SetMarkerSize(0.1); - hitsrz_barrel_tof->SetLineColor(kGreen); - hitsrz_barrel_tof->SetMarkerColor(kGreen); - hitsrz_barrel_tof_1->SetMarkerSize(0.1); - hitsrz_barrel_tof_1->SetLineColor(kGreen); - hitsrz_barrel_tof_1->SetMarkerColor(kGreen); - - - hitsrz_barrel_mm_out->SetMarkerStyle(20); - hitsrz_barrel_mm_out->SetMarkerSize(0.1); - hitsrz_barrel_mm_out->SetMarkerColor(kBlue-7); - hitsrz_barrel_mm_out->SetLineColor(kBlue-7); - - hitsrz_barrel_mm_out_1->SetMarkerSize(0.1); - hitsrz_barrel_mm_out_1->SetLineColor(kBlue-7); - hitsrz_barrel_mm_out_1->SetMarkerColor(kBlue-7); - hitsrz_endcap_tof->SetMarkerStyle(20); - hitsrz_endcap_tof->SetMarkerSize(0.1); - hitsrz_endcap_tof->SetMarkerColor(kCyan); - hitsrz_endcap_tof->SetLineColor(kCyan); - - hitsrz_endcap_tof_1->SetMarkerSize(0.1); - hitsrz_endcap_tof_1->SetLineColor(kCyan); - hitsrz_endcap_tof_1->SetMarkerColor(kCyan); - - hitsrz_disks_si->SetMarkerStyle(20); - hitsrz_disks_si->SetMarkerSize(0.1); - hitsrz_disks_si->SetMarkerColor(kRed); - hitsrz_disks_si->SetLineColor(kRed); - - hitsrz_disks_si_1->SetMarkerSize(0.1); - hitsrz_disks_si_1->SetLineColor(kRed); - hitsrz_disks_si_1->SetMarkerColor(kRed); - - hitsrz_fwd_mpgd->SetMarkerSize(0.1); - hitsrz_fwd_mpgd->SetLineColor(kRed-7); - hitsrz_fwd_mpgd->SetMarkerColor(kRed-7); - hitsrz_fwd_mpgd_1->SetMarkerSize(0.1); - hitsrz_fwd_mpgd_1->SetLineColor(kRed-7); - hitsrz_fwd_mpgd_1->SetMarkerColor(kRed-7); - hitsrz_bwd_mpgd->SetMarkerSize(0.1); - hitsrz_bwd_mpgd->SetLineColor(kOrange); - hitsrz_bwd_mpgd->SetMarkerColor(kOrange); - - hitsrz_bwd_mpgd_1->SetMarkerSize(0.1); - hitsrz_bwd_mpgd_1->SetLineColor(kOrange); - hitsrz_bwd_mpgd_1->SetMarkerColor(kOrange); - - c2->cd(); - hitsrz_vtx_si->Draw(); - hitsrz_vtx_si_1->Draw("same"); - hitsrz_barrel_si->Draw("same"); - hitsrz_barrel_si_1->Draw("same"); - hitsrz_barrel_mm_in->Draw("same"); - hitsrz_barrel_mm_in_1->Draw("same"); - hitsrz_barrel_tof->Draw("same"); - hitsrz_barrel_tof_1->Draw("same"); - hitsrz_barrel_mm_out->Draw("same"); - hitsrz_barrel_mm_out_1->Draw("same"); - hitsrz_endcap_tof->Draw("same"); - hitsrz_endcap_tof_1->Draw("same"); - hitsrz_disks_si->Draw("same"); - hitsrz_disks_si_1->Draw("same"); - hitsrz_fwd_mpgd->Draw("same"); - hitsrz_fwd_mpgd_1->Draw("same"); - hitsrz_bwd_mpgd->Draw("same"); - hitsrz_bwd_mpgd_1->Draw("same"); - - TLegend *l1= new TLegend(0.11,0.88,0.95,0.99); + hitsxy_barrel_mm_out->Draw("same"); + + TLegend* l = new TLegend(0.65, 0.85, 0.90, 1.0); + l->SetTextSize(0.025); + l->SetBorderSize(0); + l->AddEntry(hitsxy_vtx_si, "VertexBarrelHits"); + l->AddEntry(hitsxy_barrel_si, "SiBarrelHits"); + l->AddEntry(hitsxy_barrel_mm_in, "MPGDBarrelHits"); + l->AddEntry(hitsxy_barrel_tof, "TOFBarrelHits"); + l->AddEntry(hitsxy_barrel_mm_out, "OuterMPGDBarrelHits"); + l->Draw(); + c1->SaveAs("hitsxy_dd4hep.png"); + + TCanvas* c2 = new TCanvas("c2", "c2", 1200, 1000); + c2->SetMargin(0.09, 0.03, 0.1, 0.06); + // Y-Z Hits + Int_t nbinsx = 400, nbinsy = 1800.; + x = 200.; + y = 90.; + double xmin = -200.; + + TH2D* hitsrz_vtx_si = new TH2D("hitsrz_vtx_si", "hitsrz_vtx_si", nbinsx, xmin, x, nbinsy, -y, y); + TH2D* hitsrz_barrel_si = + new TH2D("hitsrz_barrel_si", "hitsrz_barrel_si", nbinsx, -x, x, nbinsy, -y, y); + TH2D* hitsrz_barrel_mm_in = + new TH2D("hitsrz_barrel_mm_in", "hitsrz_barrel_mm_in", nbinsx, -x, x, nbinsy, -y, y); + TH2D* hitsrz_barrel_mm_out = + new TH2D("hitsrz_barrel_mm_out", "hitsrz_barrel_mm_out", nbinsx, -x, x, nbinsy, -y, y); + TH2D* hitsrz_barrel_tof = + new TH2D("hitsrz_barrel_tof", "hitsrz_barrel_tof", nbinsx, -x, x, nbinsy, -y, y); + TH2D* hitsrz_disks_si = + new TH2D("hitsrz_disks_si", "hitsrz_disks_si", nbinsx, -x, x, nbinsy, -y, y); + TH2D* hitsrz_endcap_tof = + new TH2D("hitsrz_endcap_tof", "hitsrz_endcap_tof", nbinsx, -x, x, nbinsy, -y, y); + TH2D* hitsrz_fwd_mpgd = + new TH2D("hitsrz_fwd_mpgd", "hitsrz_fwd_mpgd", nbinsx, -x, x, nbinsy, -y, y); + TH2D* hitsrz_bwd_mpgd = + new TH2D("hitsrz_bwd_mpgd", "hitsrz_bwd_mpgd", nbinsx, -x, x, nbinsy, -y, y); + + TH2D* hitsrz_vtx_si_1 = + new TH2D("hitsrz_vtx_si_1", "hitsrz_vtx_si_1", nbinsx, xmin, x, nbinsy, -y, y); + TH2D* hitsrz_barrel_si_1 = + new TH2D("hitsrz_barrel_si_1", "hitsrz_barrel_si_1", nbinsx, -x, x, nbinsy, -y, y); + TH2D* hitsrz_barrel_mm_in_1 = + new TH2D("hitsrz_barrel_mm_in_1", "hitsrz_barrel_mm_in_1", nbinsx, -x, x, nbinsy, -y, y); + TH2D* hitsrz_barrel_mm_out_1 = + new TH2D("hitsrz_barrel_mm_out_1", "hitsrz_barrel_mm_out_1", nbinsx, -x, x, nbinsy, -y, y); + TH2D* hitsrz_barrel_tof_1 = + new TH2D("hitsrz_barrel_tof_1", "hitsrz_barrel_tof_1", nbinsx, -x, x, nbinsy, -y, y); + TH2D* hitsrz_disks_si_1 = + new TH2D("hitsrz_disks_si_1", "hitsrz_disks_si_1", nbinsx, -x, x, nbinsy, -y, y); + TH2D* hitsrz_endcap_tof_1 = + new TH2D("hitsrz_endcap_tof_1", "hitsrz_endcap_tof_1", nbinsx, -x, x, nbinsy, -y, y); + TH2D* hitsrz_fwd_mpgd_1 = + new TH2D("hitsrz_fwd_mpgd_1", "hitsrz_fwd_mpgd_1", nbinsx, -x, x, nbinsy, -y, y); + TH2D* hitsrz_bwd_mpgd_1 = + new TH2D("hitsrz_bwd_mpgd_1", "hitsrz_bwd_mpgd_1", nbinsx, -x, x, nbinsy, -y, y); + + TString si_vtx_hitsrz_posR = + "sqrt(VertexBarrelHits.position.x*VertexBarrelHits.position.x+VertexBarrelHits.position.y*" + "VertexBarrelHits.position.y)*0.1:VertexBarrelHits.position.z*0.1>>hitsrz_vtx_si"; + + TString si_barrel_hitsrz_posR = + "sqrt(SiBarrelHits.position.x*SiBarrelHits.position.x+SiBarrelHits.position.y*SiBarrelHits." + "position.y)*0.1:SiBarrelHits.position.z*0.1>>hitsrz_barrel_si"; + + TString barrel_mpgd_in_hitsrz_posR = + "sqrt(MPGDBarrelHits.position.x*MPGDBarrelHits.position.x+MPGDBarrelHits.position.y*" + "MPGDBarrelHits.position.y)*0.1:MPGDBarrelHits.position.z*0.1>>hitsrz_barrel_mm_in"; + + TString tof_barrel_hitsrz_posR = + "sqrt(TOFBarrelHits.position.x*TOFBarrelHits.position.x+TOFBarrelHits.position.y*" + "TOFBarrelHits.position.y)*0.1:TOFBarrelHits.position.z*0.1>>hitsrz_barrel_tof"; + + TString barrel_mpgd_out_hitsrz_posR = + "sqrt(OuterMPGDBarrelHits.position.x*OuterMPGDBarrelHits.position.x+OuterMPGDBarrelHits." + "position.y*OuterMPGDBarrelHits.position.y)*0.1:OuterMPGDBarrelHits.position.z*0.1>>hitsrz_" + "barrel_mm_out"; + + TString disks_si_hitsrz_posR = + "sqrt(TrackerEndcapHits.position.x*TrackerEndcapHits.position.x+TrackerEndcapHits.position.y*" + "TrackerEndcapHits.position.y)*0.1:TrackerEndcapHits.position.z*0.1>>hitsrz_disks_si"; + + TString endcap_tof_hitsrz_posR = + "sqrt(TOFEndcapHits.position.x*TOFEndcapHits.position.x+TOFEndcapHits.position.y*" + "TOFEndcapHits.position.y)*0.1:TOFEndcapHits.position.z*0.1>>hitsrz_endcap_tof"; + + TString fwd_mpgd_hitsrz_posR = + "sqrt(ForwardMPGDEndcapHits.position.x*ForwardMPGDEndcapHits.position.x+" + "ForwardMPGDEndcapHits.position.y*ForwardMPGDEndcapHits.position.y)*0.1:" + "ForwardMPGDEndcapHits.position.z*0.1>>hitsrz_fwd_mpgd"; + + TString bwd_mpgd_hitsrz_posR = + "sqrt(BackwardMPGDEndcapHits.position.x*BackwardMPGDEndcapHits.position.x+" + "BackwardMPGDEndcapHits.position.y*BackwardMPGDEndcapHits.position.y)*0.1:" + "BackwardMPGDEndcapHits.position.z*0.1>>hitsrz_bwd_mpgd"; + + sim->Draw(si_vtx_hitsrz_posR.Data(), "VertexBarrelHits.position.y>0", + ""); // Multiply by 0.1 for cm + sim->Draw(si_barrel_hitsrz_posR.Data(), "SiBarrelHits.position.y>0", ""); + sim->Draw(barrel_mpgd_in_hitsrz_posR.Data(), "MPGDBarrelHits.position.y>0", ""); + sim->Draw(tof_barrel_hitsrz_posR.Data(), "TOFBarrelHits.position.y>0", ""); + sim->Draw(disks_si_hitsrz_posR.Data(), "TrackerEndcapHits.position.y>0", ""); + sim->Draw(endcap_tof_hitsrz_posR.Data(), "TOFEndcapHits.position.y>0", ""); + sim->Draw(barrel_mpgd_out_hitsrz_posR.Data(), "OuterMPGDBarrelHits.position.y>0", ""); + sim->Draw(fwd_mpgd_hitsrz_posR.Data(), "ForwardMPGDEndcapHits.position.y>0", ""); + sim->Draw(bwd_mpgd_hitsrz_posR.Data(), "BackwardMPGDEndcapHits.position.y>0", ""); + + TString si_vtx_hitsrz_negR = + "-1.0*sqrt(VertexBarrelHits.position.x*VertexBarrelHits.position.x+VertexBarrelHits.position." + "y*VertexBarrelHits.position.y)*0.1:VertexBarrelHits.position.z*0.1>>hitsrz_vtx_si_1"; + + TString si_barrel_hitsrz_negR = + "-1.0*sqrt(SiBarrelHits.position.x*SiBarrelHits.position.x+SiBarrelHits.position.y*" + "SiBarrelHits.position.y)*0.1:SiBarrelHits.position.z*0.1>>hitsrz_barrel_si_1"; + + TString barrel_mpgd_in_hitsrz_negR = + "-1.0*sqrt(MPGDBarrelHits.position.x*MPGDBarrelHits.position.x+MPGDBarrelHits.position.y*" + "MPGDBarrelHits.position.y)*0.1:MPGDBarrelHits.position.z*0.1>>hitsrz_barrel_mm_in_1"; + + TString tof_barrel_hitsrz_negR = + "-1.0*sqrt(TOFBarrelHits.position.x*TOFBarrelHits.position.x+TOFBarrelHits.position.y*" + "TOFBarrelHits.position.y)*0.1:TOFBarrelHits.position.z*0.1>>hitsrz_barrel_tof_1"; + + TString barrel_mpgd_out_hitsrz_negR = + "-1.0*sqrt(OuterMPGDBarrelHits.position.x*OuterMPGDBarrelHits.position.x+OuterMPGDBarrelHits." + "position.y*OuterMPGDBarrelHits.position.y)*0.1:OuterMPGDBarrelHits.position.z*0.1>>hitsrz_" + "barrel_mm_out_1"; + + TString disks_si_hitsrz_negR = + "-1.0*sqrt(TrackerEndcapHits.position.x*TrackerEndcapHits.position.x+TrackerEndcapHits." + "position.y*TrackerEndcapHits.position.y)*0.1:TrackerEndcapHits.position.z*0.1>>hitsrz_disks_" + "si_1"; + + TString endcap_tof_hitsrz_negR = + "-1.0*sqrt(TOFEndcapHits.position.x*TOFEndcapHits.position.x+TOFEndcapHits.position.y*" + "TOFEndcapHits.position.y)*0.1:TOFEndcapHits.position.z*0.1>>hitsrz_endcap_tof_1"; + + TString fwd_mpgd_hitsrz_negR = + "-1.0*sqrt(ForwardMPGDEndcapHits.position.x*ForwardMPGDEndcapHits.position.x+" + "ForwardMPGDEndcapHits.position.y*ForwardMPGDEndcapHits.position.y)*0.1:" + "ForwardMPGDEndcapHits.position.z*0.1>>hitsrz_fwd_mpgd_1"; + + TString bwd_mpgd_hitsrz_negR = + "-1.0*sqrt(BackwardMPGDEndcapHits.position.x*BackwardMPGDEndcapHits.position.x+" + "BackwardMPGDEndcapHits.position.y*BackwardMPGDEndcapHits.position.y)*0.1:" + "BackwardMPGDEndcapHits.position.z*0.1>>hitsrz_bwd_mpgd_1"; + + sim->Draw(si_vtx_hitsrz_negR.Data(), "VertexBarrelHits.position.y<0", + ""); // Multiply by 0.1 for cm + sim->Draw(si_barrel_hitsrz_negR.Data(), "SiBarrelHits.position.y<0", ""); + sim->Draw(barrel_mpgd_in_hitsrz_negR.Data(), "MPGDBarrelHits.position.y<0", ""); + sim->Draw(tof_barrel_hitsrz_negR.Data(), "TOFBarrelHits.position.y<0", ""); + sim->Draw(disks_si_hitsrz_negR.Data(), "TrackerEndcapHits.position.y<0", ""); + sim->Draw(endcap_tof_hitsrz_negR.Data(), "TOFEndcapHits.position.y<0", ""); + sim->Draw(barrel_mpgd_out_hitsrz_negR.Data(), "OuterMPGDBarrelHits.position.y<0", ""); + sim->Draw(fwd_mpgd_hitsrz_negR.Data(), "ForwardMPGDEndcapHits.position.y<0", ""); + sim->Draw(bwd_mpgd_hitsrz_negR.Data(), "BackwardMPGDEndcapHits.position.y<0", ""); + + hitsrz_vtx_si->SetMarkerStyle(31); + hitsrz_vtx_si->SetTitle(""); + hitsrz_vtx_si->SetMarkerSize(0.1); + hitsrz_vtx_si->SetLineColor(kBlack); + hitsrz_vtx_si->SetMarkerColor(kBlack); + hitsrz_vtx_si->GetXaxis()->SetTitle("Z [cm]"); + hitsrz_vtx_si->GetYaxis()->SetTitle("R [cm]"); + hitsrz_vtx_si->GetXaxis()->CenterTitle(); + hitsrz_vtx_si->GetYaxis()->CenterTitle(); + + hitsrz_vtx_si_1->SetMarkerSize(0.1); + hitsrz_vtx_si_1->SetLineColor(kBlack); + hitsrz_vtx_si_1->SetMarkerColor(kBlack); + + hitsrz_barrel_si->SetMarkerStyle(20); + hitsrz_barrel_si->SetMarkerSize(0.1); + hitsrz_barrel_si->SetMarkerColor(kMagenta); + hitsrz_barrel_si->SetLineColor(kMagenta); + + hitsrz_barrel_si_1->SetMarkerSize(0.1); + hitsrz_barrel_si_1->SetLineColor(kMagenta); + hitsrz_barrel_si_1->SetMarkerColor(kMagenta); + + hitsrz_barrel_mm_in->SetMarkerStyle(20); + hitsrz_barrel_mm_in->SetMarkerSize(0.1); + hitsrz_barrel_mm_in->SetLineColor(kBlue); + hitsrz_barrel_mm_in->SetMarkerColor(kBlue); + hitsrz_barrel_mm_in_1->SetMarkerSize(0.1); + hitsrz_barrel_mm_in_1->SetLineColor(kBlue); + hitsrz_barrel_mm_in_1->SetMarkerColor(kBlue); + + hitsrz_barrel_tof->SetMarkerStyle(20); + hitsrz_barrel_tof->SetMarkerSize(0.1); + hitsrz_barrel_tof->SetLineColor(kGreen); + hitsrz_barrel_tof->SetMarkerColor(kGreen); + hitsrz_barrel_tof_1->SetMarkerSize(0.1); + hitsrz_barrel_tof_1->SetLineColor(kGreen); + hitsrz_barrel_tof_1->SetMarkerColor(kGreen); + + hitsrz_barrel_mm_out->SetMarkerStyle(20); + hitsrz_barrel_mm_out->SetMarkerSize(0.1); + hitsrz_barrel_mm_out->SetMarkerColor(kBlue - 7); + hitsrz_barrel_mm_out->SetLineColor(kBlue - 7); + + hitsrz_barrel_mm_out_1->SetMarkerSize(0.1); + hitsrz_barrel_mm_out_1->SetLineColor(kBlue - 7); + hitsrz_barrel_mm_out_1->SetMarkerColor(kBlue - 7); + hitsrz_endcap_tof->SetMarkerStyle(20); + hitsrz_endcap_tof->SetMarkerSize(0.1); + hitsrz_endcap_tof->SetMarkerColor(kCyan); + hitsrz_endcap_tof->SetLineColor(kCyan); + + hitsrz_endcap_tof_1->SetMarkerSize(0.1); + hitsrz_endcap_tof_1->SetLineColor(kCyan); + hitsrz_endcap_tof_1->SetMarkerColor(kCyan); + + hitsrz_disks_si->SetMarkerStyle(20); + hitsrz_disks_si->SetMarkerSize(0.1); + hitsrz_disks_si->SetMarkerColor(kRed); + hitsrz_disks_si->SetLineColor(kRed); + + hitsrz_disks_si_1->SetMarkerSize(0.1); + hitsrz_disks_si_1->SetLineColor(kRed); + hitsrz_disks_si_1->SetMarkerColor(kRed); + + hitsrz_fwd_mpgd->SetMarkerSize(0.1); + hitsrz_fwd_mpgd->SetLineColor(kRed - 7); + hitsrz_fwd_mpgd->SetMarkerColor(kRed - 7); + hitsrz_fwd_mpgd_1->SetMarkerSize(0.1); + hitsrz_fwd_mpgd_1->SetLineColor(kRed - 7); + hitsrz_fwd_mpgd_1->SetMarkerColor(kRed - 7); + hitsrz_bwd_mpgd->SetMarkerSize(0.1); + hitsrz_bwd_mpgd->SetLineColor(kOrange); + hitsrz_bwd_mpgd->SetMarkerColor(kOrange); + + hitsrz_bwd_mpgd_1->SetMarkerSize(0.1); + hitsrz_bwd_mpgd_1->SetLineColor(kOrange); + hitsrz_bwd_mpgd_1->SetMarkerColor(kOrange); + + c2->cd(); + hitsrz_vtx_si->Draw(); + hitsrz_vtx_si_1->Draw("same"); + hitsrz_barrel_si->Draw("same"); + hitsrz_barrel_si_1->Draw("same"); + hitsrz_barrel_mm_in->Draw("same"); + hitsrz_barrel_mm_in_1->Draw("same"); + hitsrz_barrel_tof->Draw("same"); + hitsrz_barrel_tof_1->Draw("same"); + hitsrz_barrel_mm_out->Draw("same"); + hitsrz_barrel_mm_out_1->Draw("same"); + hitsrz_endcap_tof->Draw("same"); + hitsrz_endcap_tof_1->Draw("same"); + hitsrz_disks_si->Draw("same"); + hitsrz_disks_si_1->Draw("same"); + hitsrz_fwd_mpgd->Draw("same"); + hitsrz_fwd_mpgd_1->Draw("same"); + hitsrz_bwd_mpgd->Draw("same"); + hitsrz_bwd_mpgd_1->Draw("same"); + + TLegend* l1 = new TLegend(0.11, 0.88, 0.95, 0.99); l1->SetNColumns(3); l1->SetTextSize(0.025); l1->SetBorderSize(0); - l1->AddEntry(hitsrz_vtx_si,"VertexBarrelHits"); - l1->AddEntry(hitsrz_barrel_si,"SiBarrelHits"); - l1->AddEntry(hitsrz_barrel_mm_in,"MPGDBarrelHits"); - l1->AddEntry(hitsrz_barrel_tof,"TOFBarrelHits"); - l1->AddEntry(hitsrz_barrel_mm_out,"OuterMPGDBarrelHits"); - l1->AddEntry(hitsrz_disks_si,"TrackerEndcapHits"); - l1->AddEntry(hitsrz_endcap_tof,"TOFEndcapHits"); - l1->AddEntry(hitsrz_fwd_mpgd,"ForwardMPGDEndcapHits"); - l1->AddEntry(hitsrz_bwd_mpgd,"BackwardMPGDEndcapHits"); + l1->AddEntry(hitsrz_vtx_si, "VertexBarrelHits"); + l1->AddEntry(hitsrz_barrel_si, "SiBarrelHits"); + l1->AddEntry(hitsrz_barrel_mm_in, "MPGDBarrelHits"); + l1->AddEntry(hitsrz_barrel_tof, "TOFBarrelHits"); + l1->AddEntry(hitsrz_barrel_mm_out, "OuterMPGDBarrelHits"); + l1->AddEntry(hitsrz_disks_si, "TrackerEndcapHits"); + l1->AddEntry(hitsrz_endcap_tof, "TOFEndcapHits"); + l1->AddEntry(hitsrz_fwd_mpgd, "ForwardMPGDEndcapHits"); + l1->AddEntry(hitsrz_bwd_mpgd, "BackwardMPGDEndcapHits"); l1->Draw(); c2->SaveAs("hitsrz_dd4hep.png"); - // Timer Stop + // Timer Stop timer.Stop(); Double_t realtime = timer.RealTime(); - Double_t cputime = timer.CpuTime(); - printf("RealTime=%f seconds, CpuTime=%f seconds\n",realtime,cputime); - + Double_t cputime = timer.CpuTime(); + printf("RealTime=%f seconds, CpuTime=%f seconds\n", realtime, cputime); } diff --git a/src/benchmarks/reconstruction/tracking_efficiency/tracking_efficiency.cc b/src/benchmarks/reconstruction/tracking_efficiency/tracking_efficiency.cc index 656b0fbe0d..77389af37b 100644 --- a/src/benchmarks/reconstruction/tracking_efficiency/tracking_efficiency.cc +++ b/src/benchmarks/reconstruction/tracking_efficiency/tracking_efficiency.cc @@ -8,8 +8,8 @@ #include "TrackingEfficiency_processor.h" extern "C" { - void InitPlugin(JApplication *app) { - InitJANAPlugin(app); - app->Add(new TrackingEfficiency_processor(app)); - } +void InitPlugin(JApplication* app) { + InitJANAPlugin(app); + app->Add(new TrackingEfficiency_processor(app)); +} } diff --git a/src/benchmarks/reconstruction/tracking_occupancy/HitReconstructionAnalysis.cc b/src/benchmarks/reconstruction/tracking_occupancy/HitReconstructionAnalysis.cc index ef3614c305..aa13c0d46f 100644 --- a/src/benchmarks/reconstruction/tracking_occupancy/HitReconstructionAnalysis.cc +++ b/src/benchmarks/reconstruction/tracking_occupancy/HitReconstructionAnalysis.cc @@ -14,48 +14,52 @@ #include "HitReconstructionAnalysis.h" -void HitReconstructionAnalysis::init(JApplication *app, TDirectory *plugin_tdir) { +void HitReconstructionAnalysis::init(JApplication* app, TDirectory* plugin_tdir) { - auto *dir = plugin_tdir->mkdir("RecOccupancies"); // TODO create directory for this analysis + auto* dir = plugin_tdir->mkdir("RecOccupancies"); // TODO create directory for this analysis - auto z_limit_min = -2000; - auto z_limit_max = 2000; - auto r_limit_min = 0; - auto r_limit_max = 1200; + auto z_limit_min = -2000; + auto z_limit_max = 2000; + auto r_limit_min = 0; + auto r_limit_max = 1200; - m_total_occup_th2 = new TH2F("total_occup", "Occupancy plot for all readouts", 200, z_limit_min, +z_limit_max, 100, r_limit_min, r_limit_max); - m_total_occup_th2->SetDirectory(dir); + m_total_occup_th2 = new TH2F("total_occup", "Occupancy plot for all readouts", 200, z_limit_min, + +z_limit_max, 100, r_limit_min, r_limit_max); + m_total_occup_th2->SetDirectory(dir); - for(auto &name: m_data_names) { - auto count_hist = std::make_shared(("count_" + name).c_str(), ("Count hits for " + name).c_str(), 100, 0, 30); - count_hist->SetDirectory(dir); - m_hits_count_hists.push_back(count_hist); + for (auto& name : m_data_names) { + auto count_hist = std::make_shared(("count_" + name).c_str(), + ("Count hits for " + name).c_str(), 100, 0, 30); + count_hist->SetDirectory(dir); + m_hits_count_hists.push_back(count_hist); - auto occup_hist = std::make_shared(("occup_" + name).c_str(), ("Occupancy plot for" + name).c_str(), 100, z_limit_min, z_limit_max, 200, r_limit_min, r_limit_max); - occup_hist->SetDirectory(dir); - m_hits_occup_hists.push_back(occup_hist); - } + auto occup_hist = + std::make_shared(("occup_" + name).c_str(), ("Occupancy plot for" + name).c_str(), + 100, z_limit_min, z_limit_max, 200, r_limit_min, r_limit_max); + occup_hist->SetDirectory(dir); + m_hits_occup_hists.push_back(occup_hist); + } } -void HitReconstructionAnalysis::process(const std::shared_ptr &event) { - for(size_t name_index = 0; name_index < m_data_names.size(); name_index++ ) { - std::string data_name = m_data_names[name_index]; - auto &count_hist = m_hits_count_hists[name_index]; - auto &occup_hist = m_hits_occup_hists[name_index]; - - try { - auto hits = event->Get(data_name); - count_hist->Fill(hits.size()); - for(const auto *hit: hits) { - float x = hit->getPosition().x; - float y = hit->getPosition().y; - float z = hit->getPosition().z; - float r = sqrt(x*x + y*y); - occup_hist->Fill(z, r); - m_total_occup_th2->Fill(z, r); - } - } catch(std::exception& e) { - // silently skip missing collections - } +void HitReconstructionAnalysis::process(const std::shared_ptr& event) { + for (size_t name_index = 0; name_index < m_data_names.size(); name_index++) { + std::string data_name = m_data_names[name_index]; + auto& count_hist = m_hits_count_hists[name_index]; + auto& occup_hist = m_hits_occup_hists[name_index]; + + try { + auto hits = event->Get(data_name); + count_hist->Fill(hits.size()); + for (const auto* hit : hits) { + float x = hit->getPosition().x; + float y = hit->getPosition().y; + float z = hit->getPosition().z; + float r = sqrt(x * x + y * y); + occup_hist->Fill(z, r); + m_total_occup_th2->Fill(z, r); + } + } catch (std::exception& e) { + // silently skip missing collections } + } } diff --git a/src/benchmarks/reconstruction/tracking_occupancy/HitReconstructionAnalysis.h b/src/benchmarks/reconstruction/tracking_occupancy/HitReconstructionAnalysis.h index 3a275adcda..0212522e1e 100644 --- a/src/benchmarks/reconstruction/tracking_occupancy/HitReconstructionAnalysis.h +++ b/src/benchmarks/reconstruction/tracking_occupancy/HitReconstructionAnalysis.h @@ -15,34 +15,33 @@ class HitReconstructionAnalysis { public: - void init(JApplication *app, TDirectory *plugin_tdir); + void init(JApplication* app, TDirectory* plugin_tdir); - void process(const std::shared_ptr &event); + void process(const std::shared_ptr& event); private: - - /// This is edm4hep::SimTrackerHits names of different detector readouts - std::vector m_data_names = { - "SiBarrelTrackerRecHits", // Barrel Tracker - "SiBarrelVertexRecHits", // Vertex - "SiEndcapTrackerRecHits", // End Cap tracker - // MPGD - "MPGDBarrelRecHits", - "MPGDDIRCRecHits", - "OuterMPGDBarrelRecHits", - "ForwardMPGDEndcapRecHits", - "BackwardMPGDEndcapRecHits", - // TOF - "TOFEndcapRecHits", - "TOFBarrelRecHit", - }; - - /// Hits count histogram for each hits readout name - std::vector> m_hits_count_hists; - - /// Hits occupancy histogram for each hits readout name - std::vector> m_hits_occup_hists; - - /// Total occupancy of all m_data_names - TH2F * m_total_occup_th2; /// MC Particles px,py + /// This is edm4hep::SimTrackerHits names of different detector readouts + std::vector m_data_names = { + "SiBarrelTrackerRecHits", // Barrel Tracker + "SiBarrelVertexRecHits", // Vertex + "SiEndcapTrackerRecHits", // End Cap tracker + // MPGD + "MPGDBarrelRecHits", + "MPGDDIRCRecHits", + "OuterMPGDBarrelRecHits", + "ForwardMPGDEndcapRecHits", + "BackwardMPGDEndcapRecHits", + // TOF + "TOFEndcapRecHits", + "TOFBarrelRecHit", + }; + + /// Hits count histogram for each hits readout name + std::vector> m_hits_count_hists; + + /// Hits occupancy histogram for each hits readout name + std::vector> m_hits_occup_hists; + + /// Total occupancy of all m_data_names + TH2F* m_total_occup_th2; /// MC Particles px,py }; diff --git a/src/benchmarks/reconstruction/tracking_occupancy/TrackingOccupancyAnalysis.cc b/src/benchmarks/reconstruction/tracking_occupancy/TrackingOccupancyAnalysis.cc index 5a5104bb1d..20b78c228c 100644 --- a/src/benchmarks/reconstruction/tracking_occupancy/TrackingOccupancyAnalysis.cc +++ b/src/benchmarks/reconstruction/tracking_occupancy/TrackingOccupancyAnalysis.cc @@ -14,51 +14,52 @@ #include "TrackingOccupancyAnalysis.h" +void TrackingOccupancyAnalysis::init(JApplication* app, TDirectory* plugin_tdir) { + auto* dir = plugin_tdir->mkdir("SimOccupancies"); // TODO create directory for this analysis -void TrackingOccupancyAnalysis::init(JApplication *app, TDirectory *plugin_tdir) { - auto *dir = plugin_tdir->mkdir("SimOccupancies"); // TODO create directory for this analysis + auto z_limit_min = -2000; + auto z_limit_max = 2000; + auto r_limit_min = 0; + auto r_limit_max = 1200; - auto z_limit_min = -2000; - auto z_limit_max = 2000; - auto r_limit_min = 0; - auto r_limit_max = 1200; + m_total_occup_th2 = new TH2F("total_occup", "Occupancy plot for all readouts", 200, z_limit_min, + +z_limit_max, 100, r_limit_min, r_limit_max); + m_total_occup_th2->SetDirectory(dir); + for (auto& name : m_data_names) { + auto count_hist = std::make_shared(("count_" + name).c_str(), + ("Count hits for " + name).c_str(), 100, 0, 30); + count_hist->SetDirectory(dir); + m_hits_count_hists.push_back(count_hist); - m_total_occup_th2 = new TH2F("total_occup", "Occupancy plot for all readouts", 200, z_limit_min, +z_limit_max, 100, r_limit_min, r_limit_max); - m_total_occup_th2->SetDirectory(dir); - - for(auto &name: m_data_names) { - auto count_hist = std::make_shared(("count_" + name).c_str(), ("Count hits for " + name).c_str(), 100, 0, 30); - count_hist->SetDirectory(dir); - m_hits_count_hists.push_back(count_hist); - - auto occup_hist = std::make_shared(("occup_" + name).c_str(), ("Occupancy plot for" + name).c_str(), 100, z_limit_min, z_limit_max, 200, r_limit_min, r_limit_max); - occup_hist->SetDirectory(dir); - m_hits_occup_hists.push_back(occup_hist); - } + auto occup_hist = + std::make_shared(("occup_" + name).c_str(), ("Occupancy plot for" + name).c_str(), + 100, z_limit_min, z_limit_max, 200, r_limit_min, r_limit_max); + occup_hist->SetDirectory(dir); + m_hits_occup_hists.push_back(occup_hist); + } } +void TrackingOccupancyAnalysis::process(const std::shared_ptr& event) { -void TrackingOccupancyAnalysis::process(const std::shared_ptr &event) { - - for(size_t name_index = 0; name_index < m_data_names.size(); name_index++ ) { - std::string data_name = m_data_names[name_index]; - auto &count_hist = m_hits_count_hists[name_index]; - auto &occup_hist = m_hits_occup_hists[name_index]; + for (size_t name_index = 0; name_index < m_data_names.size(); name_index++) { + std::string data_name = m_data_names[name_index]; + auto& count_hist = m_hits_count_hists[name_index]; + auto& occup_hist = m_hits_occup_hists[name_index]; - try { - auto hits = event->Get(data_name); - count_hist->Fill(hits.size()); - for(const auto *hit: hits) { - float x = hit->getPosition().x; - float y = hit->getPosition().y; - float z = hit->getPosition().z; - float r = sqrt(x*x + y*y); - occup_hist->Fill(z, r); - m_total_occup_th2->Fill(z, r); - } - } catch(std::exception& e) { - // silently skip missing collections - } + try { + auto hits = event->Get(data_name); + count_hist->Fill(hits.size()); + for (const auto* hit : hits) { + float x = hit->getPosition().x; + float y = hit->getPosition().y; + float z = hit->getPosition().z; + float r = sqrt(x * x + y * y); + occup_hist->Fill(z, r); + m_total_occup_th2->Fill(z, r); + } + } catch (std::exception& e) { + // silently skip missing collections } + } } diff --git a/src/benchmarks/reconstruction/tracking_occupancy/TrackingOccupancyAnalysis.h b/src/benchmarks/reconstruction/tracking_occupancy/TrackingOccupancyAnalysis.h index 43004436aa..f8447faee2 100644 --- a/src/benchmarks/reconstruction/tracking_occupancy/TrackingOccupancyAnalysis.h +++ b/src/benchmarks/reconstruction/tracking_occupancy/TrackingOccupancyAnalysis.h @@ -16,34 +16,33 @@ class TrackingOccupancyAnalysis { public: - void init(JApplication *app, TDirectory *plugin_tdir); + void init(JApplication* app, TDirectory* plugin_tdir); - void process(const std::shared_ptr &event); + void process(const std::shared_ptr& event); private: - - /// This is edm4hep::SimTrackerHits names of different detector readouts - std::vector m_data_names = { - "SiBarrelHits", // Barrel Tracker - "VertexBarrelHits", // Vertex - "TrackerEndcapHits", // End Cap tracker - // MPGD - "MPGDBarrelHits", - "MPGDDIRCHits", - "OuterMPGDBarrelHits", - "ForwardMPGDEndcapHits", - "BackwardMPGDEndcapHits", - // TOF - "TOFEndcapHits", - "TOFBarrelHits", - }; - - /// Hits count histogram for each hits readout name - std::vector> m_hits_count_hists; - - /// Hits occupancy histogram for each hits readout name - std::vector> m_hits_occup_hists; - - /// Total occupancy of all m_data_names - TH2F * m_total_occup_th2; /// MC Particles px,py + /// This is edm4hep::SimTrackerHits names of different detector readouts + std::vector m_data_names = { + "SiBarrelHits", // Barrel Tracker + "VertexBarrelHits", // Vertex + "TrackerEndcapHits", // End Cap tracker + // MPGD + "MPGDBarrelHits", + "MPGDDIRCHits", + "OuterMPGDBarrelHits", + "ForwardMPGDEndcapHits", + "BackwardMPGDEndcapHits", + // TOF + "TOFEndcapHits", + "TOFBarrelHits", + }; + + /// Hits count histogram for each hits readout name + std::vector> m_hits_count_hists; + + /// Hits occupancy histogram for each hits readout name + std::vector> m_hits_occup_hists; + + /// Total occupancy of all m_data_names + TH2F* m_total_occup_th2; /// MC Particles px,py }; diff --git a/src/benchmarks/reconstruction/tracking_occupancy/TrackingOccupancy_processor.cc b/src/benchmarks/reconstruction/tracking_occupancy/TrackingOccupancy_processor.cc index ddc5149a09..38361d01d6 100644 --- a/src/benchmarks/reconstruction/tracking_occupancy/TrackingOccupancy_processor.cc +++ b/src/benchmarks/reconstruction/tracking_occupancy/TrackingOccupancy_processor.cc @@ -16,62 +16,56 @@ //------------------ // OccupancyAnalysis (Constructor) //------------------ -TrackingOccupancy_processor::TrackingOccupancy_processor(JApplication *app) : - JEventProcessor(app) -{ -} +TrackingOccupancy_processor::TrackingOccupancy_processor(JApplication* app) + : JEventProcessor(app) {} //------------------ // Init //------------------ -void TrackingOccupancy_processor::Init() -{ - std::string plugin_name=("tracking_occupancy"); +void TrackingOccupancy_processor::Init() { + std::string plugin_name = ("tracking_occupancy"); - // Get JANA application - auto *app = GetApplication(); + // Get JANA application + auto* app = GetApplication(); - // Ask service locator a file to write histograms to - auto root_file_service = app->GetService(); + // Ask service locator a file to write histograms to + auto root_file_service = app->GetService(); - // Get TDirectory for histograms root file - auto globalRootLock = app->GetService(); - globalRootLock->acquire_write_lock(); - auto *file = root_file_service->GetHistFile(); - globalRootLock->release_lock(); + // Get TDirectory for histograms root file + auto globalRootLock = app->GetService(); + globalRootLock->acquire_write_lock(); + auto* file = root_file_service->GetHistFile(); + globalRootLock->release_lock(); - // Create a directory for this plugin. And subdirectories for series of histograms - m_dir_main = file->mkdir(plugin_name.c_str()); + // Create a directory for this plugin. And subdirectories for series of histograms + m_dir_main = file->mkdir(plugin_name.c_str()); - // Occupancy analysis - m_occupancy_analysis.init(app, m_dir_main); - m_hit_reco_analysis.init(app, m_dir_main); + // Occupancy analysis + m_occupancy_analysis.init(app, m_dir_main); + m_hit_reco_analysis.init(app, m_dir_main); - // Get log level from user parameter or default - std::string log_level_str = "info"; - m_log = app->GetService()->logger(plugin_name); - app->SetDefaultParameter(plugin_name + ":LogLevel", log_level_str, "LogLevel: trace, debug, info, warn, err, critical, off"); - m_log->set_level(eicrecon::ParseLogLevel(log_level_str)); + // Get log level from user parameter or default + std::string log_level_str = "info"; + m_log = app->GetService()->logger(plugin_name); + app->SetDefaultParameter(plugin_name + ":LogLevel", log_level_str, + "LogLevel: trace, debug, info, warn, err, critical, off"); + m_log->set_level(eicrecon::ParseLogLevel(log_level_str)); } - //------------------ // Process //------------------ -void TrackingOccupancy_processor::Process(const std::shared_ptr& event) -{ - // Process raw hits from DD4Hep - m_occupancy_analysis.process(event); +void TrackingOccupancy_processor::Process(const std::shared_ptr& event) { + // Process raw hits from DD4Hep + m_occupancy_analysis.process(event); - // Process hits reconstructed with - m_hit_reco_analysis.process(event); + // Process hits reconstructed with + m_hit_reco_analysis.process(event); } - //------------------ // Finish //------------------ -void TrackingOccupancy_processor::Finish() -{ - // Nothing to do here +void TrackingOccupancy_processor::Finish() { + // Nothing to do here } diff --git a/src/benchmarks/reconstruction/tracking_occupancy/TrackingOccupancy_processor.h b/src/benchmarks/reconstruction/tracking_occupancy/TrackingOccupancy_processor.h index 9c02f3e08c..c4b4432bb5 100644 --- a/src/benchmarks/reconstruction/tracking_occupancy/TrackingOccupancy_processor.h +++ b/src/benchmarks/reconstruction/tracking_occupancy/TrackingOccupancy_processor.h @@ -12,49 +12,47 @@ #include "HitReconstructionAnalysis.h" #include "TrackingOccupancyAnalysis.h" -class TrackingOccupancy_processor:public JEventProcessor -{ +class TrackingOccupancy_processor : public JEventProcessor { public: - explicit TrackingOccupancy_processor(JApplication *); - ~TrackingOccupancy_processor() override = default; - - //---------------------------- - // Init - // - // This is called once before the first call to the Process method - // below. You may, for example, want to open an output file here. - // Only one thread will call this. - void Init() override; - - //---------------------------- - // Process - // - // This is called for every event. Multiple threads may call this - // simultaneously. If you write something to an output file here - // then make sure to protect it with a mutex or similar mechanism. - // Minimize what is done while locked since that directly affects - // the multi-threaded performance. - void Process(const std::shared_ptr& event) override; - - //---------------------------- - // Finish - // - // This is called once after all events have been processed. You may, - // for example, want to close an output file here. - // Only one thread will call this. - void Finish() override; + explicit TrackingOccupancy_processor(JApplication*); + ~TrackingOccupancy_processor() override = default; + + //---------------------------- + // Init + // + // This is called once before the first call to the Process method + // below. You may, for example, want to open an output file here. + // Only one thread will call this. + void Init() override; + + //---------------------------- + // Process + // + // This is called for every event. Multiple threads may call this + // simultaneously. If you write something to an output file here + // then make sure to protect it with a mutex or similar mechanism. + // Minimize what is done while locked since that directly affects + // the multi-threaded performance. + void Process(const std::shared_ptr& event) override; + + //---------------------------- + // Finish + // + // This is called once after all events have been processed. You may, + // for example, want to close an output file here. + // Only one thread will call this. + void Finish() override; private: + TrackingOccupancyAnalysis m_occupancy_analysis; + HitReconstructionAnalysis m_hit_reco_analysis; - TrackingOccupancyAnalysis m_occupancy_analysis; - HitReconstructionAnalysis m_hit_reco_analysis; + TDirectory* m_dir_main; /// Main TDirectory for this plugin 'occupancy_ana' + TH1F* m_th1_prt_pz; /// MC Particles pz + TH1F* m_th1_prt_energy; /// MC Particles total E + TH1F* m_th1_prt_theta; /// MC Particles theta angle + TH1F* m_th1_prt_phi; /// MC Particles phi angle + TH2F* m_th2_prt_pxy; /// MC Particles px,py - TDirectory* m_dir_main; /// Main TDirectory for this plugin 'occupancy_ana' - TH1F * m_th1_prt_pz; /// MC Particles pz - TH1F * m_th1_prt_energy; /// MC Particles total E - TH1F * m_th1_prt_theta; /// MC Particles theta angle - TH1F * m_th1_prt_phi; /// MC Particles phi angle - TH2F * m_th2_prt_pxy; /// MC Particles px,py - - std::shared_ptr m_log; + std::shared_ptr m_log; }; diff --git a/src/benchmarks/reconstruction/tracking_occupancy/tracking_occupancy.cc b/src/benchmarks/reconstruction/tracking_occupancy/tracking_occupancy.cc index 426472a153..5c37ffbc8f 100644 --- a/src/benchmarks/reconstruction/tracking_occupancy/tracking_occupancy.cc +++ b/src/benchmarks/reconstruction/tracking_occupancy/tracking_occupancy.cc @@ -8,8 +8,8 @@ #include "TrackingOccupancy_processor.h" extern "C" { - void InitPlugin(JApplication *app) { - InitJANAPlugin(app); - app->Add(new TrackingOccupancy_processor(app)); - } +void InitPlugin(JApplication* app) { + InitJANAPlugin(app); + app->Add(new TrackingOccupancy_processor(app)); +} } diff --git a/src/detectors/B0ECAL/B0ECAL.cc b/src/detectors/B0ECAL/B0ECAL.cc index f7ab44c002..12b2c749a0 100644 --- a/src/detectors/B0ECAL/B0ECAL.cc +++ b/src/detectors/B0ECAL/B0ECAL.cc @@ -17,94 +17,74 @@ #include "factories/calorimetry/CalorimeterTruthClustering_factory.h" extern "C" { - void InitPlugin(JApplication *app) { +void InitPlugin(JApplication* app) { - using namespace eicrecon; + using namespace eicrecon; - InitJANAPlugin(app); + InitJANAPlugin(app); - app->Add(new JOmniFactoryGeneratorT( - "B0ECalRawHits", {"B0ECalHits"}, {"B0ECalRawHits"}, - { - .eRes = {0.0 * sqrt(dd4hep::GeV), 0.02, 0.0 * dd4hep::GeV}, - .tRes = 0.0 * dd4hep::ns, - .threshold= 5.0 * dd4hep::MeV, - .capADC = 16384, - .dyRangeADC = 20 * dd4hep::GeV, - .pedMeanADC = 100, - .pedSigmaADC = 1, - .resolutionTDC = 1e-11, - .corrMeanScale = 1.0, - .readout = "B0ECalHits", - }, - app - )); - app->Add(new JOmniFactoryGeneratorT( - "B0ECalRecHits", {"B0ECalRawHits"}, {"B0ECalRecHits"}, - { - .capADC = 16384, - .dyRangeADC = 20. * dd4hep::GeV, - .pedMeanADC = 100, - .pedSigmaADC = 1, - .resolutionTDC = 1e-11, - .thresholdFactor = 0.0, - .thresholdValue = 0.0, - .sampFrac = 0.998, - .readout = "B0ECalHits", - .sectorField = "sector", - }, - app - )); - app->Add(new JOmniFactoryGeneratorT( - "B0ECalTruthProtoClusters", {"B0ECalRecHits", "B0ECalHits"}, {"B0ECalTruthProtoClusters"}, - app - )); - app->Add(new JOmniFactoryGeneratorT( - "B0ECalIslandProtoClusters", {"B0ECalRecHits"}, {"B0ECalIslandProtoClusters"}, - { - .sectorDist = 5.0 * dd4hep::cm, - .dimScaledLocalDistXY = {1.8,1.8}, - .splitCluster = false, - .minClusterHitEdep = 1.0 * dd4hep::MeV, - .minClusterCenterEdep = 30.0 * dd4hep::MeV, - .transverseEnergyProfileMetric = "globalDistEtaPhi", - .transverseEnergyProfileScale = 1., - }, - app - )); + app->Add(new JOmniFactoryGeneratorT( + "B0ECalRawHits", {"B0ECalHits"}, {"B0ECalRawHits"}, + { + .eRes = {0.0 * sqrt(dd4hep::GeV), 0.02, 0.0 * dd4hep::GeV}, + .tRes = 0.0 * dd4hep::ns, + .threshold = 5.0 * dd4hep::MeV, + .capADC = 16384, + .dyRangeADC = 20 * dd4hep::GeV, + .pedMeanADC = 100, + .pedSigmaADC = 1, + .resolutionTDC = 1e-11, + .corrMeanScale = 1.0, + .readout = "B0ECalHits", + }, + app)); + app->Add(new JOmniFactoryGeneratorT( + "B0ECalRecHits", {"B0ECalRawHits"}, {"B0ECalRecHits"}, + { + .capADC = 16384, + .dyRangeADC = 20. * dd4hep::GeV, + .pedMeanADC = 100, + .pedSigmaADC = 1, + .resolutionTDC = 1e-11, + .thresholdFactor = 0.0, + .thresholdValue = 0.0, + .sampFrac = 0.998, + .readout = "B0ECalHits", + .sectorField = "sector", + }, + app)); + app->Add(new JOmniFactoryGeneratorT( + "B0ECalTruthProtoClusters", {"B0ECalRecHits", "B0ECalHits"}, {"B0ECalTruthProtoClusters"}, + app)); + app->Add(new JOmniFactoryGeneratorT( + "B0ECalIslandProtoClusters", {"B0ECalRecHits"}, {"B0ECalIslandProtoClusters"}, + { + .sectorDist = 5.0 * dd4hep::cm, + .dimScaledLocalDistXY = {1.8, 1.8}, + .splitCluster = false, + .minClusterHitEdep = 1.0 * dd4hep::MeV, + .minClusterCenterEdep = 30.0 * dd4hep::MeV, + .transverseEnergyProfileMetric = "globalDistEtaPhi", + .transverseEnergyProfileScale = 1., + }, + app)); - app->Add( - new JOmniFactoryGeneratorT( - "B0ECalClusters", - {"B0ECalIslandProtoClusters", // edm4eic::ProtoClusterCollection - "B0ECalHits"}, // edm4hep::SimCalorimeterHitCollection - {"B0ECalClusters", // edm4eic::Cluster - "B0ECalClusterAssociations"}, // edm4eic::MCRecoClusterParticleAssociation - { - .energyWeight = "log", - .sampFrac = 1.0, - .logWeightBase = 3.6, - .enableEtaBounds = false - }, - app - ) - ); + app->Add(new JOmniFactoryGeneratorT( + "B0ECalClusters", + {"B0ECalIslandProtoClusters", // edm4eic::ProtoClusterCollection + "B0ECalHits"}, // edm4hep::SimCalorimeterHitCollection + {"B0ECalClusters", // edm4eic::Cluster + "B0ECalClusterAssociations"}, // edm4eic::MCRecoClusterParticleAssociation + {.energyWeight = "log", .sampFrac = 1.0, .logWeightBase = 3.6, .enableEtaBounds = false}, + app)); - app->Add( - new JOmniFactoryGeneratorT( - "B0ECalTruthClusters", - {"B0ECalTruthProtoClusters", // edm4eic::ProtoClusterCollection - "B0ECalHits"}, // edm4hep::SimCalorimeterHitCollection - {"B0ECalTruthClusters", // edm4eic::Cluster - "B0ECalTruthClusterAssociations"}, // edm4eic::MCRecoClusterParticleAssociation - { - .energyWeight = "log", - .sampFrac = 1.0, - .logWeightBase = 6.2, - .enableEtaBounds = false - }, - app - ) - ); - } + app->Add(new JOmniFactoryGeneratorT( + "B0ECalTruthClusters", + {"B0ECalTruthProtoClusters", // edm4eic::ProtoClusterCollection + "B0ECalHits"}, // edm4hep::SimCalorimeterHitCollection + {"B0ECalTruthClusters", // edm4eic::Cluster + "B0ECalTruthClusterAssociations"}, // edm4eic::MCRecoClusterParticleAssociation + {.energyWeight = "log", .sampFrac = 1.0, .logWeightBase = 6.2, .enableEtaBounds = false}, + app)); +} } diff --git a/src/detectors/B0TRK/B0TRK.cc b/src/detectors/B0TRK/B0TRK.cc index a6f0473391..e1b337b987 100644 --- a/src/detectors/B0TRK/B0TRK.cc +++ b/src/detectors/B0TRK/B0TRK.cc @@ -13,33 +13,26 @@ #include "factories/tracking/TrackerHitReconstruction_factory.h" extern "C" { -void InitPlugin(JApplication *app) { - InitJANAPlugin(app); +void InitPlugin(JApplication* app) { + InitJANAPlugin(app); - using namespace eicrecon; + using namespace eicrecon; - // Digitization - app->Add(new JOmniFactoryGeneratorT( - "B0TrackerRawHits", - {"B0TrackerHits"}, - {"B0TrackerRawHits"}, - { - .threshold = 10.0 * dd4hep::keV, - .timeResolution = 8, - }, - app - )); - - // Convert raw digitized hits into hits with geometry info (ready for tracking) - app->Add(new JOmniFactoryGeneratorT( - "B0TrackerRecHits", - {"B0TrackerRawHits"}, - {"B0TrackerRecHits"}, - { - .timeResolution = 8, - }, - app - )); + // Digitization + app->Add(new JOmniFactoryGeneratorT( + "B0TrackerRawHits", {"B0TrackerHits"}, {"B0TrackerRawHits"}, + { + .threshold = 10.0 * dd4hep::keV, + .timeResolution = 8, + }, + app)); + // Convert raw digitized hits into hits with geometry info (ready for tracking) + app->Add(new JOmniFactoryGeneratorT( + "B0TrackerRecHits", {"B0TrackerRawHits"}, {"B0TrackerRecHits"}, + { + .timeResolution = 8, + }, + app)); } } // extern "C" diff --git a/src/detectors/BEMC/BEMC.cc b/src/detectors/BEMC/BEMC.cc index 421a2138b7..c6d2d2eedd 100644 --- a/src/detectors/BEMC/BEMC.cc +++ b/src/detectors/BEMC/BEMC.cc @@ -19,191 +19,164 @@ #include "factories/calorimetry/ImagingTopoCluster_factory.h" #include "factories/calorimetry/TruthEnergyPositionClusterMerger_factory.h" - extern "C" { - void InitPlugin(JApplication *app) { - - using namespace eicrecon; +void InitPlugin(JApplication* app) { - InitJANAPlugin(app); + using namespace eicrecon; + InitJANAPlugin(app); - // Make sure digi and reco use the same value - decltype(CalorimeterHitDigiConfig::capADC) EcalBarrelScFi_capADC = 16384; //16384, 14bit ADC - decltype(CalorimeterHitDigiConfig::dyRangeADC) EcalBarrelScFi_dyRangeADC = 1500 * dd4hep::MeV; - decltype(CalorimeterHitDigiConfig::pedMeanADC) EcalBarrelScFi_pedMeanADC = 100; - decltype(CalorimeterHitDigiConfig::pedSigmaADC) EcalBarrelScFi_pedSigmaADC = 1; - decltype(CalorimeterHitDigiConfig::resolutionTDC) EcalBarrelScFi_resolutionTDC = 10 * dd4hep::picosecond; - app->Add(new JOmniFactoryGeneratorT( - "EcalBarrelScFiRawHits", - {"EcalBarrelScFiHits"}, - {"EcalBarrelScFiRawHits"}, - { - .eRes = {0.0 * sqrt(dd4hep::GeV), 0.0, 0.0 * dd4hep::GeV}, - .tRes = 0.0 * dd4hep::ns, - .threshold = 0.0*dd4hep::keV, // threshold is set in ADC in reco - .capADC = EcalBarrelScFi_capADC, - .dyRangeADC = EcalBarrelScFi_dyRangeADC, - .pedMeanADC = EcalBarrelScFi_pedMeanADC, - .pedSigmaADC = EcalBarrelScFi_pedSigmaADC, - .resolutionTDC = EcalBarrelScFi_resolutionTDC, - .corrMeanScale = 1.0, - .readout = "EcalBarrelScFiHits", - .fields = {"fiber", "z"}, - }, - app // TODO: Remove me once fixed - )); - app->Add(new JOmniFactoryGeneratorT( - "EcalBarrelScFiRecHits", {"EcalBarrelScFiRawHits"}, {"EcalBarrelScFiRecHits"}, - { - .capADC = EcalBarrelScFi_capADC, - .dyRangeADC = EcalBarrelScFi_dyRangeADC, - .pedMeanADC = EcalBarrelScFi_pedMeanADC, - .pedSigmaADC = EcalBarrelScFi_pedSigmaADC, // not needed; use only thresholdValue - .resolutionTDC = EcalBarrelScFi_resolutionTDC, - .thresholdFactor = 0.0, // use only thresholdValue - .thresholdValue = 5.0, // 16384 ADC counts/1500 MeV * 0.5 MeV (desired threshold) = 5.46 - .sampFrac = 0.10200085, - .readout = "EcalBarrelScFiHits", - .layerField = "layer", - .sectorField = "sector", - .localDetFields = {"system"}, - // here we want to use grid center position (XY) but keeps the z information from fiber-segment - // TODO: a more realistic way to get z is to reconstruct it from timing - .maskPos = "xy", - .maskPosFields = {"fiber", "z"}, - }, - app // TODO: Remove me once fixed - )); - app->Add(new JOmniFactoryGeneratorT( - "EcalBarrelScFiProtoClusters", {"EcalBarrelScFiRecHits"}, {"EcalBarrelScFiProtoClusters"}, - { - .sectorDist = 50. * dd4hep::mm, - .localDistXZ = {40 * dd4hep::mm, 40 * dd4hep::mm}, - .splitCluster = false, - .minClusterHitEdep = 5.0 * dd4hep::MeV, - .minClusterCenterEdep = 100.0 * dd4hep::MeV, - }, - app // TODO: Remove me once fixed - )); - app->Add( - new JOmniFactoryGeneratorT( - "EcalBarrelScFiClusters", - {"EcalBarrelScFiProtoClusters", // edm4eic::ProtoClusterCollection - "EcalBarrelScFiHits"}, // edm4hep::SimCalorimeterHitCollection - {"EcalBarrelScFiClusters", // edm4eic::Cluster - "EcalBarrelScFiClusterAssociations"}, // edm4eic::MCRecoClusterParticleAssociation - { - .energyWeight = "log", - .sampFrac = 1.0, - .logWeightBase = 6.2, - .enableEtaBounds = false - }, - app // TODO: Remove me once fixed - ) - ); + // Make sure digi and reco use the same value + decltype(CalorimeterHitDigiConfig::capADC) EcalBarrelScFi_capADC = 16384; //16384, 14bit ADC + decltype(CalorimeterHitDigiConfig::dyRangeADC) EcalBarrelScFi_dyRangeADC = 1500 * dd4hep::MeV; + decltype(CalorimeterHitDigiConfig::pedMeanADC) EcalBarrelScFi_pedMeanADC = 100; + decltype(CalorimeterHitDigiConfig::pedSigmaADC) EcalBarrelScFi_pedSigmaADC = 1; + decltype(CalorimeterHitDigiConfig::resolutionTDC) EcalBarrelScFi_resolutionTDC = + 10 * dd4hep::picosecond; + app->Add(new JOmniFactoryGeneratorT( + "EcalBarrelScFiRawHits", {"EcalBarrelScFiHits"}, {"EcalBarrelScFiRawHits"}, + { + .eRes = {0.0 * sqrt(dd4hep::GeV), 0.0, 0.0 * dd4hep::GeV}, + .tRes = 0.0 * dd4hep::ns, + .threshold = 0.0 * dd4hep::keV, // threshold is set in ADC in reco + .capADC = EcalBarrelScFi_capADC, + .dyRangeADC = EcalBarrelScFi_dyRangeADC, + .pedMeanADC = EcalBarrelScFi_pedMeanADC, + .pedSigmaADC = EcalBarrelScFi_pedSigmaADC, + .resolutionTDC = EcalBarrelScFi_resolutionTDC, + .corrMeanScale = 1.0, + .readout = "EcalBarrelScFiHits", + .fields = {"fiber", "z"}, + }, + app // TODO: Remove me once fixed + )); + app->Add(new JOmniFactoryGeneratorT( + "EcalBarrelScFiRecHits", {"EcalBarrelScFiRawHits"}, {"EcalBarrelScFiRecHits"}, + { + .capADC = EcalBarrelScFi_capADC, + .dyRangeADC = EcalBarrelScFi_dyRangeADC, + .pedMeanADC = EcalBarrelScFi_pedMeanADC, + .pedSigmaADC = EcalBarrelScFi_pedSigmaADC, // not needed; use only thresholdValue + .resolutionTDC = EcalBarrelScFi_resolutionTDC, + .thresholdFactor = 0.0, // use only thresholdValue + .thresholdValue = 5.0, // 16384 ADC counts/1500 MeV * 0.5 MeV (desired threshold) = 5.46 + .sampFrac = 0.10200085, + .readout = "EcalBarrelScFiHits", + .layerField = "layer", + .sectorField = "sector", + .localDetFields = {"system"}, + // here we want to use grid center position (XY) but keeps the z information from fiber-segment + // TODO: a more realistic way to get z is to reconstruct it from timing + .maskPos = "xy", + .maskPosFields = {"fiber", "z"}, + }, + app // TODO: Remove me once fixed + )); + app->Add(new JOmniFactoryGeneratorT( + "EcalBarrelScFiProtoClusters", {"EcalBarrelScFiRecHits"}, {"EcalBarrelScFiProtoClusters"}, + { + .sectorDist = 50. * dd4hep::mm, + .localDistXZ = {40 * dd4hep::mm, 40 * dd4hep::mm}, + .splitCluster = false, + .minClusterHitEdep = 5.0 * dd4hep::MeV, + .minClusterCenterEdep = 100.0 * dd4hep::MeV, + }, + app // TODO: Remove me once fixed + )); + app->Add(new JOmniFactoryGeneratorT( + "EcalBarrelScFiClusters", + {"EcalBarrelScFiProtoClusters", // edm4eic::ProtoClusterCollection + "EcalBarrelScFiHits"}, // edm4hep::SimCalorimeterHitCollection + {"EcalBarrelScFiClusters", // edm4eic::Cluster + "EcalBarrelScFiClusterAssociations"}, // edm4eic::MCRecoClusterParticleAssociation + {.energyWeight = "log", .sampFrac = 1.0, .logWeightBase = 6.2, .enableEtaBounds = false}, + app // TODO: Remove me once fixed + )); - // Make sure digi and reco use the same value - decltype(CalorimeterHitDigiConfig::capADC) EcalBarrelImaging_capADC = 8192; //8192, 13bit ADC - decltype(CalorimeterHitDigiConfig::dyRangeADC) EcalBarrelImaging_dyRangeADC = 3 * dd4hep::MeV; - decltype(CalorimeterHitDigiConfig::pedMeanADC) EcalBarrelImaging_pedMeanADC = 14; // Noise floor at 5 keV: 8192 / 3 * 0.005 - decltype(CalorimeterHitDigiConfig::pedSigmaADC) EcalBarrelImaging_pedSigmaADC = 5; // Upper limit for sigma for AstroPix - decltype(CalorimeterHitDigiConfig::resolutionTDC) EcalBarrelImaging_resolutionTDC = 3.25 * dd4hep::nanosecond; - app->Add(new JOmniFactoryGeneratorT( - "EcalBarrelImagingRawHits", - {"EcalBarrelImagingHits"}, - {"EcalBarrelImagingRawHits"}, - { - .eRes = {0.0 * sqrt(dd4hep::GeV), 0.02, 0.0 * dd4hep::GeV}, - .tRes = 0.0 * dd4hep::ns, - .capADC = EcalBarrelImaging_capADC, - .dyRangeADC = EcalBarrelImaging_dyRangeADC, - .pedMeanADC = EcalBarrelImaging_pedMeanADC, - .pedSigmaADC = EcalBarrelImaging_pedSigmaADC, - .resolutionTDC = EcalBarrelImaging_resolutionTDC, - .corrMeanScale = 1.0, - .readout = "EcalBarrelImagingHits", - }, - app // TODO: Remove me once fixed - )); - app->Add(new JOmniFactoryGeneratorT( - "EcalBarrelImagingRecHits", {"EcalBarrelImagingRawHits"}, {"EcalBarrelImagingRecHits"}, - { - .capADC = EcalBarrelImaging_capADC, - .dyRangeADC = EcalBarrelImaging_dyRangeADC, - .pedMeanADC = EcalBarrelImaging_pedMeanADC, - .pedSigmaADC = EcalBarrelImaging_pedSigmaADC, // not needed; use only thresholdValue - .resolutionTDC = EcalBarrelImaging_resolutionTDC, - .thresholdFactor = 0.0, // use only thresholdValue - .thresholdValue = 41, // 8192 ADC counts/3 MeV * 0.015 MeV (desired threshold) = 41 - .sampFrac = 0.00619766, - .readout = "EcalBarrelImagingHits", - .layerField = "layer", - .sectorField = "sector", - }, - app // TODO: Remove me once fixed - )); - app->Add(new JOmniFactoryGeneratorT( - "EcalBarrelImagingProtoClusters", {"EcalBarrelImagingRecHits"}, {"EcalBarrelImagingProtoClusters"}, - { - .neighbourLayersRange = 2, // # id diff for adjacent layer - .localDistXY = {2.0 * dd4hep::mm, 2 * dd4hep::mm}, // # same layer - .layerDistEtaPhi = {10 * dd4hep::mrad, 10 * dd4hep::mrad}, // # adjacent layer - .sectorDist = 3.0 * dd4hep::cm, - .minClusterHitEdep = 0, - .minClusterCenterEdep = 0, - .minClusterEdep = 100 * dd4hep::MeV, - .minClusterNhits = 10, - }, - app // TODO: Remove me once fixed - )); + // Make sure digi and reco use the same value + decltype(CalorimeterHitDigiConfig::capADC) EcalBarrelImaging_capADC = 8192; //8192, 13bit ADC + decltype(CalorimeterHitDigiConfig::dyRangeADC) EcalBarrelImaging_dyRangeADC = 3 * dd4hep::MeV; + decltype(CalorimeterHitDigiConfig::pedMeanADC) EcalBarrelImaging_pedMeanADC = + 14; // Noise floor at 5 keV: 8192 / 3 * 0.005 + decltype(CalorimeterHitDigiConfig::pedSigmaADC) EcalBarrelImaging_pedSigmaADC = + 5; // Upper limit for sigma for AstroPix + decltype(CalorimeterHitDigiConfig::resolutionTDC) EcalBarrelImaging_resolutionTDC = + 3.25 * dd4hep::nanosecond; + app->Add(new JOmniFactoryGeneratorT( + "EcalBarrelImagingRawHits", {"EcalBarrelImagingHits"}, {"EcalBarrelImagingRawHits"}, + { + .eRes = {0.0 * sqrt(dd4hep::GeV), 0.02, 0.0 * dd4hep::GeV}, + .tRes = 0.0 * dd4hep::ns, + .capADC = EcalBarrelImaging_capADC, + .dyRangeADC = EcalBarrelImaging_dyRangeADC, + .pedMeanADC = EcalBarrelImaging_pedMeanADC, + .pedSigmaADC = EcalBarrelImaging_pedSigmaADC, + .resolutionTDC = EcalBarrelImaging_resolutionTDC, + .corrMeanScale = 1.0, + .readout = "EcalBarrelImagingHits", + }, + app // TODO: Remove me once fixed + )); + app->Add(new JOmniFactoryGeneratorT( + "EcalBarrelImagingRecHits", {"EcalBarrelImagingRawHits"}, {"EcalBarrelImagingRecHits"}, + { + .capADC = EcalBarrelImaging_capADC, + .dyRangeADC = EcalBarrelImaging_dyRangeADC, + .pedMeanADC = EcalBarrelImaging_pedMeanADC, + .pedSigmaADC = EcalBarrelImaging_pedSigmaADC, // not needed; use only thresholdValue + .resolutionTDC = EcalBarrelImaging_resolutionTDC, + .thresholdFactor = 0.0, // use only thresholdValue + .thresholdValue = 41, // 8192 ADC counts/3 MeV * 0.015 MeV (desired threshold) = 41 + .sampFrac = 0.00619766, + .readout = "EcalBarrelImagingHits", + .layerField = "layer", + .sectorField = "sector", + }, + app // TODO: Remove me once fixed + )); + app->Add(new JOmniFactoryGeneratorT( + "EcalBarrelImagingProtoClusters", {"EcalBarrelImagingRecHits"}, + {"EcalBarrelImagingProtoClusters"}, + { + .neighbourLayersRange = 2, // # id diff for adjacent layer + .localDistXY = {2.0 * dd4hep::mm, 2 * dd4hep::mm}, // # same layer + .layerDistEtaPhi = {10 * dd4hep::mrad, 10 * dd4hep::mrad}, // # adjacent layer + .sectorDist = 3.0 * dd4hep::cm, + .minClusterHitEdep = 0, + .minClusterCenterEdep = 0, + .minClusterEdep = 100 * dd4hep::MeV, + .minClusterNhits = 10, + }, + app // TODO: Remove me once fixed + )); - app->Add(new JOmniFactoryGeneratorT( - "EcalBarrelImagingClusters", - {"EcalBarrelImagingProtoClusters", - "EcalBarrelImagingHits"}, - {"EcalBarrelImagingClusters", - "EcalBarrelImagingClusterAssociations", - "EcalBarrelImagingLayers" - }, - { - .trackStopLayer = 6, - }, - app // TODO: Remove me once fixed - )); - app->Add(new JOmniFactoryGeneratorT( - "EcalBarrelClusters", - { - "EcalBarrelScFiClusters", - "EcalBarrelScFiClusterAssociations", - "EcalBarrelImagingClusters", - "EcalBarrelImagingClusterAssociations" - }, - { - "EcalBarrelClusters", - "EcalBarrelClusterAssociations" - }, - { - .energyRelTolerance = 0.5, - .phiTolerance = 0.1, - .etaTolerance = 0.2, - }, - app // TODO: Remove me once fixed - )); - app->Add(new JOmniFactoryGeneratorT( - "EcalBarrelTruthClusters", - { - "MCParticles", - "EcalBarrelScFiClusters", - "EcalBarrelScFiClusterAssociations", - "EcalBarrelImagingClusters", - "EcalBarrelImagingClusterAssociations" - }, - { - "EcalBarrelTruthClusters", - "EcalBarrelTruthClusterAssociations" - }, - app // TODO: Remove me once fixed - )); - } + app->Add(new JOmniFactoryGeneratorT( + "EcalBarrelImagingClusters", {"EcalBarrelImagingProtoClusters", "EcalBarrelImagingHits"}, + {"EcalBarrelImagingClusters", "EcalBarrelImagingClusterAssociations", + "EcalBarrelImagingLayers"}, + { + .trackStopLayer = 6, + }, + app // TODO: Remove me once fixed + )); + app->Add(new JOmniFactoryGeneratorT( + "EcalBarrelClusters", + {"EcalBarrelScFiClusters", "EcalBarrelScFiClusterAssociations", "EcalBarrelImagingClusters", + "EcalBarrelImagingClusterAssociations"}, + {"EcalBarrelClusters", "EcalBarrelClusterAssociations"}, + { + .energyRelTolerance = 0.5, + .phiTolerance = 0.1, + .etaTolerance = 0.2, + }, + app // TODO: Remove me once fixed + )); + app->Add(new JOmniFactoryGeneratorT( + "EcalBarrelTruthClusters", + {"MCParticles", "EcalBarrelScFiClusters", "EcalBarrelScFiClusterAssociations", + "EcalBarrelImagingClusters", "EcalBarrelImagingClusterAssociations"}, + {"EcalBarrelTruthClusters", "EcalBarrelTruthClusterAssociations"}, + app // TODO: Remove me once fixed + )); +} } diff --git a/src/detectors/BHCAL/BHCAL.cc b/src/detectors/BHCAL/BHCAL.cc index a5670ab37d..a7345662fc 100644 --- a/src/detectors/BHCAL/BHCAL.cc +++ b/src/detectors/BHCAL/BHCAL.cc @@ -23,158 +23,147 @@ extern "C" { - bool UseSectorIndexedBHCalReadout(JApplication *app) { - - using namespace eicrecon; - - // grab detector & segmentation descriptor - auto detector = app->GetService()->detector(); - dd4hep::IDDescriptor descriptor; - try { - descriptor = detector->readout("HcalBarrelHits").idSpec(); - } catch(const std::runtime_error &e) { - // detector not found in the geometry, result should not matter - - // default to non-deprecated behavior - return true; - } - - // check if sector field is present - bool useSectorIndex = false; - try { - auto sector = descriptor.field("sector"); - return true; - } catch(const std::runtime_error &e) { - return false; - } - - } // end 'UseSectorIndexedBHCalReadout(JApplication*)' - - void InitPlugin(JApplication *app) { - - using namespace eicrecon; - - InitJANAPlugin(app); - - // Make sure digi and reco use the same value - decltype(CalorimeterHitDigiConfig::capADC) HcalBarrel_capADC = 65536; //65536, 16bit ADC - decltype(CalorimeterHitDigiConfig::dyRangeADC) HcalBarrel_dyRangeADC = 1.0 * dd4hep::GeV; - decltype(CalorimeterHitDigiConfig::pedMeanADC) HcalBarrel_pedMeanADC = 300; - decltype(CalorimeterHitDigiConfig::pedSigmaADC) HcalBarrel_pedSigmaADC = 2; - decltype(CalorimeterHitDigiConfig::resolutionTDC) HcalBarrel_resolutionTDC = 1 * dd4hep::picosecond; - - // Set default adjacency matrix. Magic constants: - // 320 - number of tiles per row - decltype(CalorimeterIslandClusterConfig::adjacencyMatrix) HcalBarrel_adjacencyMatrix = - "(" - // check for vertically adjacent tiles - " ( (abs(eta_1 - eta_2) == 1) && (abs(phi_1 - phi_2) == 0) ) ||" - // check for horizontally adjacent tiles - " ( (abs(eta_1 - eta_2) == 0) && (abs(phi_1 - phi_2) == 1) ) ||" - // check for horizontally adjacent tiles at wraparound - " ( (abs(eta_1 - eta_2) == 0) && (abs(phi_1 - phi_2) == (320 - 1)) )" - ") == 1"; - - // If using readout structure with sector segmentation, - // ensure adjacency matrix uses sector indices - if ( UseSectorIndexedBHCalReadout(app) ) { - HcalBarrel_adjacencyMatrix = - "(" - " abs(fmod(tower_1, 24) - fmod(tower_2, 24))" - " + min(" - " abs((sector_1 - sector_2) * (2 * 5) + (floor(tower_1 / 24) - floor(tower_2 / 24)) * 5 + fmod(tile_1, 5) - fmod(tile_2, 5))," - " (32 * 2 * 5) - abs((sector_1 - sector_2) * (2 * 5) + (floor(tower_1 / 24) - floor(tower_2 / 24)) * 5 + fmod(tile_1, 5) - fmod(tile_2, 5))" - " )" - ") == 1"; - } - - app->Add(new JOmniFactoryGeneratorT( - "HcalBarrelRawHits", {"HcalBarrelHits"}, {"HcalBarrelRawHits"}, - { - .eRes = {}, - .tRes = 0.0 * dd4hep::ns, - .threshold = 0.0, // Use ADC cut instead - .capADC = HcalBarrel_capADC, - .capTime = 100, // given in ns, 4 samples in HGCROC - .dyRangeADC = HcalBarrel_dyRangeADC, - .pedMeanADC = HcalBarrel_pedMeanADC, - .pedSigmaADC = HcalBarrel_pedSigmaADC, - .resolutionTDC = HcalBarrel_resolutionTDC, - .corrMeanScale = 1.0, - .readout = "HcalBarrelHits", - }, - app // TODO: Remove me once fixed - )); - app->Add(new JOmniFactoryGeneratorT( - "HcalBarrelRecHits", {"HcalBarrelRawHits"}, {"HcalBarrelRecHits"}, - { - .capADC = HcalBarrel_capADC, - .dyRangeADC = HcalBarrel_dyRangeADC, - .pedMeanADC = HcalBarrel_pedMeanADC, - .pedSigmaADC = HcalBarrel_pedSigmaADC, // not used; relying on energy cut - .resolutionTDC = HcalBarrel_resolutionTDC, - .thresholdFactor = 0.0, // not used; relying on flat ADC cut - .thresholdValue = 33, // pedSigmaADC + thresholdValue = half-MIP (333 ADC) - .sampFrac = 0.033, // average, from sPHENIX simulations - .readout = "HcalBarrelHits", - .layerField = "", - .sectorField = "", - }, - app // TODO: Remove me once fixed - )); - app->Add(new JOmniFactoryGeneratorT( - "HcalBarrelTruthProtoClusters", {"HcalBarrelRecHits", "HcalBarrelHits"}, {"HcalBarrelTruthProtoClusters"}, - app // TODO: Remove me once fixed - )); - app->Add(new JOmniFactoryGeneratorT( - "HcalBarrelIslandProtoClusters", {"HcalBarrelRecHits"}, {"HcalBarrelIslandProtoClusters"}, - { - .adjacencyMatrix = HcalBarrel_adjacencyMatrix, - .readout = "HcalBarrelHits", - .sectorDist = 5.0 * dd4hep::cm, - .localDistXY = {15*dd4hep::mm, 15*dd4hep::mm}, - .dimScaledLocalDistXY = {50.0*dd4hep::mm, 50.0*dd4hep::mm}, - .splitCluster = false, - .minClusterHitEdep = 5.0 * dd4hep::MeV, - .minClusterCenterEdep = 30.0 * dd4hep::MeV, - .transverseEnergyProfileMetric = "globalDistEtaPhi", - .transverseEnergyProfileScale = 1., - }, - app // TODO: Remove me once fixed - )); - - app->Add( - new JOmniFactoryGeneratorT( - "HcalBarrelClusters", - {"HcalBarrelIslandProtoClusters", // edm4eic::ProtoClusterCollection - "HcalBarrelHits"}, // edm4hep::SimCalorimeterHitCollection - {"HcalBarrelClusters", // edm4eic::Cluster - "HcalBarrelClusterAssociations"}, // edm4eic::MCRecoClusterParticleAssociation - { - .energyWeight = "log", - .sampFrac = 1.0, - .logWeightBase = 6.2, - .enableEtaBounds = false - }, - app // TODO: Remove me once fixed - ) - ); - - app->Add( - new JOmniFactoryGeneratorT( - "HcalBarrelTruthClusters", - {"HcalBarrelTruthProtoClusters", // edm4eic::ProtoClusterCollection - "HcalBarrelHits"}, // edm4hep::SimCalorimeterHitCollection - {"HcalBarrelTruthClusters", // edm4eic::Cluster - "HcalBarrelTruthClusterAssociations"}, // edm4eic::MCRecoClusterParticleAssociation - { - .energyWeight = "log", - .sampFrac = 1.0, - .logWeightBase = 6.2, - .enableEtaBounds = false - }, - app // TODO: Remove me once fixed - ) - ); - - } +bool UseSectorIndexedBHCalReadout(JApplication* app) { + + using namespace eicrecon; + + // grab detector & segmentation descriptor + auto detector = app->GetService()->detector(); + dd4hep::IDDescriptor descriptor; + try { + descriptor = detector->readout("HcalBarrelHits").idSpec(); + } catch (const std::runtime_error& e) { + // detector not found in the geometry, result should not matter - + // default to non-deprecated behavior + return true; + } + + // check if sector field is present + bool useSectorIndex = false; + try { + auto sector = descriptor.field("sector"); + return true; + } catch (const std::runtime_error& e) { + return false; + } + +} // end 'UseSectorIndexedBHCalReadout(JApplication*)' + +void InitPlugin(JApplication* app) { + + using namespace eicrecon; + + InitJANAPlugin(app); + + // Make sure digi and reco use the same value + decltype(CalorimeterHitDigiConfig::capADC) HcalBarrel_capADC = 65536; //65536, 16bit ADC + decltype(CalorimeterHitDigiConfig::dyRangeADC) HcalBarrel_dyRangeADC = 1.0 * dd4hep::GeV; + decltype(CalorimeterHitDigiConfig::pedMeanADC) HcalBarrel_pedMeanADC = 300; + decltype(CalorimeterHitDigiConfig::pedSigmaADC) HcalBarrel_pedSigmaADC = 2; + decltype(CalorimeterHitDigiConfig::resolutionTDC) HcalBarrel_resolutionTDC = + 1 * dd4hep::picosecond; + + // Set default adjacency matrix. Magic constants: + // 320 - number of tiles per row + decltype(CalorimeterIslandClusterConfig::adjacencyMatrix) HcalBarrel_adjacencyMatrix = + "(" + // check for vertically adjacent tiles + " ( (abs(eta_1 - eta_2) == 1) && (abs(phi_1 - phi_2) == 0) ) ||" + // check for horizontally adjacent tiles + " ( (abs(eta_1 - eta_2) == 0) && (abs(phi_1 - phi_2) == 1) ) ||" + // check for horizontally adjacent tiles at wraparound + " ( (abs(eta_1 - eta_2) == 0) && (abs(phi_1 - phi_2) == (320 - 1)) )" + ") == 1"; + + // If using readout structure with sector segmentation, + // ensure adjacency matrix uses sector indices + if (UseSectorIndexedBHCalReadout(app)) { + HcalBarrel_adjacencyMatrix = + "(" + " abs(fmod(tower_1, 24) - fmod(tower_2, 24))" + " + min(" + " abs((sector_1 - sector_2) * (2 * 5) + (floor(tower_1 / 24) - floor(tower_2 / 24)) * " + "5 + fmod(tile_1, 5) - fmod(tile_2, 5))," + " (32 * 2 * 5) - abs((sector_1 - sector_2) * (2 * 5) + (floor(tower_1 / 24) - " + "floor(tower_2 / 24)) * 5 + fmod(tile_1, 5) - fmod(tile_2, 5))" + " )" + ") == 1"; + } + + app->Add(new JOmniFactoryGeneratorT( + "HcalBarrelRawHits", {"HcalBarrelHits"}, {"HcalBarrelRawHits"}, + { + .eRes = {}, + .tRes = 0.0 * dd4hep::ns, + .threshold = 0.0, // Use ADC cut instead + .capADC = HcalBarrel_capADC, + .capTime = 100, // given in ns, 4 samples in HGCROC + .dyRangeADC = HcalBarrel_dyRangeADC, + .pedMeanADC = HcalBarrel_pedMeanADC, + .pedSigmaADC = HcalBarrel_pedSigmaADC, + .resolutionTDC = HcalBarrel_resolutionTDC, + .corrMeanScale = 1.0, + .readout = "HcalBarrelHits", + }, + app // TODO: Remove me once fixed + )); + app->Add(new JOmniFactoryGeneratorT( + "HcalBarrelRecHits", {"HcalBarrelRawHits"}, {"HcalBarrelRecHits"}, + { + .capADC = HcalBarrel_capADC, + .dyRangeADC = HcalBarrel_dyRangeADC, + .pedMeanADC = HcalBarrel_pedMeanADC, + .pedSigmaADC = HcalBarrel_pedSigmaADC, // not used; relying on energy cut + .resolutionTDC = HcalBarrel_resolutionTDC, + .thresholdFactor = 0.0, // not used; relying on flat ADC cut + .thresholdValue = 33, // pedSigmaADC + thresholdValue = half-MIP (333 ADC) + .sampFrac = 0.033, // average, from sPHENIX simulations + .readout = "HcalBarrelHits", + .layerField = "", + .sectorField = "", + }, + app // TODO: Remove me once fixed + )); + app->Add(new JOmniFactoryGeneratorT( + "HcalBarrelTruthProtoClusters", {"HcalBarrelRecHits", "HcalBarrelHits"}, + {"HcalBarrelTruthProtoClusters"}, + app // TODO: Remove me once fixed + )); + app->Add(new JOmniFactoryGeneratorT( + "HcalBarrelIslandProtoClusters", {"HcalBarrelRecHits"}, {"HcalBarrelIslandProtoClusters"}, + { + .adjacencyMatrix = HcalBarrel_adjacencyMatrix, + .readout = "HcalBarrelHits", + .sectorDist = 5.0 * dd4hep::cm, + .localDistXY = {15 * dd4hep::mm, 15 * dd4hep::mm}, + .dimScaledLocalDistXY = {50.0 * dd4hep::mm, 50.0 * dd4hep::mm}, + .splitCluster = false, + .minClusterHitEdep = 5.0 * dd4hep::MeV, + .minClusterCenterEdep = 30.0 * dd4hep::MeV, + .transverseEnergyProfileMetric = "globalDistEtaPhi", + .transverseEnergyProfileScale = 1., + }, + app // TODO: Remove me once fixed + )); + + app->Add(new JOmniFactoryGeneratorT( + "HcalBarrelClusters", + {"HcalBarrelIslandProtoClusters", // edm4eic::ProtoClusterCollection + "HcalBarrelHits"}, // edm4hep::SimCalorimeterHitCollection + {"HcalBarrelClusters", // edm4eic::Cluster + "HcalBarrelClusterAssociations"}, // edm4eic::MCRecoClusterParticleAssociation + {.energyWeight = "log", .sampFrac = 1.0, .logWeightBase = 6.2, .enableEtaBounds = false}, + app // TODO: Remove me once fixed + )); + + app->Add(new JOmniFactoryGeneratorT( + "HcalBarrelTruthClusters", + {"HcalBarrelTruthProtoClusters", // edm4eic::ProtoClusterCollection + "HcalBarrelHits"}, // edm4hep::SimCalorimeterHitCollection + {"HcalBarrelTruthClusters", // edm4eic::Cluster + "HcalBarrelTruthClusterAssociations"}, // edm4eic::MCRecoClusterParticleAssociation + {.energyWeight = "log", .sampFrac = 1.0, .logWeightBase = 6.2, .enableEtaBounds = false}, + app // TODO: Remove me once fixed + )); +} } diff --git a/src/detectors/BTOF/BTOF.cc b/src/detectors/BTOF/BTOF.cc index 113912c8c8..d3857896a6 100644 --- a/src/detectors/BTOF/BTOF.cc +++ b/src/detectors/BTOF/BTOF.cc @@ -13,33 +13,27 @@ #include "factories/tracking/TrackerHitReconstruction_factory.h" extern "C" { -void InitPlugin(JApplication *app) { - InitJANAPlugin(app); +void InitPlugin(JApplication* app) { + InitJANAPlugin(app); - using namespace eicrecon; + using namespace eicrecon; - // Digitization - app->Add(new JOmniFactoryGeneratorT( - "TOFBarrelRawHit", - {"TOFBarrelHits"}, - {"TOFBarrelRawHit"}, - { - .threshold = 6.0 * dd4hep::keV, - .timeResolution = 0.025, // [ns] - }, - app - )); - - // Convert raw digitized hits into hits with geometry info (ready for tracking) - app->Add(new JOmniFactoryGeneratorT( - "TOFBarrelRecHit", - {"TOFBarrelRawHit"}, // Input data collection tags - {"TOFBarrelRecHit"}, // Output data tag - { - .timeResolution = 10, - }, - app - )); // Hit reco default config for factories + // Digitization + app->Add(new JOmniFactoryGeneratorT( + "TOFBarrelRawHit", {"TOFBarrelHits"}, {"TOFBarrelRawHit"}, + { + .threshold = 6.0 * dd4hep::keV, + .timeResolution = 0.025, // [ns] + }, + app)); + // Convert raw digitized hits into hits with geometry info (ready for tracking) + app->Add(new JOmniFactoryGeneratorT( + "TOFBarrelRecHit", {"TOFBarrelRawHit"}, // Input data collection tags + {"TOFBarrelRecHit"}, // Output data tag + { + .timeResolution = 10, + }, + app)); // Hit reco default config for factories } } // extern "C" diff --git a/src/detectors/BTRK/BTRK.cc b/src/detectors/BTRK/BTRK.cc index 18693f5c81..5193dc23f1 100644 --- a/src/detectors/BTRK/BTRK.cc +++ b/src/detectors/BTRK/BTRK.cc @@ -13,31 +13,23 @@ #include "factories/tracking/TrackerHitReconstruction_factory.h" extern "C" { -void InitPlugin(JApplication *app) { - InitJANAPlugin(app); - - using namespace eicrecon; - - // Digitization - app->Add(new JOmniFactoryGeneratorT( - "SiBarrelRawHits", - {"SiBarrelHits"}, - {"SiBarrelRawHits"}, - { - .threshold = 0.54 * dd4hep::keV, - }, - app - )); - - - // Convert raw digitized hits into hits with geometry info (ready for tracking) - app->Add(new JOmniFactoryGeneratorT( - "SiBarrelTrackerRecHits", - {"SiBarrelRawHits"}, - {"SiBarrelTrackerRecHits"}, - {}, // default config - app - )); - +void InitPlugin(JApplication* app) { + InitJANAPlugin(app); + + using namespace eicrecon; + + // Digitization + app->Add(new JOmniFactoryGeneratorT( + "SiBarrelRawHits", {"SiBarrelHits"}, {"SiBarrelRawHits"}, + { + .threshold = 0.54 * dd4hep::keV, + }, + app)); + + // Convert raw digitized hits into hits with geometry info (ready for tracking) + app->Add(new JOmniFactoryGeneratorT( + "SiBarrelTrackerRecHits", {"SiBarrelRawHits"}, {"SiBarrelTrackerRecHits"}, + {}, // default config + app)); } } // extern "C" diff --git a/src/detectors/BVTX/BVTX.cc b/src/detectors/BVTX/BVTX.cc index 4c60d8d240..1a85a5b801 100644 --- a/src/detectors/BVTX/BVTX.cc +++ b/src/detectors/BVTX/BVTX.cc @@ -13,30 +13,23 @@ #include "factories/tracking/TrackerHitReconstruction_factory.h" extern "C" { -void InitPlugin(JApplication *app) { - InitJANAPlugin(app); +void InitPlugin(JApplication* app) { + InitJANAPlugin(app); - using namespace eicrecon; + using namespace eicrecon; - // Digitization - app->Add(new JOmniFactoryGeneratorT( - "SiBarrelVertexRawHits", - {"VertexBarrelHits"}, - {"SiBarrelVertexRawHits"}, - { - .threshold = 0.54 * dd4hep::keV, - }, - app - )); - - // Convert raw digitized hits into hits with geometry info (ready for tracking) - app->Add(new JOmniFactoryGeneratorT( - "SiBarrelVertexRecHits", - {"SiBarrelVertexRawHits"}, - {"SiBarrelVertexRecHits"}, - {}, // default config - app - )); + // Digitization + app->Add(new JOmniFactoryGeneratorT( + "SiBarrelVertexRawHits", {"VertexBarrelHits"}, {"SiBarrelVertexRawHits"}, + { + .threshold = 0.54 * dd4hep::keV, + }, + app)); + // Convert raw digitized hits into hits with geometry info (ready for tracking) + app->Add(new JOmniFactoryGeneratorT( + "SiBarrelVertexRecHits", {"SiBarrelVertexRawHits"}, {"SiBarrelVertexRecHits"}, + {}, // default config + app)); } } // extern "C" diff --git a/src/detectors/DIRC/DIRC.cc b/src/detectors/DIRC/DIRC.cc index f8c64fa58a..93a4153173 100644 --- a/src/detectors/DIRC/DIRC.cc +++ b/src/detectors/DIRC/DIRC.cc @@ -15,30 +15,29 @@ // factories #include "global/digi/PhotoMultiplierHitDigi_factory.h" - extern "C" { - void InitPlugin(JApplication *app) { - InitJANAPlugin(app); +void InitPlugin(JApplication* app) { + InitJANAPlugin(app); - using namespace eicrecon; + using namespace eicrecon; - // configuration parameters /////////////////////////////////////////////// + // configuration parameters /////////////////////////////////////////////// - // digitization - PhotoMultiplierHitDigiConfig digi_cfg; - digi_cfg.seed = 5; // FIXME: set to 0 for a 'unique' seed, but - // that seems to delay the RNG from actually randomizing - digi_cfg.hitTimeWindow = 20.0; // [ns] - digi_cfg.timeResolution = 1/16.0; // [ns] - digi_cfg.speMean = 80.0; - digi_cfg.speError = 16.0; - digi_cfg.pedMean = 200.0; - digi_cfg.pedError = 3.0; - digi_cfg.enablePixelGaps = false; - digi_cfg.safetyFactor = 1.0; - digi_cfg.quantumEfficiency.clear(); + // digitization + PhotoMultiplierHitDigiConfig digi_cfg; + digi_cfg.seed = 5; // FIXME: set to 0 for a 'unique' seed, but + // that seems to delay the RNG from actually randomizing + digi_cfg.hitTimeWindow = 20.0; // [ns] + digi_cfg.timeResolution = 1 / 16.0; // [ns] + digi_cfg.speMean = 80.0; + digi_cfg.speError = 16.0; + digi_cfg.pedMean = 200.0; + digi_cfg.pedError = 3.0; + digi_cfg.enablePixelGaps = false; + digi_cfg.safetyFactor = 1.0; + digi_cfg.quantumEfficiency.clear(); - std::vector sensor_qe{ + std::vector sensor_qe{ 0, 0, 14.0, 14.8, 14.5, 14.9, 14.4, 14.2, 13.9, 14.6, 15.2, 15.7, 16.4, 16.9, 17.5, 17.7, 18.1, 18.8, 19.3, 19.8, 20.6, 21.4, 22.4, 23.1, 23.6, 24.1, 24.2, 24.6, 24.8, 25.2, 25.7, 26.5, 27.1, 28.2, 29.0, 29.9, 30.8, 31.1, 31.7, 31.8, 31.6, 31.5, 31.5, 31.3, 31.0, @@ -57,21 +56,13 @@ extern "C" { 1.8, 1.6, 1.5, 1.5, 1.6, 1.8, 1.9, 1.4, 0.8, 0.9, 0.8, 0.7, 0.6, 0.3, 0.3, 0.5, 0.3, 0.4, 0.3, 0.1, 0.2, 0.1, 0.2, 0.3, 0.0}; - for(size_t i=0; i < sensor_qe.size(); i++) - { - double wavelength = 180 + i * 2; // wavelength units are [nm] - digi_cfg.quantumEfficiency.push_back({wavelength, sensor_qe[i]*0.01}); - } - - - // digitization - app->Add(new JOmniFactoryGeneratorT( - "DIRCRawHits", - {"DIRCBarHits"}, - {"DIRCRawHits", "DIRCRawHitsAssociations"}, - digi_cfg, - app - )); - + for (size_t i = 0; i < sensor_qe.size(); i++) { + double wavelength = 180 + i * 2; // wavelength units are [nm] + digi_cfg.quantumEfficiency.push_back({wavelength, sensor_qe[i] * 0.01}); } + + // digitization + app->Add(new JOmniFactoryGeneratorT( + "DIRCRawHits", {"DIRCBarHits"}, {"DIRCRawHits", "DIRCRawHitsAssociations"}, digi_cfg, app)); +} } diff --git a/src/detectors/DRICH/DRICH.cc b/src/detectors/DRICH/DRICH.cc index d244dd9c5f..ac2edddac9 100644 --- a/src/detectors/DRICH/DRICH.cc +++ b/src/detectors/DRICH/DRICH.cc @@ -24,82 +24,68 @@ #include "global/pid/RichTrack_factory.h" extern "C" { - void InitPlugin(JApplication *app) { - InitJANAPlugin(app); +void InitPlugin(JApplication* app) { + InitJANAPlugin(app); - using namespace eicrecon; + using namespace eicrecon; - // configuration parameters /////////////////////////////////////////////// + // configuration parameters /////////////////////////////////////////////// - // digitization - PhotoMultiplierHitDigiConfig digi_cfg; - digi_cfg.seed = 5; // FIXME: set to 0 for a 'unique' seed, but - // that seems to delay the RNG from actually randomizing - digi_cfg.hitTimeWindow = 20.0; // [ns] - digi_cfg.timeResolution = 1/16.0; // [ns] - digi_cfg.speMean = 80.0; - digi_cfg.speError = 16.0; - digi_cfg.pedMean = 200.0; - digi_cfg.pedError = 3.0; - digi_cfg.enablePixelGaps = true; - digi_cfg.safetyFactor = 0.7; - digi_cfg.enableNoise = false; - digi_cfg.noiseRate = 20000; // [Hz] - digi_cfg.noiseTimeWindow = 20.0 * dd4hep::ns; // [ns] - digi_cfg.quantumEfficiency.clear(); - digi_cfg.quantumEfficiency = { // wavelength units are [nm] - {315, 0.00}, - {325, 0.04}, - {340, 0.10}, - {350, 0.20}, - {370, 0.30}, - {400, 0.35}, - {450, 0.40}, - {500, 0.38}, - {550, 0.35}, - {600, 0.27}, - {650, 0.20}, - {700, 0.15}, - {750, 0.12}, - {800, 0.08}, - {850, 0.06}, - {900, 0.04}, - {1000, 0.00} - }; + // digitization + PhotoMultiplierHitDigiConfig digi_cfg; + digi_cfg.seed = 5; // FIXME: set to 0 for a 'unique' seed, but + // that seems to delay the RNG from actually randomizing + digi_cfg.hitTimeWindow = 20.0; // [ns] + digi_cfg.timeResolution = 1 / 16.0; // [ns] + digi_cfg.speMean = 80.0; + digi_cfg.speError = 16.0; + digi_cfg.pedMean = 200.0; + digi_cfg.pedError = 3.0; + digi_cfg.enablePixelGaps = true; + digi_cfg.safetyFactor = 0.7; + digi_cfg.enableNoise = false; + digi_cfg.noiseRate = 20000; // [Hz] + digi_cfg.noiseTimeWindow = 20.0 * dd4hep::ns; // [ns] + digi_cfg.quantumEfficiency.clear(); + digi_cfg.quantumEfficiency = {// wavelength units are [nm] + {315, 0.00}, {325, 0.04}, {340, 0.10}, {350, 0.20}, {370, 0.30}, + {400, 0.35}, {450, 0.40}, {500, 0.38}, {550, 0.35}, {600, 0.27}, + {650, 0.20}, {700, 0.15}, {750, 0.12}, {800, 0.08}, {850, 0.06}, + {900, 0.04}, {1000, 0.00}}; - // track propagation to each radiator - RichTrackConfig track_cfg; - track_cfg.numPlanes.insert({ "Aerogel", 5 }); - track_cfg.numPlanes.insert({ "Gas", 10 }); + // track propagation to each radiator + RichTrackConfig track_cfg; + track_cfg.numPlanes.insert({"Aerogel", 5}); + track_cfg.numPlanes.insert({"Gas", 10}); - // IRT PID - IrtCherenkovParticleIDConfig irt_cfg; - // - refractive index interpolation - irt_cfg.numRIndexBins = 100; - // - aerogel - irt_cfg.radiators.insert({"Aerogel", RadiatorConfig{}}); - irt_cfg.radiators.at("Aerogel").referenceRIndex = 1.0190; - irt_cfg.radiators.at("Aerogel").attenuation = 48; // [mm] - irt_cfg.radiators.at("Aerogel").smearingMode = "gaussian"; - irt_cfg.radiators.at("Aerogel").smearing = 2e-3; // [radians] - // - gas - irt_cfg.radiators.insert({"Gas", RadiatorConfig{}}); - irt_cfg.radiators.at("Gas").referenceRIndex = 1.00076; - irt_cfg.radiators.at("Gas").attenuation = 0; // [mm] - irt_cfg.radiators.at("Gas").smearingMode = "gaussian"; - irt_cfg.radiators.at("Gas").smearing = 5e-3; // [radians] - // - PDG list - irt_cfg.pdgList.insert(irt_cfg.pdgList.end(), { 11, 211, 321, 2212 }); - // - cheat modes - irt_cfg.cheatPhotonVertex = false; - irt_cfg.cheatTrueRadiator = false; + // IRT PID + IrtCherenkovParticleIDConfig irt_cfg; + // - refractive index interpolation + irt_cfg.numRIndexBins = 100; + // - aerogel + irt_cfg.radiators.insert({"Aerogel", RadiatorConfig{}}); + irt_cfg.radiators.at("Aerogel").referenceRIndex = 1.0190; + irt_cfg.radiators.at("Aerogel").attenuation = 48; // [mm] + irt_cfg.radiators.at("Aerogel").smearingMode = "gaussian"; + irt_cfg.radiators.at("Aerogel").smearing = 2e-3; // [radians] + // - gas + irt_cfg.radiators.insert({"Gas", RadiatorConfig{}}); + irt_cfg.radiators.at("Gas").referenceRIndex = 1.00076; + irt_cfg.radiators.at("Gas").attenuation = 0; // [mm] + irt_cfg.radiators.at("Gas").smearingMode = "gaussian"; + irt_cfg.radiators.at("Gas").smearing = 5e-3; // [radians] + // - PDG list + irt_cfg.pdgList.insert(irt_cfg.pdgList.end(), {11, 211, 321, 2212}); + // - cheat modes + irt_cfg.cheatPhotonVertex = false; + irt_cfg.cheatTrueRadiator = false; - // Merge PID from radiators - MergeParticleIDConfig merge_cfg; - merge_cfg.mergeMode = MergeParticleIDConfig::kAddWeights; + // Merge PID from radiators + MergeParticleIDConfig merge_cfg; + merge_cfg.mergeMode = MergeParticleIDConfig::kAddWeights; - // wiring between factories and data /////////////////////////////////////// - // clang-format off + // wiring between factories and data /////////////////////////////////////// + // clang-format off // digitization app->Add(new JOmniFactoryGeneratorT( @@ -148,6 +134,6 @@ extern "C" { app )); - // clang-format on - } + // clang-format on +} } diff --git a/src/detectors/ECTOF/ECTOF.cc b/src/detectors/ECTOF/ECTOF.cc index e26a1caf63..9f61df8d3c 100644 --- a/src/detectors/ECTOF/ECTOF.cc +++ b/src/detectors/ECTOF/ECTOF.cc @@ -13,33 +13,27 @@ #include "factories/tracking/TrackerHitReconstruction_factory.h" extern "C" { -void InitPlugin(JApplication *app) { - InitJANAPlugin(app); +void InitPlugin(JApplication* app) { + InitJANAPlugin(app); - using namespace eicrecon; + using namespace eicrecon; - // Digitization - app->Add(new JOmniFactoryGeneratorT( - "TOFEndcapRawHits", - {"TOFEndcapHits"}, - {"TOFEndcapRawHits"}, + // Digitization + app->Add(new JOmniFactoryGeneratorT( + "TOFEndcapRawHits", {"TOFEndcapHits"}, {"TOFEndcapRawHits"}, { - .threshold = 6.0 * dd4hep::keV, - .timeResolution = 0.025, + .threshold = 6.0 * dd4hep::keV, + .timeResolution = 0.025, }, - app - )); + app)); - // Convert raw digitized hits into hits with geometry info (ready for tracking) - app->Add(new JOmniFactoryGeneratorT( - "TOFEndcapRecHits", - {"TOFEndcapRawHits"}, // Input data collection tags - {"TOFEndcapRecHits"}, // Output data tag + // Convert raw digitized hits into hits with geometry info (ready for tracking) + app->Add(new JOmniFactoryGeneratorT( + "TOFEndcapRecHits", {"TOFEndcapRawHits"}, // Input data collection tags + {"TOFEndcapRecHits"}, // Output data tag { - .timeResolution = 0.025, + .timeResolution = 0.025, }, - app - )); - + app)); } } // extern "C" diff --git a/src/detectors/ECTRK/ECTRK.cc b/src/detectors/ECTRK/ECTRK.cc index 621e665c53..f0ccfc4855 100644 --- a/src/detectors/ECTRK/ECTRK.cc +++ b/src/detectors/ECTRK/ECTRK.cc @@ -13,30 +13,23 @@ #include "factories/tracking/TrackerHitReconstruction_factory.h" extern "C" { -void InitPlugin(JApplication *app) { - InitJANAPlugin(app); +void InitPlugin(JApplication* app) { + InitJANAPlugin(app); - using namespace eicrecon; + using namespace eicrecon; - // Digitization - app->Add(new JOmniFactoryGeneratorT( - "SiEndcapTrackerRawHits", - {"TrackerEndcapHits"}, - {"SiEndcapTrackerRawHits"}, - { - .threshold = 0.54 * dd4hep::keV, - }, - app - )); - - // Convert raw digitized hits into hits with geometry info (ready for tracking) - app->Add(new JOmniFactoryGeneratorT( - "SiEndcapTrackerRecHits", - {"SiEndcapTrackerRawHits"}, - {"SiEndcapTrackerRecHits"}, - {}, // default config - app - )); + // Digitization + app->Add(new JOmniFactoryGeneratorT( + "SiEndcapTrackerRawHits", {"TrackerEndcapHits"}, {"SiEndcapTrackerRawHits"}, + { + .threshold = 0.54 * dd4hep::keV, + }, + app)); + // Convert raw digitized hits into hits with geometry info (ready for tracking) + app->Add(new JOmniFactoryGeneratorT( + "SiEndcapTrackerRecHits", {"SiEndcapTrackerRawHits"}, {"SiEndcapTrackerRecHits"}, + {}, // default config + app)); } } // extern "C" diff --git a/src/detectors/EEMC/EEMC.cc b/src/detectors/EEMC/EEMC.cc index 25e5a9bbdb..ca603a7962 100644 --- a/src/detectors/EEMC/EEMC.cc +++ b/src/detectors/EEMC/EEMC.cc @@ -17,101 +17,94 @@ #include "factories/calorimetry/CalorimeterTruthClustering_factory.h" extern "C" { - void InitPlugin(JApplication *app) { +void InitPlugin(JApplication* app) { - using namespace eicrecon; + using namespace eicrecon; - InitJANAPlugin(app); + InitJANAPlugin(app); - // Make sure digi and reco use the same value - decltype(CalorimeterHitDigiConfig::capADC) EcalEndcapN_capADC = 16384; //65536, 16bit ADC - decltype(CalorimeterHitDigiConfig::dyRangeADC) EcalEndcapN_dyRangeADC = 20.0 * dd4hep::GeV; - decltype(CalorimeterHitDigiConfig::pedMeanADC) EcalEndcapN_pedMeanADC = 20; - decltype(CalorimeterHitDigiConfig::pedSigmaADC) EcalEndcapN_pedSigmaADC = 1; - decltype(CalorimeterHitDigiConfig::resolutionTDC) EcalEndcapN_resolutionTDC = 10 * dd4hep::picosecond; - app->Add(new JOmniFactoryGeneratorT( - "EcalEndcapNRawHits", {"EcalEndcapNHits"}, {"EcalEndcapNRawHits"}, - { - .eRes = {0.0 * sqrt(dd4hep::GeV), 0.02, 0.0 * dd4hep::GeV}, - .tRes = 0.0 * dd4hep::ns, - .threshold = 0.0 * dd4hep::MeV, // Use ADC cut instead - .capADC = EcalEndcapN_capADC, - .dyRangeADC = EcalEndcapN_dyRangeADC, - .pedMeanADC = EcalEndcapN_pedMeanADC, - .pedSigmaADC = EcalEndcapN_pedSigmaADC, - .resolutionTDC = EcalEndcapN_resolutionTDC, - .corrMeanScale = 1.0, - .readout = "EcalEndcapNHits", - }, - app // TODO: Remove me once fixed - )); - app->Add(new JOmniFactoryGeneratorT( - "EcalEndcapNRecHits", {"EcalEndcapNRawHits"}, {"EcalEndcapNRecHits"}, - { - .capADC = EcalEndcapN_capADC, - .dyRangeADC = EcalEndcapN_dyRangeADC, - .pedMeanADC = EcalEndcapN_pedMeanADC, - .pedSigmaADC = EcalEndcapN_pedSigmaADC, - .resolutionTDC = EcalEndcapN_resolutionTDC, - .thresholdFactor = 0.0, - .thresholdValue = 4.0, // (20. GeV / 16384) * 4 ~= 5 MeV - .sampFrac = 0.998, - .readout = "EcalEndcapNHits", - .sectorField = "sector", - }, - app // TODO: Remove me once fixed - )); - app->Add(new JOmniFactoryGeneratorT( - "EcalEndcapNTruthProtoClusters", {"EcalEndcapNRecHits", "EcalEndcapNHits"}, {"EcalEndcapNTruthProtoClusters"}, - app // TODO: Remove me once fixed - )); - app->Add(new JOmniFactoryGeneratorT( - "EcalEndcapNIslandProtoClusters", {"EcalEndcapNRecHits"}, {"EcalEndcapNIslandProtoClusters"}, - { - .adjacencyMatrix = "(abs(row_1 - row_2) + abs(column_1 - column_2)) == 1", - .readout = "EcalEndcapNHits", - .sectorDist = 5.0 * dd4hep::cm, - .splitCluster = true, - .minClusterHitEdep = 1.0 * dd4hep::MeV, - .minClusterCenterEdep = 30.0 * dd4hep::MeV, - .transverseEnergyProfileMetric = "globalDistEtaPhi", - .transverseEnergyProfileScale = 0.08, - }, - app // TODO: Remove me once fixed - )); + // Make sure digi and reco use the same value + decltype(CalorimeterHitDigiConfig::capADC) EcalEndcapN_capADC = 16384; //65536, 16bit ADC + decltype(CalorimeterHitDigiConfig::dyRangeADC) EcalEndcapN_dyRangeADC = 20.0 * dd4hep::GeV; + decltype(CalorimeterHitDigiConfig::pedMeanADC) EcalEndcapN_pedMeanADC = 20; + decltype(CalorimeterHitDigiConfig::pedSigmaADC) EcalEndcapN_pedSigmaADC = 1; + decltype(CalorimeterHitDigiConfig::resolutionTDC) EcalEndcapN_resolutionTDC = + 10 * dd4hep::picosecond; + app->Add(new JOmniFactoryGeneratorT( + "EcalEndcapNRawHits", {"EcalEndcapNHits"}, {"EcalEndcapNRawHits"}, + { + .eRes = {0.0 * sqrt(dd4hep::GeV), 0.02, 0.0 * dd4hep::GeV}, + .tRes = 0.0 * dd4hep::ns, + .threshold = 0.0 * dd4hep::MeV, // Use ADC cut instead + .capADC = EcalEndcapN_capADC, + .dyRangeADC = EcalEndcapN_dyRangeADC, + .pedMeanADC = EcalEndcapN_pedMeanADC, + .pedSigmaADC = EcalEndcapN_pedSigmaADC, + .resolutionTDC = EcalEndcapN_resolutionTDC, + .corrMeanScale = 1.0, + .readout = "EcalEndcapNHits", + }, + app // TODO: Remove me once fixed + )); + app->Add(new JOmniFactoryGeneratorT( + "EcalEndcapNRecHits", {"EcalEndcapNRawHits"}, {"EcalEndcapNRecHits"}, + { + .capADC = EcalEndcapN_capADC, + .dyRangeADC = EcalEndcapN_dyRangeADC, + .pedMeanADC = EcalEndcapN_pedMeanADC, + .pedSigmaADC = EcalEndcapN_pedSigmaADC, + .resolutionTDC = EcalEndcapN_resolutionTDC, + .thresholdFactor = 0.0, + .thresholdValue = 4.0, // (20. GeV / 16384) * 4 ~= 5 MeV + .sampFrac = 0.998, + .readout = "EcalEndcapNHits", + .sectorField = "sector", + }, + app // TODO: Remove me once fixed + )); + app->Add(new JOmniFactoryGeneratorT( + "EcalEndcapNTruthProtoClusters", {"EcalEndcapNRecHits", "EcalEndcapNHits"}, + {"EcalEndcapNTruthProtoClusters"}, + app // TODO: Remove me once fixed + )); + app->Add(new JOmniFactoryGeneratorT( + "EcalEndcapNIslandProtoClusters", {"EcalEndcapNRecHits"}, {"EcalEndcapNIslandProtoClusters"}, + { + .adjacencyMatrix = "(abs(row_1 - row_2) + abs(column_1 - column_2)) == 1", + .readout = "EcalEndcapNHits", + .sectorDist = 5.0 * dd4hep::cm, + .splitCluster = true, + .minClusterHitEdep = 1.0 * dd4hep::MeV, + .minClusterCenterEdep = 30.0 * dd4hep::MeV, + .transverseEnergyProfileMetric = "globalDistEtaPhi", + .transverseEnergyProfileScale = 0.08, + }, + app // TODO: Remove me once fixed + )); - app->Add( - new JOmniFactoryGeneratorT( - "EcalEndcapNTruthClusters", - {"EcalEndcapNTruthProtoClusters", // edm4eic::ProtoClusterCollection - "EcalEndcapNHits"}, // edm4hep::SimCalorimeterHitCollection - {"EcalEndcapNTruthClusters", // edm4eic::Cluster - "EcalEndcapNTruthClusterAssociations"}, // edm4eic::MCRecoClusterParticleAssociation - { - .energyWeight = "log", - .sampFrac = 1.0, - .logWeightBase = 4.6, - .enableEtaBounds = false - }, - app // TODO: Remove me once fixed - ) - ); + app->Add(new JOmniFactoryGeneratorT( + "EcalEndcapNTruthClusters", + {"EcalEndcapNTruthProtoClusters", // edm4eic::ProtoClusterCollection + "EcalEndcapNHits"}, // edm4hep::SimCalorimeterHitCollection + {"EcalEndcapNTruthClusters", // edm4eic::Cluster + "EcalEndcapNTruthClusterAssociations"}, // edm4eic::MCRecoClusterParticleAssociation + {.energyWeight = "log", .sampFrac = 1.0, .logWeightBase = 4.6, .enableEtaBounds = false}, + app // TODO: Remove me once fixed + )); - app->Add( - new JOmniFactoryGeneratorT( - "EcalEndcapNClusters", - {"EcalEndcapNIslandProtoClusters", // edm4eic::ProtoClusterCollection - "EcalEndcapNHits"}, // edm4hep::SimCalorimeterHitCollection - {"EcalEndcapNClusters", // edm4eic::Cluster - "EcalEndcapNClusterAssociations"}, // edm4eic::MCRecoClusterParticleAssociation - { - .energyWeight = "log", - .sampFrac = 1.0, - .logWeightBase = 3.6, - .enableEtaBounds = false, - }, - app // TODO: Remove me once fixed - ) - ); - } + app->Add(new JOmniFactoryGeneratorT( + "EcalEndcapNClusters", + {"EcalEndcapNIslandProtoClusters", // edm4eic::ProtoClusterCollection + "EcalEndcapNHits"}, // edm4hep::SimCalorimeterHitCollection + {"EcalEndcapNClusters", // edm4eic::Cluster + "EcalEndcapNClusterAssociations"}, // edm4eic::MCRecoClusterParticleAssociation + { + .energyWeight = "log", + .sampFrac = 1.0, + .logWeightBase = 3.6, + .enableEtaBounds = false, + }, + app // TODO: Remove me once fixed + )); +} } diff --git a/src/detectors/EHCAL/EHCAL.cc b/src/detectors/EHCAL/EHCAL.cc index ae45ee2870..71ba4d5c4a 100644 --- a/src/detectors/EHCAL/EHCAL.cc +++ b/src/detectors/EHCAL/EHCAL.cc @@ -17,106 +17,104 @@ #include "factories/calorimetry/CalorimeterTruthClustering_factory.h" extern "C" { - void InitPlugin(JApplication *app) { +void InitPlugin(JApplication* app) { - using namespace eicrecon; + using namespace eicrecon; - InitJANAPlugin(app); - // Make sure digi and reco use the same value - decltype(CalorimeterHitDigiConfig::capADC) HcalEndcapN_capADC = 32768; // assuming 15 bit ADC like FHCal - decltype(CalorimeterHitDigiConfig::dyRangeADC) HcalEndcapN_dyRangeADC = 200 * dd4hep::MeV; // to be verified with simulations - decltype(CalorimeterHitDigiConfig::pedMeanADC) HcalEndcapN_pedMeanADC = 10; - decltype(CalorimeterHitDigiConfig::pedSigmaADC) HcalEndcapN_pedSigmaADC = 2; - decltype(CalorimeterHitDigiConfig::resolutionTDC) HcalEndcapN_resolutionTDC = 10 * dd4hep::picosecond; + InitJANAPlugin(app); + // Make sure digi and reco use the same value + decltype(CalorimeterHitDigiConfig::capADC) HcalEndcapN_capADC = + 32768; // assuming 15 bit ADC like FHCal + decltype(CalorimeterHitDigiConfig::dyRangeADC) HcalEndcapN_dyRangeADC = + 200 * dd4hep::MeV; // to be verified with simulations + decltype(CalorimeterHitDigiConfig::pedMeanADC) HcalEndcapN_pedMeanADC = 10; + decltype(CalorimeterHitDigiConfig::pedSigmaADC) HcalEndcapN_pedSigmaADC = 2; + decltype(CalorimeterHitDigiConfig::resolutionTDC) HcalEndcapN_resolutionTDC = + 10 * dd4hep::picosecond; - app->Add(new JOmniFactoryGeneratorT( - "HcalEndcapNRawHits", {"HcalEndcapNHits"}, {"HcalEndcapNRawHits"}, - { - .tRes = 0.0 * dd4hep::ns, - .capADC = HcalEndcapN_capADC, - .capTime = 100, // given in ns, 4 samples in HGCROC - .dyRangeADC = HcalEndcapN_dyRangeADC, - .pedMeanADC = HcalEndcapN_pedMeanADC, - .pedSigmaADC = HcalEndcapN_pedSigmaADC, - .resolutionTDC = HcalEndcapN_resolutionTDC, - .corrMeanScale = 1.0, - .readout = "HcalEndcapNHits", - }, - app // TODO: Remove me once fixed - )); - app->Add(new JOmniFactoryGeneratorT( - "HcalEndcapNRecHits", {"HcalEndcapNRawHits"}, {"HcalEndcapNRecHits"}, - { - .capADC = HcalEndcapN_capADC, - .dyRangeADC = HcalEndcapN_dyRangeADC, - .pedMeanADC = HcalEndcapN_pedMeanADC, - .pedSigmaADC = HcalEndcapN_pedSigmaADC, - .resolutionTDC = HcalEndcapN_resolutionTDC, - .thresholdFactor = 0.0, - .thresholdValue = 41.0, // 0.1875 MeV deposition out of 200 MeV max (per layer) --> adc = 10 + 0.1875 / 200 * 32768 == 41 - .sampFrac = 0.0095, // from latest study - implement at level of reco hits rather than clusters - .readout = "HcalEndcapNHits", - }, - app // TODO: Remove me once fixed - )); - app->Add(new JOmniFactoryGeneratorT( - "HcalEndcapNMergedHits", {"HcalEndcapNRecHits"}, {"HcalEndcapNMergedHits"}, - { - .readout = "HcalEndcapNHits", - .fields = {"layer", "slice"}, - .refs = {4, 0}, // place merged hits at ~1 interaction length deep - }, - app // TODO: Remove me once fixed - )); - app->Add(new JOmniFactoryGeneratorT( - "HcalEndcapNTruthProtoClusters", {"HcalEndcapNMergedHits", "HcalEndcapNHits"}, {"HcalEndcapNTruthProtoClusters"}, - app // TODO: Remove me once fixed - )); - app->Add(new JOmniFactoryGeneratorT( - "HcalEndcapNIslandProtoClusters", {"HcalEndcapNMergedHits"}, {"HcalEndcapNIslandProtoClusters"}, - { - .sectorDist = 5.0 * dd4hep::cm, - .localDistXY = {15*dd4hep::cm, 15*dd4hep::cm}, - .splitCluster = true, - .minClusterHitEdep = 0.0 * dd4hep::MeV, - .minClusterCenterEdep = 30.0 * dd4hep::MeV, - .transverseEnergyProfileMetric = "globalDistEtaPhi", - .transverseEnergyProfileScale = 1., - }, - app // TODO: Remove me once fixed - )); - app->Add( - new JOmniFactoryGeneratorT( - "HcalEndcapNTruthClusters", - {"HcalEndcapNTruthProtoClusters", // edm4eic::ProtoClusterCollection - "HcalEndcapNHits"}, // edm4hep::SimCalorimeterHitCollection - {"HcalEndcapNTruthClusters", // edm4eic::Cluster - "HcalEndcapNTruthClusterAssociations"}, // edm4eic::MCRecoClusterParticleAssociation - { - .energyWeight = "log", - .sampFrac = 1.0, - .logWeightBase = 6.2, - .enableEtaBounds = false - }, - app // TODO: Remove me once fixed - ) - ); + app->Add(new JOmniFactoryGeneratorT( + "HcalEndcapNRawHits", {"HcalEndcapNHits"}, {"HcalEndcapNRawHits"}, + { + .tRes = 0.0 * dd4hep::ns, + .capADC = HcalEndcapN_capADC, + .capTime = 100, // given in ns, 4 samples in HGCROC + .dyRangeADC = HcalEndcapN_dyRangeADC, + .pedMeanADC = HcalEndcapN_pedMeanADC, + .pedSigmaADC = HcalEndcapN_pedSigmaADC, + .resolutionTDC = HcalEndcapN_resolutionTDC, + .corrMeanScale = 1.0, + .readout = "HcalEndcapNHits", + }, + app // TODO: Remove me once fixed + )); + app->Add(new JOmniFactoryGeneratorT( + "HcalEndcapNRecHits", {"HcalEndcapNRawHits"}, {"HcalEndcapNRecHits"}, + { + .capADC = HcalEndcapN_capADC, + .dyRangeADC = HcalEndcapN_dyRangeADC, + .pedMeanADC = HcalEndcapN_pedMeanADC, + .pedSigmaADC = HcalEndcapN_pedSigmaADC, + .resolutionTDC = HcalEndcapN_resolutionTDC, + .thresholdFactor = 0.0, + .thresholdValue = + 41.0, // 0.1875 MeV deposition out of 200 MeV max (per layer) --> adc = 10 + 0.1875 / 200 * 32768 == 41 + .sampFrac = + 0.0095, // from latest study - implement at level of reco hits rather than clusters + .readout = "HcalEndcapNHits", + }, + app // TODO: Remove me once fixed + )); + app->Add(new JOmniFactoryGeneratorT( + "HcalEndcapNMergedHits", {"HcalEndcapNRecHits"}, {"HcalEndcapNMergedHits"}, + { + .readout = "HcalEndcapNHits", + .fields = {"layer", "slice"}, + .refs = {4, 0}, // place merged hits at ~1 interaction length deep + }, + app // TODO: Remove me once fixed + )); + app->Add(new JOmniFactoryGeneratorT( + "HcalEndcapNTruthProtoClusters", {"HcalEndcapNMergedHits", "HcalEndcapNHits"}, + {"HcalEndcapNTruthProtoClusters"}, + app // TODO: Remove me once fixed + )); + app->Add(new JOmniFactoryGeneratorT( + "HcalEndcapNIslandProtoClusters", {"HcalEndcapNMergedHits"}, + {"HcalEndcapNIslandProtoClusters"}, + { + .sectorDist = 5.0 * dd4hep::cm, + .localDistXY = {15 * dd4hep::cm, 15 * dd4hep::cm}, + .splitCluster = true, + .minClusterHitEdep = 0.0 * dd4hep::MeV, + .minClusterCenterEdep = 30.0 * dd4hep::MeV, + .transverseEnergyProfileMetric = "globalDistEtaPhi", + .transverseEnergyProfileScale = 1., + }, + app // TODO: Remove me once fixed + )); + app->Add(new JOmniFactoryGeneratorT( + "HcalEndcapNTruthClusters", + {"HcalEndcapNTruthProtoClusters", // edm4eic::ProtoClusterCollection + "HcalEndcapNHits"}, // edm4hep::SimCalorimeterHitCollection + {"HcalEndcapNTruthClusters", // edm4eic::Cluster + "HcalEndcapNTruthClusterAssociations"}, // edm4eic::MCRecoClusterParticleAssociation + {.energyWeight = "log", .sampFrac = 1.0, .logWeightBase = 6.2, .enableEtaBounds = false}, + app // TODO: Remove me once fixed + )); - app->Add( - new JOmniFactoryGeneratorT( - "HcalEndcapNClusters", - {"HcalEndcapNIslandProtoClusters", // edm4eic::ProtoClusterCollection - "HcalEndcapNHits"}, // edm4hep::SimCalorimeterHitCollection - {"HcalEndcapNClusters", // edm4eic::Cluster - "HcalEndcapNClusterAssociations"}, // edm4eic::MCRecoClusterParticleAssociation - { - .energyWeight = "log", - .sampFrac = 1.0, - .logWeightBase = 6.2, - .enableEtaBounds = false, - }, - app // TODO: Remove me once fixed - ) - ); - } + app->Add(new JOmniFactoryGeneratorT( + "HcalEndcapNClusters", + {"HcalEndcapNIslandProtoClusters", // edm4eic::ProtoClusterCollection + "HcalEndcapNHits"}, // edm4hep::SimCalorimeterHitCollection + {"HcalEndcapNClusters", // edm4eic::Cluster + "HcalEndcapNClusterAssociations"}, // edm4eic::MCRecoClusterParticleAssociation + { + .energyWeight = "log", + .sampFrac = 1.0, + .logWeightBase = 6.2, + .enableEtaBounds = false, + }, + app // TODO: Remove me once fixed + )); +} } diff --git a/src/detectors/FEMC/FEMC.cc b/src/detectors/FEMC/FEMC.cc index 8930bebc82..e0bb19d146 100644 --- a/src/detectors/FEMC/FEMC.cc +++ b/src/detectors/FEMC/FEMC.cc @@ -17,189 +17,179 @@ #include "factories/calorimetry/CalorimeterTruthClustering_factory.h" extern "C" { - void InitPlugin(JApplication *app) { +void InitPlugin(JApplication* app) { - using namespace eicrecon; + using namespace eicrecon; - InitJANAPlugin(app); - // Make sure digi and reco use the same value - decltype(CalorimeterHitDigiConfig::capADC) EcalEndcapP_capADC = 16384; //16384, assuming 14 bits. For approximate HGCROC resolution use 65536 - decltype(CalorimeterHitDigiConfig::dyRangeADC) EcalEndcapP_dyRangeADC = 3 * dd4hep::GeV; - decltype(CalorimeterHitDigiConfig::pedMeanADC) EcalEndcapP_pedMeanADC = 200; - decltype(CalorimeterHitDigiConfig::pedSigmaADC) EcalEndcapP_pedSigmaADC = 2.4576; - decltype(CalorimeterHitDigiConfig::resolutionTDC) EcalEndcapP_resolutionTDC = 10 * dd4hep::picosecond; - app->Add(new JOmniFactoryGeneratorT( - "EcalEndcapPRawHits", {"EcalEndcapPHits"}, {"EcalEndcapPRawHits"}, - { - .eRes = {0.11333 * sqrt(dd4hep::GeV), 0.03, 0.0 * dd4hep::GeV}, // (11.333% / sqrt(E)) \oplus 3% - .tRes = 0.0, - .threshold = 0.0, - // .threshold = 15 * dd4hep::MeV for a single tower, applied on ADC level - .capADC = EcalEndcapP_capADC, - .capTime = 100, // given in ns, 4 samples in HGCROC - .dyRangeADC = EcalEndcapP_dyRangeADC, - .pedMeanADC = EcalEndcapP_pedMeanADC, - .pedSigmaADC = EcalEndcapP_pedSigmaADC, - .resolutionTDC = EcalEndcapP_resolutionTDC, - .corrMeanScale = 0.03, - .readout = "EcalEndcapPHits", - }, - app // TODO: Remove me once fixed - )); - app->Add(new JOmniFactoryGeneratorT( - "EcalEndcapPRecHits", {"EcalEndcapPRawHits"}, {"EcalEndcapPRecHits"}, - { - .capADC = EcalEndcapP_capADC, - .dyRangeADC = EcalEndcapP_dyRangeADC, - .pedMeanADC = EcalEndcapP_pedMeanADC, - .pedSigmaADC = EcalEndcapP_pedSigmaADC, - .resolutionTDC = EcalEndcapP_resolutionTDC, - .thresholdFactor = 0.0, - .thresholdValue = 2, // The ADC of a 15 MeV particle is adc = 200 + 15 * 0.03 * ( 1.0 + 0) / 3000 * 16384 = 200 + 2.4576 - .sampFrac =0.03, - .readout = "EcalEndcapPHits", - }, - app // TODO: Remove me once fixed - )); - app->Add(new JOmniFactoryGeneratorT( - "EcalEndcapPTruthProtoClusters", {"EcalEndcapPRecHits", "EcalEndcapPHits"}, {"EcalEndcapPTruthProtoClusters"}, - app // TODO: Remove me once fixed - )); - app->Add(new JOmniFactoryGeneratorT( - "EcalEndcapPIslandProtoClusters", {"EcalEndcapPRecHits"}, {"EcalEndcapPIslandProtoClusters"}, - { - .sectorDist = 5.0 * dd4hep::cm, - .localDistXY = {10.0 * dd4hep::cm, 10.0 * dd4hep::cm}, - .dimScaledLocalDistXY = {1.5, 1.5}, - .splitCluster = true, - .minClusterHitEdep = 0.0 * dd4hep::MeV, - .minClusterCenterEdep = 10.0 * dd4hep::MeV, - .transverseEnergyProfileMetric = "globalDistEtaPhi", - .transverseEnergyProfileScale = 0.04, - }, - app // TODO: Remove me once fixed - )); + InitJANAPlugin(app); + // Make sure digi and reco use the same value + decltype(CalorimeterHitDigiConfig::capADC) EcalEndcapP_capADC = + 16384; //16384, assuming 14 bits. For approximate HGCROC resolution use 65536 + decltype(CalorimeterHitDigiConfig::dyRangeADC) EcalEndcapP_dyRangeADC = 3 * dd4hep::GeV; + decltype(CalorimeterHitDigiConfig::pedMeanADC) EcalEndcapP_pedMeanADC = 200; + decltype(CalorimeterHitDigiConfig::pedSigmaADC) EcalEndcapP_pedSigmaADC = 2.4576; + decltype(CalorimeterHitDigiConfig::resolutionTDC) EcalEndcapP_resolutionTDC = + 10 * dd4hep::picosecond; + app->Add(new JOmniFactoryGeneratorT( + "EcalEndcapPRawHits", {"EcalEndcapPHits"}, {"EcalEndcapPRawHits"}, + { + .eRes = {0.11333 * sqrt(dd4hep::GeV), 0.03, + 0.0 * dd4hep::GeV}, // (11.333% / sqrt(E)) \oplus 3% + .tRes = 0.0, + .threshold = 0.0, + // .threshold = 15 * dd4hep::MeV for a single tower, applied on ADC level + .capADC = EcalEndcapP_capADC, + .capTime = 100, // given in ns, 4 samples in HGCROC + .dyRangeADC = EcalEndcapP_dyRangeADC, + .pedMeanADC = EcalEndcapP_pedMeanADC, + .pedSigmaADC = EcalEndcapP_pedSigmaADC, + .resolutionTDC = EcalEndcapP_resolutionTDC, + .corrMeanScale = 0.03, + .readout = "EcalEndcapPHits", + }, + app // TODO: Remove me once fixed + )); + app->Add(new JOmniFactoryGeneratorT( + "EcalEndcapPRecHits", {"EcalEndcapPRawHits"}, {"EcalEndcapPRecHits"}, + { + .capADC = EcalEndcapP_capADC, + .dyRangeADC = EcalEndcapP_dyRangeADC, + .pedMeanADC = EcalEndcapP_pedMeanADC, + .pedSigmaADC = EcalEndcapP_pedSigmaADC, + .resolutionTDC = EcalEndcapP_resolutionTDC, + .thresholdFactor = 0.0, + .thresholdValue = + 2, // The ADC of a 15 MeV particle is adc = 200 + 15 * 0.03 * ( 1.0 + 0) / 3000 * 16384 = 200 + 2.4576 + .sampFrac = 0.03, + .readout = "EcalEndcapPHits", + }, + app // TODO: Remove me once fixed + )); + app->Add(new JOmniFactoryGeneratorT( + "EcalEndcapPTruthProtoClusters", {"EcalEndcapPRecHits", "EcalEndcapPHits"}, + {"EcalEndcapPTruthProtoClusters"}, + app // TODO: Remove me once fixed + )); + app->Add(new JOmniFactoryGeneratorT( + "EcalEndcapPIslandProtoClusters", {"EcalEndcapPRecHits"}, {"EcalEndcapPIslandProtoClusters"}, + { + .sectorDist = 5.0 * dd4hep::cm, + .localDistXY = {10.0 * dd4hep::cm, 10.0 * dd4hep::cm}, + .dimScaledLocalDistXY = {1.5, 1.5}, + .splitCluster = true, + .minClusterHitEdep = 0.0 * dd4hep::MeV, + .minClusterCenterEdep = 10.0 * dd4hep::MeV, + .transverseEnergyProfileMetric = "globalDistEtaPhi", + .transverseEnergyProfileScale = 0.04, + }, + app // TODO: Remove me once fixed + )); - app->Add( - new JOmniFactoryGeneratorT( - "EcalEndcapPTruthClusters", - {"EcalEndcapPTruthProtoClusters", // edm4eic::ProtoClusterCollection - "EcalEndcapPHits"}, // edm4hep::SimCalorimeterHitCollection - {"EcalEndcapPTruthClusters", // edm4eic::Cluster - "EcalEndcapPTruthClusterAssociations"}, // edm4eic::MCRecoClusterParticleAssociation - { - .energyWeight = "log", - .sampFrac = 1.0, - .logWeightBase = 6.2, - .enableEtaBounds = true - }, - app // TODO: Remove me once fixed - ) - ); + app->Add(new JOmniFactoryGeneratorT( + "EcalEndcapPTruthClusters", + {"EcalEndcapPTruthProtoClusters", // edm4eic::ProtoClusterCollection + "EcalEndcapPHits"}, // edm4hep::SimCalorimeterHitCollection + {"EcalEndcapPTruthClusters", // edm4eic::Cluster + "EcalEndcapPTruthClusterAssociations"}, // edm4eic::MCRecoClusterParticleAssociation + {.energyWeight = "log", .sampFrac = 1.0, .logWeightBase = 6.2, .enableEtaBounds = true}, + app // TODO: Remove me once fixed + )); - app->Add( - new JOmniFactoryGeneratorT( - "EcalEndcapPClusters", - {"EcalEndcapPIslandProtoClusters", // edm4eic::ProtoClusterCollection - "EcalEndcapPHits"}, // edm4hep::SimCalorimeterHitCollection - {"EcalEndcapPClusters", // edm4eic::Cluster - "EcalEndcapPClusterAssociations"}, // edm4eic::MCRecoClusterParticleAssociation - { - .energyWeight = "log", - .sampFrac = 1.0, - .logWeightBase = 3.6, - .enableEtaBounds = false, - }, - app // TODO: Remove me once fixed - ) - ); + app->Add(new JOmniFactoryGeneratorT( + "EcalEndcapPClusters", + {"EcalEndcapPIslandProtoClusters", // edm4eic::ProtoClusterCollection + "EcalEndcapPHits"}, // edm4hep::SimCalorimeterHitCollection + {"EcalEndcapPClusters", // edm4eic::Cluster + "EcalEndcapPClusterAssociations"}, // edm4eic::MCRecoClusterParticleAssociation + { + .energyWeight = "log", + .sampFrac = 1.0, + .logWeightBase = 3.6, + .enableEtaBounds = false, + }, + app // TODO: Remove me once fixed + )); - // Insert is identical to regular Ecal - app->Add(new JOmniFactoryGeneratorT( - "EcalEndcapPInsertRawHits", {"EcalEndcapPInsertHits"}, {"EcalEndcapPInsertRawHits"}, - { - .eRes = {0.11333 * sqrt(dd4hep::GeV), 0.03, 0.0 * dd4hep::GeV}, // (11.333% / sqrt(E)) \oplus 3% - .tRes = 0.0, - .threshold = 0.0, - // .threshold = 15 * dd4hep::MeV for a single tower, applied on ADC level - .capADC = EcalEndcapP_capADC, - .capTime = 100, // given in ns, 4 samples in HGCROC - .dyRangeADC = EcalEndcapP_dyRangeADC, - .pedMeanADC = EcalEndcapP_pedMeanADC, - .pedSigmaADC = EcalEndcapP_pedSigmaADC, - .resolutionTDC = EcalEndcapP_resolutionTDC, - .corrMeanScale = 0.03, - .readout = "EcalEndcapPInsertHits", - }, - app // TODO: Remove me once fixed - )); - app->Add(new JOmniFactoryGeneratorT( - "EcalEndcapPInsertRecHits", {"EcalEndcapPInsertRawHits"}, {"EcalEndcapPInsertRecHits"}, - { - .capADC = EcalEndcapP_capADC, - .dyRangeADC = EcalEndcapP_dyRangeADC, - .pedMeanADC = EcalEndcapP_pedMeanADC, - .pedSigmaADC = EcalEndcapP_pedSigmaADC, - .resolutionTDC = EcalEndcapP_resolutionTDC, - .thresholdFactor = 0.0, - .thresholdValue = 2, // The ADC of a 15 MeV particle is adc = 200 + 15 * 0.03 * ( 1.0 + 0) / 3000 * 16384 = 200 + 2.4576 - .sampFrac =0.03, - .readout = "EcalEndcapPInsertHits", - }, - app // TODO: Remove me once fixed - )); - app->Add(new JOmniFactoryGeneratorT( - "EcalEndcapPInsertTruthProtoClusters", {"EcalEndcapPInsertRecHits", "EcalEndcapPInsertHits"}, {"EcalEndcapPInsertTruthProtoClusters"}, - app // TODO: Remove me once fixed - )); - app->Add(new JOmniFactoryGeneratorT( - "EcalEndcapPInsertIslandProtoClusters", {"EcalEndcapPInsertRecHits"}, {"EcalEndcapPInsertIslandProtoClusters"}, - { - .sectorDist = 5.0 * dd4hep::cm, - .localDistXY = {10.0 * dd4hep::cm, 10.0 * dd4hep::cm}, - .dimScaledLocalDistXY = {1.5,1.5}, - .splitCluster = false, - .minClusterHitEdep = 0.0 * dd4hep::MeV, - .minClusterCenterEdep = 10.0 * dd4hep::MeV, - .transverseEnergyProfileMetric = "globalDistEtaPhi", - .transverseEnergyProfileScale = 1., - }, - app // TODO: Remove me once fixed - )); + // Insert is identical to regular Ecal + app->Add(new JOmniFactoryGeneratorT( + "EcalEndcapPInsertRawHits", {"EcalEndcapPInsertHits"}, {"EcalEndcapPInsertRawHits"}, + { + .eRes = {0.11333 * sqrt(dd4hep::GeV), 0.03, + 0.0 * dd4hep::GeV}, // (11.333% / sqrt(E)) \oplus 3% + .tRes = 0.0, + .threshold = 0.0, + // .threshold = 15 * dd4hep::MeV for a single tower, applied on ADC level + .capADC = EcalEndcapP_capADC, + .capTime = 100, // given in ns, 4 samples in HGCROC + .dyRangeADC = EcalEndcapP_dyRangeADC, + .pedMeanADC = EcalEndcapP_pedMeanADC, + .pedSigmaADC = EcalEndcapP_pedSigmaADC, + .resolutionTDC = EcalEndcapP_resolutionTDC, + .corrMeanScale = 0.03, + .readout = "EcalEndcapPInsertHits", + }, + app // TODO: Remove me once fixed + )); + app->Add(new JOmniFactoryGeneratorT( + "EcalEndcapPInsertRecHits", {"EcalEndcapPInsertRawHits"}, {"EcalEndcapPInsertRecHits"}, + { + .capADC = EcalEndcapP_capADC, + .dyRangeADC = EcalEndcapP_dyRangeADC, + .pedMeanADC = EcalEndcapP_pedMeanADC, + .pedSigmaADC = EcalEndcapP_pedSigmaADC, + .resolutionTDC = EcalEndcapP_resolutionTDC, + .thresholdFactor = 0.0, + .thresholdValue = + 2, // The ADC of a 15 MeV particle is adc = 200 + 15 * 0.03 * ( 1.0 + 0) / 3000 * 16384 = 200 + 2.4576 + .sampFrac = 0.03, + .readout = "EcalEndcapPInsertHits", + }, + app // TODO: Remove me once fixed + )); + app->Add(new JOmniFactoryGeneratorT( + "EcalEndcapPInsertTruthProtoClusters", {"EcalEndcapPInsertRecHits", "EcalEndcapPInsertHits"}, + {"EcalEndcapPInsertTruthProtoClusters"}, + app // TODO: Remove me once fixed + )); + app->Add(new JOmniFactoryGeneratorT( + "EcalEndcapPInsertIslandProtoClusters", {"EcalEndcapPInsertRecHits"}, + {"EcalEndcapPInsertIslandProtoClusters"}, + { + .sectorDist = 5.0 * dd4hep::cm, + .localDistXY = {10.0 * dd4hep::cm, 10.0 * dd4hep::cm}, + .dimScaledLocalDistXY = {1.5, 1.5}, + .splitCluster = false, + .minClusterHitEdep = 0.0 * dd4hep::MeV, + .minClusterCenterEdep = 10.0 * dd4hep::MeV, + .transverseEnergyProfileMetric = "globalDistEtaPhi", + .transverseEnergyProfileScale = 1., + }, + app // TODO: Remove me once fixed + )); - app->Add( - new JOmniFactoryGeneratorT( - "EcalEndcapPInsertTruthClusters", - {"EcalEndcapPInsertTruthProtoClusters", // edm4eic::ProtoClusterCollection - "EcalEndcapPInsertHits"}, // edm4hep::SimCalorimeterHitCollection - {"EcalEndcapPInsertTruthClusters", // edm4eic::Cluster - "EcalEndcapPInsertTruthClusterAssociations"}, // edm4eic::MCRecoClusterParticleAssociation - { - .energyWeight = "log", - .sampFrac = 1.0, - .logWeightBase = 6.2, - .enableEtaBounds = true - }, - app // TODO: Remove me once fixed - ) - ); + app->Add(new JOmniFactoryGeneratorT( + "EcalEndcapPInsertTruthClusters", + {"EcalEndcapPInsertTruthProtoClusters", // edm4eic::ProtoClusterCollection + "EcalEndcapPInsertHits"}, // edm4hep::SimCalorimeterHitCollection + {"EcalEndcapPInsertTruthClusters", // edm4eic::Cluster + "EcalEndcapPInsertTruthClusterAssociations"}, // edm4eic::MCRecoClusterParticleAssociation + {.energyWeight = "log", .sampFrac = 1.0, .logWeightBase = 6.2, .enableEtaBounds = true}, + app // TODO: Remove me once fixed + )); - app->Add( - new JOmniFactoryGeneratorT( - "EcalEndcapPInsertClusters", - {"EcalEndcapPInsertIslandProtoClusters", // edm4eic::ProtoClusterCollection - "EcalEndcapPInsertHits"}, // edm4hep::SimCalorimeterHitCollection - {"EcalEndcapPInsertClusters", // edm4eic::Cluster - "EcalEndcapPInsertClusterAssociations"}, // edm4eic::MCRecoClusterParticleAssociation - { - .energyWeight = "log", - .sampFrac = 1.0, - .logWeightBase = 3.6, - .enableEtaBounds = false, - }, - app // TODO: Remove me once fixed - ) - ); - - } + app->Add(new JOmniFactoryGeneratorT( + "EcalEndcapPInsertClusters", + {"EcalEndcapPInsertIslandProtoClusters", // edm4eic::ProtoClusterCollection + "EcalEndcapPInsertHits"}, // edm4hep::SimCalorimeterHitCollection + {"EcalEndcapPInsertClusters", // edm4eic::Cluster + "EcalEndcapPInsertClusterAssociations"}, // edm4eic::MCRecoClusterParticleAssociation + { + .energyWeight = "log", + .sampFrac = 1.0, + .logWeightBase = 3.6, + .enableEtaBounds = false, + }, + app // TODO: Remove me once fixed + )); +} } diff --git a/src/detectors/FHCAL/FHCAL.cc b/src/detectors/FHCAL/FHCAL.cc index 928a31aa0a..e62b71c357 100644 --- a/src/detectors/FHCAL/FHCAL.cc +++ b/src/detectors/FHCAL/FHCAL.cc @@ -16,238 +16,225 @@ #include "factories/calorimetry/CalorimeterTruthClustering_factory.h" extern "C" { - void InitPlugin(JApplication *app) { - - using namespace eicrecon; - - InitJANAPlugin(app); - - // Make sure digi and reco use the same value - decltype(CalorimeterHitDigiConfig::capADC) HcalEndcapPInsert_capADC = 32768; - decltype(CalorimeterHitDigiConfig::dyRangeADC) HcalEndcapPInsert_dyRangeADC = 200 * dd4hep::MeV; - decltype(CalorimeterHitDigiConfig::pedMeanADC) HcalEndcapPInsert_pedMeanADC = 10; - decltype(CalorimeterHitDigiConfig::pedSigmaADC) HcalEndcapPInsert_pedSigmaADC = 2; - decltype(CalorimeterHitDigiConfig::resolutionTDC) HcalEndcapPInsert_resolutionTDC = 10 * dd4hep::picosecond; - - app->Add(new JOmniFactoryGeneratorT( - "HcalEndcapPInsertRawHits", {"HcalEndcapPInsertHits"}, {"HcalEndcapPInsertRawHits"}, - { - .eRes = {}, - .tRes = 0.0 * dd4hep::ns, - .capADC = HcalEndcapPInsert_capADC, - .dyRangeADC = HcalEndcapPInsert_dyRangeADC, - .pedMeanADC = HcalEndcapPInsert_pedMeanADC, - .pedSigmaADC = HcalEndcapPInsert_pedSigmaADC, - .resolutionTDC = HcalEndcapPInsert_resolutionTDC, - .corrMeanScale = 1.0, - .readout = "HcalEndcapPInsertHits", - }, - app // TODO: Remove me once fixed - )); - app->Add(new JOmniFactoryGeneratorT( - "HcalEndcapPInsertRecHits", {"HcalEndcapPInsertRawHits"}, {"HcalEndcapPInsertRecHits"}, - { - .capADC = HcalEndcapPInsert_capADC, - .dyRangeADC = HcalEndcapPInsert_dyRangeADC, - .pedMeanADC = HcalEndcapPInsert_pedMeanADC, - .pedSigmaADC = HcalEndcapPInsert_pedSigmaADC, - .resolutionTDC = HcalEndcapPInsert_resolutionTDC, - .thresholdFactor = 0., - .thresholdValue = 41.0, // 0.25 MeV --> 0.25 / 200 * 32768 = 41 - - .sampFrac = 0.0098, - .readout = "HcalEndcapPInsertHits", - }, - app // TODO: Remove me once fixed - )); - app->Add(new JOmniFactoryGeneratorT( - "HcalEndcapPInsertMergedHits", {"HcalEndcapPInsertRecHits"}, {"HcalEndcapPInsertMergedHits"}, - { - .readout = "HcalEndcapPInsertHits", - .fields = {"layer", "slice"}, - .refs = {1, 0}, - }, - app // TODO: Remove me once fixed - )); - app->Add(new JOmniFactoryGeneratorT( - "HcalEndcapPInsertTruthProtoClusters", {"HcalEndcapPInsertMergedHits", "HcalEndcapPInsertHits"}, {"HcalEndcapPInsertTruthProtoClusters"}, - app // TODO: Remove me once fixed - )); - app->Add(new JOmniFactoryGeneratorT( - "HcalEndcapPInsertIslandProtoClusters", {"HcalEndcapPInsertMergedHits"}, {"HcalEndcapPInsertIslandProtoClusters"}, - { - .sectorDist = 5.0 * dd4hep::cm, - .localDistXY = {15*dd4hep::mm, 15*dd4hep::mm}, - .dimScaledLocalDistXY = {15.0*dd4hep::mm, 15.0*dd4hep::mm}, - .splitCluster = true, - .minClusterHitEdep = 0.0 * dd4hep::MeV, - .minClusterCenterEdep = 30.0 * dd4hep::MeV, - .transverseEnergyProfileMetric = "globalDistEtaPhi", - .transverseEnergyProfileScale = 1., - }, - app // TODO: Remove me once fixed - )); - - app->Add( - new JOmniFactoryGeneratorT( - "HcalEndcapPInsertTruthClusters", - {"HcalEndcapPInsertTruthProtoClusters", // edm4eic::ProtoClusterCollection - "HcalEndcapPInsertHits"}, // edm4hep::SimCalorimeterHitCollection - {"HcalEndcapPInsertTruthClusters", // edm4eic::Cluster - "HcalEndcapPInsertTruthClusterAssociations"}, // edm4eic::MCRecoClusterParticleAssociation - { - .energyWeight = "log", - .sampFrac = 1.0, - .logWeightBase = 3.6, - .enableEtaBounds = true - }, - app // TODO: Remove me once fixed - ) - ); - - app->Add( - new JOmniFactoryGeneratorT( - "HcalEndcapPInsertClusters", - {"HcalEndcapPInsertIslandProtoClusters", // edm4eic::ProtoClusterCollection - "HcalEndcapPInsertHits"}, // edm4hep::SimCalorimeterHitCollection - {"HcalEndcapPInsertClusters", // edm4eic::Cluster - "HcalEndcapPInsertClusterAssociations"}, // edm4eic::MCRecoClusterParticleAssociation - { - .energyWeight = "log", - .sampFrac = 1.0, - .logWeightBase = 6.2, - .enableEtaBounds = false, - }, - app // TODO: Remove me once fixed - ) - ); - - // Make sure digi and reco use the same value - decltype(CalorimeterHitDigiConfig::capADC) LFHCAL_capADC = 65536; - decltype(CalorimeterHitDigiConfig::dyRangeADC) LFHCAL_dyRangeADC = 1 * dd4hep::GeV; - decltype(CalorimeterHitDigiConfig::pedMeanADC) LFHCAL_pedMeanADC = 50; - decltype(CalorimeterHitDigiConfig::pedSigmaADC) LFHCAL_pedSigmaADC = 10; - decltype(CalorimeterHitDigiConfig::resolutionTDC) LFHCAL_resolutionTDC = 10 * dd4hep::picosecond; - - app->Add(new JOmniFactoryGeneratorT( - "LFHCALRawHits", {"LFHCALHits"}, {"LFHCALRawHits"}, - { - .eRes = {}, - .tRes = 0.0 * dd4hep::ns, - .capADC = LFHCAL_capADC, - .capTime = 100, - .dyRangeADC = LFHCAL_dyRangeADC, - .pedMeanADC = LFHCAL_pedMeanADC, - .pedSigmaADC = LFHCAL_pedSigmaADC, - .resolutionTDC = LFHCAL_resolutionTDC, - .corrMeanScale = 1.0, - .readout = "LFHCALHits", - .fields = {"layerz"}, - }, - app // TODO: Remove me once fixed - )); - app->Add(new JOmniFactoryGeneratorT( - "LFHCALRecHits", {"LFHCALRawHits"}, {"LFHCALRecHits"}, - { - .capADC = LFHCAL_capADC, - .dyRangeADC = LFHCAL_dyRangeADC, - .pedMeanADC = LFHCAL_pedMeanADC, - .pedSigmaADC = LFHCAL_pedSigmaADC, - .resolutionTDC = LFHCAL_resolutionTDC, - .thresholdFactor = 0.0, - .thresholdValue = 20, // 0.3 MeV deposition --> adc = 50 + 0.3 / 1000 * 65536 == 70 - .sampFrac = 0.033, - .sampFracLayer = { - 0.019, // 0 - 0.037, // 1 - 0.037, // 2 - 0.037, // 3 - 0.037, // 4 - 0.037, // 5 - 0.037, // 6 - 0.037, // 7 - 0.037, // 8 - 0.037, // 9 - 0.037, // 10 - 0.037, // 11 - 0.037, // 12 - 0.037, // 13 - }, - .readout = "LFHCALHits", - .layerField = "rlayerz", - }, - app // TODO: Remove me once fixed - )); - app->Add(new JOmniFactoryGeneratorT( - "LFHCALTruthProtoClusters", {"LFHCALRecHits", "LFHCALHits"}, {"LFHCALTruthProtoClusters"}, - app // TODO: Remove me once fixed - )); - - // Magic constants: - // 54 - number of modules in a row/column - // 2 - number of towers in a module - std::string cellIdx_1 = "(54*2-moduleIDx_1*2+towerx_1)"; - std::string cellIdx_2 = "(54*2-moduleIDx_2*2+towerx_2)"; - std::string cellIdy_1 = "(54*2-moduleIDy_1*2+towery_1)"; - std::string cellIdy_2 = "(54*2-moduleIDy_2*2+towery_2)"; - std::string cellIdz_1 = "rlayerz_1"; - std::string cellIdz_2 = "rlayerz_2"; - std::string deltaX = Form("abs(%s-%s)", cellIdx_2.data(), cellIdx_1.data()); - std::string deltaY = Form("abs(%s-%s)", cellIdy_2.data(), cellIdy_1.data()); - std::string deltaZ = Form("abs(%s-%s)", cellIdz_2.data(), cellIdz_1.data()); - std::string neighbor = Form("(%s+%s+%s==1)", deltaX.data(), deltaY.data(), deltaZ.data()); - std::string corner2D = Form("((%s==0&&%s==1&&%s==1)||(%s==1&&%s==0&&%s==1)||(%s==1&&%s==1&&%s==0))", - deltaZ.data(), deltaX.data(), deltaY.data(), - deltaZ.data(), deltaX.data(), deltaY.data(), - deltaZ.data(), deltaX.data(), deltaY.data()); - - app->Add(new JOmniFactoryGeneratorT( - "LFHCALIslandProtoClusters", {"LFHCALRecHits"}, {"LFHCALIslandProtoClusters"}, - { - .adjacencyMatrix = Form("%s||%s", neighbor.data(), corner2D.data()), - .readout = "LFHCALHits", - .sectorDist = 0 * dd4hep::cm, - .splitCluster = false, - .minClusterHitEdep = 1 * dd4hep::MeV, - .minClusterCenterEdep = 100.0 * dd4hep::MeV, - .transverseEnergyProfileMetric = "globalDistEtaPhi", - .transverseEnergyProfileScale = 1., - }, - app // TODO: Remove me once fixed - )); - - app->Add( - new JOmniFactoryGeneratorT( - "LFHCALTruthClusters", - {"LFHCALTruthProtoClusters", // edm4eic::ProtoClusterCollection - "LFHCALHits"}, // edm4hep::SimCalorimeterHitCollection - {"LFHCALTruthClusters", // edm4eic::Cluster - "LFHCALTruthClusterAssociations"}, // edm4eic::MCRecoClusterParticleAssociation - { - .energyWeight = "log", - .sampFrac = 1.0, - .logWeightBase = 4.5, - .enableEtaBounds = false - }, - app // TODO: Remove me once fixed - ) - ); - - app->Add( - new JOmniFactoryGeneratorT( - "LFHCALClusters", - {"LFHCALIslandProtoClusters", // edm4eic::ProtoClusterCollection - "LFHCALHits"}, // edm4hep::SimCalorimeterHitCollection - {"LFHCALClusters", // edm4eic::Cluster - "LFHCALClusterAssociations"}, // edm4eic::MCRecoClusterParticleAssociation - { - .energyWeight = "log", - .sampFrac = 1.0, - .logWeightBase = 4.5, - .enableEtaBounds = false, - }, - app // TODO: Remove me once fixed - ) - ); - } +void InitPlugin(JApplication* app) { + + using namespace eicrecon; + + InitJANAPlugin(app); + + // Make sure digi and reco use the same value + decltype(CalorimeterHitDigiConfig::capADC) HcalEndcapPInsert_capADC = 32768; + decltype(CalorimeterHitDigiConfig::dyRangeADC) HcalEndcapPInsert_dyRangeADC = 200 * dd4hep::MeV; + decltype(CalorimeterHitDigiConfig::pedMeanADC) HcalEndcapPInsert_pedMeanADC = 10; + decltype(CalorimeterHitDigiConfig::pedSigmaADC) HcalEndcapPInsert_pedSigmaADC = 2; + decltype(CalorimeterHitDigiConfig::resolutionTDC) HcalEndcapPInsert_resolutionTDC = + 10 * dd4hep::picosecond; + + app->Add(new JOmniFactoryGeneratorT( + "HcalEndcapPInsertRawHits", {"HcalEndcapPInsertHits"}, {"HcalEndcapPInsertRawHits"}, + { + .eRes = {}, + .tRes = 0.0 * dd4hep::ns, + .capADC = HcalEndcapPInsert_capADC, + .dyRangeADC = HcalEndcapPInsert_dyRangeADC, + .pedMeanADC = HcalEndcapPInsert_pedMeanADC, + .pedSigmaADC = HcalEndcapPInsert_pedSigmaADC, + .resolutionTDC = HcalEndcapPInsert_resolutionTDC, + .corrMeanScale = 1.0, + .readout = "HcalEndcapPInsertHits", + }, + app // TODO: Remove me once fixed + )); + app->Add(new JOmniFactoryGeneratorT( + "HcalEndcapPInsertRecHits", {"HcalEndcapPInsertRawHits"}, {"HcalEndcapPInsertRecHits"}, + { + .capADC = HcalEndcapPInsert_capADC, + .dyRangeADC = HcalEndcapPInsert_dyRangeADC, + .pedMeanADC = HcalEndcapPInsert_pedMeanADC, + .pedSigmaADC = HcalEndcapPInsert_pedSigmaADC, + .resolutionTDC = HcalEndcapPInsert_resolutionTDC, + .thresholdFactor = 0., + .thresholdValue = 41.0, // 0.25 MeV --> 0.25 / 200 * 32768 = 41 + + .sampFrac = 0.0098, + .readout = "HcalEndcapPInsertHits", + }, + app // TODO: Remove me once fixed + )); + app->Add(new JOmniFactoryGeneratorT( + "HcalEndcapPInsertMergedHits", {"HcalEndcapPInsertRecHits"}, {"HcalEndcapPInsertMergedHits"}, + { + .readout = "HcalEndcapPInsertHits", + .fields = {"layer", "slice"}, + .refs = {1, 0}, + }, + app // TODO: Remove me once fixed + )); + app->Add(new JOmniFactoryGeneratorT( + "HcalEndcapPInsertTruthProtoClusters", + {"HcalEndcapPInsertMergedHits", "HcalEndcapPInsertHits"}, + {"HcalEndcapPInsertTruthProtoClusters"}, + app // TODO: Remove me once fixed + )); + app->Add(new JOmniFactoryGeneratorT( + "HcalEndcapPInsertIslandProtoClusters", {"HcalEndcapPInsertMergedHits"}, + {"HcalEndcapPInsertIslandProtoClusters"}, + { + .sectorDist = 5.0 * dd4hep::cm, + .localDistXY = {15 * dd4hep::mm, 15 * dd4hep::mm}, + .dimScaledLocalDistXY = {15.0 * dd4hep::mm, 15.0 * dd4hep::mm}, + .splitCluster = true, + .minClusterHitEdep = 0.0 * dd4hep::MeV, + .minClusterCenterEdep = 30.0 * dd4hep::MeV, + .transverseEnergyProfileMetric = "globalDistEtaPhi", + .transverseEnergyProfileScale = 1., + }, + app // TODO: Remove me once fixed + )); + + app->Add(new JOmniFactoryGeneratorT( + "HcalEndcapPInsertTruthClusters", + {"HcalEndcapPInsertTruthProtoClusters", // edm4eic::ProtoClusterCollection + "HcalEndcapPInsertHits"}, // edm4hep::SimCalorimeterHitCollection + {"HcalEndcapPInsertTruthClusters", // edm4eic::Cluster + "HcalEndcapPInsertTruthClusterAssociations"}, // edm4eic::MCRecoClusterParticleAssociation + {.energyWeight = "log", .sampFrac = 1.0, .logWeightBase = 3.6, .enableEtaBounds = true}, + app // TODO: Remove me once fixed + )); + + app->Add(new JOmniFactoryGeneratorT( + "HcalEndcapPInsertClusters", + {"HcalEndcapPInsertIslandProtoClusters", // edm4eic::ProtoClusterCollection + "HcalEndcapPInsertHits"}, // edm4hep::SimCalorimeterHitCollection + {"HcalEndcapPInsertClusters", // edm4eic::Cluster + "HcalEndcapPInsertClusterAssociations"}, // edm4eic::MCRecoClusterParticleAssociation + { + .energyWeight = "log", + .sampFrac = 1.0, + .logWeightBase = 6.2, + .enableEtaBounds = false, + }, + app // TODO: Remove me once fixed + )); + + // Make sure digi and reco use the same value + decltype(CalorimeterHitDigiConfig::capADC) LFHCAL_capADC = 65536; + decltype(CalorimeterHitDigiConfig::dyRangeADC) LFHCAL_dyRangeADC = 1 * dd4hep::GeV; + decltype(CalorimeterHitDigiConfig::pedMeanADC) LFHCAL_pedMeanADC = 50; + decltype(CalorimeterHitDigiConfig::pedSigmaADC) LFHCAL_pedSigmaADC = 10; + decltype(CalorimeterHitDigiConfig::resolutionTDC) LFHCAL_resolutionTDC = 10 * dd4hep::picosecond; + + app->Add(new JOmniFactoryGeneratorT( + "LFHCALRawHits", {"LFHCALHits"}, {"LFHCALRawHits"}, + { + .eRes = {}, + .tRes = 0.0 * dd4hep::ns, + .capADC = LFHCAL_capADC, + .capTime = 100, + .dyRangeADC = LFHCAL_dyRangeADC, + .pedMeanADC = LFHCAL_pedMeanADC, + .pedSigmaADC = LFHCAL_pedSigmaADC, + .resolutionTDC = LFHCAL_resolutionTDC, + .corrMeanScale = 1.0, + .readout = "LFHCALHits", + .fields = {"layerz"}, + }, + app // TODO: Remove me once fixed + )); + app->Add(new JOmniFactoryGeneratorT( + "LFHCALRecHits", {"LFHCALRawHits"}, {"LFHCALRecHits"}, + { + .capADC = LFHCAL_capADC, + .dyRangeADC = LFHCAL_dyRangeADC, + .pedMeanADC = LFHCAL_pedMeanADC, + .pedSigmaADC = LFHCAL_pedSigmaADC, + .resolutionTDC = LFHCAL_resolutionTDC, + .thresholdFactor = 0.0, + .thresholdValue = 20, // 0.3 MeV deposition --> adc = 50 + 0.3 / 1000 * 65536 == 70 + .sampFrac = 0.033, + .sampFracLayer = + { + 0.019, // 0 + 0.037, // 1 + 0.037, // 2 + 0.037, // 3 + 0.037, // 4 + 0.037, // 5 + 0.037, // 6 + 0.037, // 7 + 0.037, // 8 + 0.037, // 9 + 0.037, // 10 + 0.037, // 11 + 0.037, // 12 + 0.037, // 13 + }, + .readout = "LFHCALHits", + .layerField = "rlayerz", + }, + app // TODO: Remove me once fixed + )); + app->Add(new JOmniFactoryGeneratorT( + "LFHCALTruthProtoClusters", {"LFHCALRecHits", "LFHCALHits"}, {"LFHCALTruthProtoClusters"}, + app // TODO: Remove me once fixed + )); + + // Magic constants: + // 54 - number of modules in a row/column + // 2 - number of towers in a module + std::string cellIdx_1 = "(54*2-moduleIDx_1*2+towerx_1)"; + std::string cellIdx_2 = "(54*2-moduleIDx_2*2+towerx_2)"; + std::string cellIdy_1 = "(54*2-moduleIDy_1*2+towery_1)"; + std::string cellIdy_2 = "(54*2-moduleIDy_2*2+towery_2)"; + std::string cellIdz_1 = "rlayerz_1"; + std::string cellIdz_2 = "rlayerz_2"; + std::string deltaX = Form("abs(%s-%s)", cellIdx_2.data(), cellIdx_1.data()); + std::string deltaY = Form("abs(%s-%s)", cellIdy_2.data(), cellIdy_1.data()); + std::string deltaZ = Form("abs(%s-%s)", cellIdz_2.data(), cellIdz_1.data()); + std::string neighbor = Form("(%s+%s+%s==1)", deltaX.data(), deltaY.data(), deltaZ.data()); + std::string corner2D = + Form("((%s==0&&%s==1&&%s==1)||(%s==1&&%s==0&&%s==1)||(%s==1&&%s==1&&%s==0))", deltaZ.data(), + deltaX.data(), deltaY.data(), deltaZ.data(), deltaX.data(), deltaY.data(), deltaZ.data(), + deltaX.data(), deltaY.data()); + + app->Add(new JOmniFactoryGeneratorT( + "LFHCALIslandProtoClusters", {"LFHCALRecHits"}, {"LFHCALIslandProtoClusters"}, + { + .adjacencyMatrix = Form("%s||%s", neighbor.data(), corner2D.data()), + .readout = "LFHCALHits", + .sectorDist = 0 * dd4hep::cm, + .splitCluster = false, + .minClusterHitEdep = 1 * dd4hep::MeV, + .minClusterCenterEdep = 100.0 * dd4hep::MeV, + .transverseEnergyProfileMetric = "globalDistEtaPhi", + .transverseEnergyProfileScale = 1., + }, + app // TODO: Remove me once fixed + )); + + app->Add(new JOmniFactoryGeneratorT( + "LFHCALTruthClusters", + {"LFHCALTruthProtoClusters", // edm4eic::ProtoClusterCollection + "LFHCALHits"}, // edm4hep::SimCalorimeterHitCollection + {"LFHCALTruthClusters", // edm4eic::Cluster + "LFHCALTruthClusterAssociations"}, // edm4eic::MCRecoClusterParticleAssociation + {.energyWeight = "log", .sampFrac = 1.0, .logWeightBase = 4.5, .enableEtaBounds = false}, + app // TODO: Remove me once fixed + )); + + app->Add(new JOmniFactoryGeneratorT( + "LFHCALClusters", + {"LFHCALIslandProtoClusters", // edm4eic::ProtoClusterCollection + "LFHCALHits"}, // edm4hep::SimCalorimeterHitCollection + {"LFHCALClusters", // edm4eic::Cluster + "LFHCALClusterAssociations"}, // edm4eic::MCRecoClusterParticleAssociation + { + .energyWeight = "log", + .sampFrac = 1.0, + .logWeightBase = 4.5, + .enableEtaBounds = false, + }, + app // TODO: Remove me once fixed + )); +} } diff --git a/src/detectors/FOFFMTRK/FOFFMTRK.cc b/src/detectors/FOFFMTRK/FOFFMTRK.cc index 4fea2aa927..a86c9a6ee0 100644 --- a/src/detectors/FOFFMTRK/FOFFMTRK.cc +++ b/src/detectors/FOFFMTRK/FOFFMTRK.cc @@ -13,56 +13,49 @@ #include "factories/fardetectors/MatrixTransferStatic_factory.h" #include "factories/tracking/TrackerHitReconstruction_factory.h" - extern "C" { -void InitPlugin(JApplication *app) { - InitJANAPlugin(app); - using namespace eicrecon; - - MatrixTransferStaticConfig recon_cfg; - - //Digitized hits, especially for thresholds - app->Add(new JOmniFactoryGeneratorT( - "ForwardOffMTrackerRawHits", - {"ForwardOffMTrackerHits"}, - {"ForwardOffMTrackerRawHits"}, - { - .threshold = 10.0 * dd4hep::keV, - .timeResolution = 8, - }, - app - )); - - app->Add(new JOmniFactoryGeneratorT( - "ForwardOffMTrackerRecHits", - {"ForwardOffMTrackerRawHits"}, - {"ForwardOffMTrackerRecHits"}, - { - .timeResolution = 8, - }, - app - )); - - //Static transport matrix for Off Momentum detectors - recon_cfg.aX = {{1.6248, 12.966293}, - {0.1832, -2.8636535}}; - recon_cfg.aY = {{0.0001674, -28.6003}, - {0.0000837, -2.87985}}; - - recon_cfg.local_x_offset = -11.9872; // in mm --> this is from misalignment of the detector - recon_cfg.local_y_offset = -0.0146; // in mm --> this is from misalignment of the detector - recon_cfg.local_x_slope_offset = -14.75315; // in mrad - recon_cfg.local_y_slope_offset = -0.0073; // in mrad - recon_cfg.nomMomentum = 137.5; // in GEV --> exactly half of the top energy momentum (for proton spectators from deuteron breakup) - - recon_cfg.hit1minZ = 22499.0; - recon_cfg.hit1maxZ = 22522.0; - recon_cfg.hit2minZ = 24499.0; - recon_cfg.hit2maxZ = 24522.0; - - recon_cfg.readout = "ForwardOffMTrackerRecHits"; - - app->Add(new JOmniFactoryGeneratorT("ForwardOffMRecParticles",{"MCParticles","ForwardOffMTrackerRecHits"},{"ForwardOffMRecParticles"},recon_cfg,app)); - +void InitPlugin(JApplication* app) { + InitJANAPlugin(app); + using namespace eicrecon; + + MatrixTransferStaticConfig recon_cfg; + + //Digitized hits, especially for thresholds + app->Add(new JOmniFactoryGeneratorT( + "ForwardOffMTrackerRawHits", {"ForwardOffMTrackerHits"}, {"ForwardOffMTrackerRawHits"}, + { + .threshold = 10.0 * dd4hep::keV, + .timeResolution = 8, + }, + app)); + + app->Add(new JOmniFactoryGeneratorT( + "ForwardOffMTrackerRecHits", {"ForwardOffMTrackerRawHits"}, {"ForwardOffMTrackerRecHits"}, + { + .timeResolution = 8, + }, + app)); + + //Static transport matrix for Off Momentum detectors + recon_cfg.aX = {{1.6248, 12.966293}, {0.1832, -2.8636535}}; + recon_cfg.aY = {{0.0001674, -28.6003}, {0.0000837, -2.87985}}; + + recon_cfg.local_x_offset = -11.9872; // in mm --> this is from misalignment of the detector + recon_cfg.local_y_offset = -0.0146; // in mm --> this is from misalignment of the detector + recon_cfg.local_x_slope_offset = -14.75315; // in mrad + recon_cfg.local_y_slope_offset = -0.0073; // in mrad + recon_cfg.nomMomentum = + 137.5; // in GEV --> exactly half of the top energy momentum (for proton spectators from deuteron breakup) + + recon_cfg.hit1minZ = 22499.0; + recon_cfg.hit1maxZ = 22522.0; + recon_cfg.hit2minZ = 24499.0; + recon_cfg.hit2maxZ = 24522.0; + + recon_cfg.readout = "ForwardOffMTrackerRecHits"; + + app->Add(new JOmniFactoryGeneratorT( + "ForwardOffMRecParticles", {"MCParticles", "ForwardOffMTrackerRecHits"}, + {"ForwardOffMRecParticles"}, recon_cfg, app)); } } diff --git a/src/detectors/LOWQ2/LOWQ2.cc b/src/detectors/LOWQ2/LOWQ2.cc index 361b780d5f..f67717eb57 100644 --- a/src/detectors/LOWQ2/LOWQ2.cc +++ b/src/detectors/LOWQ2/LOWQ2.cc @@ -19,49 +19,42 @@ #include "factories/meta/SubDivideCollection_factory.h" extern "C" { - void InitPlugin(JApplication *app) { - InitJANAPlugin(app); - - using namespace eicrecon; - - // Digitization of silicon hits - app->Add(new JOmniFactoryGeneratorT( - "TaggerTrackerRawHits", - {"TaggerTrackerHits"}, - {"TaggerTrackerRawHits"}, - { - .threshold = 1.5 * dd4hep::keV, - .timeResolution = 2 * dd4hep::ns, - }, - app - )); - - // Divide collection based on geometry segmentation labels - // This should really be done before digitization as summing hits in the same cell couldn't even be mixed between layers. At the moment just prep for clustering. - std::string readout = "TaggerTrackerHits"; - std::vector geometryLabels {"module","layer"}; - std::vector moduleIDs{1,2}; - std::vector layerIDs {0,1,2,3}; - std::vector> geometryDivisions{}; - std::vector geometryDivisionCollectionNames; - - for(int mod_id : moduleIDs){ - for(int lay_id : layerIDs){ - geometryDivisions.push_back({mod_id,lay_id}); - geometryDivisionCollectionNames.push_back(fmt::format("TaggerTrackerM{}L{}RawHits",mod_id,lay_id)); - } +void InitPlugin(JApplication* app) { + InitJANAPlugin(app); + + using namespace eicrecon; + + // Digitization of silicon hits + app->Add(new JOmniFactoryGeneratorT( + "TaggerTrackerRawHits", {"TaggerTrackerHits"}, {"TaggerTrackerRawHits"}, + { + .threshold = 1.5 * dd4hep::keV, + .timeResolution = 2 * dd4hep::ns, + }, + app)); + + // Divide collection based on geometry segmentation labels + // This should really be done before digitization as summing hits in the same cell couldn't even be mixed between layers. At the moment just prep for clustering. + std::string readout = "TaggerTrackerHits"; + std::vector geometryLabels{"module", "layer"}; + std::vector moduleIDs{1, 2}; + std::vector layerIDs{0, 1, 2, 3}; + std::vector> geometryDivisions{}; + std::vector geometryDivisionCollectionNames; + + for (int mod_id : moduleIDs) { + for (int lay_id : layerIDs) { + geometryDivisions.push_back({mod_id, lay_id}); + geometryDivisionCollectionNames.push_back( + fmt::format("TaggerTrackerM{}L{}RawHits", mod_id, lay_id)); } - - app->Add(new JOmniFactoryGeneratorT>( - "TaggerTrackerSplitHits", - {"TaggerTrackerRawHits"}, - geometryDivisionCollectionNames, - { - .function = GeometrySplit{geometryDivisions,readout,geometryLabels}, - }, - app - ) - ); - } + + app->Add(new JOmniFactoryGeneratorT>( + "TaggerTrackerSplitHits", {"TaggerTrackerRawHits"}, geometryDivisionCollectionNames, + { + .function = GeometrySplit{geometryDivisions, readout, geometryLabels}, + }, + app)); +} } diff --git a/src/detectors/LUMISPECCAL/LUMISPECCAL.cc b/src/detectors/LUMISPECCAL/LUMISPECCAL.cc index c1f13157cb..53f80b6d84 100644 --- a/src/detectors/LUMISPECCAL/LUMISPECCAL.cc +++ b/src/detectors/LUMISPECCAL/LUMISPECCAL.cc @@ -17,94 +17,84 @@ #include "factories/calorimetry/CalorimeterTruthClustering_factory.h" extern "C" { - void InitPlugin(JApplication *app) { +void InitPlugin(JApplication* app) { - using namespace eicrecon; + using namespace eicrecon; - InitJANAPlugin(app); + InitJANAPlugin(app); - app->Add(new JOmniFactoryGeneratorT( - "EcalLumiSpecRawHits", {"LumiSpecCALHits"}, {"EcalLumiSpecRawHits"}, - { - .eRes = {0.0 * sqrt(dd4hep::GeV), 0.02, 0.0 * dd4hep::GeV}, // flat 2% - .tRes = 0.0 * dd4hep::ns, - .capADC = 16384, - .dyRangeADC = 20 * dd4hep::GeV, - .pedMeanADC = 100, - .pedSigmaADC = 1, - .resolutionTDC = 10 * dd4hep::picosecond, - .corrMeanScale = 1.0, - .readout = "LumiSpecCALHits", - }, - app // TODO: Remove me once fixed - )); - app->Add(new JOmniFactoryGeneratorT( - "EcalLumiSpecRecHits", {"EcalLumiSpecRawHits"}, {"EcalLumiSpecRecHits"}, - { - .capADC = 16384, - .dyRangeADC = 20. * dd4hep::GeV, - .pedMeanADC = 100, - .pedSigmaADC = 1, - .resolutionTDC = 10 * dd4hep::picosecond, - .thresholdFactor = 0.0, - .thresholdValue = 2.0, - .sampFrac = 1.0, - .readout = "LumiSpecCALHits", - .sectorField = "sector", - }, - app // TODO: Remove me once fixed - )); - app->Add(new JOmniFactoryGeneratorT( - "EcalLumiSpecTruthProtoClusters", {"EcalLumiSpecRecHits", "LumiSpecCALHits"}, {"EcalLumiSpecTruthProtoClusters"}, - app // TODO: Remove me once fixed - )); - app->Add(new JOmniFactoryGeneratorT( - "EcalLumiSpecIslandProtoClusters", {"EcalLumiSpecRecHits"}, {"EcalLumiSpecIslandProtoClusters"}, - { - .adjacencyMatrix = "(sector_1 == sector_2) && ((abs(floor(module_1 / 10) - floor(module_2 / 10)) + abs(fmod(module_1, 10) - fmod(module_2, 10))) == 1)", - .readout = "LumiSpecCALHits", - .sectorDist = 0.0 * dd4hep::cm, - .splitCluster=true, - .minClusterHitEdep = 1.0 * dd4hep::MeV, - .minClusterCenterEdep = 30.0 * dd4hep::MeV, - .transverseEnergyProfileMetric = "localDistXY", - .transverseEnergyProfileScale = 10. * dd4hep::mm, - }, - app // TODO: Remove me once fixed - )); + app->Add(new JOmniFactoryGeneratorT( + "EcalLumiSpecRawHits", {"LumiSpecCALHits"}, {"EcalLumiSpecRawHits"}, + { + .eRes = {0.0 * sqrt(dd4hep::GeV), 0.02, 0.0 * dd4hep::GeV}, // flat 2% + .tRes = 0.0 * dd4hep::ns, + .capADC = 16384, + .dyRangeADC = 20 * dd4hep::GeV, + .pedMeanADC = 100, + .pedSigmaADC = 1, + .resolutionTDC = 10 * dd4hep::picosecond, + .corrMeanScale = 1.0, + .readout = "LumiSpecCALHits", + }, + app // TODO: Remove me once fixed + )); + app->Add(new JOmniFactoryGeneratorT( + "EcalLumiSpecRecHits", {"EcalLumiSpecRawHits"}, {"EcalLumiSpecRecHits"}, + { + .capADC = 16384, + .dyRangeADC = 20. * dd4hep::GeV, + .pedMeanADC = 100, + .pedSigmaADC = 1, + .resolutionTDC = 10 * dd4hep::picosecond, + .thresholdFactor = 0.0, + .thresholdValue = 2.0, + .sampFrac = 1.0, + .readout = "LumiSpecCALHits", + .sectorField = "sector", + }, + app // TODO: Remove me once fixed + )); + app->Add(new JOmniFactoryGeneratorT( + "EcalLumiSpecTruthProtoClusters", {"EcalLumiSpecRecHits", "LumiSpecCALHits"}, + {"EcalLumiSpecTruthProtoClusters"}, + app // TODO: Remove me once fixed + )); + app->Add(new JOmniFactoryGeneratorT( + "EcalLumiSpecIslandProtoClusters", {"EcalLumiSpecRecHits"}, + {"EcalLumiSpecIslandProtoClusters"}, + { + .adjacencyMatrix = + "(sector_1 == sector_2) && ((abs(floor(module_1 / 10) - floor(module_2 / 10)) + " + "abs(fmod(module_1, 10) - fmod(module_2, 10))) == 1)", + .readout = "LumiSpecCALHits", + .sectorDist = 0.0 * dd4hep::cm, + .splitCluster = true, + .minClusterHitEdep = 1.0 * dd4hep::MeV, + .minClusterCenterEdep = 30.0 * dd4hep::MeV, + .transverseEnergyProfileMetric = "localDistXY", + .transverseEnergyProfileScale = 10. * dd4hep::mm, + }, + app // TODO: Remove me once fixed + )); - app->Add( - new JOmniFactoryGeneratorT( - "EcalLumiSpecClusters", - {"EcalLumiSpecIslandProtoClusters", // edm4eic::ProtoClusterCollection - "LumiSpecCALHits"}, // edm4hep::SimCalorimeterHitCollection - {"EcalLumiSpecClusters", // edm4eic::Cluster - "EcalLumiSpecClusterAssociations"}, // edm4eic::MCRecoClusterParticleAssociation - { - .energyWeight = "log", - .sampFrac = 1.0, - .logWeightBase = 3.6, - .enableEtaBounds = false - }, - app // TODO: Remove me once fixed - ) - ); + app->Add(new JOmniFactoryGeneratorT( + "EcalLumiSpecClusters", + {"EcalLumiSpecIslandProtoClusters", // edm4eic::ProtoClusterCollection + "LumiSpecCALHits"}, // edm4hep::SimCalorimeterHitCollection + {"EcalLumiSpecClusters", // edm4eic::Cluster + "EcalLumiSpecClusterAssociations"}, // edm4eic::MCRecoClusterParticleAssociation + {.energyWeight = "log", .sampFrac = 1.0, .logWeightBase = 3.6, .enableEtaBounds = false}, + app // TODO: Remove me once fixed + )); - app->Add( - new JOmniFactoryGeneratorT( - "EcalLumiSpecTruthClusters", - {"EcalLumiSpecTruthProtoClusters", // edm4eic::ProtoClusterCollection - "LumiSpecCALHits"}, // edm4hep::SimCalorimeterHitCollection - {"EcalLumiSpecTruthClusters", // edm4eic::Cluster - "EcalLumiSpecTruthClusterAssociations"}, // edm4eic::MCRecoClusterParticleAssociation - { - .energyWeight = "log", - .sampFrac = 1.0, - .logWeightBase = 4.6, - .enableEtaBounds = false - }, - app // TODO: Remove me once fixed - ) - ); - } + app->Add(new JOmniFactoryGeneratorT( + "EcalLumiSpecTruthClusters", + {"EcalLumiSpecTruthProtoClusters", // edm4eic::ProtoClusterCollection + "LumiSpecCALHits"}, // edm4hep::SimCalorimeterHitCollection + {"EcalLumiSpecTruthClusters", // edm4eic::Cluster + "EcalLumiSpecTruthClusterAssociations"}, // edm4eic::MCRecoClusterParticleAssociation + {.energyWeight = "log", .sampFrac = 1.0, .logWeightBase = 4.6, .enableEtaBounds = false}, + app // TODO: Remove me once fixed + )); +} } diff --git a/src/detectors/MPGD/MPGD.cc b/src/detectors/MPGD/MPGD.cc index 8cb695596c..73cd885048 100644 --- a/src/detectors/MPGD/MPGD.cc +++ b/src/detectors/MPGD/MPGD.cc @@ -13,126 +13,99 @@ #include "factories/tracking/TrackerHitReconstruction_factory.h" extern "C" { -void InitPlugin(JApplication *app) { - InitJANAPlugin(app); - - using namespace eicrecon; - - // Digitization - app->Add(new JOmniFactoryGeneratorT( - "MPGDBarrelRawHits", - {"MPGDBarrelHits"}, - {"MPGDBarrelRawHits"}, - { - .threshold = 0.25 * dd4hep::keV, - .timeResolution = 10, - }, - app - )); - - // Convert raw digitized hits into hits with geometry info (ready for tracking) - app->Add(new JOmniFactoryGeneratorT( - "MPGDBarrelRecHits", - {"MPGDBarrelRawHits"}, // Input data collection tags - {"MPGDBarrelRecHits"}, // Output data tag - { - .timeResolution = 10, - }, - app - )); - - // Digitization - app->Add(new JOmniFactoryGeneratorT( - "MPGDDIRCRawHits", - {"MPGDDIRCHits"}, - {"MPGDDIRCRawHits"}, - { - .threshold = 0.25 * dd4hep::keV, - .timeResolution = 10, - }, - app - )); - - // Convert raw digitized hits into hits with geometry info (ready for tracking) - app->Add(new JOmniFactoryGeneratorT( - "MPGDDIRCRecHits", - {"MPGDDIRCRawHits"}, // Input data collection tags - {"MPGDDIRCRecHits"}, // Output data tag - { - .timeResolution = 10, - }, - app - )); - - - // Digitization - app->Add(new JOmniFactoryGeneratorT( - "OuterMPGDBarrelRawHits", - {"OuterMPGDBarrelHits"}, - {"OuterMPGDBarrelRawHits"}, - { - .threshold = 0.25 * dd4hep::keV, - .timeResolution = 10, - }, - app - )); - - // Convert raw digitized hits into hits with geometry info (ready for tracking) - app->Add(new JOmniFactoryGeneratorT( - "OuterMPGDBarrelRecHits", - {"OuterMPGDBarrelRawHits"}, // Input data collection tags - {"OuterMPGDBarrelRecHits"}, // Output data tag - { - .timeResolution = 10, - }, - app - )); - - // Digitization - app->Add(new JOmniFactoryGeneratorT( - "BackwardMPGDEndcapRawHits", - {"BackwardMPGDEndcapHits"}, - {"BackwardMPGDEndcapRawHits"}, - { - .threshold = 0.25 * dd4hep::keV, - .timeResolution = 10, - }, - app - )); - - // Convert raw digitized hits into hits with geometry info (ready for tracking) - app->Add(new JOmniFactoryGeneratorT( - "BackwardMPGDEndcapRecHits", - {"BackwardMPGDEndcapRawHits"}, // Input data collection tags - {"BackwardMPGDEndcapRecHits"}, // Output data tag - { - .timeResolution = 10, - }, - app - )); - - // Digitization - app->Add(new JOmniFactoryGeneratorT( - "ForwardMPGDEndcapRawHits", - {"ForwardMPGDEndcapHits"}, - {"ForwardMPGDEndcapRawHits"}, - { - .threshold = 0.25 * dd4hep::keV, - .timeResolution = 10, - }, - app - )); - - // Convert raw digitized hits into hits with geometry info (ready for tracking) - app->Add(new JOmniFactoryGeneratorT( - "ForwardMPGDEndcapRecHits", - {"ForwardMPGDEndcapRawHits"}, // Input data collection tags - {"ForwardMPGDEndcapRecHits"}, // Output data tag - { - .timeResolution = 10, - }, - app - )); - +void InitPlugin(JApplication* app) { + InitJANAPlugin(app); + + using namespace eicrecon; + + // Digitization + app->Add(new JOmniFactoryGeneratorT( + "MPGDBarrelRawHits", {"MPGDBarrelHits"}, {"MPGDBarrelRawHits"}, + { + .threshold = 0.25 * dd4hep::keV, + .timeResolution = 10, + }, + app)); + + // Convert raw digitized hits into hits with geometry info (ready for tracking) + app->Add(new JOmniFactoryGeneratorT( + "MPGDBarrelRecHits", {"MPGDBarrelRawHits"}, // Input data collection tags + {"MPGDBarrelRecHits"}, // Output data tag + { + .timeResolution = 10, + }, + app)); + + // Digitization + app->Add(new JOmniFactoryGeneratorT( + "MPGDDIRCRawHits", {"MPGDDIRCHits"}, {"MPGDDIRCRawHits"}, + { + .threshold = 0.25 * dd4hep::keV, + .timeResolution = 10, + }, + app)); + + // Convert raw digitized hits into hits with geometry info (ready for tracking) + app->Add(new JOmniFactoryGeneratorT( + "MPGDDIRCRecHits", {"MPGDDIRCRawHits"}, // Input data collection tags + {"MPGDDIRCRecHits"}, // Output data tag + { + .timeResolution = 10, + }, + app)); + + // Digitization + app->Add(new JOmniFactoryGeneratorT( + "OuterMPGDBarrelRawHits", {"OuterMPGDBarrelHits"}, {"OuterMPGDBarrelRawHits"}, + { + .threshold = 0.25 * dd4hep::keV, + .timeResolution = 10, + }, + app)); + + // Convert raw digitized hits into hits with geometry info (ready for tracking) + app->Add(new JOmniFactoryGeneratorT( + "OuterMPGDBarrelRecHits", {"OuterMPGDBarrelRawHits"}, // Input data collection tags + {"OuterMPGDBarrelRecHits"}, // Output data tag + { + .timeResolution = 10, + }, + app)); + + // Digitization + app->Add(new JOmniFactoryGeneratorT( + "BackwardMPGDEndcapRawHits", {"BackwardMPGDEndcapHits"}, {"BackwardMPGDEndcapRawHits"}, + { + .threshold = 0.25 * dd4hep::keV, + .timeResolution = 10, + }, + app)); + + // Convert raw digitized hits into hits with geometry info (ready for tracking) + app->Add(new JOmniFactoryGeneratorT( + "BackwardMPGDEndcapRecHits", {"BackwardMPGDEndcapRawHits"}, // Input data collection tags + {"BackwardMPGDEndcapRecHits"}, // Output data tag + { + .timeResolution = 10, + }, + app)); + + // Digitization + app->Add(new JOmniFactoryGeneratorT( + "ForwardMPGDEndcapRawHits", {"ForwardMPGDEndcapHits"}, {"ForwardMPGDEndcapRawHits"}, + { + .threshold = 0.25 * dd4hep::keV, + .timeResolution = 10, + }, + app)); + + // Convert raw digitized hits into hits with geometry info (ready for tracking) + app->Add(new JOmniFactoryGeneratorT( + "ForwardMPGDEndcapRecHits", {"ForwardMPGDEndcapRawHits"}, // Input data collection tags + {"ForwardMPGDEndcapRecHits"}, // Output data tag + { + .timeResolution = 10, + }, + app)); } } // extern "C" diff --git a/src/detectors/RPOTS/RPOTS.cc b/src/detectors/RPOTS/RPOTS.cc index 89c85215af..01fee9a810 100644 --- a/src/detectors/RPOTS/RPOTS.cc +++ b/src/detectors/RPOTS/RPOTS.cc @@ -13,57 +13,49 @@ #include "factories/fardetectors/MatrixTransferStatic_factory.h" #include "factories/tracking/TrackerHitReconstruction_factory.h" - extern "C" { -void InitPlugin(JApplication *app) { - InitJANAPlugin(app); - using namespace eicrecon; - - MatrixTransferStaticConfig recon_cfg; - - //Digitized hits, especially for thresholds - app->Add(new JOmniFactoryGeneratorT( - "ForwardRomanPotRawHits", - {"ForwardRomanPotHits"}, - {"ForwardRomanPotRawHits"}, - { - .threshold = 10.0 * dd4hep::keV, - .timeResolution = 8, - }, - app - )); - - app->Add(new JOmniFactoryGeneratorT( - "ForwardRomanPotRecHits", - {"ForwardRomanPotRawHits"}, - {"ForwardRomanPotRecHits"}, - { - .timeResolution = 8, - }, - app - )); - - - //Static transport matrix for Roman Pots detectors - recon_cfg.aX = {{2.102403743, 29.11067626}, - {0.186640381, 0.192604619}}; - recon_cfg.aY = {{0.0000159900, 3.94082098}, - {0.0000079946, -0.1402995}}; - - recon_cfg.local_x_offset = 0.0; // in mm --> this is from misalignment of the detector - recon_cfg.local_y_offset = 0.0; // in mm --> this is from misalignment of the detector - recon_cfg.local_x_slope_offset = -0.00622147; // in mrad - recon_cfg.local_y_slope_offset = -0.0451035; // in mrad - recon_cfg.nomMomentum = 275.0; // in GEV --> exactly half of the top energy momentum (for proton spectators from deuteron breakup) - - recon_cfg.hit1minZ = 25099.0; - recon_cfg.hit1maxZ = 26022.0; - recon_cfg.hit2minZ = 27099.0; - recon_cfg.hit2maxZ = 28022.0; - - recon_cfg.readout = "ForwardRomanPotRecHits"; - - app->Add(new JOmniFactoryGeneratorT("ForwardRomanPotRecParticles",{"MCParticles","ForwardRomanPotRecHits"},{"ForwardRomanPotRecParticles"},recon_cfg,app)); - +void InitPlugin(JApplication* app) { + InitJANAPlugin(app); + using namespace eicrecon; + + MatrixTransferStaticConfig recon_cfg; + + //Digitized hits, especially for thresholds + app->Add(new JOmniFactoryGeneratorT( + "ForwardRomanPotRawHits", {"ForwardRomanPotHits"}, {"ForwardRomanPotRawHits"}, + { + .threshold = 10.0 * dd4hep::keV, + .timeResolution = 8, + }, + app)); + + app->Add(new JOmniFactoryGeneratorT( + "ForwardRomanPotRecHits", {"ForwardRomanPotRawHits"}, {"ForwardRomanPotRecHits"}, + { + .timeResolution = 8, + }, + app)); + + //Static transport matrix for Roman Pots detectors + recon_cfg.aX = {{2.102403743, 29.11067626}, {0.186640381, 0.192604619}}; + recon_cfg.aY = {{0.0000159900, 3.94082098}, {0.0000079946, -0.1402995}}; + + recon_cfg.local_x_offset = 0.0; // in mm --> this is from misalignment of the detector + recon_cfg.local_y_offset = 0.0; // in mm --> this is from misalignment of the detector + recon_cfg.local_x_slope_offset = -0.00622147; // in mrad + recon_cfg.local_y_slope_offset = -0.0451035; // in mrad + recon_cfg.nomMomentum = + 275.0; // in GEV --> exactly half of the top energy momentum (for proton spectators from deuteron breakup) + + recon_cfg.hit1minZ = 25099.0; + recon_cfg.hit1maxZ = 26022.0; + recon_cfg.hit2minZ = 27099.0; + recon_cfg.hit2maxZ = 28022.0; + + recon_cfg.readout = "ForwardRomanPotRecHits"; + + app->Add(new JOmniFactoryGeneratorT( + "ForwardRomanPotRecParticles", {"MCParticles", "ForwardRomanPotRecHits"}, + {"ForwardRomanPotRecParticles"}, recon_cfg, app)); } } diff --git a/src/detectors/ZDC/ZDC.cc b/src/detectors/ZDC/ZDC.cc index 9f9130dc45..aea0d864df 100644 --- a/src/detectors/ZDC/ZDC.cc +++ b/src/detectors/ZDC/ZDC.cc @@ -18,234 +18,224 @@ #include "factories/calorimetry/HEXPLIT_factory.h" extern "C" { - void InitPlugin(JApplication *app) { - - using namespace eicrecon; - - InitJANAPlugin(app); - - // LYSO part of the ZDC - app->Add(new JOmniFactoryGeneratorT( - "EcalFarForwardZDCRawHits", {"EcalFarForwardZDCHits"}, {"EcalFarForwardZDCRawHits"}, - { - .tRes = 0.0 * dd4hep::ns, - .capADC = 32768, - .dyRangeADC = 2000 * dd4hep::MeV, - .pedMeanADC = 400, - .pedSigmaADC = 3.2, - .resolutionTDC = 10 * dd4hep::picosecond, - .corrMeanScale = 1.0, - .readout = "EcalFarForwardZDCHits", - }, - app // TODO: Remove me once fixed - )); - app->Add(new JOmniFactoryGeneratorT( - "EcalFarForwardZDCRecHits", {"EcalFarForwardZDCRawHits"}, {"EcalFarForwardZDCRecHits"}, - { - .capADC = 32768, - .dyRangeADC = 2000. * dd4hep::MeV, - .pedMeanADC = 400, - .pedSigmaADC = 3.2, - .resolutionTDC = 10 * dd4hep::picosecond, - .thresholdFactor = 4.0, - .thresholdValue = 0.0, - .sampFrac = 1.0, - .readout = "EcalFarForwardZDCHits", - }, - app // TODO: Remove me once fixed - )); - app->Add(new JOmniFactoryGeneratorT( - "EcalFarForwardZDCTruthProtoClusters", {"EcalFarForwardZDCRecHits", "EcalFarForwardZDCHits"}, {"EcalFarForwardZDCTruthProtoClusters"}, - app // TODO: Remove me once fixed - )); - app->Add(new JOmniFactoryGeneratorT( - "EcalFarForwardZDCIslandProtoClusters", {"EcalFarForwardZDCRecHits"}, {"EcalFarForwardZDCIslandProtoClusters"}, - { - .sectorDist = 5.0 * dd4hep::cm, - .localDistXY = {50 * dd4hep::cm, 50 * dd4hep::cm}, - .dimScaledLocalDistXY = {50.0*dd4hep::mm, 50.0*dd4hep::mm}, - .splitCluster = true, - .minClusterHitEdep = 0.1 * dd4hep::MeV, - .minClusterCenterEdep = 3.0 * dd4hep::MeV, - .transverseEnergyProfileMetric = "globalDistEtaPhi", - .transverseEnergyProfileScale = 1., - }, - app // TODO: Remove me once fixed - )); - - app->Add( - new JOmniFactoryGeneratorT( - "EcalFarForwardZDCTruthClusters", - {"EcalFarForwardZDCTruthProtoClusters", // edm4eic::ProtoClusterCollection - "EcalFarForwardZDCHits"}, // edm4hep::SimCalorimeterHitCollection - {"EcalFarForwardZDCTruthClusters", // edm4eic::Cluster - "EcalFarForwardZDCTruthClusterAssociations"}, // edm4eic::MCRecoClusterParticleAssociation - { - .energyWeight = "log", - .sampFrac = 1.0, - .logWeightBase = 3.6, - .enableEtaBounds = false - }, - app // TODO: Remove me once fixed - ) - ); - - app->Add( - new JOmniFactoryGeneratorT( - "EcalFarForwardZDCClusters", - {"EcalFarForwardZDCIslandProtoClusters", // edm4eic::ProtoClusterCollection - "EcalFarForwardZDCHits"}, // edm4hep::SimCalorimeterHitCollection - {"EcalFarForwardZDCClusters", // edm4eic::Cluster - "EcalFarForwardZDCClusterAssociations"}, // edm4eic::MCRecoClusterParticleAssociation - { - .energyWeight = "log", - .sampFrac = 1.0, - .logWeightBase = 6.2, - .enableEtaBounds = false, - }, - app // TODO: Remove me once fixed - ) - ); - - app->Add(new JOmniFactoryGeneratorT( - "HcalFarForwardZDCRawHits", {"HcalFarForwardZDCHits"}, {"HcalFarForwardZDCRawHits"}, - { - .tRes = 0.0 * dd4hep::ns, - .capADC = 32768, - .dyRangeADC = 800 * dd4hep::MeV, - .pedMeanADC = 400, - .pedSigmaADC = 10, - .resolutionTDC = 10 * dd4hep::picosecond, - .corrMeanScale = 1.0, - .readout = "HcalFarForwardZDCHits", - }, - app // TODO: Remove me once fixed - )); - - app->Add(new JOmniFactoryGeneratorT( - "HcalFarForwardZDCRecHits", {"HcalFarForwardZDCRawHits"}, {"HcalFarForwardZDCRecHits"}, - { - .capADC = 32678, - .dyRangeADC = 800. * dd4hep::MeV, - .pedMeanADC = 400, - .pedSigmaADC = 10, - .resolutionTDC = 10 * dd4hep::picosecond, - .thresholdFactor = 0.0, - .thresholdValue = -100.0, - .sampFrac = 1.0, - .readout = "HcalFarForwardZDCHits", - .layerField = "layer", - .sectorField = "system", - }, - app // TODO: Remove me once fixed - )); - - app->Add(new JOmniFactoryGeneratorT( - "HcalFarForwardZDCSubcellHits", {"HcalFarForwardZDCRecHits"}, {"HcalFarForwardZDCSubcellHits"}, - { - .MIP = 472. * dd4hep::keV, - .Emin_in_MIPs=0.1, - .tmax=320 * dd4hep::ns, - }, - app // TODO: Remove me once fixed - )); - - double side_length=31.3 * dd4hep::mm; - app->Add(new JOmniFactoryGeneratorT( - "HcalFarForwardZDCImagingProtoClusters", {"HcalFarForwardZDCSubcellHits"}, {"HcalFarForwardZDCImagingProtoClusters"}, - { - .neighbourLayersRange = 1, - .localDistXY = {0.76*side_length, 0.76*side_length*sin(M_PI/3)}, - .layerDistEtaPhi = {17e-3, 18.1e-3}, - .sectorDist = 10.0 * dd4hep::cm, - .minClusterHitEdep = 100.0 * dd4hep::keV, - .minClusterCenterEdep = 11.0 * dd4hep::MeV, - .minClusterEdep = 11.0 * dd4hep::MeV, - .minClusterNhits = 10, - }, - app // TODO: Remove me once fixed - )); - - app->Add(new JOmniFactoryGeneratorT( - "HcalFarForwardZDCIslandProtoClusters", {"HcalFarForwardZDCSubcellHits"}, {"HcalFarForwardZDCIslandProtoClusters"}, - { - .sectorDist = 1.5 * dd4hep::cm, - .localDistXY = {0.9*side_length, 0.76*side_length*sin(M_PI/3)}, - .splitCluster = false, - .minClusterHitEdep = 100.0 * dd4hep::keV, - .minClusterCenterEdep = 1.0 * dd4hep::MeV, - // .transverseEnergyProfileMetric = "globalDistEtaPhi", - // .transverseEnergyProfileScale = 1., - }, - app - )); - - app->Add(new JOmniFactoryGeneratorT( - "HcalFarForwardZDCClusters", - {"HcalFarForwardZDCIslandProtoClusters", // edm4eic::ProtoClusterCollection - "HcalFarForwardZDCHits"}, // edm4hep::SimCalorimeterHitCollection - {"HcalFarForwardZDCClusters", // edm4eic::Cluster - "HcalFarForwardZDCClusterAssociations"}, // edm4eic::MCRecoClusterParticleAssociation - { - .energyWeight = "log", - .sampFrac = 0.0203, - .logWeightBaseCoeffs={5.0,0.65,0.31}, - .logWeightBase_Eref=50*dd4hep::GeV, - }, - app // TODO: Remove me once fixed - )); - - app->Add(new JOmniFactoryGeneratorT( - "HcalFarForwardZDCTruthProtoClusters", {"HcalFarForwardZDCRecHits", "HcalFarForwardZDCHits"}, {"HcalFarForwardZDCTruthProtoClusters"}, - app // TODO: Remove me once fixed - )); - - //Clusters with the baseline algorithm (no HEXPLIT) - app->Add(new JOmniFactoryGeneratorT( - "HcalFarForwardZDCIslandProtoClustersBaseline", {"HcalFarForwardZDCRecHits"}, {"HcalFarForwardZDCIslandProtoClustersBaseline"}, - { - .sectorDist = 5.0 * dd4hep::cm, - .localDistXY = {50 * dd4hep::cm, 50 * dd4hep::cm}, - .dimScaledLocalDistXY = {50.0*dd4hep::mm, 50.0*dd4hep::mm}, - .splitCluster = true, - .minClusterHitEdep = 0.1 * dd4hep::MeV, - .minClusterCenterEdep = 3.0 * dd4hep::MeV, - .transverseEnergyProfileMetric = "globalDistEtaPhi", - .transverseEnergyProfileScale = 1., - }, - app // TODO: Remove me once fixed - )); - - app->Add(new JOmniFactoryGeneratorT( - "HcalFarForwardZDCTruthClusters", - {"HcalFarForwardZDCTruthProtoClusters", // edm4eic::ProtoClusterCollection - "HcalFarForwardZDCHits"}, // edm4hep::SimCalorimeterHitCollection - {"HcalFarForwardZDCTruthClusters", // edm4eic::Cluster - "HcalFarForwardZDCTruthClusterAssociations"}, // edm4eic::MCRecoClusterParticleAssociation - { - .energyWeight = "log", - .sampFrac = 1.0, - .logWeightBase = 3.6, - .enableEtaBounds = false - }, - app // TODO: Remove me once fixed - ) - ); - - app->Add(new JOmniFactoryGeneratorT( - "HcalFarForwardZDCClustersBaseline", - {"HcalFarForwardZDCIslandProtoClustersBaseline", // edm4eic::ProtoClusterCollection - "HcalFarForwardZDCHits"}, // edm4hep::SimCalorimeterHitCollection - {"HcalFarForwardZDCClustersBaseline", // edm4eic::Cluster - "HcalFarForwardZDCClusterAssociationsBaseline"}, // edm4eic::MCRecoClusterParticleAssociation - { - .energyWeight = "log", - .sampFrac = 0.0203, - .logWeightBase = 6.2, - .enableEtaBounds = false, - }, - app // TODO: Remove me once fixed - ) - ); - } +void InitPlugin(JApplication* app) { + + using namespace eicrecon; + + InitJANAPlugin(app); + + // LYSO part of the ZDC + app->Add(new JOmniFactoryGeneratorT( + "EcalFarForwardZDCRawHits", {"EcalFarForwardZDCHits"}, {"EcalFarForwardZDCRawHits"}, + { + .tRes = 0.0 * dd4hep::ns, + .capADC = 32768, + .dyRangeADC = 2000 * dd4hep::MeV, + .pedMeanADC = 400, + .pedSigmaADC = 3.2, + .resolutionTDC = 10 * dd4hep::picosecond, + .corrMeanScale = 1.0, + .readout = "EcalFarForwardZDCHits", + }, + app // TODO: Remove me once fixed + )); + app->Add(new JOmniFactoryGeneratorT( + "EcalFarForwardZDCRecHits", {"EcalFarForwardZDCRawHits"}, {"EcalFarForwardZDCRecHits"}, + { + .capADC = 32768, + .dyRangeADC = 2000. * dd4hep::MeV, + .pedMeanADC = 400, + .pedSigmaADC = 3.2, + .resolutionTDC = 10 * dd4hep::picosecond, + .thresholdFactor = 4.0, + .thresholdValue = 0.0, + .sampFrac = 1.0, + .readout = "EcalFarForwardZDCHits", + }, + app // TODO: Remove me once fixed + )); + app->Add(new JOmniFactoryGeneratorT( + "EcalFarForwardZDCTruthProtoClusters", {"EcalFarForwardZDCRecHits", "EcalFarForwardZDCHits"}, + {"EcalFarForwardZDCTruthProtoClusters"}, + app // TODO: Remove me once fixed + )); + app->Add(new JOmniFactoryGeneratorT( + "EcalFarForwardZDCIslandProtoClusters", {"EcalFarForwardZDCRecHits"}, + {"EcalFarForwardZDCIslandProtoClusters"}, + { + .sectorDist = 5.0 * dd4hep::cm, + .localDistXY = {50 * dd4hep::cm, 50 * dd4hep::cm}, + .dimScaledLocalDistXY = {50.0 * dd4hep::mm, 50.0 * dd4hep::mm}, + .splitCluster = true, + .minClusterHitEdep = 0.1 * dd4hep::MeV, + .minClusterCenterEdep = 3.0 * dd4hep::MeV, + .transverseEnergyProfileMetric = "globalDistEtaPhi", + .transverseEnergyProfileScale = 1., + }, + app // TODO: Remove me once fixed + )); + + app->Add(new JOmniFactoryGeneratorT( + "EcalFarForwardZDCTruthClusters", + {"EcalFarForwardZDCTruthProtoClusters", // edm4eic::ProtoClusterCollection + "EcalFarForwardZDCHits"}, // edm4hep::SimCalorimeterHitCollection + {"EcalFarForwardZDCTruthClusters", // edm4eic::Cluster + "EcalFarForwardZDCTruthClusterAssociations"}, // edm4eic::MCRecoClusterParticleAssociation + {.energyWeight = "log", .sampFrac = 1.0, .logWeightBase = 3.6, .enableEtaBounds = false}, + app // TODO: Remove me once fixed + )); + + app->Add(new JOmniFactoryGeneratorT( + "EcalFarForwardZDCClusters", + {"EcalFarForwardZDCIslandProtoClusters", // edm4eic::ProtoClusterCollection + "EcalFarForwardZDCHits"}, // edm4hep::SimCalorimeterHitCollection + {"EcalFarForwardZDCClusters", // edm4eic::Cluster + "EcalFarForwardZDCClusterAssociations"}, // edm4eic::MCRecoClusterParticleAssociation + { + .energyWeight = "log", + .sampFrac = 1.0, + .logWeightBase = 6.2, + .enableEtaBounds = false, + }, + app // TODO: Remove me once fixed + )); + + app->Add(new JOmniFactoryGeneratorT( + "HcalFarForwardZDCRawHits", {"HcalFarForwardZDCHits"}, {"HcalFarForwardZDCRawHits"}, + { + .tRes = 0.0 * dd4hep::ns, + .capADC = 32768, + .dyRangeADC = 800 * dd4hep::MeV, + .pedMeanADC = 400, + .pedSigmaADC = 10, + .resolutionTDC = 10 * dd4hep::picosecond, + .corrMeanScale = 1.0, + .readout = "HcalFarForwardZDCHits", + }, + app // TODO: Remove me once fixed + )); + + app->Add(new JOmniFactoryGeneratorT( + "HcalFarForwardZDCRecHits", {"HcalFarForwardZDCRawHits"}, {"HcalFarForwardZDCRecHits"}, + { + .capADC = 32678, + .dyRangeADC = 800. * dd4hep::MeV, + .pedMeanADC = 400, + .pedSigmaADC = 10, + .resolutionTDC = 10 * dd4hep::picosecond, + .thresholdFactor = 0.0, + .thresholdValue = -100.0, + .sampFrac = 1.0, + .readout = "HcalFarForwardZDCHits", + .layerField = "layer", + .sectorField = "system", + }, + app // TODO: Remove me once fixed + )); + + app->Add(new JOmniFactoryGeneratorT("HcalFarForwardZDCSubcellHits", + {"HcalFarForwardZDCRecHits"}, + {"HcalFarForwardZDCSubcellHits"}, + { + .MIP = 472. * dd4hep::keV, + .Emin_in_MIPs = 0.1, + .tmax = 320 * dd4hep::ns, + }, + app // TODO: Remove me once fixed + )); + + double side_length = 31.3 * dd4hep::mm; + app->Add(new JOmniFactoryGeneratorT( + "HcalFarForwardZDCImagingProtoClusters", {"HcalFarForwardZDCSubcellHits"}, + {"HcalFarForwardZDCImagingProtoClusters"}, + { + .neighbourLayersRange = 1, + .localDistXY = {0.76 * side_length, 0.76 * side_length * sin(M_PI / 3)}, + .layerDistEtaPhi = {17e-3, 18.1e-3}, + .sectorDist = 10.0 * dd4hep::cm, + .minClusterHitEdep = 100.0 * dd4hep::keV, + .minClusterCenterEdep = 11.0 * dd4hep::MeV, + .minClusterEdep = 11.0 * dd4hep::MeV, + .minClusterNhits = 10, + }, + app // TODO: Remove me once fixed + )); + + app->Add(new JOmniFactoryGeneratorT( + "HcalFarForwardZDCIslandProtoClusters", {"HcalFarForwardZDCSubcellHits"}, + {"HcalFarForwardZDCIslandProtoClusters"}, + { + .sectorDist = 1.5 * dd4hep::cm, + .localDistXY = {0.9 * side_length, 0.76 * side_length * sin(M_PI / 3)}, + .splitCluster = false, + .minClusterHitEdep = 100.0 * dd4hep::keV, + .minClusterCenterEdep = 1.0 * dd4hep::MeV, + // .transverseEnergyProfileMetric = "globalDistEtaPhi", + // .transverseEnergyProfileScale = 1., + }, + app)); + + app->Add(new JOmniFactoryGeneratorT( + "HcalFarForwardZDCClusters", + {"HcalFarForwardZDCIslandProtoClusters", // edm4eic::ProtoClusterCollection + "HcalFarForwardZDCHits"}, // edm4hep::SimCalorimeterHitCollection + {"HcalFarForwardZDCClusters", // edm4eic::Cluster + "HcalFarForwardZDCClusterAssociations"}, // edm4eic::MCRecoClusterParticleAssociation + { + .energyWeight = "log", + .sampFrac = 0.0203, + .logWeightBaseCoeffs = {5.0, 0.65, 0.31}, + .logWeightBase_Eref = 50 * dd4hep::GeV, + }, + app // TODO: Remove me once fixed + )); + + app->Add(new JOmniFactoryGeneratorT( + "HcalFarForwardZDCTruthProtoClusters", {"HcalFarForwardZDCRecHits", "HcalFarForwardZDCHits"}, + {"HcalFarForwardZDCTruthProtoClusters"}, + app // TODO: Remove me once fixed + )); + + //Clusters with the baseline algorithm (no HEXPLIT) + app->Add(new JOmniFactoryGeneratorT( + "HcalFarForwardZDCIslandProtoClustersBaseline", {"HcalFarForwardZDCRecHits"}, + {"HcalFarForwardZDCIslandProtoClustersBaseline"}, + { + .sectorDist = 5.0 * dd4hep::cm, + .localDistXY = {50 * dd4hep::cm, 50 * dd4hep::cm}, + .dimScaledLocalDistXY = {50.0 * dd4hep::mm, 50.0 * dd4hep::mm}, + .splitCluster = true, + .minClusterHitEdep = 0.1 * dd4hep::MeV, + .minClusterCenterEdep = 3.0 * dd4hep::MeV, + .transverseEnergyProfileMetric = "globalDistEtaPhi", + .transverseEnergyProfileScale = 1., + }, + app // TODO: Remove me once fixed + )); + + app->Add(new JOmniFactoryGeneratorT( + "HcalFarForwardZDCTruthClusters", + {"HcalFarForwardZDCTruthProtoClusters", // edm4eic::ProtoClusterCollection + "HcalFarForwardZDCHits"}, // edm4hep::SimCalorimeterHitCollection + {"HcalFarForwardZDCTruthClusters", // edm4eic::Cluster + "HcalFarForwardZDCTruthClusterAssociations"}, // edm4eic::MCRecoClusterParticleAssociation + {.energyWeight = "log", .sampFrac = 1.0, .logWeightBase = 3.6, .enableEtaBounds = false}, + app // TODO: Remove me once fixed + )); + + app->Add(new JOmniFactoryGeneratorT( + "HcalFarForwardZDCClustersBaseline", + {"HcalFarForwardZDCIslandProtoClustersBaseline", // edm4eic::ProtoClusterCollection + "HcalFarForwardZDCHits"}, // edm4hep::SimCalorimeterHitCollection + {"HcalFarForwardZDCClustersBaseline", // edm4eic::Cluster + "HcalFarForwardZDCClusterAssociationsBaseline"}, // edm4eic::MCRecoClusterParticleAssociation + { + .energyWeight = "log", + .sampFrac = 0.0203, + .logWeightBase = 6.2, + .enableEtaBounds = false, + }, + app // TODO: Remove me once fixed + )); +} } diff --git a/src/examples/track_matching/reco_particles_track_matching.cc b/src/examples/track_matching/reco_particles_track_matching.cc index c5a7c41f2b..25423715d1 100644 --- a/src/examples/track_matching/reco_particles_track_matching.cc +++ b/src/examples/track_matching/reco_particles_track_matching.cc @@ -13,48 +13,48 @@ #include #include -void reco_particles_track_matching(const std::string &file_name) { - auto *file = new TFile(file_name.c_str()); - auto *tree = (TTree *) file->Get("events"); - TTreeReader tree_reader(tree); // !the tree reader - tree->Print(); - - // Reconstructed particles pz array for each reconstructed particle - TTreeReaderArray reco_pz_array = {tree_reader, "ReconstructedChargedParticles.momentum.z"}; - - // MC particle pz array for each MC particle - TTreeReaderArray mc_pz_array = {tree_reader, "MCParticles.momentum.z"}; - - // Next arrays correspond to particle associations - // Each association has 2 ids - indexes in corresponding reco and MC arrays - TTreeReaderArray rec_id = {tree_reader, "ReconstructedChargedParticleAssociations.recID"}; - TTreeReaderArray sim_id = {tree_reader, "ReconstructedChargedParticleAssociations.simID"}; - - - // Read 100 events - tree_reader.SetEntriesRange(0, 100); - while (tree_reader.Next()) { - - // Number of mc particles, reco particles and associations may differ - fmt::print("New event. N reco particles: {}, N mc particles: {}, N assoc: {}\n", - reco_pz_array.GetSize(), mc_pz_array.GetSize(), rec_id.GetSize()); - - // Iterate over associations - for(unsigned int i=0; i < rec_id.GetSize(); i++) { - - // For each association pull index of reco and MC array - auto reco_array_index = rec_id[i]; - auto mc_array_index = sim_id[i]; - - float reco_pz = reco_pz_array[reco_array_index]; - float mc_pz = mc_pz_array[mc_array_index]; - fmt::print(" reco={:>10.4f} mc={:>10.4f}\n", reco_pz, mc_pz); - } +void reco_particles_track_matching(const std::string& file_name) { + auto* file = new TFile(file_name.c_str()); + auto* tree = (TTree*)file->Get("events"); + TTreeReader tree_reader(tree); // !the tree reader + tree->Print(); + + // Reconstructed particles pz array for each reconstructed particle + TTreeReaderArray reco_pz_array = {tree_reader, "ReconstructedChargedParticles.momentum.z"}; + + // MC particle pz array for each MC particle + TTreeReaderArray mc_pz_array = {tree_reader, "MCParticles.momentum.z"}; + + // Next arrays correspond to particle associations + // Each association has 2 ids - indexes in corresponding reco and MC arrays + TTreeReaderArray rec_id = {tree_reader, + "ReconstructedChargedParticleAssociations.recID"}; + TTreeReaderArray sim_id = {tree_reader, + "ReconstructedChargedParticleAssociations.simID"}; + + // Read 100 events + tree_reader.SetEntriesRange(0, 100); + while (tree_reader.Next()) { + + // Number of mc particles, reco particles and associations may differ + fmt::print("New event. N reco particles: {}, N mc particles: {}, N assoc: {}\n", + reco_pz_array.GetSize(), mc_pz_array.GetSize(), rec_id.GetSize()); + + // Iterate over associations + for (unsigned int i = 0; i < rec_id.GetSize(); i++) { + + // For each association pull index of reco and MC array + auto reco_array_index = rec_id[i]; + auto mc_array_index = sim_id[i]; + + float reco_pz = reco_pz_array[reco_array_index]; + float mc_pz = mc_pz_array[mc_array_index]; + fmt::print(" reco={:>10.4f} mc={:>10.4f}\n", reco_pz, mc_pz); } + } } - int main() { - reco_particles_track_matching("input.edm4eic.root"); - return 0; + reco_particles_track_matching("input.edm4eic.root"); + return 0; } diff --git a/src/extensions/jana/JChainMultifactoryGeneratorT.h b/src/extensions/jana/JChainMultifactoryGeneratorT.h index 4f75ce23c6..fe73e500d9 100644 --- a/src/extensions/jana/JChainMultifactoryGeneratorT.h +++ b/src/extensions/jana/JChainMultifactoryGeneratorT.h @@ -11,80 +11,77 @@ #include "JChainMultifactoryT.h" -template -class JChainMultifactoryGeneratorT : public JFactoryGenerator { +template class JChainMultifactoryGeneratorT : public JFactoryGenerator { public: - - // using FactoryOutputType = typename FactoryT::OutputType; - using FactoryConfigType = typename FactoryT::ConfigType; - - /// Constructor with config - explicit JChainMultifactoryGeneratorT(std::string tag, std::vector default_input_tags, std::vector output_tags, FactoryConfigType cfg, JApplication* app): - m_tag(tag), - m_default_input_tags(std::move(default_input_tags)), - m_default_output_tags(std::move(output_tags)), - m_default_cfg(cfg), - m_app(app) - { - }; - - /// Constructor for NoConfig configuration - explicit JChainMultifactoryGeneratorT(std::string tag, std::vector default_input_tags, std::vector output_tags, JApplication* app): - m_tag(tag), - m_default_input_tags(std::move(default_input_tags)), - m_default_output_tags(std::move(output_tags)), - m_app(app) - { - }; - - void GenerateFactories(JFactorySet *factory_set) override { - // initialization is delayed to let caller set plugin name first - if (!m_init_done) { - Init(); - m_init_done = true; - } - - FactoryT *factory; - if constexpr(std:: is_base_of()) { - factory = new FactoryT(m_tag, m_input_tags, m_output_tags); - } else { - factory = new FactoryT(m_tag, m_input_tags, m_output_tags, m_default_cfg); - } - factory->SetPrefix(m_prefix); - factory->SetFactoryName(JTypeInfo::demangle()); - factory->SetPluginName(this->GetPluginName()); - factory->SetApplication(m_app); - factory_set->Add(factory); + // using FactoryOutputType = typename FactoryT::OutputType; + using FactoryConfigType = typename FactoryT::ConfigType; + + /// Constructor with config + explicit JChainMultifactoryGeneratorT(std::string tag, + std::vector default_input_tags, + std::vector output_tags, FactoryConfigType cfg, + JApplication* app) + : m_tag(tag) + , m_default_input_tags(std::move(default_input_tags)) + , m_default_output_tags(std::move(output_tags)) + , m_default_cfg(cfg) + , m_app(app){}; + + /// Constructor for NoConfig configuration + explicit JChainMultifactoryGeneratorT(std::string tag, + std::vector default_input_tags, + std::vector output_tags, JApplication* app) + : m_tag(tag) + , m_default_input_tags(std::move(default_input_tags)) + , m_default_output_tags(std::move(output_tags)) + , m_app(app){}; + + void GenerateFactories(JFactorySet* factory_set) override { + // initialization is delayed to let caller set plugin name first + if (!m_init_done) { + Init(); + m_init_done = true; } - - void Init() { - std::string plugin_name = this->GetPluginName(); - m_prefix = plugin_name + ":" + m_tag; - - // Get input data tags - m_app->SetDefaultParameter(m_prefix + ":InputTags", m_input_tags, "Input data tag names"); - if(m_input_tags.empty()) { - m_input_tags = m_default_input_tags; - } - - m_app->SetDefaultParameter(m_prefix + ":OutputTags", m_output_tags, "Output data tag names"); - if(m_output_tags.empty()) { - m_output_tags = m_default_output_tags; - } + FactoryT* factory; + if constexpr (std::is_base_of()) { + factory = new FactoryT(m_tag, m_input_tags, m_output_tags); + } else { + factory = new FactoryT(m_tag, m_input_tags, m_output_tags, m_default_cfg); + } + factory->SetPrefix(m_prefix); + factory->SetFactoryName(JTypeInfo::demangle()); + factory->SetPluginName(this->GetPluginName()); + factory->SetApplication(m_app); + factory_set->Add(factory); + } + + void Init() { + std::string plugin_name = this->GetPluginName(); + m_prefix = plugin_name + ":" + m_tag; + + // Get input data tags + m_app->SetDefaultParameter(m_prefix + ":InputTags", m_input_tags, "Input data tag names"); + if (m_input_tags.empty()) { + m_input_tags = m_default_input_tags; } + m_app->SetDefaultParameter(m_prefix + ":OutputTags", m_output_tags, "Output data tag names"); + if (m_output_tags.empty()) { + m_output_tags = m_default_output_tags; + } + } private: - std::string m_tag; - std::string m_prefix; - std::vector m_default_input_tags; - std::vector m_default_output_tags; - std::vector m_input_tags; - std::vector m_output_tags; - - FactoryConfigType m_default_cfg; /// Default config for a factories. (!) Must be properly copyable - JApplication* m_app; // TODO: NWB: Remove me - bool m_init_done = false; + std::string m_tag; + std::string m_prefix; + std::vector m_default_input_tags; + std::vector m_default_output_tags; + std::vector m_input_tags; + std::vector m_output_tags; + + FactoryConfigType m_default_cfg; /// Default config for a factories. (!) Must be properly copyable + JApplication* m_app; // TODO: NWB: Remove me + bool m_init_done = false; }; diff --git a/src/extensions/jana/JChainMultifactoryT.h b/src/extensions/jana/JChainMultifactoryT.h index 63412b544b..3354372fe6 100644 --- a/src/extensions/jana/JChainMultifactoryT.h +++ b/src/extensions/jana/JChainMultifactoryT.h @@ -24,82 +24,70 @@ #include #include "algorithms/interfaces/WithPodConfig.h" - -template -class JChainMultifactoryT : public JMultifactory { +template class JChainMultifactoryT : public JMultifactory { public: + using ConfigType = ConfigT; - using ConfigType = ConfigT; - - /// Constructor with NoConfig - JChainMultifactoryT( std::string tag, - std::vector input_tags, - std::vector output_tags, - ConfigT cfg): - m_tag(std::move(tag)), - m_input_tags( std::move(input_tags) ), - m_output_tags(std::move(output_tags)), - m_default_cfg(cfg) - { - } - - /// Constructor for NoConfig case - explicit JChainMultifactoryT( std::string tag, std::vector input_tags, std::vector output_tags): - m_tag(std::move(tag)), - m_input_tags( std::move(input_tags) ), - m_output_tags(std::move(output_tags)) - { - } + /// Constructor with NoConfig + JChainMultifactoryT(std::string tag, std::vector input_tags, + std::vector output_tags, ConfigT cfg) + : m_tag(std::move(tag)) + , m_input_tags(std::move(input_tags)) + , m_output_tags(std::move(output_tags)) + , m_default_cfg(cfg) {} - /// The unique tag for the multifactory instance. Used for the param_prefix - std::string& GetTag() { return m_tag; } + /// Constructor for NoConfig case + explicit JChainMultifactoryT(std::string tag, std::vector input_tags, + std::vector output_tags) + : m_tag(std::move(tag)) + , m_input_tags(std::move(input_tags)) + , m_output_tags(std::move(output_tags)) {} - /// Gets final input tags (with adjustment by user parameters) - std::vector& GetInputTags() { return m_input_tags; } + /// The unique tag for the multifactory instance. Used for the param_prefix + std::string& GetTag() { return m_tag; } - /// Gets final output tags (with adjustment by user parameters) - std::vector& GetOutputTags() { return m_output_tags; } + /// Gets final input tags (with adjustment by user parameters) + std::vector& GetInputTags() { return m_input_tags; } - /// Gets config - ConfigT& GetDefaultConfig() { return m_default_cfg; } + /// Gets final output tags (with adjustment by user parameters) + std::vector& GetOutputTags() { return m_output_tags; } + /// Gets config + ConfigT& GetDefaultConfig() { return m_default_cfg; } - // Setters and getters for things that really belong on JMultifactory - // TODO: NWB: Remove - void SetPluginName(std::string plugin_name) { m_plugin_name = std::move(plugin_name);} + // Setters and getters for things that really belong on JMultifactory + // TODO: NWB: Remove + void SetPluginName(std::string plugin_name) { m_plugin_name = std::move(plugin_name); } - std::string GetPluginName() { return m_plugin_name; } + std::string GetPluginName() { return m_plugin_name; } - void SetApplication(JApplication* app) { m_app = app; } + void SetApplication(JApplication* app) { m_app = app; } - JApplication* GetApplication() { return m_app; } + JApplication* GetApplication() { return m_app; } - void SetPrefix(std::string prefix) { m_prefix = std::move(prefix); } - - std::string& GetPrefix() { return m_prefix; } + void SetPrefix(std::string prefix) { m_prefix = std::move(prefix); } + std::string& GetPrefix() { return m_prefix; } protected: - - /// Underlying algorithm config - ConfigT m_default_cfg; + /// Underlying algorithm config + ConfigT m_default_cfg; private: - // Used to uniquely identify an _instance_ of this particular JChainMultifactory (since there is no longer a unique - // output tag we can use) - std::string m_tag; - - // Prefix for parameters and loggers, derived from plugin name and tag in Init(). - std::string m_prefix; + // Used to uniquely identify an _instance_ of this particular JChainMultifactory (since there is no longer a unique + // output tag we can use) + std::string m_tag; - /// Working input tags (with adjustment by user parameters) - std::vector m_input_tags; + // Prefix for parameters and loggers, derived from plugin name and tag in Init(). + std::string m_prefix; - /// Output tags - std::vector m_output_tags; + /// Working input tags (with adjustment by user parameters) + std::vector m_input_tags; - /// TODO: NWB: Pull these directly into JMultifactory - JApplication* m_app; - std::string m_plugin_name; + /// Output tags + std::vector m_output_tags; + /// TODO: NWB: Pull these directly into JMultifactory + JApplication* m_app; + std::string m_plugin_name; }; diff --git a/src/extensions/jana/JOmniFactory.h b/src/extensions/jana/JOmniFactory.h index 4ee9aff7d8..c7397e498b 100644 --- a/src/extensions/jana/JOmniFactory.h +++ b/src/extensions/jana/JOmniFactory.h @@ -24,570 +24,532 @@ using namespace eicrecon; struct EmptyConfig {}; -template +template class JOmniFactory : public JMultifactory { public: + /// ======================== + /// Handle input collections + /// ======================== - /// ======================== - /// Handle input collections - /// ======================== + struct InputBase { + std::string type_name; + std::vector collection_names; + bool is_variadic = false; - struct InputBase { - std::string type_name; - std::vector collection_names; - bool is_variadic = false; + virtual void GetCollection(const JEvent& event) = 0; + }; - virtual void GetCollection(const JEvent& event) = 0; - }; - - template - class Input : public InputBase { - - std::vector m_data; - - public: - Input(JOmniFactory* owner, std::string default_tag="") { - owner->RegisterInput(this); - this->collection_names.push_back(default_tag); - this->type_name = JTypeInfo::demangle(); - } - - const std::vector& operator()() { return m_data; } - - private: - friend class JOmniFactory; + template class Input : public InputBase { - void GetCollection(const JEvent& event) { - m_data = event.Get(this->collection_names[0]); - } - }; - - - template - class PodioInput : public InputBase { + std::vector m_data; - const typename PodioTypeMap::collection_t* m_data; - - public: - - PodioInput(JOmniFactory* owner, std::string default_collection_name="") { - owner->RegisterInput(this); - this->collection_names.push_back(default_collection_name); - this->type_name = JTypeInfo::demangle(); - } + public: + Input(JOmniFactory* owner, std::string default_tag = "") { + owner->RegisterInput(this); + this->collection_names.push_back(default_tag); + this->type_name = JTypeInfo::demangle(); + } - const typename PodioTypeMap::collection_t* operator()() { - return m_data; - } + const std::vector& operator()() { return m_data; } - private: - friend class JOmniFactory; + private: + friend class JOmniFactory; - void GetCollection(const JEvent& event) { - m_data = event.GetCollection(this->collection_names[0]); - } - }; + void GetCollection(const JEvent& event) { m_data = event.Get(this->collection_names[0]); } + }; + template class PodioInput : public InputBase { - template - class VariadicPodioInput : public InputBase { + const typename PodioTypeMap::collection_t* m_data; - std::vector::collection_t*> m_data; - - public: - - VariadicPodioInput(JOmniFactory* owner, std::vector default_names = {}) { - owner->RegisterInput(this); - this->collection_names = default_names; - this->type_name = JTypeInfo::demangle(); - this->is_variadic = true; - } - - const std::vector::collection_t*> operator()() { - return m_data; - } + public: + PodioInput(JOmniFactory* owner, std::string default_collection_name = "") { + owner->RegisterInput(this); + this->collection_names.push_back(default_collection_name); + this->type_name = JTypeInfo::demangle(); + } - private: - friend class JOmniFactory; + const typename PodioTypeMap::collection_t* operator()() { return m_data; } - void GetCollection(const JEvent& event) { - m_data.clear(); - for (auto& coll_name : this->collection_names) { - m_data.push_back(event.GetCollection(coll_name)); - } - } - }; + private: + friend class JOmniFactory; - void RegisterInput(InputBase* input) { - m_inputs.push_back(input); + void GetCollection(const JEvent& event) { + m_data = event.GetCollection(this->collection_names[0]); } + }; + template class VariadicPodioInput : public InputBase { - /// ========================= - /// Handle output collections - /// ========================= + std::vector::collection_t*> m_data; - struct OutputBase { - std::string type_name; - std::vector collection_names; - bool is_variadic = false; + public: + VariadicPodioInput(JOmniFactory* owner, std::vector default_names = {}) { + owner->RegisterInput(this); + this->collection_names = default_names; + this->type_name = JTypeInfo::demangle(); + this->is_variadic = true; + } - virtual void CreateHelperFactory(JOmniFactory& fac) = 0; - virtual void SetCollection(JOmniFactory& fac) = 0; - virtual void Reset() = 0; - }; + const std::vector::collection_t*> operator()() { + return m_data; + } - template - class Output : public OutputBase { - std::vector m_data; + private: + friend class JOmniFactory; - public: - Output(JOmniFactory* owner, std::string default_tag_name="") { - owner->RegisterOutput(this); - this->collection_names.push_back(default_tag_name); - this->type_name = JTypeInfo::demangle(); - } + void GetCollection(const JEvent& event) { + m_data.clear(); + for (auto& coll_name : this->collection_names) { + m_data.push_back(event.GetCollection(coll_name)); + } + } + }; - std::vector& operator()() { return m_data; } + void RegisterInput(InputBase* input) { m_inputs.push_back(input); } - private: - friend class JOmniFactory; + /// ========================= + /// Handle output collections + /// ========================= - void CreateHelperFactory(JOmniFactory& fac) override { - fac.DeclareOutput(this->collection_names[0]); - } + struct OutputBase { + std::string type_name; + std::vector collection_names; + bool is_variadic = false; - void SetCollection(JOmniFactory& fac) override { - fac.SetData(this->collection_names[0], this->m_data); - } + virtual void CreateHelperFactory(JOmniFactory& fac) = 0; + virtual void SetCollection(JOmniFactory& fac) = 0; + virtual void Reset() = 0; + }; - void Reset() override { } - }; + template class Output : public OutputBase { + std::vector m_data; + public: + Output(JOmniFactory* owner, std::string default_tag_name = "") { + owner->RegisterOutput(this); + this->collection_names.push_back(default_tag_name); + this->type_name = JTypeInfo::demangle(); + } - template - class PodioOutput : public OutputBase { + std::vector& operator()() { return m_data; } - std::unique_ptr::collection_t> m_data; + private: + friend class JOmniFactory; - public: + void CreateHelperFactory(JOmniFactory& fac) override { + fac.DeclareOutput(this->collection_names[0]); + } - PodioOutput(JOmniFactory* owner, std::string default_collection_name="") { - owner->RegisterOutput(this); - this->collection_names.push_back(default_collection_name); - this->type_name = JTypeInfo::demangle(); - } + void SetCollection(JOmniFactory& fac) override { + fac.SetData(this->collection_names[0], this->m_data); + } - std::unique_ptr::collection_t>& operator()() { return m_data; } + void Reset() override {} + }; - private: - friend class JOmniFactory; + template class PodioOutput : public OutputBase { - void CreateHelperFactory(JOmniFactory& fac) override { - fac.DeclarePodioOutput(this->collection_names[0]); - } + std::unique_ptr::collection_t> m_data; - void SetCollection(JOmniFactory& fac) override { - if (m_data == nullptr) { - throw JException("JOmniFactory: SetCollection failed due to missing output collection '%s'", this->collection_names[0].c_str()); - // Otherwise this leads to a PODIO segfault - } - fac.SetCollection(this->collection_names[0], std::move(this->m_data)); - } + public: + PodioOutput(JOmniFactory* owner, std::string default_collection_name = "") { + owner->RegisterOutput(this); + this->collection_names.push_back(default_collection_name); + this->type_name = JTypeInfo::demangle(); + } - void Reset() override { - m_data = std::move(std::make_unique::collection_t>()); - } - }; + std::unique_ptr::collection_t>& operator()() { return m_data; } + private: + friend class JOmniFactory; - template - class VariadicPodioOutput : public OutputBase { + void CreateHelperFactory(JOmniFactory& fac) override { + fac.DeclarePodioOutput(this->collection_names[0]); + } - std::vector::collection_t>> m_data; + void SetCollection(JOmniFactory& fac) override { + if (m_data == nullptr) { + throw JException("JOmniFactory: SetCollection failed due to missing output collection '%s'", + this->collection_names[0].c_str()); + // Otherwise this leads to a PODIO segfault + } + fac.SetCollection(this->collection_names[0], std::move(this->m_data)); + } - public: + void Reset() override { + m_data = std::move(std::make_unique::collection_t>()); + } + }; - VariadicPodioOutput(JOmniFactory* owner, std::vector default_collection_names={}) { - owner->RegisterOutput(this); - this->collection_names = default_collection_names; - this->type_name = JTypeInfo::demangle(); - this->is_variadic = true; - } + template class VariadicPodioOutput : public OutputBase { - std::vector::collection_t>>& operator()() { return m_data; } + std::vector::collection_t>> m_data; - private: - friend class JOmniFactory; + public: + VariadicPodioOutput(JOmniFactory* owner, + std::vector default_collection_names = {}) { + owner->RegisterOutput(this); + this->collection_names = default_collection_names; + this->type_name = JTypeInfo::demangle(); + this->is_variadic = true; + } - void CreateHelperFactory(JOmniFactory& fac) override { - for (auto& coll_name : this->collection_names) { - fac.DeclarePodioOutput(coll_name); - } - } + std::vector::collection_t>>& operator()() { + return m_data; + } - void SetCollection(JOmniFactory& fac) override { - if (m_data.size() != this->collection_names.size()) { - throw JException("JOmniFactory: VariadicPodioOutput SetCollection failed: Declared %d collections, but provided %d.", this->collection_names.size(), m_data.size()); - // Otherwise this leads to a PODIO segfault - } - size_t i = 0; - for (auto& coll_name : this->collection_names) { - fac.SetCollection(coll_name, std::move(this->m_data[i++])); - } - } + private: + friend class JOmniFactory; - void Reset() override { - m_data.clear(); - for (auto& coll_name : this->collection_names) { - m_data.push_back(std::make_unique::collection_t>()); - } - } - }; + void CreateHelperFactory(JOmniFactory& fac) override { + for (auto& coll_name : this->collection_names) { + fac.DeclarePodioOutput(coll_name); + } + } - void RegisterOutput(OutputBase* output) { - m_outputs.push_back(output); + void SetCollection(JOmniFactory& fac) override { + if (m_data.size() != this->collection_names.size()) { + throw JException("JOmniFactory: VariadicPodioOutput SetCollection failed: Declared %d " + "collections, but provided %d.", + this->collection_names.size(), m_data.size()); + // Otherwise this leads to a PODIO segfault + } + size_t i = 0; + for (auto& coll_name : this->collection_names) { + fac.SetCollection(coll_name, std::move(this->m_data[i++])); + } } + void Reset() override { + m_data.clear(); + for (auto& coll_name : this->collection_names) { + m_data.push_back(std::make_unique::collection_t>()); + } + } + }; - // ================= - // Handle parameters - // ================= + void RegisterOutput(OutputBase* output) { m_outputs.push_back(output); } - struct ParameterBase { - std::string m_name; - std::string m_description; - virtual void Configure(JParameterManager& parman, const std::string& prefix) = 0; - virtual void Configure(std::map fields) = 0; - }; + // ================= + // Handle parameters + // ================= - template - class ParameterRef : public ParameterBase { + struct ParameterBase { + std::string m_name; + std::string m_description; + virtual void Configure(JParameterManager& parman, const std::string& prefix) = 0; + virtual void Configure(std::map fields) = 0; + }; - T* m_data; + template class ParameterRef : public ParameterBase { - public: - ParameterRef(JOmniFactory* owner, std::string name, T& slot, std::string description="") { - owner->RegisterParameter(this); - this->m_name = name; - this->m_description = description; - m_data = &slot; - } + T* m_data; - const T& operator()() { return *m_data; } + public: + ParameterRef(JOmniFactory* owner, std::string name, T& slot, std::string description = "") { + owner->RegisterParameter(this); + this->m_name = name; + this->m_description = description; + m_data = &slot; + } - private: - friend class JOmniFactory; + const T& operator()() { return *m_data; } - void Configure(JParameterManager& parman, const std::string& prefix) override { - parman.SetDefaultParameter(prefix + ":" + this->m_name, *m_data, this->m_description); - } - void Configure(std::map fields) override { - auto it = fields.find(this->m_name); - if (it != fields.end()) { - const auto& value_str = it->second; - if constexpr (10000 * JVersion::major - + 100 * JVersion::minor - + 1 * JVersion::patch < 20102) { - *m_data = JParameterManager::Parse(value_str); - } else { - JParameterManager::Parse(value_str, *m_data); - } - } - } - }; + private: + friend class JOmniFactory; - template - class Parameter : public ParameterBase { + void Configure(JParameterManager& parman, const std::string& prefix) override { + parman.SetDefaultParameter(prefix + ":" + this->m_name, *m_data, this->m_description); + } + void Configure(std::map fields) override { + auto it = fields.find(this->m_name); + if (it != fields.end()) { + const auto& value_str = it->second; + if constexpr (10000 * JVersion::major + 100 * JVersion::minor + 1 * JVersion::patch < + 20102) { + *m_data = JParameterManager::Parse(value_str); + } else { + JParameterManager::Parse(value_str, *m_data); + } + } + } + }; - T m_data; + template class Parameter : public ParameterBase { - public: - Parameter(JOmniFactory* owner, std::string name, T default_value, std::string description) { - owner->RegisterParameter(this); - this->m_name = name; - this->m_description = description; - m_data = default_value; - } + T m_data; - const T& operator()() { return m_data; } + public: + Parameter(JOmniFactory* owner, std::string name, T default_value, std::string description) { + owner->RegisterParameter(this); + this->m_name = name; + this->m_description = description; + m_data = default_value; + } - private: - friend class JOmniFactory; + const T& operator()() { return m_data; } - void Configure(JParameterManager& parman, const std::string& prefix) override { - parman.SetDefaultParameter(m_prefix + ":" + this->m_name, m_data, this->m_description); - } - void Configure(std::map fields) override { - auto it = fields.find(this->m_name); - if (it != fields.end()) { - const auto& value_str = it->second; - if constexpr (10000 * JVersion::major - + 100 * JVersion::minor - + 1 * JVersion::patch < 20102) { - m_data = JParameterManager::Parse(value_str); - } else { - JParameterManager::Parse(value_str, m_data); - } - } - } - }; + private: + friend class JOmniFactory; - void RegisterParameter(ParameterBase* parameter) { - m_parameters.push_back(parameter); + void Configure(JParameterManager& parman, const std::string& prefix) override { + parman.SetDefaultParameter(m_prefix + ":" + this->m_name, m_data, this->m_description); } - - void ConfigureAllParameters(std::map fields) { - for (auto* parameter : this->m_parameters) { - parameter->Configure(fields); - } + void Configure(std::map fields) override { + auto it = fields.find(this->m_name); + if (it != fields.end()) { + const auto& value_str = it->second; + if constexpr (10000 * JVersion::major + 100 * JVersion::minor + 1 * JVersion::patch < + 20102) { + m_data = JParameterManager::Parse(value_str); + } else { + JParameterManager::Parse(value_str, m_data); + } + } } + }; - // =============== - // Handle services - // =============== + void RegisterParameter(ParameterBase* parameter) { m_parameters.push_back(parameter); } - struct ServiceBase { - virtual void Init(JApplication* app) = 0; - }; + void ConfigureAllParameters(std::map fields) { + for (auto* parameter : this->m_parameters) { + parameter->Configure(fields); + } + } - template - class Service : public ServiceBase { + // =============== + // Handle services + // =============== - std::shared_ptr m_data; + struct ServiceBase { + virtual void Init(JApplication* app) = 0; + }; - public: + template class Service : public ServiceBase { - Service(JOmniFactory* owner) { - owner->RegisterService(this); - } + std::shared_ptr m_data; - ServiceT& operator()() { - return *m_data; - } + public: + Service(JOmniFactory* owner) { owner->RegisterService(this); } - private: + ServiceT& operator()() { return *m_data; } - friend class JOmniFactory; + private: + friend class JOmniFactory; - void Init(JApplication* app) { - m_data = app->GetService(); - } + void Init(JApplication* app) { m_data = app->GetService(); } + }; - }; + void RegisterService(ServiceBase* service) { m_services.push_back(service); } - void RegisterService(ServiceBase* service) { - m_services.push_back(service); - } + // ================ + // Handle resources + // ================ + struct ResourceBase { + virtual void ChangeRun(const JEvent& event) = 0; + }; - // ================ - // Handle resources - // ================ + template + class Resource : public ResourceBase { + ResourceT m_data; + LambdaT m_lambda; - struct ResourceBase { - virtual void ChangeRun(const JEvent& event) = 0; + public: + Resource(JOmniFactory* owner, LambdaT lambda) : m_lambda(lambda) { + owner->RegisterResource(this); }; - template - class Resource : public ResourceBase { - ResourceT m_data; - LambdaT m_lambda; - - public: - - Resource(JOmniFactory* owner, LambdaT lambda) : m_lambda(lambda) { - owner->RegisterResource(this); - }; - - const ResourceT& operator()() { return m_data; } - - private: - friend class JOmniFactory; + const ResourceT& operator()() { return m_data; } - void ChangeRun(const JEvent& event) { - auto run_nr = event.GetRunNumber(); - std::shared_ptr service = event.GetJApplication()->template GetService(); - m_data = m_lambda(service, run_nr); - } - }; + private: + friend class JOmniFactory; - void RegisterResource(ResourceBase* resource) { - m_resources.push_back(resource); + void ChangeRun(const JEvent& event) { + auto run_nr = event.GetRunNumber(); + std::shared_ptr service = event.GetJApplication()->template GetService(); + m_data = m_lambda(service, run_nr); } + }; + void RegisterResource(ResourceBase* resource) { m_resources.push_back(resource); } public: - std::vector m_inputs; - std::vector m_outputs; - std::vector m_parameters; - std::vector m_services; - std::vector m_resources; + std::vector m_inputs; + std::vector m_outputs; + std::vector m_parameters; + std::vector m_services; + std::vector m_resources; private: + // App belongs on JMultifactory, it is just missing temporarily + JApplication* m_app; - // App belongs on JMultifactory, it is just missing temporarily - JApplication* m_app; + // Plugin name belongs on JMultifactory, it is just missing temporarily + std::string m_plugin_name; - // Plugin name belongs on JMultifactory, it is just missing temporarily - std::string m_plugin_name; + // Prefix for parameters and loggers, derived from plugin name and tag in PreInit(). + std::string m_prefix; - // Prefix for parameters and loggers, derived from plugin name and tag in PreInit(). - std::string m_prefix; + /// Current logger + std::shared_ptr m_logger; - /// Current logger - std::shared_ptr m_logger; - - /// Configuration - ConfigT m_config; + /// Configuration + ConfigT m_config; public: - - size_t FindVariadicCollectionCount(size_t total_input_count, size_t variadic_input_count, size_t total_collection_count, bool is_input) { - - size_t variadic_collection_count = total_collection_count - (total_input_count - variadic_input_count); - - if (variadic_input_count == 0) { - // No variadic inputs: check that collection_name count matches input count exactly - if (total_input_count != total_collection_count) { - throw JException("JOmniFactory '%s': Wrong number of %s collection names: %d expected, %d found.", - m_prefix.c_str(), (is_input ? "input" : "output"), total_input_count, total_collection_count); - } - } - else { - // Variadic inputs: check that we have enough collection names for the non-variadic inputs - if (total_input_count-variadic_input_count > total_collection_count) { - throw JException("JOmniFactory '%s': Not enough %s collection names: %d needed, %d found.", - m_prefix.c_str(), (is_input ? "input" : "output"), total_input_count-variadic_input_count, total_collection_count); - } - - // Variadic inputs: check that the variadic collection names is evenly divided by the variadic input count - if (variadic_collection_count % variadic_input_count != 0) { - throw JException("JOmniFactory '%s': Wrong number of %s collection names: %d found total, but %d can't be distributed among %d variadic inputs evenly.", - m_prefix.c_str(), (is_input ? "input" : "output"), total_collection_count, variadic_collection_count, variadic_input_count); - } - } - return variadic_collection_count; + size_t FindVariadicCollectionCount(size_t total_input_count, size_t variadic_input_count, + size_t total_collection_count, bool is_input) { + + size_t variadic_collection_count = + total_collection_count - (total_input_count - variadic_input_count); + + if (variadic_input_count == 0) { + // No variadic inputs: check that collection_name count matches input count exactly + if (total_input_count != total_collection_count) { + throw JException( + "JOmniFactory '%s': Wrong number of %s collection names: %d expected, %d found.", + m_prefix.c_str(), (is_input ? "input" : "output"), total_input_count, + total_collection_count); + } + } else { + // Variadic inputs: check that we have enough collection names for the non-variadic inputs + if (total_input_count - variadic_input_count > total_collection_count) { + throw JException("JOmniFactory '%s': Not enough %s collection names: %d needed, %d found.", + m_prefix.c_str(), (is_input ? "input" : "output"), + total_input_count - variadic_input_count, total_collection_count); + } + + // Variadic inputs: check that the variadic collection names is evenly divided by the variadic input count + if (variadic_collection_count % variadic_input_count != 0) { + throw JException("JOmniFactory '%s': Wrong number of %s collection names: %d found total, " + "but %d can't be distributed among %d variadic inputs evenly.", + m_prefix.c_str(), (is_input ? "input" : "output"), total_collection_count, + variadic_collection_count, variadic_input_count); + } + } + return variadic_collection_count; + } + + inline void PreInit(std::string tag, std::vector default_input_collection_names, + std::vector default_output_collection_names) { + + // TODO: NWB: JMultiFactory::GetTag,SetTag are not currently usable + m_prefix = (this->GetPluginName().empty()) ? tag : this->GetPluginName() + ":" + tag; + + // Obtain collection name overrides if provided. + // Priority = [JParameterManager, JOmniFactoryGenerator] + m_app->SetDefaultParameter(m_prefix + ":InputTags", default_input_collection_names, + "Input collection names"); + m_app->SetDefaultParameter(m_prefix + ":OutputTags", default_output_collection_names, + "Output collection names"); + + // Figure out variadic inputs + size_t variadic_input_count = 0; + for (auto* input : m_inputs) { + if (input->is_variadic) { + variadic_input_count += 1; + } + } + size_t variadic_input_collection_count = FindVariadicCollectionCount( + m_inputs.size(), variadic_input_count, default_input_collection_names.size(), true); + + // Set input collection names + for (size_t i = 0; auto* input : m_inputs) { + input->collection_names.clear(); + if (input->is_variadic) { + for (size_t j = 0; j < (variadic_input_collection_count / variadic_input_count); ++j) { + input->collection_names.push_back(default_input_collection_names[i++]); + } + } else { + input->collection_names.push_back(default_input_collection_names[i++]); + } } - inline void PreInit(std::string tag, - std::vector default_input_collection_names, - std::vector default_output_collection_names ) { - - // TODO: NWB: JMultiFactory::GetTag,SetTag are not currently usable - m_prefix = (this->GetPluginName().empty()) ? tag : this->GetPluginName() + ":" + tag; - - // Obtain collection name overrides if provided. - // Priority = [JParameterManager, JOmniFactoryGenerator] - m_app->SetDefaultParameter(m_prefix + ":InputTags", default_input_collection_names, "Input collection names"); - m_app->SetDefaultParameter(m_prefix + ":OutputTags", default_output_collection_names, "Output collection names"); - - // Figure out variadic inputs - size_t variadic_input_count = 0; - for (auto* input : m_inputs) { - if (input->is_variadic) { - variadic_input_count += 1; - } - } - size_t variadic_input_collection_count = FindVariadicCollectionCount(m_inputs.size(), variadic_input_count, default_input_collection_names.size(), true); - - // Set input collection names - for (size_t i = 0; auto* input : m_inputs) { - input->collection_names.clear(); - if (input->is_variadic) { - for (size_t j = 0; j<(variadic_input_collection_count/variadic_input_count); ++j) { - input->collection_names.push_back(default_input_collection_names[i++]); - } - } - else { - input->collection_names.push_back(default_input_collection_names[i++]); - } - } + // Figure out variadic outputs + size_t variadic_output_count = 0; + for (auto* output : m_outputs) { + if (output->is_variadic) { + variadic_output_count += 1; + } + } + size_t variadic_output_collection_count = FindVariadicCollectionCount( + m_outputs.size(), variadic_output_count, default_output_collection_names.size(), true); + + // Set output collection names and create corresponding helper factories + for (size_t i = 0; auto* output : m_outputs) { + output->collection_names.clear(); + if (output->is_variadic) { + for (size_t j = 0; j < (variadic_output_collection_count / variadic_output_count); ++j) { + output->collection_names.push_back(default_output_collection_names[i++]); + } + } else { + output->collection_names.push_back(default_output_collection_names[i++]); + } + output->CreateHelperFactory(*this); + } - // Figure out variadic outputs - size_t variadic_output_count = 0; - for (auto* output : m_outputs) { - if (output->is_variadic) { - variadic_output_count += 1; - } - } - size_t variadic_output_collection_count = FindVariadicCollectionCount(m_outputs.size(), variadic_output_count, default_output_collection_names.size(), true); - - // Set output collection names and create corresponding helper factories - for (size_t i = 0; auto* output : m_outputs) { - output->collection_names.clear(); - if (output->is_variadic) { - for (size_t j = 0; j<(variadic_output_collection_count/variadic_output_count); ++j) { - output->collection_names.push_back(default_output_collection_names[i++]); - } - } - else { - output->collection_names.push_back(default_output_collection_names[i++]); - } - output->CreateHelperFactory(*this); - } + // Obtain logger + m_logger = m_app->GetService()->logger(m_prefix); - // Obtain logger - m_logger = m_app->GetService()->logger(m_prefix); + // Configure logger. Priority = [JParameterManager, system log level] + std::string default_log_level = eicrecon::LogLevelToString(m_logger->level()); + m_app->SetDefaultParameter(m_prefix + ":LogLevel", default_log_level, + "LogLevel: trace, debug, info, warn, err, critical, off"); + m_logger->set_level(eicrecon::ParseLogLevel(default_log_level)); + } - // Configure logger. Priority = [JParameterManager, system log level] - std::string default_log_level = eicrecon::LogLevelToString(m_logger->level()); - m_app->SetDefaultParameter(m_prefix + ":LogLevel", default_log_level, "LogLevel: trace, debug, info, warn, err, critical, off"); - m_logger->set_level(eicrecon::ParseLogLevel(default_log_level)); + void Init() override { + auto app = GetApplication(); + for (auto* parameter : m_parameters) { + parameter->Configure(*(app->GetJParameterManager()), m_prefix); } - - void Init() override { - auto app = GetApplication(); - for (auto* parameter : m_parameters) { - parameter->Configure(*(app->GetJParameterManager()), m_prefix); - } - for (auto* service : m_services) { - service->Init(app); - } - static_cast(this)->Configure(); + for (auto* service : m_services) { + service->Init(app); } + static_cast(this)->Configure(); + } - void BeginRun(const std::shared_ptr& event) override { - for (auto* resource : m_resources) { - resource->ChangeRun(*event); - } - static_cast(this)->ChangeRun(event->GetRunNumber()); - } - - void Process(const std::shared_ptr &event) override { - try { - for (auto* input : m_inputs) { - input->GetCollection(*event); - } - for (auto* output : m_outputs) { - output->Reset(); - } - static_cast(this)->Process(event->GetRunNumber(), event->GetEventNumber()); - for (auto* output : m_outputs) { - output->SetCollection(*this); - } - } - catch(std::exception &e) { - throw JException(e.what()); - } + void BeginRun(const std::shared_ptr& event) override { + for (auto* resource : m_resources) { + resource->ChangeRun(*event); } + static_cast(this)->ChangeRun(event->GetRunNumber()); + } + + void Process(const std::shared_ptr& event) override { + try { + for (auto* input : m_inputs) { + input->GetCollection(*event); + } + for (auto* output : m_outputs) { + output->Reset(); + } + static_cast(this)->Process(event->GetRunNumber(), event->GetEventNumber()); + for (auto* output : m_outputs) { + output->SetCollection(*this); + } + } catch (std::exception& e) { + throw JException(e.what()); + } + } - using ConfigType = ConfigT; - - void SetApplication(JApplication* app) { m_app = app; } + using ConfigType = ConfigT; - JApplication* GetApplication() { return m_app; } + void SetApplication(JApplication* app) { m_app = app; } - void SetPluginName(std::string plugin_name) { m_plugin_name = plugin_name; } + JApplication* GetApplication() { return m_app; } - std::string GetPluginName() { return m_plugin_name; } + void SetPluginName(std::string plugin_name) { m_plugin_name = plugin_name; } - inline std::string GetPrefix() { return m_prefix; } + std::string GetPluginName() { return m_plugin_name; } - /// Retrieve reference to already-configured logger - std::shared_ptr &logger() { return m_logger; } + inline std::string GetPrefix() { return m_prefix; } - /// Retrieve reference to embedded config object - ConfigT& config() { return m_config; } + /// Retrieve reference to already-configured logger + std::shared_ptr& logger() { return m_logger; } + /// Retrieve reference to embedded config object + ConfigT& config() { return m_config; } }; diff --git a/src/extensions/jana/JOmniFactoryGeneratorT.h b/src/extensions/jana/JOmniFactoryGeneratorT.h index 14ed7080b9..d02c3f6330 100644 --- a/src/extensions/jana/JOmniFactoryGeneratorT.h +++ b/src/extensions/jana/JOmniFactoryGeneratorT.h @@ -8,113 +8,94 @@ #include #include -template -class JOmniFactoryGeneratorT : public JFactoryGenerator { +template class JOmniFactoryGeneratorT : public JFactoryGenerator { public: - using FactoryConfigType = typename FactoryT::ConfigType; + using FactoryConfigType = typename FactoryT::ConfigType; private: - struct TypedWiring { - std::string m_tag; - std::vector m_default_input_tags; - std::vector m_default_output_tags; - FactoryConfigType m_default_cfg; /// Must be properly copyable! - }; - - struct UntypedWiring { - std::string m_tag; - std::vector m_default_input_tags; - std::vector m_default_output_tags; - std::map m_config_params; - }; + struct TypedWiring { + std::string m_tag; + std::vector m_default_input_tags; + std::vector m_default_output_tags; + FactoryConfigType m_default_cfg; /// Must be properly copyable! + }; + + struct UntypedWiring { + std::string m_tag; + std::vector m_default_input_tags; + std::vector m_default_output_tags; + std::map m_config_params; + }; public: - - - explicit JOmniFactoryGeneratorT(std::string tag, - std::vector default_input_tags, - std::vector default_output_tags, - FactoryConfigType cfg, - JApplication* app) { - m_app = app; - m_wirings.push_back({.m_tag=tag, - .m_default_input_tags=default_input_tags, - .m_default_output_tags=default_output_tags, - .m_default_cfg=cfg - }); - }; - - explicit JOmniFactoryGeneratorT(std::string tag, - std::vector default_input_tags, - std::vector default_output_tags, - JApplication* app) { - m_app = app; - m_wirings.push_back({.m_tag=tag, - .m_default_input_tags=default_input_tags, - .m_default_output_tags=default_output_tags - }); - - } - - explicit JOmniFactoryGeneratorT(JApplication* app) : m_app(app) { - } - - void AddWiring(std::string tag, - std::vector default_input_tags, - std::vector default_output_tags, - FactoryConfigType cfg) { - - m_wirings.push_back({.m_tag=tag, - .m_default_input_tags=default_input_tags, - .m_default_output_tags=default_output_tags, - .m_default_cfg=cfg - }); - } - - void AddWiring(std::string tag, - std::vector default_input_tags, - std::vector default_output_tags, - std::map config_params) { - - // Create throwaway factory so we can populate its config using our map. - FactoryT factory; - factory.ConfigureAllParameters(config_params); - auto config = factory.config(); - - m_wirings.push_back({.m_tag=tag, - .m_default_input_tags=default_input_tags, - .m_default_output_tags=default_output_tags, - .m_default_cfg=config - }); - - } - - void GenerateFactories(JFactorySet *factory_set) override { - - for (const auto& wiring : m_wirings) { - - - FactoryT *factory = new FactoryT; - factory->SetApplication(m_app); - factory->SetPluginName(this->GetPluginName()); - factory->SetFactoryName(JTypeInfo::demangle()); - // factory->SetTag(wiring.m_tag); - // We do NOT want to do this because JMF will use the tag to suffix the collection names - // TODO: NWB: Change this in JANA - factory->config() = wiring.m_default_cfg; - - // Set up all of the wiring prereqs so that Init() can do its thing - // Specifically, it needs valid input/output tags, a valid logger, and - // valid default values in its Config object - factory->PreInit(wiring.m_tag, wiring.m_default_input_tags, wiring.m_default_output_tags); - - // Factory is ready - factory_set->Add(factory); - } + explicit JOmniFactoryGeneratorT(std::string tag, std::vector default_input_tags, + std::vector default_output_tags, + FactoryConfigType cfg, JApplication* app) { + m_app = app; + m_wirings.push_back({.m_tag = tag, + .m_default_input_tags = default_input_tags, + .m_default_output_tags = default_output_tags, + .m_default_cfg = cfg}); + }; + + explicit JOmniFactoryGeneratorT(std::string tag, std::vector default_input_tags, + std::vector default_output_tags, JApplication* app) { + m_app = app; + m_wirings.push_back({.m_tag = tag, + .m_default_input_tags = default_input_tags, + .m_default_output_tags = default_output_tags}); + } + + explicit JOmniFactoryGeneratorT(JApplication* app) : m_app(app) {} + + void AddWiring(std::string tag, std::vector default_input_tags, + std::vector default_output_tags, FactoryConfigType cfg) { + + m_wirings.push_back({.m_tag = tag, + .m_default_input_tags = default_input_tags, + .m_default_output_tags = default_output_tags, + .m_default_cfg = cfg}); + } + + void AddWiring(std::string tag, std::vector default_input_tags, + std::vector default_output_tags, + std::map config_params) { + + // Create throwaway factory so we can populate its config using our map. + FactoryT factory; + factory.ConfigureAllParameters(config_params); + auto config = factory.config(); + + m_wirings.push_back({.m_tag = tag, + .m_default_input_tags = default_input_tags, + .m_default_output_tags = default_output_tags, + .m_default_cfg = config}); + } + + void GenerateFactories(JFactorySet* factory_set) override { + + for (const auto& wiring : m_wirings) { + + FactoryT* factory = new FactoryT; + factory->SetApplication(m_app); + factory->SetPluginName(this->GetPluginName()); + factory->SetFactoryName(JTypeInfo::demangle()); + // factory->SetTag(wiring.m_tag); + // We do NOT want to do this because JMF will use the tag to suffix the collection names + // TODO: NWB: Change this in JANA + factory->config() = wiring.m_default_cfg; + + // Set up all of the wiring prereqs so that Init() can do its thing + // Specifically, it needs valid input/output tags, a valid logger, and + // valid default values in its Config object + factory->PreInit(wiring.m_tag, wiring.m_default_input_tags, wiring.m_default_output_tags); + + // Factory is ready + factory_set->Add(factory); } + } private: - std::vector m_wirings; - JApplication* m_app; - + std::vector m_wirings; + JApplication* m_app; }; diff --git a/src/extensions/spdlog/SpdlogExtensions.h b/src/extensions/spdlog/SpdlogExtensions.h index aeaeb8117f..c6869af8e9 100644 --- a/src/extensions/spdlog/SpdlogExtensions.h +++ b/src/extensions/spdlog/SpdlogExtensions.h @@ -9,50 +9,58 @@ #include namespace eicrecon { - inline spdlog::level::level_enum ParseLogLevel(const std::string &input) { - - // Convert the source string to lower case - std::string lc_input; // Lower case input - lc_input.resize(input.size()); - std::transform(input.begin(), input.end(), lc_input.begin(), ::tolower); - - if(lc_input == "trace" || lc_input == std::to_string(SPDLOG_LEVEL_TRACE)) return spdlog::level::trace; - if(lc_input == "debug" || lc_input == std::to_string(SPDLOG_LEVEL_DEBUG)) return spdlog::level::debug; - if(lc_input == "info" || lc_input == std::to_string(SPDLOG_LEVEL_INFO)) return spdlog::level::info; - if(lc_input == "warn" || lc_input == "warning" || lc_input == std::to_string(SPDLOG_LEVEL_WARN)) return spdlog::level::warn; - if(lc_input == "err" || lc_input == "error" || lc_input == std::to_string(SPDLOG_LEVEL_ERROR)) return spdlog::level::err; - if(lc_input == "critical" || lc_input == std::to_string(SPDLOG_LEVEL_CRITICAL)) return spdlog::level::critical; - if(lc_input == "off" || lc_input == std::to_string(SPDLOG_LEVEL_OFF)) return spdlog::level::off; - - auto err_msg = fmt::format("ParseLogLevel can't parse input string: '{}'", input); - throw JException(err_msg); - } - - inline std::string LogLevelToString(spdlog::level::level_enum input) { - - // Convert the source string to lower case - switch (input) { - case spdlog::level::trace: - return "trace"; - case spdlog::level::debug: - return "debug"; - case spdlog::level::info: - return "info"; - case spdlog::level::warn: - return "warn"; - case spdlog::level::err: - return "error"; - case spdlog::level::critical: - return "critical"; - case spdlog::level::off: - return "off"; - case spdlog::level::n_levels: - [[fallthrough]]; - default: - break; - } - - auto err_msg = fmt::format("ParseLogLevel don't know this log level: '{}'", fmt::underlying(input)); - throw JException(err_msg); - } +inline spdlog::level::level_enum ParseLogLevel(const std::string& input) { + + // Convert the source string to lower case + std::string lc_input; // Lower case input + lc_input.resize(input.size()); + std::transform(input.begin(), input.end(), lc_input.begin(), ::tolower); + + if (lc_input == "trace" || lc_input == std::to_string(SPDLOG_LEVEL_TRACE)) + return spdlog::level::trace; + if (lc_input == "debug" || lc_input == std::to_string(SPDLOG_LEVEL_DEBUG)) + return spdlog::level::debug; + if (lc_input == "info" || lc_input == std::to_string(SPDLOG_LEVEL_INFO)) + return spdlog::level::info; + if (lc_input == "warn" || lc_input == "warning" || lc_input == std::to_string(SPDLOG_LEVEL_WARN)) + return spdlog::level::warn; + if (lc_input == "err" || lc_input == "error" || lc_input == std::to_string(SPDLOG_LEVEL_ERROR)) + return spdlog::level::err; + if (lc_input == "critical" || lc_input == std::to_string(SPDLOG_LEVEL_CRITICAL)) + return spdlog::level::critical; + if (lc_input == "off" || lc_input == std::to_string(SPDLOG_LEVEL_OFF)) + return spdlog::level::off; + + auto err_msg = fmt::format("ParseLogLevel can't parse input string: '{}'", input); + throw JException(err_msg); +} + +inline std::string LogLevelToString(spdlog::level::level_enum input) { + + // Convert the source string to lower case + switch (input) { + case spdlog::level::trace: + return "trace"; + case spdlog::level::debug: + return "debug"; + case spdlog::level::info: + return "info"; + case spdlog::level::warn: + return "warn"; + case spdlog::level::err: + return "error"; + case spdlog::level::critical: + return "critical"; + case spdlog::level::off: + return "off"; + case spdlog::level::n_levels: + [[fallthrough]]; + default: + break; + } + + auto err_msg = + fmt::format("ParseLogLevel don't know this log level: '{}'", fmt::underlying(input)); + throw JException(err_msg); } +} // namespace eicrecon diff --git a/src/extensions/spdlog/SpdlogFormatters.h b/src/extensions/spdlog/SpdlogFormatters.h index ab8ee94c58..d350410bc6 100644 --- a/src/extensions/spdlog/SpdlogFormatters.h +++ b/src/extensions/spdlog/SpdlogFormatters.h @@ -17,11 +17,11 @@ #if FMT_VERSION >= 90000 -template<> struct fmt::formatter : fmt::ostream_formatter {}; -template<> struct fmt::formatter : fmt::ostream_formatter {}; -template<> struct fmt::formatter : fmt::ostream_formatter {}; -template<> struct fmt::formatter : fmt::ostream_formatter {}; +template <> struct fmt::formatter : fmt::ostream_formatter {}; +template <> struct fmt::formatter : fmt::ostream_formatter {}; +template <> struct fmt::formatter : fmt::ostream_formatter {}; +template <> struct fmt::formatter : fmt::ostream_formatter {}; -template<> struct fmt::formatter : fmt::ostream_formatter {}; +template <> struct fmt::formatter : fmt::ostream_formatter {}; #endif // FMT_VERSION >= 90000 diff --git a/src/extensions/spdlog/SpdlogMixin.h b/src/extensions/spdlog/SpdlogMixin.h index b134daa334..7dcd6afa55 100644 --- a/src/extensions/spdlog/SpdlogMixin.h +++ b/src/extensions/spdlog/SpdlogMixin.h @@ -11,8 +11,8 @@ #include "SpdlogExtensions.h" namespace eicrecon { - class SpdlogMixin { - /** Logger mixin +class SpdlogMixin { + /** Logger mixin * * @example: * class MyFactory : JFactory, SpdlogMixin { @@ -29,8 +29,8 @@ namespace eicrecon { * } * }; */ - public: - /** +public: + /** * Initializes logger through current LogService * @param app - JApplication pointer, as obtained from GetApplication() * @param param_prefix - name of both logger and user parameter @@ -48,25 +48,27 @@ namespace eicrecon { * * will create "BTRK:TrackerHits" logger and check -PBTRK:TrackerHits:LogLevel user parameter */ - void InitLogger(JApplication* app, const std::string ¶m_prefix, const std::string &default_level = "") { + void InitLogger(JApplication* app, const std::string& param_prefix, + const std::string& default_level = "") { - // Logger. Get plugin level sub-log - m_log = app->GetService()->logger(param_prefix); + // Logger. Get plugin level sub-log + m_log = app->GetService()->logger(param_prefix); - // Get log level from user parameter or default - std::string log_level_str = default_level.empty() ? // did user provide default level? - eicrecon::LogLevelToString(m_log->level()) : // - default_level; - app->SetDefaultParameter(param_prefix + ":LogLevel", log_level_str, "LogLevel: trace, debug, info, warn, err, critical, off"); - m_log->set_level(eicrecon::ParseLogLevel(log_level_str)); - } + // Get log level from user parameter or default + std::string log_level_str = default_level.empty() ? // did user provide default level? + eicrecon::LogLevelToString(m_log->level()) + : // + default_level; + app->SetDefaultParameter(param_prefix + ":LogLevel", log_level_str, + "LogLevel: trace, debug, info, warn, err, critical, off"); + m_log->set_level(eicrecon::ParseLogLevel(log_level_str)); + } - public: - std::shared_ptr &logger() { return m_log; } +public: + std::shared_ptr& logger() { return m_log; } - protected: // FIXME change to private - /// current logger - std::shared_ptr m_log; - - }; -} +protected: // FIXME change to private + /// current logger + std::shared_ptr m_log; +}; +} // namespace eicrecon diff --git a/src/extensions/spdlog/SpdlogToActs.h b/src/extensions/spdlog/SpdlogToActs.h index b3b5216e21..427abc8c38 100644 --- a/src/extensions/spdlog/SpdlogToActs.h +++ b/src/extensions/spdlog/SpdlogToActs.h @@ -27,19 +27,18 @@ namespace eicrecon { using namespace Acts::Logging; using SpdlogToActsLevel_t = boost::bimap; -static SpdlogToActsLevel_t kSpdlogToActsLevel = boost::assign::list_of - (spdlog::level::trace, Acts::Logging::VERBOSE) - (spdlog::level::debug, Acts::Logging::DEBUG) - (spdlog::level::info, Acts::Logging::INFO) - (spdlog::level::warn, Acts::Logging::WARNING) - (spdlog::level::err, Acts::Logging::ERROR) - (spdlog::level::critical, Acts::Logging::FATAL); +static SpdlogToActsLevel_t kSpdlogToActsLevel = + boost::assign::list_of( + spdlog::level::trace, Acts::Logging::VERBOSE)(spdlog::level::debug, Acts::Logging::DEBUG)( + spdlog::level::info, Acts::Logging::INFO)(spdlog::level::warn, Acts::Logging::WARNING)( + spdlog::level::err, Acts::Logging::ERROR)(spdlog::level::critical, Acts::Logging::FATAL); inline Acts::Logging::Level SpdlogToActsLevel(spdlog::level::level_enum input) { try { return kSpdlogToActsLevel.left.at(input); } catch (...) { - auto err_msg = fmt::format("SpdlogToActsLevel don't know this log level: '{}'", fmt::underlying(input)); + auto err_msg = + fmt::format("SpdlogToActsLevel don't know this log level: '{}'", fmt::underlying(input)); throw JException(err_msg); } } @@ -48,7 +47,8 @@ inline spdlog::level::level_enum ActsToSpdlogLevel(Acts::Logging::Level input) { try { return kSpdlogToActsLevel.right.at(input); } catch (...) { - auto err_msg = fmt::format("ActsToSpdlogLevel don't know this log level: '{}'", fmt::underlying(input)); + auto err_msg = + fmt::format("ActsToSpdlogLevel don't know this log level: '{}'", fmt::underlying(input)); throw JException(err_msg); } } @@ -58,95 +58,93 @@ inline spdlog::level::level_enum ActsToSpdlogLevel(Acts::Logging::Level input) { /// This class allows to print debug messages without further modifications to /// a specified output stream. class SpdlogPrintPolicy final : public Acts::Logging::OutputPrintPolicy { - public: - /// @brief constructor - /// - /// @param [in] out pointer to output stream object - /// - /// @pre @p out is non-zero - explicit SpdlogPrintPolicy(std::shared_ptr out, std::vector suppressions = {}) - : m_out(out) { - std::transform(suppressions.begin(), suppressions.end(), std::back_inserter(m_suppressions), - [](const std::string& supp_string) { - return std::make_tuple(supp_string, std::regex(supp_string), 0, Acts::Logging::INFO); - } - ); - } +public: + /// @brief constructor + /// + /// @param [in] out pointer to output stream object + /// + /// @pre @p out is non-zero + explicit SpdlogPrintPolicy(std::shared_ptr out, + std::vector suppressions = {}) + : m_out(out) { + std::transform(suppressions.begin(), suppressions.end(), std::back_inserter(m_suppressions), + [](const std::string& supp_string) { + return std::make_tuple(supp_string, std::regex(supp_string), 0, + Acts::Logging::INFO); + }); + } - /// @brief destructor - ~SpdlogPrintPolicy() { - for (const auto& [supp_string, supp_regex, supp_count, supp_level] : m_suppressions) { - if (supp_count > 0) { - m_out->log(ActsToSpdlogLevel(supp_level), "\"{}\" suppressed {} times", supp_string, supp_count); - } + /// @brief destructor + ~SpdlogPrintPolicy() { + for (const auto& [supp_string, supp_regex, supp_count, supp_level] : m_suppressions) { + if (supp_count > 0) { + m_out->log(ActsToSpdlogLevel(supp_level), "\"{}\" suppressed {} times", supp_string, + supp_count); } } + } - /// @brief flush the debug message to the destination stream - /// - /// @param [in] lvl debug level of debug message - /// @param [in] input text of debug message - void flush(const Level& lvl, const std::string& input) final { - for (auto& [supp_string, supp_regex, supp_count, supp_level] : m_suppressions) { - if (std::regex_search(input, supp_regex)) { - supp_count++; - supp_level = std::max(lvl, supp_level); - return; - } - } - m_out->log(ActsToSpdlogLevel(lvl), input); - if (lvl >= getFailureThreshold()) { - throw ThresholdFailure( - "Previous debug message exceeds the " - "ACTS_LOG_FAILURE_THRESHOLD=" + - std::string{levelName(getFailureThreshold())} + - " configuration, bailing out. See " - "https://acts.readthedocs.io/en/latest/core/" - "logging.html#logging-thresholds"); + /// @brief flush the debug message to the destination stream + /// + /// @param [in] lvl debug level of debug message + /// @param [in] input text of debug message + void flush(const Level& lvl, const std::string& input) final { + for (auto& [supp_string, supp_regex, supp_count, supp_level] : m_suppressions) { + if (std::regex_search(input, supp_regex)) { + supp_count++; + supp_level = std::max(lvl, supp_level); + return; } } + m_out->log(ActsToSpdlogLevel(lvl), input); + if (lvl >= getFailureThreshold()) { + throw ThresholdFailure("Previous debug message exceeds the " + "ACTS_LOG_FAILURE_THRESHOLD=" + + std::string{levelName(getFailureThreshold())} + + " configuration, bailing out. See " + "https://acts.readthedocs.io/en/latest/core/" + "logging.html#logging-thresholds"); + } + } - /// Fulfill @c OutputPrintPolicy interface. This policy doesn't actually have a - /// name, so the assumption is that somewhere in the decorator hierarchy, - /// there is something that returns a name without delegating to a wrappee, - /// before reaching this overload. - /// @note This method will throw an exception - /// @return the name, but it never returns - const std::string& name() const override { - throw std::runtime_error{ - "Default print policy doesn't have a name. Is there no named output in " - "the decorator chain?"}; - }; - - /// Make a copy of this print policy with a new name - /// @param name the new name - /// @return the copy - std::unique_ptr clone( - const std::string& name) const override { - (void)name; - return std::make_unique(m_out); - }; - - private: - /// pointer to destination output stream - std::shared_ptr m_out; - - /// regexes for messages to be suppressed - std::vector> m_suppressions; + /// Fulfill @c OutputPrintPolicy interface. This policy doesn't actually have a + /// name, so the assumption is that somewhere in the decorator hierarchy, + /// there is something that returns a name without delegating to a wrappee, + /// before reaching this overload. + /// @note This method will throw an exception + /// @return the name, but it never returns + const std::string& name() const override { + throw std::runtime_error{ + "Default print policy doesn't have a name. Is there no named output in " + "the decorator chain?"}; + }; + + /// Make a copy of this print policy with a new name + /// @param name the new name + /// @return the copy + std::unique_ptr clone(const std::string& name) const override { + (void)name; + return std::make_unique(m_out); + }; + +private: + /// pointer to destination output stream + std::shared_ptr m_out; + + /// regexes for messages to be suppressed + std::vector> + m_suppressions; }; -inline std::unique_ptr getSpdlogLogger( - const std::string& name, - std::shared_ptr log, - std::vector suppressions = {}) { +inline std::unique_ptr +getSpdlogLogger(const std::string& name, std::shared_ptr log, + std::vector suppressions = {}) { const Acts::Logging::Level lvl = SpdlogToActsLevel(log->level()); - auto output = std::make_unique( - std::make_unique(log, suppressions), - name); + auto output = std::make_unique( + std::make_unique(log, suppressions), name); auto print = std::make_unique(lvl); return std::make_unique(std::move(output), std::move(print)); } - -} // eicrecon +} // namespace eicrecon diff --git a/src/factories/calorimetry/CalorimeterClusterRecoCoG_factory.h b/src/factories/calorimetry/CalorimeterClusterRecoCoG_factory.h index 228b42dca9..2ed3078bbc 100644 --- a/src/factories/calorimetry/CalorimeterClusterRecoCoG_factory.h +++ b/src/factories/calorimetry/CalorimeterClusterRecoCoG_factory.h @@ -8,46 +8,48 @@ #include "services/algorithms_init/AlgorithmsInit_service.h" #include "extensions/jana/JOmniFactory.h" - namespace eicrecon { -class CalorimeterClusterRecoCoG_factory : public JOmniFactory { +class CalorimeterClusterRecoCoG_factory + : public JOmniFactory { public: - using AlgoT = eicrecon::CalorimeterClusterRecoCoG; + using AlgoT = eicrecon::CalorimeterClusterRecoCoG; + private: - std::unique_ptr m_algo; + std::unique_ptr m_algo; - PodioInput m_proto_input {this}; - PodioInput m_mchits_input {this}; + PodioInput m_proto_input{this}; + PodioInput m_mchits_input{this}; - PodioOutput m_cluster_output {this}; - PodioOutput m_assoc_output {this}; + PodioOutput m_cluster_output{this}; + PodioOutput m_assoc_output{this}; - ParameterRef m_energyWeight {this, "energyWeight", config().energyWeight}; - ParameterRef m_samplingFraction {this, "samplingFraction", config().sampFrac}; - ParameterRef m_logWeightBase {this, "logWeightBase", config().logWeightBase}; - ParameterRef> m_logWeightBaseCoeffs {this, "logWeightBaseCoeffs", config().logWeightBaseCoeffs}; - ParameterRef m_logWeightBase_Eref {this, "logWeightBase_Eref", config().logWeightBase_Eref}; - ParameterRef m_enableEtaBounds {this, "enableEtaBounds", config().enableEtaBounds}; + ParameterRef m_energyWeight{this, "energyWeight", config().energyWeight}; + ParameterRef m_samplingFraction{this, "samplingFraction", config().sampFrac}; + ParameterRef m_logWeightBase{this, "logWeightBase", config().logWeightBase}; + ParameterRef> m_logWeightBaseCoeffs{this, "logWeightBaseCoeffs", + config().logWeightBaseCoeffs}; + ParameterRef m_logWeightBase_Eref{this, "logWeightBase_Eref", + config().logWeightBase_Eref}; + ParameterRef m_enableEtaBounds{this, "enableEtaBounds", config().enableEtaBounds}; - Service m_algorithmsInit {this}; + Service m_algorithmsInit{this}; public: - void Configure() { - m_algo = std::make_unique(GetPrefix()); - m_algo->level((algorithms::LogLevel)logger()->level()); - m_algo->applyConfig(config()); - m_algo->init(); - } - - void ChangeRun(int64_t run_number) { - } - - void Process(int64_t run_number, uint64_t event_number) { - m_algo->process({m_proto_input(), m_mchits_input()}, - {m_cluster_output().get(), m_assoc_output().get()}); - } + void Configure() { + m_algo = std::make_unique(GetPrefix()); + m_algo->level((algorithms::LogLevel)logger()->level()); + m_algo->applyConfig(config()); + m_algo->init(); + } + + void ChangeRun(int64_t run_number) {} + + void Process(int64_t run_number, uint64_t event_number) { + m_algo->process({m_proto_input(), m_mchits_input()}, + {m_cluster_output().get(), m_assoc_output().get()}); + } }; -} // eicrecon +} // namespace eicrecon diff --git a/src/factories/calorimetry/CalorimeterHitDigi_factory.h b/src/factories/calorimetry/CalorimeterHitDigi_factory.h index 98cf78c937..55ce0f3487 100644 --- a/src/factories/calorimetry/CalorimeterHitDigi_factory.h +++ b/src/factories/calorimetry/CalorimeterHitDigi_factory.h @@ -8,46 +8,46 @@ #include "extensions/jana/JOmniFactory.h" #include "extensions/spdlog/SpdlogMixin.h" - namespace eicrecon { -class CalorimeterHitDigi_factory : public JOmniFactory { +class CalorimeterHitDigi_factory + : public JOmniFactory { public: - using AlgoT = eicrecon::CalorimeterHitDigi; + using AlgoT = eicrecon::CalorimeterHitDigi; + private: - std::unique_ptr m_algo; + std::unique_ptr m_algo; - PodioInput m_hits_input {this}; - PodioOutput m_hits_output {this}; + PodioInput m_hits_input{this}; + PodioOutput m_hits_output{this}; - ParameterRef> m_energyResolutions {this, "energyResolutions", config().eRes}; - ParameterRef m_timeResolution {this, "timeResolution", config().tRes}; - ParameterRef m_capADC {this, "capacityADC", config().capADC}; - ParameterRef m_dyRangeADC {this, "dynamicRangeADC", config().dyRangeADC}; - ParameterRef m_pedMeanADC {this, "pedestalMean", config().pedMeanADC}; - ParameterRef m_pedSigmaADC {this, "pedestalSigma", config().pedSigmaADC}; - ParameterRef m_resolutionTDC {this, "resolutionTDC", config().resolutionTDC}; - ParameterRef m_corrMeanScale {this, "scaleResponse", config().corrMeanScale}; - ParameterRef> m_fields {this, "signalSumFields", config().fields}; - ParameterRef m_readout {this, "readoutClass", config().readout}; + ParameterRef> m_energyResolutions{this, "energyResolutions", config().eRes}; + ParameterRef m_timeResolution{this, "timeResolution", config().tRes}; + ParameterRef m_capADC{this, "capacityADC", config().capADC}; + ParameterRef m_dyRangeADC{this, "dynamicRangeADC", config().dyRangeADC}; + ParameterRef m_pedMeanADC{this, "pedestalMean", config().pedMeanADC}; + ParameterRef m_pedSigmaADC{this, "pedestalSigma", config().pedSigmaADC}; + ParameterRef m_resolutionTDC{this, "resolutionTDC", config().resolutionTDC}; + ParameterRef m_corrMeanScale{this, "scaleResponse", config().corrMeanScale}; + ParameterRef> m_fields{this, "signalSumFields", config().fields}; + ParameterRef m_readout{this, "readoutClass", config().readout}; - Service m_algorithmsInit {this}; + Service m_algorithmsInit{this}; public: - void Configure() { - m_algo = std::make_unique(GetPrefix()); - m_algo->level(static_cast(logger()->level())); - m_algo->applyConfig(config()); - m_algo->init(); - } - - void ChangeRun(int64_t run_number) { - } - - void Process(int64_t run_nr, uint64_t event_nr) { - m_algo->process({m_hits_input()}, {m_hits_output().get()}); - } + void Configure() { + m_algo = std::make_unique(GetPrefix()); + m_algo->level(static_cast(logger()->level())); + m_algo->applyConfig(config()); + m_algo->init(); + } + + void ChangeRun(int64_t run_number) {} + + void Process(int64_t run_nr, uint64_t event_nr) { + m_algo->process({m_hits_input()}, {m_hits_output().get()}); + } }; -} // eicrecon +} // namespace eicrecon diff --git a/src/factories/calorimetry/CalorimeterHitReco_factory.h b/src/factories/calorimetry/CalorimeterHitReco_factory.h index f400d7b098..082b96dd2d 100644 --- a/src/factories/calorimetry/CalorimeterHitReco_factory.h +++ b/src/factories/calorimetry/CalorimeterHitReco_factory.h @@ -7,50 +7,51 @@ #include "services/algorithms_init/AlgorithmsInit_service.h" #include "extensions/jana/JOmniFactory.h" - namespace eicrecon { -class CalorimeterHitReco_factory : public JOmniFactory { +class CalorimeterHitReco_factory + : public JOmniFactory { private: public: - using AlgoT = eicrecon::CalorimeterHitReco; + using AlgoT = eicrecon::CalorimeterHitReco; + private: - std::unique_ptr m_algo; - - PodioInput m_raw_hits_input {this}; - PodioOutput m_rec_hits_output {this}; - - ParameterRef m_capADC {this, "capacityADC", config().capADC}; - ParameterRef m_dyRangeADC {this, "dynamicRangeADC", config().dyRangeADC}; - ParameterRef m_pedMeanADC {this, "pedestalMean", config().pedMeanADC}; - ParameterRef m_pedSigmaADC {this, "pedestalSigma", config().pedSigmaADC}; - ParameterRef m_resolutionTDC {this, "resolutionTDC", config().resolutionTDC}; - ParameterRef m_thresholdFactor {this, "thresholdFactor", config().thresholdFactor}; - ParameterRef m_thresholdValue {this, "thresholdValue", config().thresholdValue}; - ParameterRef m_samplingFraction {this, "samplingFraction", config().sampFrac}; - ParameterRef m_readout {this, "readout", config().readout}; - ParameterRef m_layerField {this, "layerField", config().layerField}; - ParameterRef m_sectorField {this, "sectorField", config().sectorField}; - ParameterRef m_localDetElement {this, "localDetElement", config().localDetElement}; - ParameterRef> m_localDetFields {this, "localDetFields", config().localDetFields}; - - Service m_algorithmsInit {this}; + std::unique_ptr m_algo; + + PodioInput m_raw_hits_input{this}; + PodioOutput m_rec_hits_output{this}; + + ParameterRef m_capADC{this, "capacityADC", config().capADC}; + ParameterRef m_dyRangeADC{this, "dynamicRangeADC", config().dyRangeADC}; + ParameterRef m_pedMeanADC{this, "pedestalMean", config().pedMeanADC}; + ParameterRef m_pedSigmaADC{this, "pedestalSigma", config().pedSigmaADC}; + ParameterRef m_resolutionTDC{this, "resolutionTDC", config().resolutionTDC}; + ParameterRef m_thresholdFactor{this, "thresholdFactor", config().thresholdFactor}; + ParameterRef m_thresholdValue{this, "thresholdValue", config().thresholdValue}; + ParameterRef m_samplingFraction{this, "samplingFraction", config().sampFrac}; + ParameterRef m_readout{this, "readout", config().readout}; + ParameterRef m_layerField{this, "layerField", config().layerField}; + ParameterRef m_sectorField{this, "sectorField", config().sectorField}; + ParameterRef m_localDetElement{this, "localDetElement", config().localDetElement}; + ParameterRef> m_localDetFields{this, "localDetFields", + config().localDetFields}; + + Service m_algorithmsInit{this}; public: - void Configure() { - m_algo = std::make_unique(GetPrefix()); - m_algo->level((algorithms::LogLevel)logger()->level()); - m_algo->applyConfig(config()); - m_algo->init(); - } - - void ChangeRun(int64_t run_number) { - } - - void Process(int64_t run_number, uint64_t event_number) { - m_algo->process({m_raw_hits_input()}, {m_rec_hits_output().get()}); - } + void Configure() { + m_algo = std::make_unique(GetPrefix()); + m_algo->level((algorithms::LogLevel)logger()->level()); + m_algo->applyConfig(config()); + m_algo->init(); + } + + void ChangeRun(int64_t run_number) {} + + void Process(int64_t run_number, uint64_t event_number) { + m_algo->process({m_raw_hits_input()}, {m_rec_hits_output().get()}); + } }; -} // eicrecon +} // namespace eicrecon diff --git a/src/factories/calorimetry/CalorimeterHitsMerger_factory.h b/src/factories/calorimetry/CalorimeterHitsMerger_factory.h index f7fff55355..fa986f2d5d 100644 --- a/src/factories/calorimetry/CalorimeterHitsMerger_factory.h +++ b/src/factories/calorimetry/CalorimeterHitsMerger_factory.h @@ -8,39 +8,39 @@ #include "extensions/jana/JOmniFactory.h" #include "extensions/spdlog/SpdlogMixin.h" - namespace eicrecon { -class CalorimeterHitsMerger_factory : public JOmniFactory { +class CalorimeterHitsMerger_factory + : public JOmniFactory { public: - using AlgoT = eicrecon::CalorimeterHitsMerger; + using AlgoT = eicrecon::CalorimeterHitsMerger; + private: - std::unique_ptr m_algo; + std::unique_ptr m_algo; - PodioInput m_hits_input {this}; - PodioOutput m_hits_output {this}; + PodioInput m_hits_input{this}; + PodioOutput m_hits_output{this}; - ParameterRef m_readout {this, "readout", config().readout}; - ParameterRef> m_fields {this, "fields", config().fields}; - ParameterRef> m_refs {this, "refs", config().refs}; + ParameterRef m_readout{this, "readout", config().readout}; + ParameterRef> m_fields{this, "fields", config().fields}; + ParameterRef> m_refs{this, "refs", config().refs}; - Service m_algorithmsInit {this}; + Service m_algorithmsInit{this}; public: - void Configure() { - m_algo = std::make_unique(GetPrefix()); - m_algo->level((algorithms::LogLevel)logger()->level()); - m_algo->applyConfig(config()); - m_algo->init(); - } - - void ChangeRun(int64_t run_number) { - } - - void Process(int64_t run_number, uint64_t event_number) { - m_algo->process({m_hits_input()}, {m_hits_output().get()}); - } + void Configure() { + m_algo = std::make_unique(GetPrefix()); + m_algo->level((algorithms::LogLevel)logger()->level()); + m_algo->applyConfig(config()); + m_algo->init(); + } + + void ChangeRun(int64_t run_number) {} + + void Process(int64_t run_number, uint64_t event_number) { + m_algo->process({m_hits_input()}, {m_hits_output().get()}); + } }; -} // eicrecon +} // namespace eicrecon diff --git a/src/factories/calorimetry/CalorimeterIslandCluster_factory.h b/src/factories/calorimetry/CalorimeterIslandCluster_factory.h index ba7a7f5613..f7851ac9c3 100644 --- a/src/factories/calorimetry/CalorimeterIslandCluster_factory.h +++ b/src/factories/calorimetry/CalorimeterIslandCluster_factory.h @@ -7,54 +7,58 @@ #include "services/algorithms_init/AlgorithmsInit_service.h" #include "extensions/jana/JOmniFactory.h" - namespace eicrecon { -class CalorimeterIslandCluster_factory : public JOmniFactory { +class CalorimeterIslandCluster_factory + : public JOmniFactory { public: - using AlgoT = eicrecon::CalorimeterIslandCluster; + using AlgoT = eicrecon::CalorimeterIslandCluster; + private: - std::unique_ptr m_algo; - - PodioInput m_calo_hit_input {this}; - PodioOutput m_proto_cluster_output {this}; - - ParameterRef m_sectorDist {this, "sectorDist", config().sectorDist}; - ParameterRef> m_localDistXY {this, "localDistXY", config().localDistXY}; - ParameterRef> m_localDistXZ {this, "localDistXZ", config().localDistXZ}; - ParameterRef> m_localDistYZ {this, "localDistYZ", config().localDistYZ}; - ParameterRef> m_globallDistRPhi {this, "globalDistRPhi", config().globalDistRPhi}; - ParameterRef> m_globalDistEtaPhi {this, "globalDistEtaPhi", config().globalDistEtaPhi}; - ParameterRef> m_dimScalledLocalDistXY {this, "dimScaledLocalDistXY", config().dimScaledLocalDistXY}; - ParameterRef m_adjacencyMatrix {this, "adjacencyMatrix", config().adjacencyMatrix}; - ParameterRef m_readout {this, "readoutClass", config().readout}; - ParameterRef m_splitCluster {this, "splitCluster", config().splitCluster}; - ParameterRef m_minClusterHitEdep {this, "minClusterHitEdep", config().minClusterHitEdep}; - ParameterRef m_minClusterCenterEdep {this, "minClusterCenterEdep", config().minClusterCenterEdep}; - ParameterRef m_tepm {this, "transverseEnergyProfileMetric", config().transverseEnergyProfileMetric}; - ParameterRef m_teps {this, "transverseEnergyProfileScale", config().transverseEnergyProfileScale}; - - Service m_algorithmsInit {this}; + std::unique_ptr m_algo; -public: + PodioInput m_calo_hit_input{this}; + PodioOutput m_proto_cluster_output{this}; - void Configure() { - m_algo = std::make_unique(GetPrefix()); - m_algo->level((algorithms::LogLevel)logger()->level()); - // Remove spaces from adjacency matrix - // cfg.adjacencyMatrix.erase( - // std::remove_if(cfg.adjacencyMatrix.begin(), cfg.adjacencyMatrix.end(), ::isspace), cfg.adjacencyMatrix.end()); - m_algo->applyConfig(config()); - m_algo->init(); - } + ParameterRef m_sectorDist{this, "sectorDist", config().sectorDist}; + ParameterRef> m_localDistXY{this, "localDistXY", config().localDistXY}; + ParameterRef> m_localDistXZ{this, "localDistXZ", config().localDistXZ}; + ParameterRef> m_localDistYZ{this, "localDistYZ", config().localDistYZ}; + ParameterRef> m_globallDistRPhi{this, "globalDistRPhi", + config().globalDistRPhi}; + ParameterRef> m_globalDistEtaPhi{this, "globalDistEtaPhi", + config().globalDistEtaPhi}; + ParameterRef> m_dimScalledLocalDistXY{this, "dimScaledLocalDistXY", + config().dimScaledLocalDistXY}; + ParameterRef m_adjacencyMatrix{this, "adjacencyMatrix", config().adjacencyMatrix}; + ParameterRef m_readout{this, "readoutClass", config().readout}; + ParameterRef m_splitCluster{this, "splitCluster", config().splitCluster}; + ParameterRef m_minClusterHitEdep{this, "minClusterHitEdep", config().minClusterHitEdep}; + ParameterRef m_minClusterCenterEdep{this, "minClusterCenterEdep", + config().minClusterCenterEdep}; + ParameterRef m_tepm{this, "transverseEnergyProfileMetric", + config().transverseEnergyProfileMetric}; + ParameterRef m_teps{this, "transverseEnergyProfileScale", + config().transverseEnergyProfileScale}; - void ChangeRun(int64_t run_number) { - } + Service m_algorithmsInit{this}; + +public: + void Configure() { + m_algo = std::make_unique(GetPrefix()); + m_algo->level((algorithms::LogLevel)logger()->level()); + // Remove spaces from adjacency matrix + // cfg.adjacencyMatrix.erase( + // std::remove_if(cfg.adjacencyMatrix.begin(), cfg.adjacencyMatrix.end(), ::isspace), cfg.adjacencyMatrix.end()); + m_algo->applyConfig(config()); + m_algo->init(); + } - void Process(int64_t run_number, uint64_t event_number) { - m_algo->process({m_calo_hit_input()}, {m_proto_cluster_output().get()}); - } + void ChangeRun(int64_t run_number) {} + void Process(int64_t run_number, uint64_t event_number) { + m_algo->process({m_calo_hit_input()}, {m_proto_cluster_output().get()}); + } }; -} // eicrecon +} // namespace eicrecon diff --git a/src/factories/calorimetry/CalorimeterTruthClustering_factory.h b/src/factories/calorimetry/CalorimeterTruthClustering_factory.h index 79a18e1d8f..041c92a9e8 100644 --- a/src/factories/calorimetry/CalorimeterTruthClustering_factory.h +++ b/src/factories/calorimetry/CalorimeterTruthClustering_factory.h @@ -8,33 +8,31 @@ #include "services/algorithms_init/AlgorithmsInit_service.h" #include "extensions/jana/JOmniFactory.h" - namespace eicrecon { class CalorimeterTruthClustering_factory : public JOmniFactory { public: - using AlgoT = eicrecon::CalorimeterTruthClustering; + using AlgoT = eicrecon::CalorimeterTruthClustering; + private: - std::unique_ptr m_algo; + std::unique_ptr m_algo; - PodioInput m_rc_hits_input {this}; - PodioInput m_mc_hits_input {this}; - PodioOutput m_proto_clusters_output {this}; + PodioInput m_rc_hits_input{this}; + PodioInput m_mc_hits_input{this}; + PodioOutput m_proto_clusters_output{this}; public: - void Configure() { - m_algo = std::make_unique(GetPrefix()); - m_algo->level((algorithms::LogLevel)logger()->level()); - m_algo->init(); - } - - void ChangeRun(int64_t run_number) { - } - - void Process(int64_t run_number, uint64_t event_number) { - m_algo->process({m_rc_hits_input(), m_mc_hits_input()}, - {m_proto_clusters_output().get()}); - } + void Configure() { + m_algo = std::make_unique(GetPrefix()); + m_algo->level((algorithms::LogLevel)logger()->level()); + m_algo->init(); + } + + void ChangeRun(int64_t run_number) {} + + void Process(int64_t run_number, uint64_t event_number) { + m_algo->process({m_rc_hits_input(), m_mc_hits_input()}, {m_proto_clusters_output().get()}); + } }; -} // eicrecon +} // namespace eicrecon diff --git a/src/factories/calorimetry/EnergyPositionClusterMerger_factory.h b/src/factories/calorimetry/EnergyPositionClusterMerger_factory.h index 4a20fac3c3..97b4925b87 100644 --- a/src/factories/calorimetry/EnergyPositionClusterMerger_factory.h +++ b/src/factories/calorimetry/EnergyPositionClusterMerger_factory.h @@ -7,47 +7,47 @@ #include "extensions/jana/JOmniFactory.h" #include "services/algorithms_init/AlgorithmsInit_service.h" - namespace eicrecon { -class EnergyPositionClusterMerger_factory : - public JOmniFactory { +class EnergyPositionClusterMerger_factory + : public JOmniFactory { public: - using AlgoT = eicrecon::EnergyPositionClusterMerger; + using AlgoT = eicrecon::EnergyPositionClusterMerger; + private: - std::unique_ptr m_algo; + std::unique_ptr m_algo; - PodioInput m_energy_cluster_input {this}; - PodioInput m_energy_assoc_input {this}; - PodioInput m_position_cluster_input {this}; - PodioInput m_position_assoc_input {this}; + PodioInput m_energy_cluster_input{this}; + PodioInput m_energy_assoc_input{this}; + PodioInput m_position_cluster_input{this}; + PodioInput m_position_assoc_input{this}; - PodioOutput m_cluster_output {this}; - PodioOutput m_assoc_output {this}; + PodioOutput m_cluster_output{this}; + PodioOutput m_assoc_output{this}; - ParameterRef m_energyRelTolerance {this, "energyRelTolerance", config().energyRelTolerance}; - ParameterRef m_phiTolerance {this, "phiTolerance", config().phiTolerance}; - ParameterRef m_etaTolerance {this, "etaTolerance", config().etaTolerance}; + ParameterRef m_energyRelTolerance{this, "energyRelTolerance", + config().energyRelTolerance}; + ParameterRef m_phiTolerance{this, "phiTolerance", config().phiTolerance}; + ParameterRef m_etaTolerance{this, "etaTolerance", config().etaTolerance}; - Service m_algorithmsInit {this}; + Service m_algorithmsInit{this}; public: - void Configure() { - m_algo = std::make_unique(GetPrefix()); - m_algo->level((algorithms::LogLevel)logger()->level()); - m_algo->applyConfig(config()); - m_algo->init(); - } - - void ChangeRun(int64_t run_number) { - } - - void Process(int64_t run_number, uint64_t event_number) { - m_algo->process({m_energy_cluster_input(), m_energy_assoc_input(), - m_position_cluster_input(), m_position_assoc_input()}, - {m_cluster_output().get(), m_assoc_output().get()}); - } + void Configure() { + m_algo = std::make_unique(GetPrefix()); + m_algo->level((algorithms::LogLevel)logger()->level()); + m_algo->applyConfig(config()); + m_algo->init(); + } + + void ChangeRun(int64_t run_number) {} + + void Process(int64_t run_number, uint64_t event_number) { + m_algo->process({m_energy_cluster_input(), m_energy_assoc_input(), m_position_cluster_input(), + m_position_assoc_input()}, + {m_cluster_output().get(), m_assoc_output().get()}); + } }; -} // eicrecon +} // namespace eicrecon diff --git a/src/factories/calorimetry/HEXPLIT_factory.h b/src/factories/calorimetry/HEXPLIT_factory.h index 8eea8402ef..2d9dd49b0b 100644 --- a/src/factories/calorimetry/HEXPLIT_factory.h +++ b/src/factories/calorimetry/HEXPLIT_factory.h @@ -7,37 +7,36 @@ #include "services/algorithms_init/AlgorithmsInit_service.h" #include "extensions/jana/JOmniFactory.h" - namespace eicrecon { class HEXPLIT_factory : public JOmniFactory { - using AlgoT = eicrecon::HEXPLIT; - private: - std::unique_ptr m_algo; - PodioInput m_rec_hits_input {this}; - PodioOutput m_subcell_hits_output {this}; + using AlgoT = eicrecon::HEXPLIT; + +private: + std::unique_ptr m_algo; + PodioInput m_rec_hits_input{this}; + PodioOutput m_subcell_hits_output{this}; - ParameterRef m_MIP {this, "MIP", config().MIP}; - ParameterRef m_Emin_in_MIPs {this, "Emin_in_MIPs", config().Emin_in_MIPs}; - ParameterRef m_tmax {this, "tmax", config().tmax}; + ParameterRef m_MIP{this, "MIP", config().MIP}; + ParameterRef m_Emin_in_MIPs{this, "Emin_in_MIPs", config().Emin_in_MIPs}; + ParameterRef m_tmax{this, "tmax", config().tmax}; - Service m_algorithmsInit {this}; + Service m_algorithmsInit{this}; public: - void Configure() { - m_algo = std::make_unique(GetPrefix()); - m_algo->level((algorithms::LogLevel)logger()->level()); - m_algo->applyConfig(config()); - m_algo->init(); - } - - void ChangeRun(int64_t run_number) { - } - - void Process(int64_t run_number, uint64_t event_number) { - m_algo->process({m_rec_hits_input()},{m_subcell_hits_output().get()}); - } + void Configure() { + m_algo = std::make_unique(GetPrefix()); + m_algo->level((algorithms::LogLevel)logger()->level()); + m_algo->applyConfig(config()); + m_algo->init(); + } + + void ChangeRun(int64_t run_number) {} + + void Process(int64_t run_number, uint64_t event_number) { + m_algo->process({m_rec_hits_input()}, {m_subcell_hits_output().get()}); + } }; -} // eicrecon +} // namespace eicrecon diff --git a/src/factories/calorimetry/ImagingClusterReco_factory.h b/src/factories/calorimetry/ImagingClusterReco_factory.h index 8ebc3dea30..b88d8c88a4 100644 --- a/src/factories/calorimetry/ImagingClusterReco_factory.h +++ b/src/factories/calorimetry/ImagingClusterReco_factory.h @@ -9,40 +9,40 @@ namespace eicrecon { -class ImagingClusterReco_factory : - public JOmniFactory { +class ImagingClusterReco_factory + : public JOmniFactory { public: - using AlgoT = eicrecon::ImagingClusterReco; + using AlgoT = eicrecon::ImagingClusterReco; + private: - std::unique_ptr m_algo; + std::unique_ptr m_algo; - PodioInput m_protos_input {this}; - PodioInput m_mchits_input {this}; + PodioInput m_protos_input{this}; + PodioInput m_mchits_input{this}; - PodioOutput m_clusters_output {this}; - PodioOutput m_assocs_output {this}; - PodioOutput m_layers_output {this}; + PodioOutput m_clusters_output{this}; + PodioOutput m_assocs_output{this}; + PodioOutput m_layers_output{this}; - ParameterRef m_trackStopLayer {this, "trackStopLayer", config().trackStopLayer}; + ParameterRef m_trackStopLayer{this, "trackStopLayer", config().trackStopLayer}; - Service m_algorithmsInit {this}; + Service m_algorithmsInit{this}; public: - void Configure() { - m_algo = std::make_unique(GetPrefix()); - m_algo->level((algorithms::LogLevel)logger()->level()); - m_algo->applyConfig(config()); - m_algo->init(); - } - - void ChangeRun(int64_t run_number) { - } - - void Process(int64_t run_number, uint64_t event_number) { - m_algo->process({m_protos_input(), m_mchits_input()}, - {m_clusters_output().get(), m_assocs_output().get(), m_layers_output().get()}); - } + void Configure() { + m_algo = std::make_unique(GetPrefix()); + m_algo->level((algorithms::LogLevel)logger()->level()); + m_algo->applyConfig(config()); + m_algo->init(); + } + + void ChangeRun(int64_t run_number) {} + + void Process(int64_t run_number, uint64_t event_number) { + m_algo->process({m_protos_input(), m_mchits_input()}, + {m_clusters_output().get(), m_assocs_output().get(), m_layers_output().get()}); + } }; -} // eicrecon +} // namespace eicrecon diff --git a/src/factories/calorimetry/ImagingTopoCluster_factory.h b/src/factories/calorimetry/ImagingTopoCluster_factory.h index 54e4dd5b85..751236001b 100644 --- a/src/factories/calorimetry/ImagingTopoCluster_factory.h +++ b/src/factories/calorimetry/ImagingTopoCluster_factory.h @@ -9,41 +9,42 @@ namespace eicrecon { -class ImagingTopoCluster_factory : public JOmniFactory { +class ImagingTopoCluster_factory + : public JOmniFactory { public: - using AlgoT = eicrecon::ImagingTopoCluster; + using AlgoT = eicrecon::ImagingTopoCluster; + private: - std::unique_ptr m_algo; + std::unique_ptr m_algo; - PodioInput m_hits_input {this}; - PodioOutput m_protos_output {this}; + PodioInput m_hits_input{this}; + PodioOutput m_protos_output{this}; - ParameterRef> m_ldxy {this, "localDistXY", config().localDistXY}; - ParameterRef> m_ldep {this, "layerDistEtaPhi", config().layerDistEtaPhi}; - ParameterRef m_nlr {this, "neighbourLayersRange", config().neighbourLayersRange}; - ParameterRef m_sd {this, "sectorDist", config().sectorDist}; - ParameterRef m_mched {this, "minClusterHitEdep", config().minClusterHitEdep}; - ParameterRef m_mcced {this, "minClusterCenterEdep", config().minClusterCenterEdep}; - ParameterRef m_mced {this, "minClusterEdep", config().minClusterEdep}; - ParameterRef m_mcnh {this, "minClusterNhits", config().minClusterNhits}; + ParameterRef> m_ldxy{this, "localDistXY", config().localDistXY}; + ParameterRef> m_ldep{this, "layerDistEtaPhi", config().layerDistEtaPhi}; + ParameterRef m_nlr{this, "neighbourLayersRange", config().neighbourLayersRange}; + ParameterRef m_sd{this, "sectorDist", config().sectorDist}; + ParameterRef m_mched{this, "minClusterHitEdep", config().minClusterHitEdep}; + ParameterRef m_mcced{this, "minClusterCenterEdep", config().minClusterCenterEdep}; + ParameterRef m_mced{this, "minClusterEdep", config().minClusterEdep}; + ParameterRef m_mcnh{this, "minClusterNhits", config().minClusterNhits}; - Service m_algorithmsInit {this}; + Service m_algorithmsInit{this}; public: - void Configure() { - m_algo = std::make_unique(GetPrefix()); - m_algo->level((algorithms::LogLevel)logger()->level()); - m_algo->applyConfig(config()); - m_algo->init(); - } - - void ChangeRun(int64_t run_number) { - } - - void Process(int64_t run_number, uint64_t event_number) { - m_algo->process({m_hits_input()}, {m_protos_output().get()}); - } + void Configure() { + m_algo = std::make_unique(GetPrefix()); + m_algo->level((algorithms::LogLevel)logger()->level()); + m_algo->applyConfig(config()); + m_algo->init(); + } + + void ChangeRun(int64_t run_number) {} + + void Process(int64_t run_number, uint64_t event_number) { + m_algo->process({m_hits_input()}, {m_protos_output().get()}); + } }; } // namespace eicrecon diff --git a/src/factories/calorimetry/TruthEnergyPositionClusterMerger_factory.h b/src/factories/calorimetry/TruthEnergyPositionClusterMerger_factory.h index c22bfb9cd0..0406056916 100644 --- a/src/factories/calorimetry/TruthEnergyPositionClusterMerger_factory.h +++ b/src/factories/calorimetry/TruthEnergyPositionClusterMerger_factory.h @@ -9,40 +9,39 @@ namespace eicrecon { -class TruthEnergyPositionClusterMerger_factory : public JOmniFactory { +class TruthEnergyPositionClusterMerger_factory + : public JOmniFactory { public: - using AlgoT = eicrecon::TruthEnergyPositionClusterMerger; + using AlgoT = eicrecon::TruthEnergyPositionClusterMerger; + private: - std::unique_ptr m_algo; + std::unique_ptr m_algo; - PodioInput m_mcparticles_input {this}; - PodioInput m_energy_clusters_input {this}; - PodioInput m_energy_assocs_input {this}; - PodioInput m_position_clusters_input {this}; - PodioInput m_position_assocs_input {this}; + PodioInput m_mcparticles_input{this}; + PodioInput m_energy_clusters_input{this}; + PodioInput m_energy_assocs_input{this}; + PodioInput m_position_clusters_input{this}; + PodioInput m_position_assocs_input{this}; - PodioOutput m_clusters_output {this}; - PodioOutput m_assocs_output {this}; + PodioOutput m_clusters_output{this}; + PodioOutput m_assocs_output{this}; - Service m_algorithmsInit {this}; + Service m_algorithmsInit{this}; public: - void Configure() { - m_algo = std::make_unique(GetPrefix()); - m_algo->level((algorithms::LogLevel)logger()->level()); - m_algo->init(); - } - - void ChangeRun(int64_t run_number) { - } - - void Process(int64_t run_number, uint64_t event_number) { - m_algo->process( - {m_mcparticles_input(), - m_energy_clusters_input(), m_energy_assocs_input(), - m_position_clusters_input(), m_position_assocs_input()}, - {m_clusters_output().get(), m_assocs_output().get()}); - } + void Configure() { + m_algo = std::make_unique(GetPrefix()); + m_algo->level((algorithms::LogLevel)logger()->level()); + m_algo->init(); + } + + void ChangeRun(int64_t run_number) {} + + void Process(int64_t run_number, uint64_t event_number) { + m_algo->process({m_mcparticles_input(), m_energy_clusters_input(), m_energy_assocs_input(), + m_position_clusters_input(), m_position_assocs_input()}, + {m_clusters_output().get(), m_assocs_output().get()}); + } }; -} // eicrecon +} // namespace eicrecon diff --git a/src/factories/digi/SiliconTrackerDigi_factory.h b/src/factories/digi/SiliconTrackerDigi_factory.h index f8f4b08467..be5b37b0dd 100644 --- a/src/factories/digi/SiliconTrackerDigi_factory.h +++ b/src/factories/digi/SiliconTrackerDigi_factory.h @@ -6,35 +6,35 @@ #include "algorithms/digi/SiliconTrackerDigi.h" #include "extensions/jana/JOmniFactory.h" - namespace eicrecon { -class SiliconTrackerDigi_factory : public JOmniFactory { +class SiliconTrackerDigi_factory + : public JOmniFactory { public: - using AlgoT = eicrecon::SiliconTrackerDigi; + using AlgoT = eicrecon::SiliconTrackerDigi; + private: - std::unique_ptr m_algo; + std::unique_ptr m_algo; - PodioInput m_sim_hits_input {this}; - PodioOutput m_raw_hits_output {this}; + PodioInput m_sim_hits_input{this}; + PodioOutput m_raw_hits_output{this}; - ParameterRef m_threshold {this, "threshold", config().threshold}; - ParameterRef m_timeResolution {this, "timeResolution", config().timeResolution}; + ParameterRef m_threshold{this, "threshold", config().threshold}; + ParameterRef m_timeResolution{this, "timeResolution", config().timeResolution}; public: - void Configure() { - m_algo = std::make_unique(GetPrefix()); - m_algo->applyConfig(config()); - m_algo->init(logger()); - } - - void ChangeRun(int64_t run_number) { - } - - void Process(int64_t run_number, uint64_t event_number) { - m_algo->process({m_sim_hits_input()}, {m_raw_hits_output().get()}); - } + void Configure() { + m_algo = std::make_unique(GetPrefix()); + m_algo->applyConfig(config()); + m_algo->init(logger()); + } + + void ChangeRun(int64_t run_number) {} + + void Process(int64_t run_number, uint64_t event_number) { + m_algo->process({m_sim_hits_input()}, {m_raw_hits_output().get()}); + } }; -} // eicrecon +} // namespace eicrecon diff --git a/src/factories/fardetectors/MatrixTransferStatic_factory.h b/src/factories/fardetectors/MatrixTransferStatic_factory.h index 7fc2fb0ae3..3ff8f528ed 100644 --- a/src/factories/fardetectors/MatrixTransferStatic_factory.h +++ b/src/factories/fardetectors/MatrixTransferStatic_factory.h @@ -17,58 +17,59 @@ namespace eicrecon { -class MatrixTransferStatic_factory : - public JOmniFactory { +class MatrixTransferStatic_factory + : public JOmniFactory { public: - using AlgoT = eicrecon::MatrixTransferStatic; + using AlgoT = eicrecon::MatrixTransferStatic; + private: - std::unique_ptr m_algo; + std::unique_ptr m_algo; - PodioInput m_mcparts_input {this}; - PodioInput m_hits_input {this}; - PodioOutput m_tracks_output {this}; + PodioInput m_mcparts_input{this}; + PodioInput m_hits_input{this}; + PodioOutput m_tracks_output{this}; - Service m_geoSvc {this}; + Service m_geoSvc{this}; - ParameterRef partMass {this, "partMass", config().partMass}; - ParameterRef partCharge{this, "partCharge", config().partCharge}; - ParameterRef partPDG {this, "partPDG", config().partPDG}; + ParameterRef partMass{this, "partMass", config().partMass}; + ParameterRef partCharge{this, "partCharge", config().partCharge}; + ParameterRef partPDG{this, "partPDG", config().partPDG}; - ParameterRef local_x_offset {this, "local_x_offset", config().local_x_offset}; - ParameterRef local_y_offset {this, "local_y_offset", config().local_y_offset}; - ParameterRef local_x_slope_offset{this, "local_x_slope_offset", config().local_x_slope_offset}; - ParameterRef local_y_slope_offset{this, "local_y_slope_offset", config().local_y_slope_offset}; - ParameterRef crossingAngle {this, "crossingAngle", config().crossingAngle}; - ParameterRef nomMomentum {this, "nomMomentum", config().nomMomentum}; + ParameterRef local_x_offset{this, "local_x_offset", config().local_x_offset}; + ParameterRef local_y_offset{this, "local_y_offset", config().local_y_offset}; + ParameterRef local_x_slope_offset{this, "local_x_slope_offset", + config().local_x_slope_offset}; + ParameterRef local_y_slope_offset{this, "local_y_slope_offset", + config().local_y_slope_offset}; + ParameterRef crossingAngle{this, "crossingAngle", config().crossingAngle}; + ParameterRef nomMomentum{this, "nomMomentum", config().nomMomentum}; - // FIXME JANA2 does not support vector of vector - //ParameterRef>> aX {this, "aX", config().aX}; - //ParameterRef>> aY {this, "aY", config().aY}; + // FIXME JANA2 does not support vector of vector + //ParameterRef>> aX {this, "aX", config().aX}; + //ParameterRef>> aY {this, "aY", config().aY}; - ParameterRef hit1minZ {this, "hit1minZ", config().hit1minZ}; - ParameterRef hit1maxZ {this, "hit1maxZ", config().hit1maxZ}; - ParameterRef hit2minZ {this, "hit2minZ", config().hit2minZ}; - ParameterRef hit2maxZ {this, "hit2maxZ", config().hit2maxZ}; + ParameterRef hit1minZ{this, "hit1minZ", config().hit1minZ}; + ParameterRef hit1maxZ{this, "hit1maxZ", config().hit1maxZ}; + ParameterRef hit2minZ{this, "hit2minZ", config().hit2minZ}; + ParameterRef hit2maxZ{this, "hit2maxZ", config().hit2maxZ}; - ParameterRef readout {this, "readout", config().readout}; + ParameterRef readout{this, "readout", config().readout}; - Service m_algorithmsInit {this}; + Service m_algorithmsInit{this}; public: - void Configure() { - m_algo = std::make_unique(GetPrefix()); - m_algo->applyConfig(config()); - m_algo->init(); - } - - void ChangeRun(int64_t run_number) { - } + void Configure() { + m_algo = std::make_unique(GetPrefix()); + m_algo->applyConfig(config()); + m_algo->init(); + } - void Process(int64_t run_number, uint64_t event_number) { - m_algo->process({m_mcparts_input(), m_hits_input()}, {m_tracks_output().get()}); - } + void ChangeRun(int64_t run_number) {} + void Process(int64_t run_number, uint64_t event_number) { + m_algo->process({m_mcparts_input(), m_hits_input()}, {m_tracks_output().get()}); + } }; -} // eicrecon +} // namespace eicrecon diff --git a/src/factories/meta/CollectionCollector_factory.h b/src/factories/meta/CollectionCollector_factory.h index 071bf7be6f..45f754555c 100644 --- a/src/factories/meta/CollectionCollector_factory.h +++ b/src/factories/meta/CollectionCollector_factory.h @@ -6,36 +6,34 @@ namespace eicrecon { - template - class CollectionCollector_factory : public JOmniFactory> { +template +class CollectionCollector_factory : public JOmniFactory> { public: - using AlgoT = eicrecon::CollectionCollector; + using AlgoT = eicrecon::CollectionCollector; private: - std::unique_ptr m_algo; + std::unique_ptr m_algo; - typename JOmniFactory>::template VariadicPodioInput m_inputs {this}; - typename JOmniFactory>::template PodioOutput m_output {this}; + typename JOmniFactory>::template VariadicPodioInput m_inputs{ + this}; + typename JOmniFactory>::template PodioOutput m_output{this}; public: + void Configure() { + m_algo = std::make_unique(this->GetPrefix()); + m_algo->init(this->logger()); + } - void Configure() { - m_algo = std::make_unique(this->GetPrefix()); - m_algo->init(this->logger()); - } + void ChangeRun(int64_t run_number) {} - void ChangeRun(int64_t run_number) { + void Process(int64_t run_number, uint64_t event_number) { + std::vector> in_collections; + for (const auto& in_collection : m_inputs()) { + in_collections.push_back(gsl::not_null{in_collection}); } + typename T::collection_type* merged_collection = m_output().get(); + m_algo->process(in_collections, merged_collection); + }; +}; - void Process(int64_t run_number, uint64_t event_number) { - std::vector> in_collections; - for (const auto& in_collection : m_inputs()) { - in_collections.push_back(gsl::not_null{in_collection}); - } - typename T::collection_type* merged_collection = m_output().get(); - m_algo->process(in_collections, merged_collection); - }; - - }; - -} // eicrecon +} // namespace eicrecon diff --git a/src/factories/meta/SubDivideCollection_factory.h b/src/factories/meta/SubDivideCollection_factory.h index 46ee1df9dc..9bb67f40da 100644 --- a/src/factories/meta/SubDivideCollection_factory.h +++ b/src/factories/meta/SubDivideCollection_factory.h @@ -10,39 +10,37 @@ namespace eicrecon { template -class SubDivideCollection_factory : public JOmniFactory, SubDivideCollectionConfig> { +class SubDivideCollection_factory + : public JOmniFactory, SubDivideCollectionConfig> { - public: - using AlgoT = eicrecon::SubDivideCollection; - using FactoryT = JOmniFactory, SubDivideCollectionConfig>; - - private: +public: + using AlgoT = eicrecon::SubDivideCollection; + using FactoryT = JOmniFactory, SubDivideCollectionConfig>; - std::unique_ptr m_algo; +private: + std::unique_ptr m_algo; - typename FactoryT::template PodioInput m_input {this}; - typename FactoryT::template VariadicPodioOutput m_split_output {this}; + typename FactoryT::template PodioInput m_input{this}; + typename FactoryT::template VariadicPodioOutput m_split_output{this}; - typename FactoryT::template Service m_algorithmsInit {this}; + typename FactoryT::template Service m_algorithmsInit{this}; public: - void Configure() { - m_algo = std::make_unique(this->GetPrefix()); - m_algo->applyConfig(this->config()); - m_algo->init(); - } + void Configure() { + m_algo = std::make_unique(this->GetPrefix()); + m_algo->applyConfig(this->config()); + m_algo->init(); + } - void ChangeRun(int64_t run_number) { - } + void ChangeRun(int64_t run_number) {} - void Process(int64_t run_number, uint64_t event_number) { + void Process(int64_t run_number, uint64_t event_number) { std::vector> split_collections; for (const auto& split : m_split_output()) { split_collections.push_back(gsl::not_null(split.get())); } - m_algo->process(m_input(),split_collections); - -}; + m_algo->process(m_input(), split_collections); + }; }; // SplitGeometry_factory -} // eicrecon +} // namespace eicrecon diff --git a/src/factories/reco/InclusiveKinematicsReconstructed_factory.h b/src/factories/reco/InclusiveKinematicsReconstructed_factory.h index 72d1c13cc6..5d7084db84 100644 --- a/src/factories/reco/InclusiveKinematicsReconstructed_factory.h +++ b/src/factories/reco/InclusiveKinematicsReconstructed_factory.h @@ -15,33 +15,34 @@ namespace eicrecon { template -class InclusiveKinematicsReconstructed_factory : - public JOmniFactory> { +class InclusiveKinematicsReconstructed_factory + : public JOmniFactory> { public: - using FactoryT = JOmniFactory>; + using FactoryT = JOmniFactory>; private: - std::unique_ptr m_algo; + std::unique_ptr m_algo; - typename FactoryT::template PodioInput m_mc_particles_input {this}; - typename FactoryT::template PodioInput m_rc_particles_input {this}; - typename FactoryT::template PodioInput m_rc_particles_assoc_input {this}; - typename FactoryT::template PodioOutput m_inclusive_kinematics_output {this}; + typename FactoryT::template PodioInput m_mc_particles_input{this}; + typename FactoryT::template PodioInput m_rc_particles_input{this}; + typename FactoryT::template PodioInput + m_rc_particles_assoc_input{this}; + typename FactoryT::template PodioOutput + m_inclusive_kinematics_output{this}; public: - void Configure() { - m_algo = std::make_unique(this->GetPrefix()); - m_algo->init(this->logger()); - } - - void ChangeRun(int64_t run_number) { - } - - void Process(int64_t run_number, uint64_t event_number) { - m_algo->process({m_mc_particles_input(), m_rc_particles_input(), m_rc_particles_assoc_input()}, - {m_inclusive_kinematics_output().get()}); - } + void Configure() { + m_algo = std::make_unique(this->GetPrefix()); + m_algo->init(this->logger()); + } + + void ChangeRun(int64_t run_number) {} + + void Process(int64_t run_number, uint64_t event_number) { + m_algo->process({m_mc_particles_input(), m_rc_particles_input(), m_rc_particles_assoc_input()}, + {m_inclusive_kinematics_output().get()}); + } }; -} // eicrecon +} // namespace eicrecon diff --git a/src/factories/reco/InclusiveKinematicsTruth_factory.h b/src/factories/reco/InclusiveKinematicsTruth_factory.h index 48171e7667..ec418ea556 100644 --- a/src/factories/reco/InclusiveKinematicsTruth_factory.h +++ b/src/factories/reco/InclusiveKinematicsTruth_factory.h @@ -15,29 +15,28 @@ namespace eicrecon { -class InclusiveKinematicsTruth_factory : - public JOmniFactory { +class InclusiveKinematicsTruth_factory : public JOmniFactory { public: - using AlgoT = eicrecon::InclusiveKinematicsTruth; + using AlgoT = eicrecon::InclusiveKinematicsTruth; + private: - std::unique_ptr m_algo; + std::unique_ptr m_algo; - PodioInput m_mc_particles_input {this}; - PodioOutput m_inclusive_kinematics_output {this}; + PodioInput m_mc_particles_input{this}; + PodioOutput m_inclusive_kinematics_output{this}; public: - void Configure() { - m_algo = std::make_unique(GetPrefix()); - m_algo->init(logger()); - } + void Configure() { + m_algo = std::make_unique(GetPrefix()); + m_algo->init(logger()); + } - void ChangeRun(int64_t run_number) { - } + void ChangeRun(int64_t run_number) {} - void Process(int64_t run_number, uint64_t event_number) { - m_algo->process({m_mc_particles_input()}, {m_inclusive_kinematics_output().get()}); - } + void Process(int64_t run_number, uint64_t event_number) { + m_algo->process({m_mc_particles_input()}, {m_inclusive_kinematics_output().get()}); + } }; -} // eicrecon +} // namespace eicrecon diff --git a/src/factories/reco/JetReconstruction_factory.h b/src/factories/reco/JetReconstruction_factory.h index 9c15fee641..bea7f073e6 100644 --- a/src/factories/reco/JetReconstruction_factory.h +++ b/src/factories/reco/JetReconstruction_factory.h @@ -10,55 +10,59 @@ namespace eicrecon { - template - class JetReconstruction_factory : public JOmniFactory, JetReconstructionConfig> { +template +class JetReconstruction_factory + : public JOmniFactory, JetReconstructionConfig> { - public: - // algorithm to run - using Algo = eicrecon::JetReconstruction; - using FactoryT = JOmniFactory, JetReconstructionConfig>; +public: + // algorithm to run + using Algo = eicrecon::JetReconstruction; + using FactoryT = JOmniFactory, JetReconstructionConfig>; - private: - std::unique_ptr m_algo; +private: + std::unique_ptr m_algo; - // input collection - typename FactoryT::template PodioInput m_input {this}; + // input collection + typename FactoryT::template PodioInput m_input{this}; - // output collection - typename FactoryT::template PodioOutput m_output {this}; + // output collection + typename FactoryT::template PodioOutput m_output{this}; - // parameter bindings - typename FactoryT::template ParameterRef m_rJet {this, "rJet", FactoryT::config().rJet}; - typename FactoryT::template ParameterRef m_pJet {this, "pJet", FactoryT::config().pJet}; - typename FactoryT::template ParameterRef m_minCstPt {this, "minCstPt", FactoryT::config().minCstPt}; - typename FactoryT::template ParameterRef m_maxCstPt {this, "maxCstPt", FactoryT::config().maxCstPt}; - typename FactoryT::template ParameterRef m_minJetPt {this, "minJetPt", FactoryT::config().minJetPt}; - typename FactoryT::template ParameterRef m_ghostMaxRap {this, "ghostMaxRap", FactoryT::config().ghostMaxRap}; - typename FactoryT::template ParameterRef m_ghostArea {this, "ghostArea", FactoryT::config().ghostArea}; - typename FactoryT::template ParameterRef m_numGhostRepeat {this, "numGhostRepeat", FactoryT::config().numGhostRepeat}; - typename FactoryT::template ParameterRef m_jetAlgo {this, "jetAlgo", FactoryT::config().jetAlgo}; - typename FactoryT::template ParameterRef m_recombScheme {this, "recombScheme", FactoryT::config().recombScheme}; - typename FactoryT::template ParameterRef m_areaType {this, "areaType", FactoryT::config().areaType}; + // parameter bindings + typename FactoryT::template ParameterRef m_rJet{this, "rJet", FactoryT::config().rJet}; + typename FactoryT::template ParameterRef m_pJet{this, "pJet", FactoryT::config().pJet}; + typename FactoryT::template ParameterRef m_minCstPt{this, "minCstPt", + FactoryT::config().minCstPt}; + typename FactoryT::template ParameterRef m_maxCstPt{this, "maxCstPt", + FactoryT::config().maxCstPt}; + typename FactoryT::template ParameterRef m_minJetPt{this, "minJetPt", + FactoryT::config().minJetPt}; + typename FactoryT::template ParameterRef m_ghostMaxRap{this, "ghostMaxRap", + FactoryT::config().ghostMaxRap}; + typename FactoryT::template ParameterRef m_ghostArea{this, "ghostArea", + FactoryT::config().ghostArea}; + typename FactoryT::template ParameterRef m_numGhostRepeat{this, "numGhostRepeat", + FactoryT::config().numGhostRepeat}; + typename FactoryT::template ParameterRef m_jetAlgo{this, "jetAlgo", + FactoryT::config().jetAlgo}; + typename FactoryT::template ParameterRef m_recombScheme{ + this, "recombScheme", FactoryT::config().recombScheme}; + typename FactoryT::template ParameterRef m_areaType{this, "areaType", + FactoryT::config().areaType}; - public: +public: + void Configure() { + m_algo = std::make_unique(this->GetPrefix()); + m_algo->applyConfig(FactoryT::config()); + m_algo->init(FactoryT::logger()); + } - void Configure() { - m_algo = std::make_unique(this->GetPrefix()); - m_algo->applyConfig(FactoryT::config()); - m_algo->init(FactoryT::logger()); - } + void ChangeRun(int64_t run_number) { /* nothing to do */ } - void ChangeRun(int64_t run_number) { - /* nothing to do */ - } + void Process(int64_t run_number, int64_t event_number) { + m_algo->process({m_input()}, {m_output().get()}); + } - void Process(int64_t run_number, int64_t event_number) { - m_algo->process( - {m_input()}, - {m_output().get()} - ); - } +}; // end JetReconstruction_factory definition - }; // end JetReconstruction_factory definition - -} // end eicrecon namespace +} // namespace eicrecon diff --git a/src/factories/reco/TransformBreitFrame_factory.h b/src/factories/reco/TransformBreitFrame_factory.h index 403c3695a6..fb98355eab 100644 --- a/src/factories/reco/TransformBreitFrame_factory.h +++ b/src/factories/reco/TransformBreitFrame_factory.h @@ -17,41 +17,36 @@ namespace eicrecon { - class TransformBreitFrame_factory : public JOmniFactory { +class TransformBreitFrame_factory : public JOmniFactory { - public: - // algorithm to run - using Algo = eicrecon::TransformBreitFrame; - private: - std::unique_ptr m_algo; +public: + // algorithm to run + using Algo = eicrecon::TransformBreitFrame; - // input collection - PodioInput m_in_mcpart {this}; - PodioInput m_in_kine {this}; - PodioInput m_in_part {this}; +private: + std::unique_ptr m_algo; - // output collection - PodioOutput m_out_part {this}; + // input collection + PodioInput m_in_mcpart{this}; + PodioInput m_in_kine{this}; + PodioInput m_in_part{this}; - public: + // output collection + PodioOutput m_out_part{this}; - void Configure() { - m_algo = std::make_unique(GetPrefix()); - m_algo->level((algorithms::LogLevel)logger()->level()); - m_algo->init(logger()); - } +public: + void Configure() { + m_algo = std::make_unique(GetPrefix()); + m_algo->level((algorithms::LogLevel)logger()->level()); + m_algo->init(logger()); + } - void ChangeRun(int64_t run_number) { - /* nothing to do */ - } + void ChangeRun(int64_t run_number) { /* nothing to do */ } - void Process(int64_t run_number, int64_t event_number) { - m_algo->process( - {m_in_mcpart(),m_in_kine(),m_in_part()}, - {m_out_part().get()} - ); - } + void Process(int64_t run_number, int64_t event_number) { + m_algo->process({m_in_mcpart(), m_in_kine(), m_in_part()}, {m_out_part().get()}); + } - }; // end TransfromBreitFrame_factory definition +}; // end TransfromBreitFrame_factory definition -} // end eicrecon namespace +} // namespace eicrecon diff --git a/src/factories/tracking/TrackerHitReconstruction_factory.h b/src/factories/tracking/TrackerHitReconstruction_factory.h index ad59096931..25fddbdfa5 100644 --- a/src/factories/tracking/TrackerHitReconstruction_factory.h +++ b/src/factories/tracking/TrackerHitReconstruction_factory.h @@ -7,33 +7,31 @@ #include "services/geometry/dd4hep/DD4hep_service.h" #include "extensions/jana/JOmniFactory.h" - namespace eicrecon { -class TrackerHitReconstruction_factory : -public JOmniFactory { +class TrackerHitReconstruction_factory + : public JOmniFactory { - TrackerHitReconstruction m_algo; + TrackerHitReconstruction m_algo; - PodioInput m_raw_hits_input {this}; - PodioOutput m_rec_hits_output {this}; + PodioInput m_raw_hits_input{this}; + PodioOutput m_rec_hits_output{this}; - ParameterRef m_timeResolution {this, "timeResolution", config().timeResolution}; + ParameterRef m_timeResolution{this, "timeResolution", config().timeResolution}; - Service m_geoSvc {this}; + Service m_geoSvc{this}; public: - void Configure() { - m_algo.applyConfig(config()); - m_algo.init(m_geoSvc().converter(), logger()); - } + void Configure() { + m_algo.applyConfig(config()); + m_algo.init(m_geoSvc().converter(), logger()); + } - void ChangeRun(int64_t run_number) { - } + void ChangeRun(int64_t run_number) {} - void Process(int64_t run_number, uint64_t event_number) { - m_rec_hits_output() = m_algo.process(*m_raw_hits_input()); - } + void Process(int64_t run_number, uint64_t event_number) { + m_rec_hits_output() = m_algo.process(*m_raw_hits_input()); + } }; -} // eicrecon +} // namespace eicrecon diff --git a/src/global/beam/beam.cc b/src/global/beam/beam.cc index d424e1b11d..66be2f2cd9 100644 --- a/src/global/beam/beam.cc +++ b/src/global/beam/beam.cc @@ -16,25 +16,22 @@ #include "factories/meta/SubDivideCollection_factory.h" extern "C" { - void InitPlugin(JApplication *app) { - InitJANAPlugin(app); +void InitPlugin(JApplication* app) { + InitJANAPlugin(app); - using namespace eicrecon; + using namespace eicrecon; - // Divide MCParticle collection based on generator status and PDG - std::vector outCollections{"BeamElectrons","BeamProtons"}; - std::vector> values{{4,11},{4,2212}}; + // Divide MCParticle collection based on generator status and PDG + std::vector outCollections{"BeamElectrons", "BeamProtons"}; + std::vector> values{{4, 11}, {4, 2212}}; - app->Add(new JOmniFactoryGeneratorT>( - "BeamParticles", - {"MCParticles"}, - outCollections, - { - .function = ValueSplit<&edm4hep::MCParticle::getGeneratorStatus,&edm4hep::MCParticle::getPDG>{values}, - }, - app - ) - ); - - } + app->Add(new JOmniFactoryGeneratorT>( + "BeamParticles", {"MCParticles"}, outCollections, + { + .function = + ValueSplit<&edm4hep::MCParticle::getGeneratorStatus, &edm4hep::MCParticle::getPDG>{ + values}, + }, + app)); +} } diff --git a/src/global/digi/PhotoMultiplierHitDigi_factory.h b/src/global/digi/PhotoMultiplierHitDigi_factory.h index 34dba2d8ed..efa93c332c 100644 --- a/src/global/digi/PhotoMultiplierHitDigi_factory.h +++ b/src/global/digi/PhotoMultiplierHitDigi_factory.h @@ -24,61 +24,64 @@ namespace eicrecon { -class PhotoMultiplierHitDigi_factory : - public JOmniFactory { +class PhotoMultiplierHitDigi_factory + : public JOmniFactory { public: - using AlgoT = eicrecon::PhotoMultiplierHitDigi; + using AlgoT = eicrecon::PhotoMultiplierHitDigi; + private: - std::unique_ptr m_algo; - - PodioInput m_sim_hits_input {this}; - PodioOutput m_raw_hits_output {this}; - PodioOutput m_raw_assocs_output {this}; - - ParameterRef m_seed {this, "seed", config().seed, "random number generator seed"}; - ParameterRef m_hitTimeWindow {this, "hitTimeWindow", config().hitTimeWindow, ""}; - ParameterRef m_timeResolution {this, "timeResolution", config().timeResolution, ""}; - ParameterRef m_speMean {this, "speMean", config().speMean, ""}; - ParameterRef m_speError {this, "speError", config().speError, ""}; - ParameterRef m_pedMean {this, "pedMean", config().pedMean, ""}; - ParameterRef m_pedError {this, "pedError", config().pedError, ""}; - ParameterRef m_enablePixelGaps {this, "enablePixelGaps", config().enablePixelGaps, "enable/disable removal of hits in gaps between pixels"}; - ParameterRef m_safetyFactor {this, "safetyFactor", config().safetyFactor, "overall safety factor"}; - ParameterRef m_enableNoise {this, "enableNoise", config().enableNoise, ""}; - ParameterRef m_noiseRate {this, "noiseRate", config().noiseRate, ""}; - ParameterRef m_noiseTimeWindow {this, "noiseTimeWindow", config().noiseTimeWindow, ""}; - //ParameterRef>> m_quantumEfficiency {this, "quantumEfficiency", config().quantumEfficiency, ""}; - - Service m_algorithmsInit {this}; - Service m_RichGeoSvc {this}; + std::unique_ptr m_algo; + + PodioInput m_sim_hits_input{this}; + PodioOutput m_raw_hits_output{this}; + PodioOutput m_raw_assocs_output{this}; + + ParameterRef m_seed{this, "seed", config().seed, "random number generator seed"}; + ParameterRef m_hitTimeWindow{this, "hitTimeWindow", config().hitTimeWindow, ""}; + ParameterRef m_timeResolution{this, "timeResolution", config().timeResolution, ""}; + ParameterRef m_speMean{this, "speMean", config().speMean, ""}; + ParameterRef m_speError{this, "speError", config().speError, ""}; + ParameterRef m_pedMean{this, "pedMean", config().pedMean, ""}; + ParameterRef m_pedError{this, "pedError", config().pedError, ""}; + ParameterRef m_enablePixelGaps{this, "enablePixelGaps", config().enablePixelGaps, + "enable/disable removal of hits in gaps between pixels"}; + ParameterRef m_safetyFactor{this, "safetyFactor", config().safetyFactor, + "overall safety factor"}; + ParameterRef m_enableNoise{this, "enableNoise", config().enableNoise, ""}; + ParameterRef m_noiseRate{this, "noiseRate", config().noiseRate, ""}; + ParameterRef m_noiseTimeWindow{this, "noiseTimeWindow", config().noiseTimeWindow, ""}; + //ParameterRef>> m_quantumEfficiency {this, "quantumEfficiency", config().quantumEfficiency, ""}; + + Service m_algorithmsInit{this}; + Service m_RichGeoSvc{this}; public: - void Configure() { - m_algo = std::make_unique(GetPrefix()); - - // Initialize richgeo ReadoutGeo and set random CellID visitor lambda (if a RICH) - if (GetPluginName() == "DRICH" || GetPluginName() == "PFRICH") { - m_RichGeoSvc().GetReadoutGeo(GetPluginName())->SetSeed(config().seed); - m_algo->SetVisitRngCellIDs( - [this] (std::function lambda, float p) { m_RichGeoSvc().GetReadoutGeo(GetPluginName())->VisitAllRngPixels(lambda, p); } - ); - m_algo->SetPixelGapMask( - [this] (PhotoMultiplierHitDigi::CellIDType cellID, dd4hep::Position pos) { return m_RichGeoSvc().GetReadoutGeo(GetPluginName())->PixelGapMask(cellID, pos); } - ); - } - - m_algo->applyConfig(config()); - m_algo->init(); - } + void Configure() { + m_algo = std::make_unique(GetPrefix()); - void ChangeRun(int64_t run_number) { + // Initialize richgeo ReadoutGeo and set random CellID visitor lambda (if a RICH) + if (GetPluginName() == "DRICH" || GetPluginName() == "PFRICH") { + m_RichGeoSvc().GetReadoutGeo(GetPluginName())->SetSeed(config().seed); + m_algo->SetVisitRngCellIDs( + [this](std::function lambda, float p) { + m_RichGeoSvc().GetReadoutGeo(GetPluginName())->VisitAllRngPixels(lambda, p); + }); + m_algo->SetPixelGapMask( + [this](PhotoMultiplierHitDigi::CellIDType cellID, dd4hep::Position pos) { + return m_RichGeoSvc().GetReadoutGeo(GetPluginName())->PixelGapMask(cellID, pos); + }); } - void Process(int64_t run_number, uint64_t event_number) { - m_algo->process({m_sim_hits_input()}, - {m_raw_hits_output().get(), m_raw_assocs_output().get()}); - } + m_algo->applyConfig(config()); + m_algo->init(); + } + + void ChangeRun(int64_t run_number) {} + + void Process(int64_t run_number, uint64_t event_number) { + m_algo->process({m_sim_hits_input()}, {m_raw_hits_output().get(), m_raw_assocs_output().get()}); + } }; -} // eicrecon +} // namespace eicrecon diff --git a/src/global/pid/IrtCherenkovParticleID_factory.cc b/src/global/pid/IrtCherenkovParticleID_factory.cc index dfca32fba8..4759828143 100644 --- a/src/global/pid/IrtCherenkovParticleID_factory.cc +++ b/src/global/pid/IrtCherenkovParticleID_factory.cc @@ -20,7 +20,7 @@ void eicrecon::IrtCherenkovParticleID_factory::Init() { // get app and user info - auto *app = GetApplication(); + auto* app = GetApplication(); auto plugin = GetPluginName(); // plugin name should be detector name auto prefix = GetPrefix(); @@ -31,21 +31,21 @@ void eicrecon::IrtCherenkovParticleID_factory::Init() { m_log->debug("IrtCherenkovParticleID_factory: plugin='{}' prefix='{}'", plugin, prefix); // config - auto cfg = GetDefaultConfig(); - auto set_param = [&prefix, &app] (std::string name, auto &val, std::string description) { + auto cfg = GetDefaultConfig(); + auto set_param = [&prefix, &app](std::string name, auto& val, std::string description) { name = prefix + ":" + name; app->SetDefaultParameter(name, val, description); }; set_param("numRIndexBins", cfg.numRIndexBins, ""); - set_param("pdgList", cfg.pdgList, ""); - for(auto& [name,rad] : cfg.radiators) { - set_param(name+":smearingMode", rad.smearingMode, ""); - set_param(name+":smearing", rad.smearing, ""); - set_param(name+":referenceRIndex", rad.referenceRIndex, ""); - set_param(name+":attenuation", rad.attenuation, ""); + set_param("pdgList", cfg.pdgList, ""); + for (auto& [name, rad] : cfg.radiators) { + set_param(name + ":smearingMode", rad.smearingMode, ""); + set_param(name + ":smearing", rad.smearing, ""); + set_param(name + ":referenceRIndex", rad.referenceRIndex, ""); + set_param(name + ":attenuation", rad.attenuation, ""); } - set_param("cheatPhotonVertex", cfg.cheatPhotonVertex, ""); - set_param("cheatTrueRadiator", cfg.cheatTrueRadiator, ""); + set_param("cheatPhotonVertex", cfg.cheatPhotonVertex, ""); + set_param("cheatTrueRadiator", cfg.cheatTrueRadiator, ""); // initialize underlying algorithm m_irt_algo.applyConfig(cfg); @@ -53,54 +53,53 @@ void eicrecon::IrtCherenkovParticleID_factory::Init() { } //----------------------------------------------------------------------------- -void eicrecon::IrtCherenkovParticleID_factory::BeginRun(const std::shared_ptr &event) { +void eicrecon::IrtCherenkovParticleID_factory::BeginRun( + const std::shared_ptr& event) { m_irt_algo.AlgorithmChangeRun(); } //----------------------------------------------------------------------------- -void eicrecon::IrtCherenkovParticleID_factory::Process(const std::shared_ptr &event) { +void eicrecon::IrtCherenkovParticleID_factory::Process(const std::shared_ptr& event) { // get input track propagation collections from radiators - std::map charged_particles; // map : radiator_name -> collection of TrackSegments + std::map + charged_particles; // map : radiator_name -> collection of TrackSegments int tag_num = 0; - while(tag_num < richgeo::nRadiators) { + while (tag_num < richgeo::nRadiators) { auto input_tag = GetInputTags().at(tag_num++); auto radiator_id = richgeo::ParseRadiatorName(input_tag); - if(radiator_id >= 0 && radiator_id < richgeo::nRadiators) - charged_particles.insert({ - richgeo::RadiatorName(radiator_id), - (event->GetCollection(input_tag)) - }); - else m_log->error("Unknown input RICH track collection '{}'", input_tag); + if (radiator_id >= 0 && radiator_id < richgeo::nRadiators) + charged_particles.insert({richgeo::RadiatorName(radiator_id), + (event->GetCollection(input_tag))}); + else + m_log->error("Unknown input RICH track collection '{}'", input_tag); } // get merged track propagation - if(GetInputTags()[tag_num].find("Merge") != std::string::npos) - charged_particles.insert({ - "Merged", - (event->GetCollection(GetInputTags()[tag_num++])) - }); + if (GetInputTags()[tag_num].find("Merge") != std::string::npos) + charged_particles.insert( + {"Merged", (event->GetCollection(GetInputTags()[tag_num++]))}); else { m_log->critical("input tag {} should be merged tracks", tag_num); return; } // get input hit collections - const auto *raw_hits = (event->GetCollection(GetInputTags()[tag_num++])); - const auto *hit_assocs = (event->GetCollection(GetInputTags()[tag_num++])); + const auto* raw_hits = (event->GetCollection(GetInputTags()[tag_num++])); + const auto* hit_assocs = + (event->GetCollection(GetInputTags()[tag_num++])); try { // run the IrtCherenkovParticleID algorithm auto result = m_irt_algo.AlgorithmProcess(charged_particles, raw_hits, hit_assocs); // set output collections, matching radiator name to corresponding output tag - for(auto& [rad_name, coll] : result) { - for(auto& output_tag : GetOutputTags()) { - if(output_tag.find(rad_name) != std::string::npos) + for (auto& [rad_name, coll] : result) { + for (auto& output_tag : GetOutputTags()) { + if (output_tag.find(rad_name) != std::string::npos) SetCollection(output_tag, std::move(coll)); } } - } - catch(std::exception &e) { + } catch (std::exception& e) { throw JException(e.what()); } } diff --git a/src/global/pid/IrtCherenkovParticleID_factory.h b/src/global/pid/IrtCherenkovParticleID_factory.h index 5b9bdef8f8..6d3e698f51 100644 --- a/src/global/pid/IrtCherenkovParticleID_factory.h +++ b/src/global/pid/IrtCherenkovParticleID_factory.h @@ -23,38 +23,32 @@ namespace eicrecon { - class IrtCherenkovParticleID_factory : - public JChainMultifactoryT, - public SpdlogMixin - { - - public: - - explicit IrtCherenkovParticleID_factory( - std::string tag, - const std::vector& input_tags, - const std::vector& output_tags, - IrtCherenkovParticleIDConfig cfg - ): - JChainMultifactoryT(std::move(tag), input_tags, output_tags, cfg) { - for(auto& output_tag : GetOutputTags()) - DeclarePodioOutput(output_tag); - } - - /** One time initialization **/ - void Init() override; - - /** On run change preparations **/ - void BeginRun(const std::shared_ptr &event) override; - - /** Event by event processing **/ - void Process(const std::shared_ptr &event) override; - - private: - - eicrecon::IrtCherenkovParticleID m_irt_algo; - std::shared_ptr m_richGeoSvc; - CherenkovDetectorCollection *m_irt_det_coll; - - }; -} +class IrtCherenkovParticleID_factory : public JChainMultifactoryT, + public SpdlogMixin { + +public: + explicit IrtCherenkovParticleID_factory(std::string tag, + const std::vector& input_tags, + const std::vector& output_tags, + IrtCherenkovParticleIDConfig cfg) + : JChainMultifactoryT(std::move(tag), input_tags, output_tags, + cfg) { + for (auto& output_tag : GetOutputTags()) + DeclarePodioOutput(output_tag); + } + + /** One time initialization **/ + void Init() override; + + /** On run change preparations **/ + void BeginRun(const std::shared_ptr& event) override; + + /** Event by event processing **/ + void Process(const std::shared_ptr& event) override; + +private: + eicrecon::IrtCherenkovParticleID m_irt_algo; + std::shared_ptr m_richGeoSvc; + CherenkovDetectorCollection* m_irt_det_coll; +}; +} // namespace eicrecon diff --git a/src/global/pid/MergeCherenkovParticleID_factory.cc b/src/global/pid/MergeCherenkovParticleID_factory.cc index 9d0ab83882..f357df802d 100644 --- a/src/global/pid/MergeCherenkovParticleID_factory.cc +++ b/src/global/pid/MergeCherenkovParticleID_factory.cc @@ -24,8 +24,8 @@ void eicrecon::MergeCherenkovParticleID_factory::Init() { m_log->debug("MergeCherenkovParticleID_factory: plugin='{}' prefix='{}'", plugin, prefix); // config - auto cfg = GetDefaultConfig(); - auto set_param = [&prefix, &app] (std::string name, auto &val, std::string description) { + auto cfg = GetDefaultConfig(); + auto set_param = [&prefix, &app](std::string name, auto& val, std::string description) { name = prefix + ":" + name; app->SetDefaultParameter(name, val, description); }; @@ -38,14 +38,13 @@ void eicrecon::MergeCherenkovParticleID_factory::Init() { } //----------------------------------------------------------------------------- -void eicrecon::MergeCherenkovParticleID_factory::Process(const std::shared_ptr &event) { +void eicrecon::MergeCherenkovParticleID_factory::Process( + const std::shared_ptr& event) { // get input collections std::vector> cherenkov_pids; - for(auto& input_tag : GetInputTags()) { - cherenkov_pids.push_back( - (event->GetCollection(input_tag)) - ); + for (auto& input_tag : GetInputTags()) { + cherenkov_pids.push_back((event->GetCollection(input_tag))); } // call the MergeParticleID algorithm @@ -53,8 +52,7 @@ void eicrecon::MergeCherenkovParticleID_factory::Process(const std::shared_ptr(); m_algo->process({cherenkov_pids}, {merged_pids.get()}); SetCollection(GetOutputTags()[0], std::move(merged_pids)); - } - catch(std::exception &e) { + } catch (std::exception& e) { throw JException(e.what()); } } diff --git a/src/global/pid/MergeCherenkovParticleID_factory.h b/src/global/pid/MergeCherenkovParticleID_factory.h index e457cf450b..b212128b57 100644 --- a/src/global/pid/MergeCherenkovParticleID_factory.h +++ b/src/global/pid/MergeCherenkovParticleID_factory.h @@ -22,31 +22,28 @@ namespace eicrecon { - class MergeCherenkovParticleID_factory : - public JChainMultifactoryT, - public SpdlogMixin - { - - public: - using AlgoT = eicrecon::MergeParticleID; - private: - std::unique_ptr m_algo; - - public: - explicit MergeCherenkovParticleID_factory( - std::string tag, - const std::vector& input_tags, - const std::vector& output_tags, - MergeParticleIDConfig cfg) - : JChainMultifactoryT(std::move(tag), input_tags, output_tags, cfg) { - DeclarePodioOutput(GetOutputTags()[0]); - } +class MergeCherenkovParticleID_factory : public JChainMultifactoryT, + public SpdlogMixin { + +public: + using AlgoT = eicrecon::MergeParticleID; - /** One time initialization **/ - void Init() override; +private: + std::unique_ptr m_algo; + +public: + explicit MergeCherenkovParticleID_factory(std::string tag, + const std::vector& input_tags, + const std::vector& output_tags, + MergeParticleIDConfig cfg) + : JChainMultifactoryT(std::move(tag), input_tags, output_tags, cfg) { + DeclarePodioOutput(GetOutputTags()[0]); + } - /** Event by event processing **/ - void Process(const std::shared_ptr &event) override; + /** One time initialization **/ + void Init() override; - }; -} + /** Event by event processing **/ + void Process(const std::shared_ptr& event) override; +}; +} // namespace eicrecon diff --git a/src/global/pid/MergeTrack_factory.h b/src/global/pid/MergeTrack_factory.h index 89a8f3900d..df30f9a12c 100644 --- a/src/global/pid/MergeTrack_factory.h +++ b/src/global/pid/MergeTrack_factory.h @@ -20,34 +20,31 @@ namespace eicrecon { - class MergeTrack_factory : public JOmniFactory { private: + // Underlying algorithm + std::unique_ptr m_algo; - // Underlying algorithm - std::unique_ptr m_algo; - - // Declare inputs - VariadicPodioInput m_track_segments_input {this}; + // Declare inputs + VariadicPodioInput m_track_segments_input{this}; - // Declare outputs - PodioOutput m_track_segments_output {this}; + // Declare outputs + PodioOutput m_track_segments_output{this}; public: - void Configure() { - m_algo = std::make_unique(GetPrefix()); - m_algo->init(logger()); - } - - void ChangeRun(int64_t run_number) { } - - void Process(int64_t run_number, uint64_t event_number) { - auto in1 = m_track_segments_input(); - std::vector> in2; - std::copy(in1.cbegin(), in1.cend(), std::back_inserter(in2)); - - m_algo->process({in2}, {m_track_segments_output().get()}); - } - - }; -} + void Configure() { + m_algo = std::make_unique(GetPrefix()); + m_algo->init(logger()); + } + + void ChangeRun(int64_t run_number) {} + + void Process(int64_t run_number, uint64_t event_number) { + auto in1 = m_track_segments_input(); + std::vector> in2; + std::copy(in1.cbegin(), in1.cend(), std::back_inserter(in2)); + + m_algo->process({in2}, {m_track_segments_output().get()}); + } +}; +} // namespace eicrecon diff --git a/src/global/pid/ParticlesWithPID_factory.h b/src/global/pid/ParticlesWithPID_factory.h index e01f879b58..d8b332d5c2 100644 --- a/src/global/pid/ParticlesWithPID_factory.h +++ b/src/global/pid/ParticlesWithPID_factory.h @@ -18,38 +18,39 @@ #include "algorithms/pid/ParticlesWithPIDConfig.h" #include "extensions/jana/JOmniFactory.h" - namespace eicrecon { -class ParticlesWithPID_factory : public JOmniFactory { +class ParticlesWithPID_factory + : public JOmniFactory { private: - ParticlesWithPID m_algo; + ParticlesWithPID m_algo; - PodioInput m_mc_particles_input {this}; - PodioInput m_tracks_input {this}; - PodioInput m_drich_particle_id_input {this}; + PodioInput m_mc_particles_input{this}; + PodioInput m_tracks_input{this}; + PodioInput m_drich_particle_id_input{this}; - PodioOutput m_particles_output {this}; - PodioOutput m_particles_assoc_output {this}; - PodioOutput m_particle_id_output {this}; + PodioOutput m_particles_output{this}; + PodioOutput m_particles_assoc_output{this}; + PodioOutput m_particle_id_output{this}; - ParameterRef m_momentumRelativeTolerance {this, "momentumRelativeTolerance", config().momentumRelativeTolerance}; - ParameterRef m_phiTolerance {this, "phiTolerance", config().phiTolerance}; - ParameterRef m_etaTolerance {this, "etaTolerance", config().etaTolerance}; + ParameterRef m_momentumRelativeTolerance{this, "momentumRelativeTolerance", + config().momentumRelativeTolerance}; + ParameterRef m_phiTolerance{this, "phiTolerance", config().phiTolerance}; + ParameterRef m_etaTolerance{this, "etaTolerance", config().etaTolerance}; public: - void Configure() { - m_algo.applyConfig(config()); - m_algo.init(logger()); - } + void Configure() { + m_algo.applyConfig(config()); + m_algo.init(logger()); + } - void ChangeRun(int64_t run_number) { - } + void ChangeRun(int64_t run_number) {} - void Process(int64_t run_number, uint64_t event_number) { - std::tie(m_particles_output(), m_particles_assoc_output(), m_particle_id_output()) = m_algo.process(m_mc_particles_input(), m_tracks_input(), m_drich_particle_id_input()); - } + void Process(int64_t run_number, uint64_t event_number) { + std::tie(m_particles_output(), m_particles_assoc_output(), m_particle_id_output()) = + m_algo.process(m_mc_particles_input(), m_tracks_input(), m_drich_particle_id_input()); + } }; -} // eicrecon +} // namespace eicrecon diff --git a/src/global/pid/RichTrackConfig.h b/src/global/pid/RichTrackConfig.h index 906e87e561..3aae3082aa 100644 --- a/src/global/pid/RichTrackConfig.h +++ b/src/global/pid/RichTrackConfig.h @@ -7,30 +7,25 @@ namespace eicrecon { - class RichTrackConfig { - public: - - ///////////////////////////////////////////////////// - // CONFIGURATION PARAMETERS - // NOTE: some defaults are hard-coded here; override externally - - std::map numPlanes; // number of xy-planes for track projections (for each radiator) - - // - ///////////////////////////////////////////////////// - - - // print all parameters - void Print( - std::shared_ptr m_log, - spdlog::level::level_enum lvl=spdlog::level::debug - ) - { - m_log->log(lvl, "{:=^60}"," RichTrackConfig Settings "); - for(const auto& [rad,val] : numPlanes) - m_log->log(lvl, " {:>20} = {:<}", fmt::format("{} numPlanes", rad), val); - m_log->log(lvl, "{:=^60}",""); - } - - }; -} +class RichTrackConfig { +public: + ///////////////////////////////////////////////////// + // CONFIGURATION PARAMETERS + // NOTE: some defaults are hard-coded here; override externally + + std::map + numPlanes; // number of xy-planes for track projections (for each radiator) + + // + ///////////////////////////////////////////////////// + + // print all parameters + void Print(std::shared_ptr m_log, + spdlog::level::level_enum lvl = spdlog::level::debug) { + m_log->log(lvl, "{:=^60}", " RichTrackConfig Settings "); + for (const auto& [rad, val] : numPlanes) + m_log->log(lvl, " {:>20} = {:<}", fmt::format("{} numPlanes", rad), val); + m_log->log(lvl, "{:=^60}", ""); + } +}; +} // namespace eicrecon diff --git a/src/global/pid/RichTrack_factory.cc b/src/global/pid/RichTrack_factory.cc index f47535653e..8f34b58174 100644 --- a/src/global/pid/RichTrack_factory.cc +++ b/src/global/pid/RichTrack_factory.cc @@ -20,7 +20,7 @@ void eicrecon::RichTrack_factory::Init() { // get app and user info - auto *app = GetApplication(); + auto* app = GetApplication(); auto plugin = GetPluginName(); // plugin name should be detector name auto prefix = GetPrefix(); @@ -32,44 +32,37 @@ void eicrecon::RichTrack_factory::Init() { m_log->debug("RichTrack_factory: plugin='{}' prefix='{}'", plugin, prefix); // get list of radiators - std::vector> radiator_list; // < radiator_id, radiator_name, output_tag > - for(auto& output_tag : GetOutputTags()) { + std::vector> + radiator_list; // < radiator_id, radiator_name, output_tag > + for (auto& output_tag : GetOutputTags()) { auto radiator_id = richgeo::ParseRadiatorName(output_tag, m_log); - radiator_list.emplace_back( - radiator_id, - richgeo::RadiatorName(radiator_id, m_log), - output_tag - ); + radiator_list.emplace_back(radiator_id, richgeo::RadiatorName(radiator_id, m_log), output_tag); } // configuration parameters - auto cfg = GetDefaultConfig(); - auto set_param = [&prefix, &app] (std::string name, auto &val, std::string description) { + auto cfg = GetDefaultConfig(); + auto set_param = [&prefix, &app](std::string name, auto& val, std::string description) { name = prefix + ":" + name; app->SetDefaultParameter(name, val, description); }; - for(auto& [radiator_id, radiator_name, output_tag] : radiator_list) - set_param(radiator_name+":numPlanes", cfg.numPlanes[radiator_name], ""); + for (auto& [radiator_id, radiator_name, output_tag] : radiator_list) + set_param(radiator_name + ":numPlanes", cfg.numPlanes[radiator_name], ""); cfg.Print(m_log, spdlog::level::debug); // get RICH geometry for track propagation, for each radiator m_actsGeo = m_richGeoSvc->GetActsGeo(plugin); - for(auto& [radiator_id, radiator_name, output_tag] : radiator_list) { - m_tracking_planes.insert({ - output_tag, - m_actsGeo->TrackingPlanes(radiator_id, cfg.numPlanes.at(radiator_name)) - }); - m_track_point_cuts.insert({ output_tag, m_actsGeo->TrackPointCut(radiator_id) }); + for (auto& [radiator_id, radiator_name, output_tag] : radiator_list) { + m_tracking_planes.insert( + {output_tag, m_actsGeo->TrackingPlanes(radiator_id, cfg.numPlanes.at(radiator_name))}); + m_track_point_cuts.insert({output_tag, m_actsGeo->TrackPointCut(radiator_id)}); } - } //----------------------------------------------------------------------------- -void eicrecon::RichTrack_factory::BeginRun(const std::shared_ptr &event) { -} +void eicrecon::RichTrack_factory::BeginRun(const std::shared_ptr& event) {} //----------------------------------------------------------------------------- -void eicrecon::RichTrack_factory::Process(const std::shared_ptr &event) { +void eicrecon::RichTrack_factory::Process(const std::shared_ptr& event) { auto input_tags = GetInputTags(); @@ -79,11 +72,11 @@ void eicrecon::RichTrack_factory::Process(const std::shared_ptr &e // collect all trajectories from all input tags std::vector trajectories; - for(const auto& input_tag : input_tags) { + for (const auto& input_tag : input_tags) { try { - for(const auto traj : event->Get(input_tag)) + for (const auto traj : event->Get(input_tag)) trajectories.push_back(traj); - } catch(std::exception &e) { + } catch (std::exception& e) { m_log->critical(e.what()); throw JException(e.what()); } @@ -92,31 +85,24 @@ void eicrecon::RichTrack_factory::Process(const std::shared_ptr &e // choose the filter surface: all charged particles that pass through the dRICH vessel will pass // through the backplane of the gas radiator std::shared_ptr filter_surface; - for(auto& [output_tag, radiator_tracking_planes] : m_tracking_planes) { - if(richgeo::ParseRadiatorName(output_tag, m_log) == richgeo::kGas) { + for (auto& [output_tag, radiator_tracking_planes] : m_tracking_planes) { + if (richgeo::ParseRadiatorName(output_tag, m_log) == richgeo::kGas) { filter_surface = radiator_tracking_planes.back(); break; } } - if(!filter_surface) + if (!filter_surface) throw JException("cannot find filter surface for RICH track propagation"); // run track propagator algorithm, for each radiator - for(auto& [output_tag, radiator_tracking_planes] : m_tracking_planes) { + for (auto& [output_tag, radiator_tracking_planes] : m_tracking_planes) { try { auto track_point_cut = m_track_point_cuts.at(output_tag); - auto result = m_propagation_algo.propagateToSurfaceList( - trajectories, - radiator_tracking_planes, - filter_surface, - track_point_cut, - true - ); + auto result = m_propagation_algo.propagateToSurfaceList( + trajectories, radiator_tracking_planes, filter_surface, track_point_cut, true); SetCollection(output_tag, std::move(result)); - } - catch(std::exception &e) { + } catch (std::exception& e) { throw JException(e.what()); } } - } diff --git a/src/global/pid/RichTrack_factory.h b/src/global/pid/RichTrack_factory.h index 463d392403..91d022413f 100644 --- a/src/global/pid/RichTrack_factory.h +++ b/src/global/pid/RichTrack_factory.h @@ -27,45 +27,36 @@ #include "services/geometry/richgeo/RichGeo_service.h" namespace eicrecon { - class RichTrack_factory : - public JChainMultifactoryT, - public SpdlogMixin - { - public: - - explicit RichTrack_factory( - std::string tag, - const std::vector& input_tags, - const std::vector& output_tags, - RichTrackConfig cfg - ): - JChainMultifactoryT(std::move(tag), input_tags, output_tags, cfg) { - for(auto& output_tag : GetOutputTags()) - DeclarePodioOutput(output_tag); - } - - /** One time initialization **/ - void Init() override; - - /** On run change preparations **/ - void BeginRun(const std::shared_ptr &event) override; - - /** Event by event processing **/ - void Process(const std::shared_ptr &event) override; - - private: - std::string m_detector_name; - std::shared_ptr m_richGeoSvc; - std::shared_ptr m_actsSvc; - richgeo::ActsGeo *m_actsGeo; - - // map: output_tag name (for a radiator's track projections) -> a vector of xy-planes to project to - std::map< std::string, std::vector> > m_tracking_planes; - // map: output tag name -> cuts - std::map< std::string, std::function > m_track_point_cuts; - - - // underlying algorithm - eicrecon::TrackPropagation m_propagation_algo; - }; -} +class RichTrack_factory : public JChainMultifactoryT, public SpdlogMixin { +public: + explicit RichTrack_factory(std::string tag, const std::vector& input_tags, + const std::vector& output_tags, RichTrackConfig cfg) + : JChainMultifactoryT(std::move(tag), input_tags, output_tags, cfg) { + for (auto& output_tag : GetOutputTags()) + DeclarePodioOutput(output_tag); + } + + /** One time initialization **/ + void Init() override; + + /** On run change preparations **/ + void BeginRun(const std::shared_ptr& event) override; + + /** Event by event processing **/ + void Process(const std::shared_ptr& event) override; + +private: + std::string m_detector_name; + std::shared_ptr m_richGeoSvc; + std::shared_ptr m_actsSvc; + richgeo::ActsGeo* m_actsGeo; + + // map: output_tag name (for a radiator's track projections) -> a vector of xy-planes to project to + std::map>> m_tracking_planes; + // map: output tag name -> cuts + std::map> m_track_point_cuts; + + // underlying algorithm + eicrecon::TrackPropagation m_propagation_algo; +}; +} // namespace eicrecon diff --git a/src/global/pid/pid.cc b/src/global/pid/pid.cc index b1c9381b7a..12d0847f3c 100644 --- a/src/global/pid/pid.cc +++ b/src/global/pid/pid.cc @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-3.0-or-later // Copyright (C) 2022, 2023, Christopher Dilks - #include #include @@ -13,22 +12,21 @@ #include "global/pid/ParticlesWithPID_factory.h" extern "C" { - void InitPlugin(JApplication *app) { - InitJANAPlugin(app); - - using namespace eicrecon; +void InitPlugin(JApplication* app) { + InitJANAPlugin(app); - // configuration parameters /////////////////////////////////////////////// + using namespace eicrecon; - // linking of reconstructed particles to PID objects - ParticlesWithPIDConfig link_cfg; - link_cfg.momentumRelativeTolerance = 100.0; /// Matching momentum effectively disabled - link_cfg.phiTolerance = 0.1; /// Matching phi tolerance [rad] - link_cfg.etaTolerance = 0.2; /// Matching eta tolerance + // configuration parameters /////////////////////////////////////////////// + // linking of reconstructed particles to PID objects + ParticlesWithPIDConfig link_cfg; + link_cfg.momentumRelativeTolerance = 100.0; /// Matching momentum effectively disabled + link_cfg.phiTolerance = 0.1; /// Matching phi tolerance [rad] + link_cfg.etaTolerance = 0.2; /// Matching eta tolerance - // wiring between factories and data /////////////////////////////////////// - // clang-format off + // wiring between factories and data /////////////////////////////////////// + // clang-format off // link charged particles to PID and to MC truth app->Add(new JOmniFactoryGeneratorT( diff --git a/src/global/reco/ChargedMCParticleSelector_factory.h b/src/global/reco/ChargedMCParticleSelector_factory.h index 8bfbd8c531..a8c30944f8 100644 --- a/src/global/reco/ChargedMCParticleSelector_factory.h +++ b/src/global/reco/ChargedMCParticleSelector_factory.h @@ -8,34 +8,30 @@ namespace eicrecon { - class ChargedMCParticleSelector_factory : public JOmniFactory { +class ChargedMCParticleSelector_factory + : public JOmniFactory { - private: +private: + // algorithm + std::unique_ptr m_algo; - // algorithm - std::unique_ptr m_algo; + // input collection + PodioInput m_pars_in{this, "GeneratedParticles"}; - // input collection - PodioInput m_pars_in {this, "GeneratedParticles"}; + // output collection + PodioOutput m_pars_out{this}; - // output collection - PodioOutput m_pars_out {this}; +public: + void Configure() { + m_algo = std::make_unique(); + m_algo->init(logger()); + } - public: + void ChangeRun(int64_t run_number) { /* nothing to do */ } - void Configure() { - m_algo = std::make_unique(); - m_algo->init(logger()); - } + void Process(int64_t run_number, int64_t event_number) { + m_pars_out() = m_algo->process(m_pars_in()); + } +}; - void ChangeRun(int64_t run_number) { - /* nothing to do */ - } - - void Process(int64_t run_number, int64_t event_number) { - m_pars_out() = m_algo->process(m_pars_in()); - } - - }; - -} // end eicrecon namespace +} // namespace eicrecon diff --git a/src/global/reco/ChargedReconstructedParticleSelector_factory.h b/src/global/reco/ChargedReconstructedParticleSelector_factory.h index 249f306e51..a9850376b6 100644 --- a/src/global/reco/ChargedReconstructedParticleSelector_factory.h +++ b/src/global/reco/ChargedReconstructedParticleSelector_factory.h @@ -8,34 +8,30 @@ namespace eicrecon { - class ChargedReconstructedParticleSelector_factory : public JOmniFactory { +class ChargedReconstructedParticleSelector_factory + : public JOmniFactory { - private: +private: + // algorithm + std::unique_ptr m_algo; - // algorithm - std::unique_ptr m_algo; + // input collection + PodioInput m_pars_in{this, "GeneratedParticles"}; - // input collection - PodioInput m_pars_in {this, "GeneratedParticles"}; + // output collection + PodioOutput m_pars_out{this}; - // output collection - PodioOutput m_pars_out {this}; +public: + void Configure() { + m_algo = std::make_unique(); + m_algo->init(logger()); + } - public: + void ChangeRun(int64_t run_number) { /* nothing to do */ } - void Configure() { - m_algo = std::make_unique(); - m_algo->init(logger()); - } + void Process(int64_t run_number, int64_t event_number) { + m_pars_out() = m_algo->process(m_pars_in()); + } +}; - void ChangeRun(int64_t run_number) { - /* nothing to do */ - } - - void Process(int64_t run_number, int64_t event_number) { - m_pars_out() = m_algo->process(m_pars_in()); - } - - }; - -} // end eicrecon namespace +} // namespace eicrecon diff --git a/src/global/reco/MC2SmearedParticle_factory.h b/src/global/reco/MC2SmearedParticle_factory.h index a1aee66d7f..9ea2c74d0f 100644 --- a/src/global/reco/MC2SmearedParticle_factory.h +++ b/src/global/reco/MC2SmearedParticle_factory.h @@ -16,28 +16,26 @@ namespace eicrecon { -class MC2SmearedParticle_factory : - public JOmniFactory { +class MC2SmearedParticle_factory : public JOmniFactory { private: - using AlgoT = eicrecon::MC2SmearedParticle; - std::unique_ptr m_algo; + using AlgoT = eicrecon::MC2SmearedParticle; + std::unique_ptr m_algo; - PodioInput m_mc_particles_input {this}; - PodioOutput m_rc_particles_output {this}; + PodioInput m_mc_particles_input{this}; + PodioOutput m_rc_particles_output{this}; public: - void Configure() { - m_algo = std::make_unique(); - m_algo->init(logger()); - } + void Configure() { + m_algo = std::make_unique(); + m_algo->init(logger()); + } - void ChangeRun(int64_t run_number) { - } + void ChangeRun(int64_t run_number) {} - void Process(int64_t run_number, uint64_t event_number) { - m_rc_particles_output() = m_algo->produce(m_mc_particles_input()); - } + void Process(int64_t run_number, uint64_t event_number) { + m_rc_particles_output() = m_algo->produce(m_mc_particles_input()); + } }; -} // eicrecon +} // namespace eicrecon diff --git a/src/global/reco/MatchClusters_factory.h b/src/global/reco/MatchClusters_factory.h index 80988d3b03..52559ad87f 100644 --- a/src/global/reco/MatchClusters_factory.h +++ b/src/global/reco/MatchClusters_factory.h @@ -22,48 +22,45 @@ namespace eicrecon { class MatchClusters_factory : public JOmniFactory { private: + // Underlying algorithm + std::unique_ptr m_algo; - // Underlying algorithm - std::unique_ptr m_algo; + // Declare inputs + PodioInput m_mc_parts_input{this}; + PodioInput m_rec_parts_input{this}; + PodioInput m_rec_assocs_input{this}; + PodioInput m_clusters_input{this}; + PodioInput m_cluster_assocs_input{this}; - // Declare inputs - PodioInput m_mc_parts_input {this}; - PodioInput m_rec_parts_input {this}; - PodioInput m_rec_assocs_input {this}; - PodioInput m_clusters_input {this}; - PodioInput m_cluster_assocs_input {this}; + // Declare outputs + PodioOutput m_rec_parts_output{this}; + PodioOutput m_rec_assocs_output{this}; - // Declare outputs - PodioOutput m_rec_parts_output {this}; - PodioOutput m_rec_assocs_output {this}; - - Service m_algorithmsInit {this}; + Service m_algorithmsInit{this}; public: - void Configure() { - m_algo = std::make_unique(GetPrefix()); - m_algo->level((algorithms::LogLevel)logger()->level()); - m_algo->init(); - } - - void ChangeRun(int64_t run_number) { } + void Configure() { + m_algo = std::make_unique(GetPrefix()); + m_algo->level((algorithms::LogLevel)logger()->level()); + m_algo->init(); + } - void Process(int64_t run_number, uint64_t event_number) { - m_algo->process( - { - m_mc_parts_input(), - m_rec_parts_input(), - m_rec_assocs_input(), - m_clusters_input(), - m_cluster_assocs_input(), - }, - { - m_rec_parts_output().get(), - m_rec_assocs_output().get(), - } - ); - } + void ChangeRun(int64_t run_number) {} - }; + void Process(int64_t run_number, uint64_t event_number) { + m_algo->process( + { + m_mc_parts_input(), + m_rec_parts_input(), + m_rec_assocs_input(), + m_clusters_input(), + m_cluster_assocs_input(), + }, + { + m_rec_parts_output().get(), + m_rec_assocs_output().get(), + }); + } +}; -} // eicrecon +} // namespace eicrecon diff --git a/src/global/reco/ReconstructedElectrons_factory.h b/src/global/reco/ReconstructedElectrons_factory.h index 3996a937fd..982419a01e 100644 --- a/src/global/reco/ReconstructedElectrons_factory.h +++ b/src/global/reco/ReconstructedElectrons_factory.h @@ -7,64 +7,63 @@ #include "algorithms/reco/ElectronReconstruction.h" - namespace eicrecon { -class ReconstructedElectrons_factory : public JOmniFactory { +class ReconstructedElectrons_factory + : public JOmniFactory { private: + // Underlying algorithm + std::unique_ptr m_algo; - // Underlying algorithm - std::unique_ptr m_algo; - - // Declare inputs - PodioInput m_in_rc_particles {this, "ReconstructedParticles"}; - + // Declare inputs + PodioInput m_in_rc_particles{this, "ReconstructedParticles"}; - // Declare outputs - PodioOutput m_out_reco_particles {this}; + // Declare outputs + PodioOutput m_out_reco_particles{this}; - // Declare parameters - ParameterRef m_min_energy_over_momentum {this, "minEnergyOverMomentum", config().min_energy_over_momentum}; - ParameterRef m_max_energy_over_momentum {this, "maxEnergyOverMomentum", config().max_energy_over_momentum}; + // Declare parameters + ParameterRef m_min_energy_over_momentum{this, "minEnergyOverMomentum", + config().min_energy_over_momentum}; + ParameterRef m_max_energy_over_momentum{this, "maxEnergyOverMomentum", + config().max_energy_over_momentum}; - // Declare services here, e.g. - // Service m_geoSvc {this}; + // Declare services here, e.g. + // Service m_geoSvc {this}; public: - void Configure() { - // This is called when the factory is instantiated. - // Use this callback to make sure the algorithm is configured. - // The logger, parameters, and services have all been fetched before this is called - m_algo = std::make_unique(); - - // Pass config object to algorithm - m_algo->applyConfig(config()); - - // If we needed geometry, we'd obtain it like so - // m_algo->init(m_geoSvc().detector(), m_geoSvc().converter(), logger()); - - m_algo->init(logger()); - } - - void ChangeRun(int64_t run_number) { - // This is called whenever the run number is changed. - // Use this callback to retrieve state that is keyed off of run number. - // This state should usually be managed by a Service. - // Note: You usually don't need this, because you can declare a Resource instead. - } - - void Process(int64_t run_number, uint64_t event_number) { - // This is called on every event. - // Use this callback to call your Algorithm using all inputs and outputs - // The inputs will have already been fetched for you at this point. - auto output = m_algo->execute( - m_in_rc_particles() - ); - - logger()->debug( "Event {}: Found {} reconstructed electron candidates", event_number, output->size() ); - - m_out_reco_particles() = std::move(output); - // JANA will take care of publishing the outputs for you. - } + void Configure() { + // This is called when the factory is instantiated. + // Use this callback to make sure the algorithm is configured. + // The logger, parameters, and services have all been fetched before this is called + m_algo = std::make_unique(); + + // Pass config object to algorithm + m_algo->applyConfig(config()); + + // If we needed geometry, we'd obtain it like so + // m_algo->init(m_geoSvc().detector(), m_geoSvc().converter(), logger()); + + m_algo->init(logger()); + } + + void ChangeRun(int64_t run_number) { + // This is called whenever the run number is changed. + // Use this callback to retrieve state that is keyed off of run number. + // This state should usually be managed by a Service. + // Note: You usually don't need this, because you can declare a Resource instead. + } + + void Process(int64_t run_number, uint64_t event_number) { + // This is called on every event. + // Use this callback to call your Algorithm using all inputs and outputs + // The inputs will have already been fetched for you at this point. + auto output = m_algo->execute(m_in_rc_particles()); + + logger()->debug("Event {}: Found {} reconstructed electron candidates", event_number, + output->size()); + + m_out_reco_particles() = std::move(output); + // JANA will take care of publishing the outputs for you. + } }; } // namespace eicrecon diff --git a/src/global/reco/ScatteredElectronsEMinusPz_factory.h b/src/global/reco/ScatteredElectronsEMinusPz_factory.h index 7a7d1e6cf5..1748f72d90 100644 --- a/src/global/reco/ScatteredElectronsEMinusPz_factory.h +++ b/src/global/reco/ScatteredElectronsEMinusPz_factory.h @@ -15,34 +15,34 @@ namespace eicrecon { -class ScatteredElectronsEMinusPz_factory : - public JOmniFactory { +class ScatteredElectronsEMinusPz_factory + : public JOmniFactory { public: - using AlgoT = eicrecon::ScatteredElectronsEMinusPz; + using AlgoT = eicrecon::ScatteredElectronsEMinusPz; + private: - std::unique_ptr m_algo; + std::unique_ptr m_algo; - PodioInput m_rc_particles_input {this}; - PodioInput m_rc_electrons_input {this}; + PodioInput m_rc_particles_input{this}; + PodioInput m_rc_electrons_input{this}; - // Declare outputs - PodioOutput m_out_reco_particles {this}; + // Declare outputs + PodioOutput m_out_reco_particles{this}; public: - void Configure() { - m_algo = std::make_unique(); - m_algo->init(logger()); - m_algo->applyConfig(config()); - } - - void ChangeRun(int64_t run_number) { - } - - void Process(int64_t run_number, uint64_t event_number) { - auto output = m_algo->execute(m_rc_particles_input(), m_rc_electrons_input()); - m_out_reco_particles() = std::move(output); - } + void Configure() { + m_algo = std::make_unique(); + m_algo->init(logger()); + m_algo->applyConfig(config()); + } + + void ChangeRun(int64_t run_number) {} + + void Process(int64_t run_number, uint64_t event_number) { + auto output = m_algo->execute(m_rc_particles_input(), m_rc_electrons_input()); + m_out_reco_particles() = std::move(output); + } }; -} // eicrecon +} // namespace eicrecon diff --git a/src/global/reco/ScatteredElectronsTruth_factory.h b/src/global/reco/ScatteredElectronsTruth_factory.h index 3da9040f83..88dac5fee4 100644 --- a/src/global/reco/ScatteredElectronsTruth_factory.h +++ b/src/global/reco/ScatteredElectronsTruth_factory.h @@ -15,38 +15,36 @@ namespace eicrecon { -class ScatteredElectronsTruth_factory : - public JOmniFactory { +class ScatteredElectronsTruth_factory : public JOmniFactory { public: - using AlgoT = eicrecon::ScatteredElectronsTruth; + using AlgoT = eicrecon::ScatteredElectronsTruth; + private: - std::unique_ptr m_algo; + std::unique_ptr m_algo; - PodioInput m_mc_particles_input {this}; - PodioInput m_rc_particles_input {this}; - PodioInput m_rc_particles_assoc_input {this}; + PodioInput m_mc_particles_input{this}; + PodioInput m_rc_particles_input{this}; + PodioInput m_rc_particles_assoc_input{this}; - // Declare outputs - PodioOutput m_out_reco_particles {this}; + // Declare outputs + PodioOutput m_out_reco_particles{this}; - Service m_algorithmsInit {this}; + Service m_algorithmsInit{this}; public: - void Configure() { - m_algo = std::make_unique(GetPrefix()); - m_algo->level(static_cast(logger()->level())); - m_algo->init(); - } - - void ChangeRun(int64_t run_number) { - } - - void Process(int64_t run_number, uint64_t event_number) { - m_algo->process({m_mc_particles_input(), m_rc_particles_input(), m_rc_particles_assoc_input()}, - {m_out_reco_particles().get()}); - - } + void Configure() { + m_algo = std::make_unique(GetPrefix()); + m_algo->level(static_cast(logger()->level())); + m_algo->init(); + } + + void ChangeRun(int64_t run_number) {} + + void Process(int64_t run_number, uint64_t event_number) { + m_algo->process({m_mc_particles_input(), m_rc_particles_input(), m_rc_particles_assoc_input()}, + {m_out_reco_particles().get()}); + } }; -} // eicrecon +} // namespace eicrecon diff --git a/src/global/reco/reco.cc b/src/global/reco/reco.cc index 5a3c27b59c..15b48fb521 100644 --- a/src/global/reco/reco.cc +++ b/src/global/reco/reco.cc @@ -31,224 +31,128 @@ // extern "C" { -void InitPlugin(JApplication *app) { - InitJANAPlugin(app); +void InitPlugin(JApplication* app) { + InitJANAPlugin(app); - using namespace eicrecon; + using namespace eicrecon; - app->Add(new JOmniFactoryGeneratorT( - "GeneratedParticles", - {"MCParticles"}, - {"GeneratedParticles"}, - app - )); + app->Add(new JOmniFactoryGeneratorT( + "GeneratedParticles", {"MCParticles"}, {"GeneratedParticles"}, app)); - app->Add(new JOmniFactoryGeneratorT>( - "EcalClusters", - { + app->Add(new JOmniFactoryGeneratorT>( + "EcalClusters", + { "EcalEndcapNClusters", "EcalBarrelScFiClusters", "EcalEndcapPClusters", - }, - {"EcalClusters"}, - app)); + }, + {"EcalClusters"}, app)); - app->Add(new JOmniFactoryGeneratorT>( - "EcalClusterAssociations", - { + app->Add(new JOmniFactoryGeneratorT< + CollectionCollector_factory>( + "EcalClusterAssociations", + { "EcalEndcapNClusterAssociations", "EcalBarrelScFiClusterAssociations", "EcalEndcapPClusterAssociations", - }, - {"EcalClusterAssociations"}, - app)); + }, + {"EcalClusterAssociations"}, app)); - app->Add(new JOmniFactoryGeneratorT( - "ReconstructedParticlesWithAssoc", - { + app->Add(new JOmniFactoryGeneratorT( + "ReconstructedParticlesWithAssoc", + { "MCParticles", "ReconstructedChargedParticles", "ReconstructedChargedParticleAssociations", "EcalClusters", "EcalClusterAssociations", - }, - { "ReconstructedParticles", // edm4eic::ReconstructedParticle + }, + { + "ReconstructedParticles", // edm4eic::ReconstructedParticle "ReconstructedParticleAssociations" // edm4eic::MCRecoParticleAssociation - }, - app - )); - - - app->Add(new JOmniFactoryGeneratorT>( - "InclusiveKinematicsElectron", - { - "MCParticles", - "ReconstructedChargedParticles", - "ReconstructedChargedParticleAssociations" - }, - { - "InclusiveKinematicsElectron" - }, - app - )); - - app->Add(new JOmniFactoryGeneratorT( - "InclusiveKinematicsTruth", - { - "MCParticles" - }, - { - "InclusiveKinematicsTruth" - }, - app - )); - - app->Add(new JOmniFactoryGeneratorT>( - "InclusiveKinematicsJB", - { - "MCParticles", - "ReconstructedChargedParticles", - "ReconstructedChargedParticleAssociations" - }, - { - "InclusiveKinematicsJB" - }, - app - )); - - app->Add(new JOmniFactoryGeneratorT>( - "InclusiveKinematicsDA", - { - "MCParticles", - "ReconstructedChargedParticles", - "ReconstructedChargedParticleAssociations" - }, - { - "InclusiveKinematicsDA" - }, - app - )); - - app->Add(new JOmniFactoryGeneratorT>( - "InclusiveKinematicseSigma", - { - "MCParticles", - "ReconstructedChargedParticles", - "ReconstructedChargedParticleAssociations" - }, - { - "InclusiveKinematicseSigma" - }, - app - )); - - app->Add(new JOmniFactoryGeneratorT>( - "InclusiveKinematicsSigma", - { - "MCParticles", - "ReconstructedChargedParticles", - "ReconstructedChargedParticleAssociations" - }, - { - "InclusiveKinematicsSigma" - }, - app - )); - - app->Add(new JOmniFactoryGeneratorT( - "ReconstructedElectrons", - {"ReconstructedParticles"}, - {"ReconstructedElectrons"}, - {}, - app - )); - - app->Add(new JOmniFactoryGeneratorT( - "ReconstructedElectronsForDIS", - {"ReconstructedParticles"}, - {"ReconstructedElectronsForDIS"}, - { + }, + app)); + + app->Add(new JOmniFactoryGeneratorT< + InclusiveKinematicsReconstructed_factory>( + "InclusiveKinematicsElectron", + {"MCParticles", "ReconstructedChargedParticles", "ReconstructedChargedParticleAssociations"}, + {"InclusiveKinematicsElectron"}, app)); + + app->Add(new JOmniFactoryGeneratorT( + "InclusiveKinematicsTruth", {"MCParticles"}, {"InclusiveKinematicsTruth"}, app)); + + app->Add( + new JOmniFactoryGeneratorT>( + "InclusiveKinematicsJB", + {"MCParticles", "ReconstructedChargedParticles", + "ReconstructedChargedParticleAssociations"}, + {"InclusiveKinematicsJB"}, app)); + + app->Add( + new JOmniFactoryGeneratorT>( + "InclusiveKinematicsDA", + {"MCParticles", "ReconstructedChargedParticles", + "ReconstructedChargedParticleAssociations"}, + {"InclusiveKinematicsDA"}, app)); + + app->Add(new JOmniFactoryGeneratorT< + InclusiveKinematicsReconstructed_factory>( + "InclusiveKinematicseSigma", + {"MCParticles", "ReconstructedChargedParticles", "ReconstructedChargedParticleAssociations"}, + {"InclusiveKinematicseSigma"}, app)); + + app->Add(new JOmniFactoryGeneratorT< + InclusiveKinematicsReconstructed_factory>( + "InclusiveKinematicsSigma", + {"MCParticles", "ReconstructedChargedParticles", "ReconstructedChargedParticleAssociations"}, + {"InclusiveKinematicsSigma"}, app)); + + app->Add(new JOmniFactoryGeneratorT( + "ReconstructedElectrons", {"ReconstructedParticles"}, {"ReconstructedElectrons"}, {}, app)); + + app->Add(new JOmniFactoryGeneratorT( + "ReconstructedElectronsForDIS", {"ReconstructedParticles"}, {"ReconstructedElectronsForDIS"}, + { .min_energy_over_momentum = 0.7, // GeV .max_energy_over_momentum = 1.3 // GeV - }, - app - )); - - app->Add(new JOmniFactoryGeneratorT>( - "GeneratedJets", - {"GeneratedParticles"}, - {"GeneratedJets"}, - {}, - app - )); - - app->Add(new JOmniFactoryGeneratorT>( - "ReconstructedJets", - {"ReconstructedParticles"}, - {"ReconstructedJets"}, - {}, - app - )); - - app->Add(new JOmniFactoryGeneratorT( - "GeneratedChargedParticles", - {"GeneratedParticles"}, - {"GeneratedChargedParticles"}, - app - )); - - app->Add(new JOmniFactoryGeneratorT>( - "GeneratedChargedJets", - {"GeneratedChargedParticles"}, - {"GeneratedChargedJets"}, - {}, - app - )); - - app->Add(new JOmniFactoryGeneratorT>( - "ReconstructedChargedJets", - {"ReconstructedChargedParticles"}, - {"ReconstructedChargedJets"}, - {}, - app - )); - - app->Add(new JOmniFactoryGeneratorT( - "ScatteredElectronsTruth", - { - "MCParticles", - "ReconstructedChargedParticles", - "ReconstructedChargedParticleAssociations" - }, - { - "ScatteredElectronsTruth" - }, - app - )); - - app->Add(new JOmniFactoryGeneratorT( - "ScatteredElectronsEMinusPz", - { - "ReconstructedChargedParticles", - "ReconstructedElectronsForDIS" - }, - { - "ScatteredElectronsEMinusPz" - }, - { - .minEMinusPz = 0, // GeV + }, + app)); + + app->Add(new JOmniFactoryGeneratorT>( + "GeneratedJets", {"GeneratedParticles"}, {"GeneratedJets"}, {}, app)); + + app->Add(new JOmniFactoryGeneratorT>( + "ReconstructedJets", {"ReconstructedParticles"}, {"ReconstructedJets"}, {}, app)); + + app->Add(new JOmniFactoryGeneratorT( + "GeneratedChargedParticles", {"GeneratedParticles"}, {"GeneratedChargedParticles"}, app)); + + app->Add(new JOmniFactoryGeneratorT>( + "GeneratedChargedJets", {"GeneratedChargedParticles"}, {"GeneratedChargedJets"}, {}, app)); + + app->Add(new JOmniFactoryGeneratorT>( + "ReconstructedChargedJets", {"ReconstructedChargedParticles"}, {"ReconstructedChargedJets"}, + {}, app)); + + app->Add(new JOmniFactoryGeneratorT( + "ScatteredElectronsTruth", + {"MCParticles", "ReconstructedChargedParticles", "ReconstructedChargedParticleAssociations"}, + {"ScatteredElectronsTruth"}, app)); + + app->Add(new JOmniFactoryGeneratorT( + "ScatteredElectronsEMinusPz", + {"ReconstructedChargedParticles", "ReconstructedElectronsForDIS"}, + {"ScatteredElectronsEMinusPz"}, + { + .minEMinusPz = 0, // GeV .maxEMinusPz = 10000000.0 // GeV - }, - app - )); - - app->Add(new JOmniFactoryGeneratorT( - "ReconstructedBreitFrameParticles", - {"MCParticles","InclusiveKinematicsElectron","ReconstructedParticles"}, - {"ReconstructedBreitFrameParticles"}, - {}, - app - )); + }, + app)); + app->Add(new JOmniFactoryGeneratorT( + "ReconstructedBreitFrameParticles", + {"MCParticles", "InclusiveKinematicsElectron", "ReconstructedParticles"}, + {"ReconstructedBreitFrameParticles"}, {}, app)); } } // extern "C" diff --git a/src/global/tracking/CKFTracking_factory.h b/src/global/tracking/CKFTracking_factory.h index 4fe3457f2f..b6fe92dbbe 100644 --- a/src/global/tracking/CKFTracking_factory.h +++ b/src/global/tracking/CKFTracking_factory.h @@ -22,49 +22,44 @@ namespace eicrecon { -class CKFTracking_factory : - public JOmniFactory { +class CKFTracking_factory : public JOmniFactory { private: - using AlgoT = eicrecon::CKFTracking; - std::unique_ptr m_algo; + using AlgoT = eicrecon::CKFTracking; + std::unique_ptr m_algo; - PodioInput m_parameters_input {this}; - PodioInput m_measurements_input {this}; - PodioOutput m_trajectories_output {this}; - PodioOutput m_parameters_output {this}; - PodioOutput m_tracks_output {this}; - Output m_acts_trajectories_output {this}; - Output m_acts_tracks_output {this}; + PodioInput m_parameters_input{this}; + PodioInput m_measurements_input{this}; + PodioOutput m_trajectories_output{this}; + PodioOutput m_parameters_output{this}; + PodioOutput m_tracks_output{this}; + Output m_acts_trajectories_output{this}; + Output m_acts_tracks_output{this}; - ParameterRef> m_etaBins {this, "EtaBins", config().etaBins, "Eta Bins for ACTS CKF tracking reco"}; - ParameterRef> m_chi2CutOff {this, "Chi2CutOff", config().chi2CutOff, "Chi2 Cut Off for ACTS CKF tracking"}; - ParameterRef> m_numMeasurementsCutOff {this, "NumMeasurementsCutOff", config().numMeasurementsCutOff, "Number of measurements Cut Off for ACTS CKF tracking"}; + ParameterRef> m_etaBins{this, "EtaBins", config().etaBins, + "Eta Bins for ACTS CKF tracking reco"}; + ParameterRef> m_chi2CutOff{this, "Chi2CutOff", config().chi2CutOff, + "Chi2 Cut Off for ACTS CKF tracking"}; + ParameterRef> m_numMeasurementsCutOff{ + this, "NumMeasurementsCutOff", config().numMeasurementsCutOff, + "Number of measurements Cut Off for ACTS CKF tracking"}; - Service m_ACTSGeoSvc {this}; + Service m_ACTSGeoSvc{this}; public: - void Configure() { - m_algo = std::make_unique(); - m_algo->applyConfig(config()); - m_algo->init(m_ACTSGeoSvc().actsGeoProvider(), logger()); - } + void Configure() { + m_algo = std::make_unique(); + m_algo->applyConfig(config()); + m_algo->init(m_ACTSGeoSvc().actsGeoProvider(), logger()); + } - void ChangeRun(int64_t run_number) { - } + void ChangeRun(int64_t run_number) {} - void Process(int64_t run_number, uint64_t event_number) { - std::tie( - m_trajectories_output(), - m_parameters_output(), - m_tracks_output(), - m_acts_trajectories_output(), - m_acts_tracks_output() - ) = m_algo->process( - *m_measurements_input(), - *m_parameters_input() - ); - } + void Process(int64_t run_number, uint64_t event_number) { + std::tie(m_trajectories_output(), m_parameters_output(), m_tracks_output(), + m_acts_trajectories_output(), m_acts_tracks_output()) = + m_algo->process(*m_measurements_input(), *m_parameters_input()); + } }; -} // eicrecon +} // namespace eicrecon diff --git a/src/global/tracking/IterativeVertexFinder_factory.h b/src/global/tracking/IterativeVertexFinder_factory.h index 7ab8450556..f14d27caa8 100644 --- a/src/global/tracking/IterativeVertexFinder_factory.h +++ b/src/global/tracking/IterativeVertexFinder_factory.h @@ -18,37 +18,36 @@ namespace eicrecon { -class IterativeVertexFinder_factory : - public JOmniFactory { +class IterativeVertexFinder_factory + : public JOmniFactory { private: - using AlgoT = eicrecon::IterativeVertexFinder; - std::unique_ptr m_algo; + using AlgoT = eicrecon::IterativeVertexFinder; + std::unique_ptr m_algo; - Input m_acts_trajectories_input {this}; - PodioOutput m_vertices_output {this}; + Input m_acts_trajectories_input{this}; + PodioOutput m_vertices_output{this}; - ParameterRef m_maxVertices {this, "maxVertices", config().maxVertices, - "Maximum num vertices that can be found"}; - ParameterRef m_reassignTracksAfterFirstFit {this, "reassignTracksAfterFirstFit", - config().reassignTracksAfterFirstFit, - "Whether or not to reassign tracks after first fit"}; + ParameterRef m_maxVertices{this, "maxVertices", config().maxVertices, + "Maximum num vertices that can be found"}; + ParameterRef m_reassignTracksAfterFirstFit{ + this, "reassignTracksAfterFirstFit", config().reassignTracksAfterFirstFit, + "Whether or not to reassign tracks after first fit"}; - Service m_ACTSGeoSvc {this}; + Service m_ACTSGeoSvc{this}; public: - void Configure() { - m_algo = std::make_unique(); - m_algo->applyConfig(config()); - m_algo->init(m_ACTSGeoSvc().actsGeoProvider(), logger()); - } - - void ChangeRun(int64_t run_number) { - } - - void Process(int64_t run_number, uint64_t event_number) { - m_vertices_output() = m_algo->produce(m_acts_trajectories_input()); - } + void Configure() { + m_algo = std::make_unique(); + m_algo->applyConfig(config()); + m_algo->init(m_ACTSGeoSvc().actsGeoProvider(), logger()); + } + + void ChangeRun(int64_t run_number) {} + + void Process(int64_t run_number, uint64_t event_number) { + m_vertices_output() = m_algo->produce(m_acts_trajectories_input()); + } }; -} // eicrecon +} // namespace eicrecon diff --git a/src/global/tracking/TrackParamTruthInit_factory.h b/src/global/tracking/TrackParamTruthInit_factory.h index eb7b4e2d60..0bc4538926 100644 --- a/src/global/tracking/TrackParamTruthInit_factory.h +++ b/src/global/tracking/TrackParamTruthInit_factory.h @@ -19,39 +19,48 @@ namespace eicrecon { -class TrackParamTruthInit_factory : - public JOmniFactory { +class TrackParamTruthInit_factory + : public JOmniFactory { private: - using AlgoT = eicrecon::TrackParamTruthInit; - std::unique_ptr m_algo; + using AlgoT = eicrecon::TrackParamTruthInit; + std::unique_ptr m_algo; - PodioInput m_particles_input {this}; - PodioOutput m_parameters_output {this}; + PodioInput m_particles_input{this}; + PodioOutput m_parameters_output{this}; - ParameterRef m_maxVertexX {this, "MaxVertexX", config().maxVertexX , "Maximum abs(vertex x) for truth tracks turned into seed"}; - ParameterRef m_maxVertexY {this, "MaxVertexY", config().maxVertexY , "Maximum abs(vertex y) for truth tracks turned into seed"}; - ParameterRef m_maxVertexZ {this, "MaxVertexZ", config().maxVertexZ , "Maximum abs(vertex z) for truth tracks turned into seed"}; - ParameterRef m_minMomentum {this, "MinMomentum", config().minMomentum , "Minimum momentum for truth tracks turned into seed"}; - ParameterRef m_maxEtaForward {this, "MaxEtaForward", config().maxEtaForward , "Maximum forward abs(eta) for truth tracks turned into seed"}; - ParameterRef m_maxEtaBackward {this, "MaxEtaBackward", config().maxEtaBackward , "Maximum backward abs(eta) for truth tracks turned into seed"}; - ParameterRef m_momentumSmear {this, "MomentumSmear", config().momentumSmear, "Momentum magnitude fraction to use as width of gaussian smearing"}; + ParameterRef m_maxVertexX{this, "MaxVertexX", config().maxVertexX, + "Maximum abs(vertex x) for truth tracks turned into seed"}; + ParameterRef m_maxVertexY{this, "MaxVertexY", config().maxVertexY, + "Maximum abs(vertex y) for truth tracks turned into seed"}; + ParameterRef m_maxVertexZ{this, "MaxVertexZ", config().maxVertexZ, + "Maximum abs(vertex z) for truth tracks turned into seed"}; + ParameterRef m_minMomentum{this, "MinMomentum", config().minMomentum, + "Minimum momentum for truth tracks turned into seed"}; + ParameterRef m_maxEtaForward{ + this, "MaxEtaForward", config().maxEtaForward, + "Maximum forward abs(eta) for truth tracks turned into seed"}; + ParameterRef m_maxEtaBackward{ + this, "MaxEtaBackward", config().maxEtaBackward, + "Maximum backward abs(eta) for truth tracks turned into seed"}; + ParameterRef m_momentumSmear{ + this, "MomentumSmear", config().momentumSmear, + "Momentum magnitude fraction to use as width of gaussian smearing"}; - Service m_ACTSGeoSvc {this}; + Service m_ACTSGeoSvc{this}; public: - void Configure() { - m_algo = std::make_unique(); - m_algo->applyConfig(config()); - m_algo->init(m_ACTSGeoSvc().actsGeoProvider(), logger()); - } - - void ChangeRun(int64_t run_number) { - } - - void Process(int64_t run_number, uint64_t event_number) { - m_parameters_output() = m_algo->produce(m_particles_input()); - } + void Configure() { + m_algo = std::make_unique(); + m_algo->applyConfig(config()); + m_algo->init(m_ACTSGeoSvc().actsGeoProvider(), logger()); + } + + void ChangeRun(int64_t run_number) {} + + void Process(int64_t run_number, uint64_t event_number) { + m_parameters_output() = m_algo->produce(m_particles_input()); + } }; -} // eicrecon +} // namespace eicrecon diff --git a/src/global/tracking/TrackProjector_factory.h b/src/global/tracking/TrackProjector_factory.h index df40444054..5a9479ca67 100644 --- a/src/global/tracking/TrackProjector_factory.h +++ b/src/global/tracking/TrackProjector_factory.h @@ -17,30 +17,28 @@ namespace eicrecon { -class TrackProjector_factory : - public JOmniFactory { +class TrackProjector_factory : public JOmniFactory { private: - using AlgoT = eicrecon::TrackProjector; - std::unique_ptr m_algo; + using AlgoT = eicrecon::TrackProjector; + std::unique_ptr m_algo; - Input m_acts_trajectories_input {this}; - PodioOutput m_segments_output {this}; + Input m_acts_trajectories_input{this}; + PodioOutput m_segments_output{this}; - Service m_ACTSGeoSvc {this}; + Service m_ACTSGeoSvc{this}; public: - void Configure() { - m_algo = std::make_unique(); - m_algo->init(m_ACTSGeoSvc().actsGeoProvider(), logger()); - } + void Configure() { + m_algo = std::make_unique(); + m_algo->init(m_ACTSGeoSvc().actsGeoProvider(), logger()); + } - void ChangeRun(int64_t run_number) { - } + void ChangeRun(int64_t run_number) {} - void Process(int64_t run_number, uint64_t event_number) { - m_segments_output() = m_algo->execute(m_acts_trajectories_input()); - } + void Process(int64_t run_number, uint64_t event_number) { + m_segments_output() = m_algo->execute(m_acts_trajectories_input()); + } }; -} // eicrecon +} // namespace eicrecon diff --git a/src/global/tracking/TrackPropagation_factory.h b/src/global/tracking/TrackPropagation_factory.h index 697e127193..707c358053 100644 --- a/src/global/tracking/TrackPropagation_factory.h +++ b/src/global/tracking/TrackPropagation_factory.h @@ -21,36 +21,33 @@ namespace eicrecon { -class TrackPropagation_factory : - public JOmniFactory { +class TrackPropagation_factory + : public JOmniFactory { private: - using AlgoT = eicrecon::TrackPropagation; - std::unique_ptr m_algo; + using AlgoT = eicrecon::TrackPropagation; + std::unique_ptr m_algo; - Input m_acts_trajectories_input {this}; - Input m_acts_tracks_input {this}; - PodioOutput m_track_segments_output {this}; + Input m_acts_trajectories_input{this}; + Input m_acts_tracks_input{this}; + PodioOutput m_track_segments_output{this}; - Service m_GeoSvc {this}; - Service m_ACTSGeoSvc {this}; + Service m_GeoSvc{this}; + Service m_ACTSGeoSvc{this}; public: - void Configure() { - m_algo = std::make_unique(); - m_algo->applyConfig(config()); - m_algo->init(m_GeoSvc().detector(), m_ACTSGeoSvc().actsGeoProvider(), logger()); - } - - void ChangeRun(int64_t run_number) { - } - - void Process(int64_t run_number, uint64_t event_number) { - m_algo->process( - {m_acts_trajectories_input(), m_acts_tracks_input()}, - {m_track_segments_output().get()} - ); - } + void Configure() { + m_algo = std::make_unique(); + m_algo->applyConfig(config()); + m_algo->init(m_GeoSvc().detector(), m_ACTSGeoSvc().actsGeoProvider(), logger()); + } + + void ChangeRun(int64_t run_number) {} + + void Process(int64_t run_number, uint64_t event_number) { + m_algo->process({m_acts_trajectories_input(), m_acts_tracks_input()}, + {m_track_segments_output().get()}); + } }; -} // eicrecon +} // namespace eicrecon diff --git a/src/global/tracking/TrackSeeding_factory.h b/src/global/tracking/TrackSeeding_factory.h index 181e36cdba..bd9f295989 100644 --- a/src/global/tracking/TrackSeeding_factory.h +++ b/src/global/tracking/TrackSeeding_factory.h @@ -18,60 +18,99 @@ namespace eicrecon { -class TrackSeeding_factory : - public JOmniFactory { +class TrackSeeding_factory + : public JOmniFactory { private: - using AlgoT = eicrecon::TrackSeeding; - std::unique_ptr m_algo; + using AlgoT = eicrecon::TrackSeeding; + std::unique_ptr m_algo; - PodioInput m_hits_input {this}; - PodioOutput m_parameters_output {this}; + PodioInput m_hits_input{this}; + PodioOutput m_parameters_output{this}; + ParameterRef m_rMax{this, "rMax", config().rMax, + "max measurement radius for Acts::OrthogonalSeedFinder"}; + ParameterRef m_rMin{this, "rMin", config().rMin, + "min measurement radius for Acts::OrthogonalSeedFinder"}; + ParameterRef m_deltaRMinTopSP{this, "deltaRMinTopSP", config().deltaRMinTopSP, + "min distance in r between middle and top space point in " + "one seed for Acts::OrthogonalSeedFinder"}; + ParameterRef m_deltaRMaxTopSP{this, "deltaRMaxTopSP", config().deltaRMaxTopSP, + "max distance in r between middle and top space point in " + "one seed for Acts::OrthogonalSeedFinder"}; + ParameterRef m_deltaRMinBottomSP{this, "deltaRMinBottomSP", config().deltaRMinBottomSP, + "min distance in r between bottom and middle space point " + "in one seed for Acts::OrthogonalSeedFinder"}; + ParameterRef m_deltaRMaxBottomSP{this, "deltaRMaxBottomSP", config().deltaRMaxBottomSP, + "max distance in r between bottom and middle space point " + "in one seed for Acts::OrthogonalSeedFinder"}; + ParameterRef m_collisionRegionMin{ + this, "collisionRegionMin", config().collisionRegionMin, + "min location in z for collision region for Acts::OrthogonalSeedFinder"}; + ParameterRef m_collisionRegionMax{ + this, "collisionRegionMax", config().collisionRegionMax, + "max location in z for collision region for Acts::OrthogonalSeedFinder"}; + ParameterRef m_zMax{this, "zMax", config().zMax, + "Max z location for measurements for Acts::OrthogonalSeedFinder"}; + ParameterRef m_zMin{this, "zMin", config().zMin, + "Min z location for measurements for Acts::OrthogonalSeedFinder"}; + ParameterRef m_maxSeedsPerSpM{this, "maxSeedsPerSpM", config().maxSeedsPerSpM, + "Maximum number of seeds one space point can be the " + "middle of for Acts::OrthogonalSeedFinder"}; + ParameterRef m_cotThetaMax{this, "cotThetaMax", config().cotThetaMax, + "cot of maximum theta angle for Acts::OrthogonalSeedFinder"}; + ParameterRef m_sigmaScattering{ + this, "sigmaScattering", config().sigmaScattering, + "number of sigmas of scattering angle to consider for Acts::OrthogonalSeedFinder"}; + ParameterRef m_radLengthPerSeed{ + this, "radLengthPerSeed", config().radLengthPerSeed, + "Approximate number of radiation lengths one seed traverses for Acts::OrthogonalSeedFinder"}; + ParameterRef m_minPt{this, "minPt", config().minPt, + "Minimum pT to search for for Acts::OrthogonalSeedFinder"}; + ParameterRef m_bFieldInZ{ + this, "bFieldInZ", config().bFieldInZ, + "Value of B Field to use in kiloTesla for Acts::OrthogonalSeedFinder"}; + ParameterRef m_beamPosX{this, "beamPosX", config().beamPosX, + "Beam position in x for Acts::OrthogonalSeedFinder"}; + ParameterRef m_beamPosY{this, "beamPosY", config().beamPosY, + "Beam position in y for Acts::OrthogonalSeedFinder"}; + ParameterRef m_impactMax{ + this, "impactMax", config().impactMax, + "maximum impact parameter allowed for seeds for Acts::OrthogonalSeedFinder. rMin should be " + "larger than impactMax."}; + ParameterRef m_rMinMiddle{ + this, "rMinMiddle", config().rMinMiddle, + "min radius for middle space point for Acts::OrthogonalSeedFinder"}; + ParameterRef m_rMaxMiddle{ + this, "rMaxMiddle", config().rMaxMiddle, + "max radius for middle space point for Acts::OrthogonalSeedFinder"}; + ParameterRef m_locaError{this, "loc_a_Error", config().locaError, + "Error on Loc a for Acts::OrthogonalSeedFinder"}; + ParameterRef m_locbError{this, "loc_b_Error", config().locbError, + "Error on Loc b for Acts::OrthogonalSeedFinder"}; + ParameterRef m_phiError{this, "phi_Error", config().phiError, + "Error on phi for Acts::OrthogonalSeedFinder"}; + ParameterRef m_thetaError{this, "theta_Error", config().thetaError, + "Error on theta for Acts::OrthogonalSeedFinder"}; + ParameterRef m_qOverPError{this, "qOverP_Error", config().qOverPError, + "Error on q/p for Acts::OrthogonalSeedFinder"}; + ParameterRef m_timeError{this, "time_Error", config().timeError, + "Error on time for Acts::OrthogonalSeedFinder"}; - ParameterRef m_rMax {this, "rMax", config().rMax, "max measurement radius for Acts::OrthogonalSeedFinder"}; - ParameterRef m_rMin {this, "rMin", config().rMin, "min measurement radius for Acts::OrthogonalSeedFinder"}; - ParameterRef m_deltaRMinTopSP {this, "deltaRMinTopSP", config().deltaRMinTopSP, "min distance in r between middle and top space point in one seed for Acts::OrthogonalSeedFinder"}; - ParameterRef m_deltaRMaxTopSP {this, "deltaRMaxTopSP", config().deltaRMaxTopSP, "max distance in r between middle and top space point in one seed for Acts::OrthogonalSeedFinder"}; - ParameterRef m_deltaRMinBottomSP {this, "deltaRMinBottomSP", config().deltaRMinBottomSP, "min distance in r between bottom and middle space point in one seed for Acts::OrthogonalSeedFinder"}; - ParameterRef m_deltaRMaxBottomSP {this, "deltaRMaxBottomSP", config().deltaRMaxBottomSP, "max distance in r between bottom and middle space point in one seed for Acts::OrthogonalSeedFinder"}; - ParameterRef m_collisionRegionMin {this, "collisionRegionMin", config().collisionRegionMin, "min location in z for collision region for Acts::OrthogonalSeedFinder"}; - ParameterRef m_collisionRegionMax {this, "collisionRegionMax", config().collisionRegionMax, "max location in z for collision region for Acts::OrthogonalSeedFinder"}; - ParameterRef m_zMax {this, "zMax", config().zMax, "Max z location for measurements for Acts::OrthogonalSeedFinder"}; - ParameterRef m_zMin {this, "zMin", config().zMin, "Min z location for measurements for Acts::OrthogonalSeedFinder"}; - ParameterRef m_maxSeedsPerSpM {this, "maxSeedsPerSpM", config().maxSeedsPerSpM, "Maximum number of seeds one space point can be the middle of for Acts::OrthogonalSeedFinder"}; - ParameterRef m_cotThetaMax {this, "cotThetaMax", config().cotThetaMax, "cot of maximum theta angle for Acts::OrthogonalSeedFinder"}; - ParameterRef m_sigmaScattering {this, "sigmaScattering", config().sigmaScattering, "number of sigmas of scattering angle to consider for Acts::OrthogonalSeedFinder"}; - ParameterRef m_radLengthPerSeed {this, "radLengthPerSeed", config().radLengthPerSeed, "Approximate number of radiation lengths one seed traverses for Acts::OrthogonalSeedFinder"}; - ParameterRef m_minPt {this, "minPt", config().minPt, "Minimum pT to search for for Acts::OrthogonalSeedFinder"}; - ParameterRef m_bFieldInZ {this, "bFieldInZ", config().bFieldInZ, "Value of B Field to use in kiloTesla for Acts::OrthogonalSeedFinder"}; - ParameterRef m_beamPosX {this, "beamPosX", config().beamPosX, "Beam position in x for Acts::OrthogonalSeedFinder"}; - ParameterRef m_beamPosY {this, "beamPosY", config().beamPosY, "Beam position in y for Acts::OrthogonalSeedFinder"}; - ParameterRef m_impactMax {this, "impactMax", config().impactMax, "maximum impact parameter allowed for seeds for Acts::OrthogonalSeedFinder. rMin should be larger than impactMax."}; - ParameterRef m_rMinMiddle {this, "rMinMiddle", config().rMinMiddle, "min radius for middle space point for Acts::OrthogonalSeedFinder"}; - ParameterRef m_rMaxMiddle {this, "rMaxMiddle", config().rMaxMiddle, "max radius for middle space point for Acts::OrthogonalSeedFinder"}; - ParameterRef m_locaError {this, "loc_a_Error", config().locaError, "Error on Loc a for Acts::OrthogonalSeedFinder"}; - ParameterRef m_locbError {this, "loc_b_Error", config().locbError, "Error on Loc b for Acts::OrthogonalSeedFinder"}; - ParameterRef m_phiError {this, "phi_Error", config().phiError, "Error on phi for Acts::OrthogonalSeedFinder"}; - ParameterRef m_thetaError {this, "theta_Error", config().thetaError, "Error on theta for Acts::OrthogonalSeedFinder"}; - ParameterRef m_qOverPError {this, "qOverP_Error", config().qOverPError, "Error on q/p for Acts::OrthogonalSeedFinder"}; - ParameterRef m_timeError {this, "time_Error", config().timeError, "Error on time for Acts::OrthogonalSeedFinder"}; - - Service m_ACTSGeoSvc {this}; + Service m_ACTSGeoSvc{this}; public: - void Configure() { - m_algo = std::make_unique(); - m_algo->applyConfig(config()); - m_algo->init(m_ACTSGeoSvc().actsGeoProvider(), logger()); - } + void Configure() { + m_algo = std::make_unique(); + m_algo->applyConfig(config()); + m_algo->init(m_ACTSGeoSvc().actsGeoProvider(), logger()); + } - void ChangeRun(int64_t run_number) { - } + void ChangeRun(int64_t run_number) {} - void Process(int64_t run_number, uint64_t event_number) { - m_parameters_output() = m_algo->produce(*m_hits_input()); - } + void Process(int64_t run_number, uint64_t event_number) { + m_parameters_output() = m_algo->produce(*m_hits_input()); + } }; -} // eicrecon +} // namespace eicrecon diff --git a/src/global/tracking/TrackerMeasurementFromHits_factory.h b/src/global/tracking/TrackerMeasurementFromHits_factory.h index c55af36761..0d9cbc697b 100644 --- a/src/global/tracking/TrackerMeasurementFromHits_factory.h +++ b/src/global/tracking/TrackerMeasurementFromHits_factory.h @@ -20,31 +20,30 @@ namespace eicrecon { -class TrackerMeasurementFromHits_factory : - public JOmniFactory { +class TrackerMeasurementFromHits_factory : public JOmniFactory { private: - using AlgoT = eicrecon::TrackerMeasurementFromHits; - std::unique_ptr m_algo; + using AlgoT = eicrecon::TrackerMeasurementFromHits; + std::unique_ptr m_algo; - PodioInput m_hits_input {this}; - PodioOutput m_measurements_output {this}; + PodioInput m_hits_input{this}; + PodioOutput m_measurements_output{this}; - Service m_DD4hepSvc {this}; - Service m_ACTSGeoSvc {this}; + Service m_DD4hepSvc{this}; + Service m_ACTSGeoSvc{this}; public: - void Configure() { - m_algo = std::make_unique(); - m_algo->init(m_DD4hepSvc().detector(), m_DD4hepSvc().converter(), m_ACTSGeoSvc().actsGeoProvider(), logger()); - } + void Configure() { + m_algo = std::make_unique(); + m_algo->init(m_DD4hepSvc().detector(), m_DD4hepSvc().converter(), + m_ACTSGeoSvc().actsGeoProvider(), logger()); + } - void ChangeRun(int64_t run_number) { - } + void ChangeRun(int64_t run_number) {} - void Process(int64_t run_number, uint64_t event_number) { - m_measurements_output() = m_algo->produce(*m_hits_input()); - } + void Process(int64_t run_number, uint64_t event_number) { + m_measurements_output() = m_algo->produce(*m_hits_input()); + } }; -} // eicrecon +} // namespace eicrecon diff --git a/src/global/tracking/tracking.cc b/src/global/tracking/tracking.cc index 63ea93a72b..7ace0993a9 100644 --- a/src/global/tracking/tracking.cc +++ b/src/global/tracking/tracking.cc @@ -28,149 +28,117 @@ // extern "C" { -void InitPlugin(JApplication *app) { - InitJANAPlugin(app); - - using namespace eicrecon; - - app->Add(new JOmniFactoryGeneratorT( - "InitTrackParams", - {"MCParticles"}, - {"InitTrackParams"}, - {}, - app - )); - - // Possible collections from arches, brycecanyon and craterlake configurations - std::vector> possible_collections = { - {"SiBarrelHits", "SiBarrelTrackerRecHits"}, - {"VertexBarrelHits", "SiBarrelVertexRecHits"}, - {"TrackerEndcapHits", "SiEndcapTrackerRecHits"}, - {"TOFBarrelHits", "TOFBarrelRecHit"}, - {"TOFEndcapHits", "TOFEndcapRecHits"}, - {"MPGDBarrelHits", "MPGDBarrelRecHits"}, - {"MPDGDIRCHits", "MPDGDIRCRecHits"}, - {"OuterMPGDBarrelHits", "OuterMPGDBarrelRecHits"}, - {"BackwardMPGDEndcapHits", "BackwardMPGDEndcapRecHits"}, - {"ForwardMPGDEndcapHits", "ForwardMPGDEndcapRecHits"}, - {"B0TrackerHits", "B0TrackerRecHits"} - }; - - // Filter out collections that are not present in the current configuration - std::vector input_collections; - auto readouts = app->GetService()->detector()->readouts(); - for (const auto& [hit_collection, rec_collection] : possible_collections) { - if (readouts.find(hit_collection) != readouts.end()) { - // Add the collection to the list of input collections - input_collections.push_back(rec_collection); - } +void InitPlugin(JApplication* app) { + InitJANAPlugin(app); + + using namespace eicrecon; + + app->Add(new JOmniFactoryGeneratorT( + "InitTrackParams", {"MCParticles"}, {"InitTrackParams"}, {}, app)); + + // Possible collections from arches, brycecanyon and craterlake configurations + std::vector> possible_collections = { + {"SiBarrelHits", "SiBarrelTrackerRecHits"}, + {"VertexBarrelHits", "SiBarrelVertexRecHits"}, + {"TrackerEndcapHits", "SiEndcapTrackerRecHits"}, + {"TOFBarrelHits", "TOFBarrelRecHit"}, + {"TOFEndcapHits", "TOFEndcapRecHits"}, + {"MPGDBarrelHits", "MPGDBarrelRecHits"}, + {"MPDGDIRCHits", "MPDGDIRCRecHits"}, + {"OuterMPGDBarrelHits", "OuterMPGDBarrelRecHits"}, + {"BackwardMPGDEndcapHits", "BackwardMPGDEndcapRecHits"}, + {"ForwardMPGDEndcapHits", "ForwardMPGDEndcapRecHits"}, + {"B0TrackerHits", "B0TrackerRecHits"}}; + + // Filter out collections that are not present in the current configuration + std::vector input_collections; + auto readouts = app->GetService()->detector()->readouts(); + for (const auto& [hit_collection, rec_collection] : possible_collections) { + if (readouts.find(hit_collection) != readouts.end()) { + // Add the collection to the list of input collections + input_collections.push_back(rec_collection); } - - // Tracker hits collector - app->Add(new JOmniFactoryGeneratorT>( - "CentralTrackingRecHits", - input_collections, - {"CentralTrackingRecHits"}, // Output collection name - app)); - - app->Add(new JOmniFactoryGeneratorT( - "CentralTrackerMeasurements", - {"CentralTrackingRecHits"}, - {"CentralTrackerMeasurements"}, - app - )); - - app->Add(new JOmniFactoryGeneratorT( - "CentralCKFTrajectories", - { - "InitTrackParams", - "CentralTrackerMeasurements" - }, - { - "CentralCKFTrajectories", - "CentralCKFTrackParameters", - "CentralCKFTracks", - "CentralCKFActsTrajectories", - "CentralCKFActsTracks", - }, - app - )); - - app->Add(new JOmniFactoryGeneratorT( - "CentralTrackSeedingResults", - {"CentralTrackingRecHits"}, - {"CentralTrackSeedingResults"}, - {}, - app - )); - - app->Add(new JOmniFactoryGeneratorT( - "CentralCKFSeededTrajectories", - { - "CentralTrackSeedingResults", - "CentralTrackerMeasurements" - }, - { - "CentralCKFSeededTrajectories", - "CentralCKFSeededTrackParameters", - "CentralCKFSeededTracks", - "CentralCKFSeededActsTrajectories", - "CentralCKFSeededActsTracks", - }, - app - )); - - app->Add(new JOmniFactoryGeneratorT( - "CentralTrackSegments", - {"CentralCKFActsTrajectories"}, - {"CentralTrackSegments"}, - app - )); - - app->Add(new JOmniFactoryGeneratorT( - "CentralTrackVertices", - {"CentralCKFActsTrajectories"}, - {"CentralTrackVertices"}, - {}, - app - )); - - app->Add(new JOmniFactoryGeneratorT( - "CalorimeterTrackPropagator", - {"CentralCKFActsTrajectories", "CentralCKFActsTracks"}, - {"CalorimeterTrackProjections"}, - { - { - // Ecal - eicrecon::DiscSurfaceConfig{"EcalEndcapN_ID", "- EcalEndcapN_zmin", 0., "1.1*EcalEndcapN_rmax"}, - eicrecon::DiscSurfaceConfig{"EcalEndcapN_ID", "- EcalEndcapN_zmin - 50*mm", 0., "1.1*EcalEndcapN_rmax"}, - eicrecon::CylinderSurfaceConfig{"EcalBarrel_ID", "EcalBarrel_rmin", - "- 1.1*max(EcalBarrelBackward_zmax,EcalBarrelForward_zmax)", - "1.1*max(EcalBarrelBackward_zmax,EcalBarrelForward_zmax)" - }, - eicrecon::CylinderSurfaceConfig{"EcalBarrel_ID", "EcalBarrel_rmin + 50*mm", - "- 1.1*max(EcalBarrelBackward_zmax,EcalBarrelForward_zmax)", - "1.1*max(EcalBarrelBackward_zmax,EcalBarrelForward_zmax)" - }, - eicrecon::DiscSurfaceConfig{"EcalEndcapP_ID", "EcalEndcapP_zmin", 0., "1.1*EcalEndcapP_rmax"}, - eicrecon::DiscSurfaceConfig{"EcalEndcapP_ID", "EcalEndcapP_zmin + 50*mm", 0., "1.1*EcalEndcapP_rmax"}, - // Hcal - eicrecon::DiscSurfaceConfig{"HcalEndcapN_ID", "- HcalEndcapN_zmin", 0., "1.1*HcalEndcapN_rmax"}, - eicrecon::DiscSurfaceConfig{"HcalEndcapN_ID", "- HcalEndcapN_zmin - 150*mm", 0., "1.1*HcalEndcapN_rmax"}, - eicrecon::CylinderSurfaceConfig{"HcalBarrel_ID", "HcalBarrel_rmin", - "- 1.1*max(HcalBarrelBackward_zmax,HcalBarrelForward_zmax)", - "1.1*max(HcalBarrelBackward_zmax,HcalBarrelForward_zmax)" - }, - eicrecon::CylinderSurfaceConfig{"HcalBarrel_ID", "HcalBarrel_rmin + 150*mm", - "- 1.1*max(HcalBarrelBackward_zmax,HcalBarrelForward_zmax)", - "1.1*max(HcalBarrelBackward_zmax,HcalBarrelForward_zmax)" - }, - eicrecon::DiscSurfaceConfig{"LFHCAL_ID", "LFHCAL_zmin", 0., "1.1*LFHCAL_rmax"}, - eicrecon::DiscSurfaceConfig{"LFHCAL_ID", "LFHCAL_zmin + 150*mm", 0., "1.1*LFHCAL_rmax"}, - } - }, - app - )); - + } + + // Tracker hits collector + app->Add(new JOmniFactoryGeneratorT>( + "CentralTrackingRecHits", input_collections, + {"CentralTrackingRecHits"}, // Output collection name + app)); + + app->Add(new JOmniFactoryGeneratorT( + "CentralTrackerMeasurements", {"CentralTrackingRecHits"}, {"CentralTrackerMeasurements"}, + app)); + + app->Add(new JOmniFactoryGeneratorT( + "CentralCKFTrajectories", {"InitTrackParams", "CentralTrackerMeasurements"}, + { + "CentralCKFTrajectories", + "CentralCKFTrackParameters", + "CentralCKFTracks", + "CentralCKFActsTrajectories", + "CentralCKFActsTracks", + }, + app)); + + app->Add(new JOmniFactoryGeneratorT( + "CentralTrackSeedingResults", {"CentralTrackingRecHits"}, {"CentralTrackSeedingResults"}, {}, + app)); + + app->Add(new JOmniFactoryGeneratorT( + "CentralCKFSeededTrajectories", {"CentralTrackSeedingResults", "CentralTrackerMeasurements"}, + { + "CentralCKFSeededTrajectories", + "CentralCKFSeededTrackParameters", + "CentralCKFSeededTracks", + "CentralCKFSeededActsTrajectories", + "CentralCKFSeededActsTracks", + }, + app)); + + app->Add(new JOmniFactoryGeneratorT( + "CentralTrackSegments", {"CentralCKFActsTrajectories"}, {"CentralTrackSegments"}, app)); + + app->Add(new JOmniFactoryGeneratorT( + "CentralTrackVertices", {"CentralCKFActsTrajectories"}, {"CentralTrackVertices"}, {}, app)); + + app->Add(new JOmniFactoryGeneratorT( + "CalorimeterTrackPropagator", {"CentralCKFActsTrajectories", "CentralCKFActsTracks"}, + {"CalorimeterTrackProjections"}, + {{ + // Ecal + eicrecon::DiscSurfaceConfig{"EcalEndcapN_ID", "- EcalEndcapN_zmin", 0., + "1.1*EcalEndcapN_rmax"}, + eicrecon::DiscSurfaceConfig{"EcalEndcapN_ID", "- EcalEndcapN_zmin - 50*mm", 0., + "1.1*EcalEndcapN_rmax"}, + eicrecon::CylinderSurfaceConfig{ + "EcalBarrel_ID", "EcalBarrel_rmin", + "- 1.1*max(EcalBarrelBackward_zmax,EcalBarrelForward_zmax)", + "1.1*max(EcalBarrelBackward_zmax,EcalBarrelForward_zmax)"}, + eicrecon::CylinderSurfaceConfig{ + "EcalBarrel_ID", "EcalBarrel_rmin + 50*mm", + "- 1.1*max(EcalBarrelBackward_zmax,EcalBarrelForward_zmax)", + "1.1*max(EcalBarrelBackward_zmax,EcalBarrelForward_zmax)"}, + eicrecon::DiscSurfaceConfig{"EcalEndcapP_ID", "EcalEndcapP_zmin", 0., + "1.1*EcalEndcapP_rmax"}, + eicrecon::DiscSurfaceConfig{"EcalEndcapP_ID", "EcalEndcapP_zmin + 50*mm", 0., + "1.1*EcalEndcapP_rmax"}, + // Hcal + eicrecon::DiscSurfaceConfig{"HcalEndcapN_ID", "- HcalEndcapN_zmin", 0., + "1.1*HcalEndcapN_rmax"}, + eicrecon::DiscSurfaceConfig{"HcalEndcapN_ID", "- HcalEndcapN_zmin - 150*mm", 0., + "1.1*HcalEndcapN_rmax"}, + eicrecon::CylinderSurfaceConfig{ + "HcalBarrel_ID", "HcalBarrel_rmin", + "- 1.1*max(HcalBarrelBackward_zmax,HcalBarrelForward_zmax)", + "1.1*max(HcalBarrelBackward_zmax,HcalBarrelForward_zmax)"}, + eicrecon::CylinderSurfaceConfig{ + "HcalBarrel_ID", "HcalBarrel_rmin + 150*mm", + "- 1.1*max(HcalBarrelBackward_zmax,HcalBarrelForward_zmax)", + "1.1*max(HcalBarrelBackward_zmax,HcalBarrelForward_zmax)"}, + eicrecon::DiscSurfaceConfig{"LFHCAL_ID", "LFHCAL_zmin", 0., "1.1*LFHCAL_rmax"}, + eicrecon::DiscSurfaceConfig{"LFHCAL_ID", "LFHCAL_zmin + 150*mm", 0., "1.1*LFHCAL_rmax"}, + }}, + app)); } } // extern "C" diff --git a/src/services/algorithms_init/AlgorithmsInit_service.h b/src/services/algorithms_init/AlgorithmsInit_service.h index 567799ee3f..ac7a003171 100644 --- a/src/services/algorithms_init/AlgorithmsInit_service.h +++ b/src/services/algorithms_init/AlgorithmsInit_service.h @@ -3,7 +3,6 @@ #pragma once - #include #include #include @@ -19,62 +18,61 @@ /** * The AlgorithmsInit_service centralizes use of ServiceSvc */ -class AlgorithmsInit_service : public JService -{ - public: - AlgorithmsInit_service(JApplication *app) { }; - virtual ~AlgorithmsInit_service() { }; +class AlgorithmsInit_service : public JService { +public: + AlgorithmsInit_service(JApplication* app){}; + virtual ~AlgorithmsInit_service(){}; - void acquire_services(JServiceLocator *srv_locator) override { - auto& serviceSvc = algorithms::ServiceSvc::instance(); + void acquire_services(JServiceLocator* srv_locator) override { + auto& serviceSvc = algorithms::ServiceSvc::instance(); - // Get services - m_log_service = srv_locator->get(); - m_dd4hep_service = srv_locator->get(); + // Get services + m_log_service = srv_locator->get(); + m_dd4hep_service = srv_locator->get(); - // Logger for ServiceSvc - m_log = m_log_service->logger("AlgorithmsInit"); + // Logger for ServiceSvc + m_log = m_log_service->logger("AlgorithmsInit"); - // Register DD4hep_service as algorithms::GeoSvc - [[maybe_unused]] auto& geoSvc = algorithms::GeoSvc::instance(); - serviceSvc.setInit([this](auto&& g) { - this->m_log->debug("Initializing algorithms::GeoSvc"); - g.init(const_cast(this->m_dd4hep_service->detector().get())); - }); + // Register DD4hep_service as algorithms::GeoSvc + [[maybe_unused]] auto& geoSvc = algorithms::GeoSvc::instance(); + serviceSvc.setInit([this](auto&& g) { + this->m_log->debug("Initializing algorithms::GeoSvc"); + g.init(const_cast(this->m_dd4hep_service->detector().get())); + }); - // Register Log_service as algorithms::LogSvc - const algorithms::LogLevel level{ - static_cast(m_log->level())}; - serviceSvc.setInit([this,level](auto&& logger) { - this->m_log->debug("Initializing algorithms::LogSvc"); - logger.init([this](const algorithms::LogLevel l, std::string_view caller, std::string_view msg){ - static std::mutex m; - std::lock_guard lock(m); - static std::map> loggers; - if (! loggers.contains(caller)) { - this->m_log->debug("Initializing algorithms::LogSvc logger {}", caller); - loggers[caller] = this->m_log_service->logger(std::string(caller)); - } - loggers[caller]->log(static_cast(l), msg); - }); - logger.defaultLevel(level); - }); + // Register Log_service as algorithms::LogSvc + const algorithms::LogLevel level{static_cast(m_log->level())}; + serviceSvc.setInit([this, level](auto&& logger) { + this->m_log->debug("Initializing algorithms::LogSvc"); + logger.init( + [this](const algorithms::LogLevel l, std::string_view caller, std::string_view msg) { + static std::mutex m; + std::lock_guard lock(m); + static std::map> loggers; + if (!loggers.contains(caller)) { + this->m_log->debug("Initializing algorithms::LogSvc logger {}", caller); + loggers[caller] = this->m_log_service->logger(std::string(caller)); + } + loggers[caller]->log(static_cast(l), msg); + }); + logger.defaultLevel(level); + }); - // Register a random service (JANA2 does not have one) - [[maybe_unused]] auto& randomSvc = algorithms::RandomSvc::instance(); - serviceSvc.setInit([this](auto&& r) { - this->m_log->debug("Initializing algorithms::RandomSvc"); - r.setProperty("seed", static_cast(1)); - r.init(); - }); + // Register a random service (JANA2 does not have one) + [[maybe_unused]] auto& randomSvc = algorithms::RandomSvc::instance(); + serviceSvc.setInit([this](auto&& r) { + this->m_log->debug("Initializing algorithms::RandomSvc"); + r.setProperty("seed", static_cast(1)); + r.init(); + }); - // Finally, initialize the ServiceSvc - serviceSvc.init(); - } + // Finally, initialize the ServiceSvc + serviceSvc.init(); + } - private: - AlgorithmsInit_service() = default; - std::shared_ptr m_log_service; - std::shared_ptr m_dd4hep_service; - std::shared_ptr m_log; +private: + AlgorithmsInit_service() = default; + std::shared_ptr m_log_service; + std::shared_ptr m_dd4hep_service; + std::shared_ptr m_log; }; diff --git a/src/services/algorithms_init/algorithms_init.cc b/src/services/algorithms_init/algorithms_init.cc index e2863d59b7..2c4633e95f 100644 --- a/src/services/algorithms_init/algorithms_init.cc +++ b/src/services/algorithms_init/algorithms_init.cc @@ -6,10 +6,9 @@ #include "AlgorithmsInit_service.h" - extern "C" { -void InitPlugin(JApplication *app) { - InitJANAPlugin(app); - app->ProvideService(std::make_shared(app)); +void InitPlugin(JApplication* app) { + InitJANAPlugin(app); + app->ProvideService(std::make_shared(app)); } } diff --git a/src/services/geometry/acts/ACTSGeo_service.cc b/src/services/geometry/acts/ACTSGeo_service.cc index d11a62a33f..7a765e253e 100644 --- a/src/services/geometry/acts/ACTSGeo_service.cc +++ b/src/services/geometry/acts/ACTSGeo_service.cc @@ -22,7 +22,7 @@ // Virtual destructor implementation to pin vtable and typeinfo to this // translation unit -ACTSGeo_service::~ACTSGeo_service() {}; +ACTSGeo_service::~ACTSGeo_service(){}; //---------------------------------------------------------------- // detector @@ -32,98 +32,103 @@ ACTSGeo_service::~ACTSGeo_service() {}; //---------------------------------------------------------------- std::shared_ptr ACTSGeo_service::actsGeoProvider() { - try{ - std::call_once(m_init_flag, [this](){ - // Assemble everything on the first call - - if(!m_dd4hepGeo) { - throw JException("ACTSGeo_service m_dd4hepGeo==null which should never be!"); - } - - // Get material map from user parameter - std::string material_map_file; - try { - material_map_file = m_dd4hepGeo->constant("material-map"); - } catch (const std::runtime_error& e) { - material_map_file = "calibrations/materials-map.cbor"; - } - m_app->SetDefaultParameter("acts:MaterialMap", material_map_file, "JSON/CBOR material map file path"); - - // Reading the geometry may take a long time and if the JANA ticker is enabled, it will keep printing - // while no other output is coming which makes it look like something is wrong. Disable the ticker - // while parsing and loading the geometry - auto tickerEnabled = m_app->IsTickerEnabled(); - m_app->SetTicker(false); - - // Create default m_acts_provider - m_acts_provider = std::make_shared(); - - // Set ActsGeometryProvider parameters - bool objWriteIt = m_acts_provider->getObjWriteIt(); - bool plyWriteIt = m_acts_provider->getPlyWriteIt(); - m_app->SetDefaultParameter("acts:WriteObj", objWriteIt, "Write tracking geometry as obj files"); - m_app->SetDefaultParameter("acts:WritePly", plyWriteIt, "Write tracking geometry as ply files"); - m_acts_provider->setObjWriteIt(objWriteIt); - m_acts_provider->setPlyWriteIt(plyWriteIt); - - std::string outputTag = m_acts_provider->getOutputTag(); - std::string outputDir = m_acts_provider->getOutputDir(); - m_app->SetDefaultParameter("acts:OutputTag", outputTag, "Obj and ply output file tag"); - m_app->SetDefaultParameter("acts:OutputDir", outputDir, "Obj and ply output file dir"); - m_acts_provider->setOutputTag(outputTag); - m_acts_provider->setOutputDir(outputDir); - - std::array containerView = m_acts_provider->getContainerView().color; - std::array volumeView = m_acts_provider->getVolumeView().color; - std::array sensitiveView = m_acts_provider->getSensitiveView().color; - std::array passiveView = m_acts_provider->getPassiveView().color; - std::array gridView = m_acts_provider->getGridView().color; - m_app->SetDefaultParameter("acts:ContainerView", containerView, "RGB for container views"); - m_app->SetDefaultParameter("acts:VolumeView", volumeView, "RGB for volume views"); - m_app->SetDefaultParameter("acts:SensitiveView", sensitiveView, "RGB for sensitive views"); - m_app->SetDefaultParameter("acts:PassiveView", passiveView, "RGB for passive views"); - m_app->SetDefaultParameter("acts:GridView", gridView, "RGB for grid views"); - m_acts_provider->setContainerView(containerView); - m_acts_provider->setVolumeView(volumeView); - m_acts_provider->setSensitiveView(sensitiveView); - m_acts_provider->setPassiveView(passiveView); - m_acts_provider->setGridView(gridView); - - // Initialize m_acts_provider - m_acts_provider->initialize(m_dd4hepGeo, material_map_file, m_log, m_init_log); - - // Enable ticker back - m_app->SetTicker(tickerEnabled); - }); - } - catch (std::exception &ex) { - throw JException(ex.what()); - } - - return m_acts_provider; + try { + std::call_once(m_init_flag, [this]() { + // Assemble everything on the first call + + if (!m_dd4hepGeo) { + throw JException("ACTSGeo_service m_dd4hepGeo==null which should never be!"); + } + + // Get material map from user parameter + std::string material_map_file; + try { + material_map_file = m_dd4hepGeo->constant("material-map"); + } catch (const std::runtime_error& e) { + material_map_file = "calibrations/materials-map.cbor"; + } + m_app->SetDefaultParameter("acts:MaterialMap", material_map_file, + "JSON/CBOR material map file path"); + + // Reading the geometry may take a long time and if the JANA ticker is enabled, it will keep printing + // while no other output is coming which makes it look like something is wrong. Disable the ticker + // while parsing and loading the geometry + auto tickerEnabled = m_app->IsTickerEnabled(); + m_app->SetTicker(false); + + // Create default m_acts_provider + m_acts_provider = std::make_shared(); + + // Set ActsGeometryProvider parameters + bool objWriteIt = m_acts_provider->getObjWriteIt(); + bool plyWriteIt = m_acts_provider->getPlyWriteIt(); + m_app->SetDefaultParameter("acts:WriteObj", objWriteIt, + "Write tracking geometry as obj files"); + m_app->SetDefaultParameter("acts:WritePly", plyWriteIt, + "Write tracking geometry as ply files"); + m_acts_provider->setObjWriteIt(objWriteIt); + m_acts_provider->setPlyWriteIt(plyWriteIt); + + std::string outputTag = m_acts_provider->getOutputTag(); + std::string outputDir = m_acts_provider->getOutputDir(); + m_app->SetDefaultParameter("acts:OutputTag", outputTag, "Obj and ply output file tag"); + m_app->SetDefaultParameter("acts:OutputDir", outputDir, "Obj and ply output file dir"); + m_acts_provider->setOutputTag(outputTag); + m_acts_provider->setOutputDir(outputDir); + + std::array containerView = m_acts_provider->getContainerView().color; + std::array volumeView = m_acts_provider->getVolumeView().color; + std::array sensitiveView = m_acts_provider->getSensitiveView().color; + std::array passiveView = m_acts_provider->getPassiveView().color; + std::array gridView = m_acts_provider->getGridView().color; + m_app->SetDefaultParameter("acts:ContainerView", containerView, "RGB for container views"); + m_app->SetDefaultParameter("acts:VolumeView", volumeView, "RGB for volume views"); + m_app->SetDefaultParameter("acts:SensitiveView", sensitiveView, "RGB for sensitive views"); + m_app->SetDefaultParameter("acts:PassiveView", passiveView, "RGB for passive views"); + m_app->SetDefaultParameter("acts:GridView", gridView, "RGB for grid views"); + m_acts_provider->setContainerView(containerView); + m_acts_provider->setVolumeView(volumeView); + m_acts_provider->setSensitiveView(sensitiveView); + m_acts_provider->setPassiveView(passiveView); + m_acts_provider->setGridView(gridView); + + // Initialize m_acts_provider + m_acts_provider->initialize(m_dd4hepGeo, material_map_file, m_log, m_init_log); + + // Enable ticker back + m_app->SetTicker(tickerEnabled); + }); + } catch (std::exception& ex) { + throw JException(ex.what()); + } + + return m_acts_provider; } - - -void ACTSGeo_service::acquire_services(JServiceLocator * srv_locator) { - - auto log_service = srv_locator->get(); - - // ACTS general log level: - m_log = log_service->logger("acts"); - std::string log_level_str = log_service->getDefaultLevelStr(); - m_app->SetDefaultParameter("acts:LogLevel", log_level_str, "log_level: trace, debug, info, warn, error, critical, off"); - m_log->set_level(eicrecon::ParseLogLevel(log_level_str)); - m_log->info("Acts GENERAL log level is set to {} ({})", log_level_str, fmt::underlying(m_log->level())); - - // ACTS init log level (geometry conversion): - m_init_log = log_service->logger("acts_init"); - std::string init_log_level_str = eicrecon::LogLevelToString(m_log->level()); // set general acts log level, if not given by user - m_app->SetDefaultParameter("acts:InitLogLevel", init_log_level_str, "log_level: trace, debug, info, warn, error, critical, off"); - m_init_log->set_level(eicrecon::ParseLogLevel(init_log_level_str)); - m_init_log->info("Acts INIT log level is set to {} ({})", log_level_str, fmt::underlying(m_init_log->level())); - - // DD4Hep geometry - auto dd4hep_service = srv_locator->get(); - m_dd4hepGeo = dd4hep_service->detector(); +void ACTSGeo_service::acquire_services(JServiceLocator* srv_locator) { + + auto log_service = srv_locator->get(); + + // ACTS general log level: + m_log = log_service->logger("acts"); + std::string log_level_str = log_service->getDefaultLevelStr(); + m_app->SetDefaultParameter("acts:LogLevel", log_level_str, + "log_level: trace, debug, info, warn, error, critical, off"); + m_log->set_level(eicrecon::ParseLogLevel(log_level_str)); + m_log->info("Acts GENERAL log level is set to {} ({})", log_level_str, + fmt::underlying(m_log->level())); + + // ACTS init log level (geometry conversion): + m_init_log = log_service->logger("acts_init"); + std::string init_log_level_str = eicrecon::LogLevelToString( + m_log->level()); // set general acts log level, if not given by user + m_app->SetDefaultParameter("acts:InitLogLevel", init_log_level_str, + "log_level: trace, debug, info, warn, error, critical, off"); + m_init_log->set_level(eicrecon::ParseLogLevel(init_log_level_str)); + m_init_log->info("Acts INIT log level is set to {} ({})", log_level_str, + fmt::underlying(m_init_log->level())); + + // DD4Hep geometry + auto dd4hep_service = srv_locator->get(); + m_dd4hepGeo = dd4hep_service->detector(); } diff --git a/src/services/geometry/acts/ACTSGeo_service.h b/src/services/geometry/acts/ACTSGeo_service.h index 95180cdd22..fc521c5dd3 100644 --- a/src/services/geometry/acts/ACTSGeo_service.h +++ b/src/services/geometry/acts/ACTSGeo_service.h @@ -12,28 +12,24 @@ #include "algorithms/tracking/ActsGeometryProvider.h" - -class ACTSGeo_service : public JService -{ +class ACTSGeo_service : public JService { public: - ACTSGeo_service( JApplication *app ) : m_app(app) {} - virtual ~ACTSGeo_service(); + ACTSGeo_service(JApplication* app) : m_app(app) {} + virtual ~ACTSGeo_service(); - virtual std::shared_ptr actsGeoProvider(); + virtual std::shared_ptr actsGeoProvider(); protected: - - private: - ACTSGeo_service()=default; - void acquire_services(JServiceLocator *) override; + ACTSGeo_service() = default; + void acquire_services(JServiceLocator*) override; - std::once_flag m_init_flag; - JApplication *m_app = nullptr; - const dd4hep::Detector* m_dd4hepGeo = nullptr; - std::shared_ptr m_acts_provider; + std::once_flag m_init_flag; + JApplication* m_app = nullptr; + const dd4hep::Detector* m_dd4hepGeo = nullptr; + std::shared_ptr m_acts_provider; - // General acts log - std::shared_ptr m_log; - std::shared_ptr m_init_log; + // General acts log + std::shared_ptr m_log; + std::shared_ptr m_init_log; }; diff --git a/src/services/geometry/acts/acts.cc b/src/services/geometry/acts/acts.cc index a0e9c7f104..271136c222 100644 --- a/src/services/geometry/acts/acts.cc +++ b/src/services/geometry/acts/acts.cc @@ -9,8 +9,8 @@ #include "ACTSGeo_service.h" extern "C" { -void InitPlugin(JApplication *app) { - InitJANAPlugin(app); - app->ProvideService(std::make_shared(app) ); +void InitPlugin(JApplication* app) { + InitJANAPlugin(app); + app->ProvideService(std::make_shared(app)); } } diff --git a/src/services/geometry/dd4hep/DD4hep_service.cc b/src/services/geometry/dd4hep/DD4hep_service.cc index c93631e4df..7a2017e2e4 100644 --- a/src/services/geometry/dd4hep/DD4hep_service.cc +++ b/src/services/geometry/dd4hep/DD4hep_service.cc @@ -24,31 +24,34 @@ //---------------------------------------------------------------- // Services //---------------------------------------------------------------- -void DD4hep_service::acquire_services(JServiceLocator *srv_locator) { - // logging service - auto log_service = srv_locator->get(); - m_log = log_service->logger("dd4hep"); - std::string log_level_str{"info"}; - m_app->SetDefaultParameter("dd4hep:LogLevel", log_level_str, "Log level for DD4hep_service"); - m_log->set_level(eicrecon::ParseLogLevel(log_level_str)); - - // Set the DD4hep print level to be quieter by default, but let user adjust it - std::string print_level_str{"WARNING"}; - m_app->SetDefaultParameter("dd4hep:print_level", print_level_str, "Set DD4hep print level (see DD4hep/Printout.h)"); - dd4hep::setPrintLevel(dd4hep::decodePrintLevel(print_level_str)); - - // Set the TGeoManager verbose level (lower dd4hep level is more verbose) - TGeoManager::SetVerboseLevel(dd4hep::printLevel() <= dd4hep::PrintLevel::INFO ? 1 : 0); +void DD4hep_service::acquire_services(JServiceLocator* srv_locator) { + // logging service + auto log_service = srv_locator->get(); + m_log = log_service->logger("dd4hep"); + std::string log_level_str{"info"}; + m_app->SetDefaultParameter("dd4hep:LogLevel", log_level_str, "Log level for DD4hep_service"); + m_log->set_level(eicrecon::ParseLogLevel(log_level_str)); + + // Set the DD4hep print level to be quieter by default, but let user adjust it + std::string print_level_str{"WARNING"}; + m_app->SetDefaultParameter("dd4hep:print_level", print_level_str, + "Set DD4hep print level (see DD4hep/Printout.h)"); + dd4hep::setPrintLevel(dd4hep::decodePrintLevel(print_level_str)); + + // Set the TGeoManager verbose level (lower dd4hep level is more verbose) + TGeoManager::SetVerboseLevel(dd4hep::printLevel() <= dd4hep::PrintLevel::INFO ? 1 : 0); } //---------------------------------------------------------------- // destructor //---------------------------------------------------------------- -DD4hep_service::~DD4hep_service(){ - try { - if(m_dd4hepGeo) m_dd4hepGeo->destroyInstance(); - m_dd4hepGeo = nullptr; - } catch (...) {} +DD4hep_service::~DD4hep_service() { + try { + if (m_dd4hepGeo) + m_dd4hepGeo->destroyInstance(); + m_dd4hepGeo = nullptr; + } catch (...) { + } } //---------------------------------------------------------------- @@ -57,10 +60,9 @@ DD4hep_service::~DD4hep_service(){ /// Return pointer to the dd4hep::Detector object. /// Call Initialize if needed. //---------------------------------------------------------------- -gsl::not_null -DD4hep_service::detector() { - std::call_once(init_flag, &DD4hep_service::Initialize, this); - return m_dd4hepGeo.get(); +gsl::not_null DD4hep_service::detector() { + std::call_once(init_flag, &DD4hep_service::Initialize, this); + return m_dd4hepGeo.get(); } //---------------------------------------------------------------- @@ -69,10 +71,9 @@ DD4hep_service::detector() { /// Return pointer to the cellIDPositionConverter object. /// Call Initialize if needed. //---------------------------------------------------------------- -gsl::not_null -DD4hep_service::converter() { - std::call_once(init_flag, &DD4hep_service::Initialize, this); - return m_cellid_converter.get(); +gsl::not_null DD4hep_service::converter() { + std::call_once(init_flag, &DD4hep_service::Initialize, this); + return m_cellid_converter.get(); } //---------------------------------------------------------------- @@ -85,100 +86,108 @@ DD4hep_service::converter() { //---------------------------------------------------------------- void DD4hep_service::Initialize() { - if (m_dd4hepGeo) { - m_log->warn("DD4hep_service already initialized!"); + if (m_dd4hepGeo) { + m_log->warn("DD4hep_service already initialized!"); + } + + // The current recommended way of getting the XML file is to use the environment variables + // DETECTOR_PATH and DETECTOR_CONFIG. + // Look for those first, so we can use it for the default + // config parameter. + auto* detector_config_env = std::getenv("DETECTOR_CONFIG"); + auto* detector_path_env = std::getenv("DETECTOR_PATH"); + + std::string detector_config; + // Check if detector_config_env is set + if (detector_config_env != nullptr) { + detector_config = detector_config_env; + } + + // do we have default file name + if (!detector_config.empty()) { + m_xml_files.push_back(std::string(detector_path_env ? detector_path_env : ".") + "/" + + detector_config + ".xml"); + } + + // User may specify multiple geometry files via the config. parameter. Normally, this + // will be a single file which itself has includes for other files. + m_app->SetDefaultParameter("dd4hep:xml_files", m_xml_files, + "Comma separated list of XML files describing the DD4hep geometry. " + "(Defaults to ${DETECTOR_PATH}/${DETECTOR_CONFIG}.xml using envars.)"); + + if (m_xml_files.empty()) { + m_log->error("No dd4hep XML file specified for the geometry!"); + m_log->error("Set your DETECTOR_PATH and DETECTOR_CONFIG environment variables"); + m_log->error("(the latter is typically done by sourcing the setup.sh"); + m_log->error("script the epic directory.)"); + throw std::runtime_error("No dd4hep XML file specified."); + } + + // Reading the geometry may take a long time and if the JANA ticker is enabled, it will keep printing + // while no other output is coming which makes it look like something is wrong. Disable the ticker + // while parsing and loading the geometry + auto tickerEnabled = m_app->IsTickerEnabled(); + m_app->SetTicker(false); + + // load geometry + auto detector = dd4hep::Detector::make_unique(""); + try { + m_log->info("Loading DD4hep geometry from {} files", m_xml_files.size()); + for (auto& filename : m_xml_files) { + + auto resolved_filename = resolveFileName(filename, detector_path_env); + + m_log->info(" - loading geometry file: '{}' (patience ....)", resolved_filename); + try { + detector->fromCompact(resolved_filename); + } catch ( + std::runtime_error& e) { // dd4hep throws std::runtime_error, no way to detail further + throw JException(e.what()); + } } - - // The current recommended way of getting the XML file is to use the environment variables - // DETECTOR_PATH and DETECTOR_CONFIG. - // Look for those first, so we can use it for the default - // config parameter. - auto *detector_config_env = std::getenv("DETECTOR_CONFIG"); - auto *detector_path_env = std::getenv("DETECTOR_PATH"); - - std::string detector_config; - // Check if detector_config_env is set - if(detector_config_env != nullptr) { - detector_config = detector_config_env; - } - - // do we have default file name - if(!detector_config.empty()) { - m_xml_files.push_back(std::string(detector_path_env ? detector_path_env : ".") + "/" + detector_config + ".xml"); - } - - // User may specify multiple geometry files via the config. parameter. Normally, this - // will be a single file which itself has includes for other files. - m_app->SetDefaultParameter("dd4hep:xml_files", m_xml_files, "Comma separated list of XML files describing the DD4hep geometry. (Defaults to ${DETECTOR_PATH}/${DETECTOR_CONFIG}.xml using envars.)"); - - if( m_xml_files.empty() ){ - m_log->error("No dd4hep XML file specified for the geometry!"); - m_log->error("Set your DETECTOR_PATH and DETECTOR_CONFIG environment variables"); - m_log->error("(the latter is typically done by sourcing the setup.sh"); - m_log->error("script the epic directory.)"); - throw std::runtime_error("No dd4hep XML file specified."); - } - - // Reading the geometry may take a long time and if the JANA ticker is enabled, it will keep printing - // while no other output is coming which makes it look like something is wrong. Disable the ticker - // while parsing and loading the geometry - auto tickerEnabled = m_app->IsTickerEnabled(); - m_app->SetTicker( false ); - - // load geometry - auto detector = dd4hep::Detector::make_unique(""); - try { - m_log->info("Loading DD4hep geometry from {} files", m_xml_files.size()); - for (auto &filename : m_xml_files) { - - auto resolved_filename = resolveFileName(filename, detector_path_env); - - m_log->info(" - loading geometry file: '{}' (patience ....)", resolved_filename); - try { - detector->fromCompact(resolved_filename); - } catch(std::runtime_error &e) { // dd4hep throws std::runtime_error, no way to detail further - throw JException(e.what()); - } - } - detector->volumeManager(); - detector->apply("DD4hepVolumeManager", 0, nullptr); - m_cellid_converter = std::make_unique(*detector); - m_dd4hepGeo = std::move(detector); // const - - m_log->info("Geometry successfully loaded."); - } catch(std::exception &e) { - m_log->error("Problem loading geometry: {}", e.what()); - throw std::runtime_error(fmt::format("Problem loading geometry: {}", e.what())); - } - - // Restore the ticker setting - m_app->SetTicker( tickerEnabled ); + detector->volumeManager(); + detector->apply("DD4hepVolumeManager", 0, nullptr); + m_cellid_converter = std::make_unique(*detector); + m_dd4hepGeo = std::move(detector); // const + + m_log->info("Geometry successfully loaded."); + } catch (std::exception& e) { + m_log->error("Problem loading geometry: {}", e.what()); + throw std::runtime_error(fmt::format("Problem loading geometry: {}", e.what())); + } + + // Restore the ticker setting + m_app->SetTicker(tickerEnabled); } -std::string DD4hep_service::resolveFileName(const std::string &filename, char *detector_path_env) { - - std::string result(filename); - - // Check that this XML file actually exists. - if( ! std::filesystem::exists(result) ){ - - // filename does not exist, maybe DETECTOR_PATH/filename is meant? - if(detector_path_env) { - - // Try looking filename in DETECTOR_PATH - result = std::string(detector_path_env) + "/" + filename; - - if( ! std::filesystem::exists(result) ) { - // Here we go against the standard practice of throwing an error and print - // the message and exit immediately. This is because we want the last message - // on the screen to be that this file doesn't exist. - auto mess = fmt::format(fmt::emphasis::bold | fg(fmt::color::red), "ERROR: "); - mess += fmt::format(fmt::emphasis::bold, "file: {} does not exist!", filename); - mess += "\nCheck that your DETECTOR_PATH and DETECTOR_CONFIG environment variables are set correctly."; - std::cerr << std::endl << std::endl << mess << std::endl << std::endl; // TODO standard log here! - std::_Exit(EXIT_FAILURE); - } - } +std::string DD4hep_service::resolveFileName(const std::string& filename, char* detector_path_env) { + + std::string result(filename); + + // Check that this XML file actually exists. + if (!std::filesystem::exists(result)) { + + // filename does not exist, maybe DETECTOR_PATH/filename is meant? + if (detector_path_env) { + + // Try looking filename in DETECTOR_PATH + result = std::string(detector_path_env) + "/" + filename; + + if (!std::filesystem::exists(result)) { + // Here we go against the standard practice of throwing an error and print + // the message and exit immediately. This is because we want the last message + // on the screen to be that this file doesn't exist. + auto mess = fmt::format(fmt::emphasis::bold | fg(fmt::color::red), "ERROR: "); + mess += fmt::format(fmt::emphasis::bold, "file: {} does not exist!", filename); + mess += "\nCheck that your DETECTOR_PATH and DETECTOR_CONFIG environment variables are set " + "correctly."; + std::cerr << std::endl + << std::endl + << mess << std::endl + << std::endl; // TODO standard log here! + std::_Exit(EXIT_FAILURE); + } } - return result; + } + return result; } diff --git a/src/services/geometry/dd4hep/DD4hep_service.h b/src/services/geometry/dd4hep/DD4hep_service.h index e71a976be0..57baf36fba 100644 --- a/src/services/geometry/dd4hep/DD4hep_service.h +++ b/src/services/geometry/dd4hep/DD4hep_service.h @@ -15,30 +15,29 @@ #include #include -class DD4hep_service : public JService -{ +class DD4hep_service : public JService { public: - DD4hep_service( JApplication *app ) : m_app(app) {} - virtual ~DD4hep_service(); + DD4hep_service(JApplication* app) : m_app(app) {} + virtual ~DD4hep_service(); - virtual gsl::not_null detector(); - virtual gsl::not_null converter(); + virtual gsl::not_null detector(); + virtual gsl::not_null converter(); protected: - void Initialize(); + void Initialize(); private: - DD4hep_service() = default; - void acquire_services(JServiceLocator *) override; + DD4hep_service() = default; + void acquire_services(JServiceLocator*) override; - std::once_flag init_flag; - JApplication *m_app = nullptr; - std::unique_ptr m_dd4hepGeo = nullptr; - std::unique_ptr m_cellid_converter = nullptr; - std::vector m_xml_files; + std::once_flag init_flag; + JApplication* m_app = nullptr; + std::unique_ptr m_dd4hepGeo = nullptr; + std::unique_ptr m_cellid_converter = nullptr; + std::vector m_xml_files; - /// Ensures there is a geometry file that should be opened - std::string resolveFileName(const std::string &filename, char *detector_path_env); + /// Ensures there is a geometry file that should be opened + std::string resolveFileName(const std::string& filename, char* detector_path_env); - std::shared_ptr m_log; + std::shared_ptr m_log; }; diff --git a/src/services/geometry/dd4hep/dd4hep.cc b/src/services/geometry/dd4hep/dd4hep.cc index 90ef62bfbc..72d9f69333 100644 --- a/src/services/geometry/dd4hep/dd4hep.cc +++ b/src/services/geometry/dd4hep/dd4hep.cc @@ -9,8 +9,8 @@ #include "DD4hep_service.h" extern "C" { -void InitPlugin(JApplication *app) { - InitJANAPlugin(app); - app->ProvideService(std::make_shared(app) ); +void InitPlugin(JApplication* app) { + InitJANAPlugin(app); + app->ProvideService(std::make_shared(app)); } } diff --git a/src/services/geometry/richgeo/ActsGeo.cc b/src/services/geometry/richgeo/ActsGeo.cc index adaea676e7..dff4520416 100644 --- a/src/services/geometry/richgeo/ActsGeo.cc +++ b/src/services/geometry/richgeo/ActsGeo.cc @@ -21,25 +21,26 @@ #include "services/geometry/richgeo/RichGeo.h" // constructor -richgeo::ActsGeo::ActsGeo(std::string detName_, gsl::not_null det_, std::shared_ptr log_) - : m_detName(detName_), m_det(det_), m_log(log_) -{ +richgeo::ActsGeo::ActsGeo(std::string detName_, gsl::not_null det_, + std::shared_ptr log_) + : m_detName(detName_), m_det(det_), m_log(log_) { // capitalize m_detName std::transform(m_detName.begin(), m_detName.end(), m_detName.begin(), ::toupper); } // generate list ACTS disc surfaces, for a given radiator -std::vector> richgeo::ActsGeo::TrackingPlanes(int radiator, int numPlanes) { +std::vector> richgeo::ActsGeo::TrackingPlanes(int radiator, + int numPlanes) { // output list of surfaces std::vector> discs; // dRICH DD4hep-ACTS bindings -------------------------------------------------------------------- - if(m_detName=="DRICH") { + if (m_detName == "DRICH") { // vessel constants - auto zmin = m_det->constant("DRICH_zmin") / dd4hep::mm; - auto zmax = m_det->constant("DRICH_zmax") / dd4hep::mm; + auto zmin = m_det->constant("DRICH_zmin") / dd4hep::mm; + auto zmax = m_det->constant("DRICH_zmax") / dd4hep::mm; auto rmin0 = m_det->constant("DRICH_rmin0") / dd4hep::mm; auto rmin1 = m_det->constant("DRICH_rmin1") / dd4hep::mm; auto rmax0 = m_det->constant("DRICH_rmax0") / dd4hep::mm; @@ -47,12 +48,12 @@ std::vector> richgeo::ActsGeo::TrackingPlanes(int auto rmax2 = m_det->constant("DRICH_rmax2") / dd4hep::mm; // radiator constants - auto snoutLength = m_det->constant("DRICH_snout_length") / dd4hep::mm; - auto aerogelZpos = m_det->constant("DRICH_aerogel_zpos") / dd4hep::mm; + auto snoutLength = m_det->constant("DRICH_snout_length") / dd4hep::mm; + auto aerogelZpos = m_det->constant("DRICH_aerogel_zpos") / dd4hep::mm; auto aerogelThickness = m_det->constant("DRICH_aerogel_thickness") / dd4hep::mm; - auto filterZpos = m_det->constant("DRICH_filter_zpos") / dd4hep::mm; - auto filterThickness = m_det->constant("DRICH_filter_thickness") / dd4hep::mm; - auto window_thickness = m_det->constant("DRICH_window_thickness") / dd4hep::mm; + auto filterZpos = m_det->constant("DRICH_filter_zpos") / dd4hep::mm; + auto filterThickness = m_det->constant("DRICH_filter_thickness") / dd4hep::mm; + auto window_thickness = m_det->constant("DRICH_window_thickness") / dd4hep::mm; // radial wall slopes auto boreSlope = (rmin1 - rmin0) / (zmax - zmin); @@ -61,26 +62,28 @@ std::vector> richgeo::ActsGeo::TrackingPlanes(int // get z and radial limits where we will expect charged particles in the RICH double trackZmin, trackZmax; std::function trackRmin, trackRmax; - switch(radiator) { - case kAerogel: - trackZmin = aerogelZpos - aerogelThickness/2; - trackZmax = aerogelZpos + aerogelThickness/2; - trackRmax = [&] (auto z) { return rmax0 + snoutSlope * (z - zmin); }; - break; - case kGas: - trackZmin = filterZpos + filterThickness/2; - trackZmax = zmax - window_thickness; - trackRmax = [&] (auto z) { - auto z0 = z - zmin; - if(z0 < snoutLength) return rmax0 + snoutSlope * z0; - else return rmax2; - }; - break; - default: - m_log->error("unknown radiator number {}",numPlanes); - return discs; + switch (radiator) { + case kAerogel: + trackZmin = aerogelZpos - aerogelThickness / 2; + trackZmax = aerogelZpos + aerogelThickness / 2; + trackRmax = [&](auto z) { return rmax0 + snoutSlope * (z - zmin); }; + break; + case kGas: + trackZmin = filterZpos + filterThickness / 2; + trackZmax = zmax - window_thickness; + trackRmax = [&](auto z) { + auto z0 = z - zmin; + if (z0 < snoutLength) + return rmax0 + snoutSlope * z0; + else + return rmax2; + }; + break; + default: + m_log->error("unknown radiator number {}", numPlanes); + return discs; } - trackRmin = [&] (auto z) { return rmin0 + boreSlope * (z - zmin); }; + trackRmin = [&](auto z) { return rmin0 + boreSlope * (z - zmin); }; // define discs: `numPlanes` z-equidistant planes *within* the radiator; /* NOTE: do not allow planes to be at radiator boundary @@ -107,10 +110,10 @@ std::vector> richgeo::ActsGeo::TrackingPlanes(int * trackZStep */ m_log->debug("Define ACTS disks for {} radiator: {} disks in z=[ {}, {} ]", - RadiatorName(radiator), numPlanes, trackZmin, trackZmax); - double trackZstep = std::abs(trackZmax-trackZmin) / (numPlanes+1); - for(int i=0; i(rmin, rmax); @@ -121,12 +124,13 @@ std::vector> richgeo::ActsGeo::TrackingPlanes(int } // pfRICH DD4hep-ACTS bindings -------------------------------------------------------------------- - else if(m_detName=="PFRICH") { + else if (m_detName == "PFRICH") { m_log->error("TODO: pfRICH DD4hep-ACTS bindings have not yet been implemented"); } // ------------------------------------------------------------------------------------------------ - else m_log->error("ActsGeo is not defined for detector '{}'",m_detName); + else + m_log->error("ActsGeo is not defined for detector '{}'", m_detName); return discs; } @@ -136,27 +140,22 @@ std::function richgeo::ActsGeo::TrackPointCut(int rad // reject track points in dRICH gas that are beyond the dRICH mirrors // FIXME: assumes the full mirror spheres are much bigger than the dRICH // FIXME: needs to be generalized for dual or multi-mirror (per sector) design - if(m_detName=="DRICH" && radiator==kGas) { + if (m_detName == "DRICH" && radiator == kGas) { // get sphere centers std::vector mirror_centers; - for(int isec = 0; isec < m_det->constant("DRICH_num_sectors"); isec++) + for (int isec = 0; isec < m_det->constant("DRICH_num_sectors"); isec++) mirror_centers.emplace_back( m_det->constant("DRICH_mirror_center_x_sec" + std::to_string(isec)) / dd4hep::mm, m_det->constant("DRICH_mirror_center_y_sec" + std::to_string(isec)) / dd4hep::mm, - m_det->constant("DRICH_mirror_center_z_sec" + std::to_string(isec)) / dd4hep::mm - ); + m_det->constant("DRICH_mirror_center_z_sec" + std::to_string(isec)) / dd4hep::mm); auto mirror_radius = m_det->constant("DRICH_mirror_radius") / dd4hep::mm; // beyond the mirror cut - return [mirror_centers, mirror_radius] (edm4eic::TrackPoint p) { - for(const auto& c : mirror_centers) { - auto dist = std::hypot( - c.x() - p.position.x, - c.y() - p.position.y, - c.z() - p.position.z - ); - if(dist < mirror_radius) + return [mirror_centers, mirror_radius](edm4eic::TrackPoint p) { + for (const auto& c : mirror_centers) { + auto dist = std::hypot(c.x() - p.position.x, c.y() - p.position.y, c.z() - p.position.z); + if (dist < mirror_radius) return true; } return false; @@ -164,6 +163,5 @@ std::function richgeo::ActsGeo::TrackPointCut(int rad } // otherwise return a cut which always passes - return [] (edm4eic::TrackPoint p) { return true; }; - + return [](edm4eic::TrackPoint p) { return true; }; } diff --git a/src/services/geometry/richgeo/ActsGeo.h b/src/services/geometry/richgeo/ActsGeo.h index d88c6180d6..559dceb65c 100644 --- a/src/services/geometry/richgeo/ActsGeo.h +++ b/src/services/geometry/richgeo/ActsGeo.h @@ -15,30 +15,28 @@ // Forward declarations namespace Acts { - class Surface; +class Surface; } namespace richgeo { - class ActsGeo { - public: - - // constructor and destructor - ActsGeo(std::string detName_, gsl::not_null det_, std::shared_ptr log_); - ~ActsGeo() {} - - // generate list ACTS disc surfaces, for a given radiator - std::vector> TrackingPlanes(int radiator, int numPlanes); - - // generate a cut to remove any track points that should not be used - std::function TrackPointCut(int radiator); - - protected: - - std::string m_detName; - gsl::not_null m_det; - std::shared_ptr m_log; - - private: - - }; -} +class ActsGeo { +public: + // constructor and destructor + ActsGeo(std::string detName_, gsl::not_null det_, + std::shared_ptr log_); + ~ActsGeo() {} + + // generate list ACTS disc surfaces, for a given radiator + std::vector> TrackingPlanes(int radiator, int numPlanes); + + // generate a cut to remove any track points that should not be used + std::function TrackPointCut(int radiator); + +protected: + std::string m_detName; + gsl::not_null m_det; + std::shared_ptr m_log; + +private: +}; +} // namespace richgeo diff --git a/src/services/geometry/richgeo/IrtGeo.cc b/src/services/geometry/richgeo/IrtGeo.cc index f2a1f7fce1..4d1d568445 100644 --- a/src/services/geometry/richgeo/IrtGeo.cc +++ b/src/services/geometry/richgeo/IrtGeo.cc @@ -21,9 +21,10 @@ #include "services/geometry/richgeo/RichGeo.h" // constructor: creates IRT-DD4hep bindings using main `Detector` handle `*det_` -richgeo::IrtGeo::IrtGeo(std::string detName_, gsl::not_null det_, gsl::not_null conv_, std::shared_ptr log_) : - m_detName(detName_), m_det(det_), m_converter(conv_), m_log(log_) -{ +richgeo::IrtGeo::IrtGeo(std::string detName_, gsl::not_null det_, + gsl::not_null conv_, + std::shared_ptr log_) + : m_detName(detName_), m_det(det_), m_converter(conv_), m_log(log_) { Bind(); } @@ -36,54 +37,55 @@ void richgeo::IrtGeo::Bind() { // IRT geometry handles m_irtDetectorCollection = new CherenkovDetectorCollection(); - m_irtDetector = m_irtDetectorCollection->AddNewDetector(m_detName.c_str()); + m_irtDetector = m_irtDetectorCollection->AddNewDetector(m_detName.c_str()); } // ------------------------------------------------ // define the `cell ID -> pixel position` converter, correcting to sensor surface void richgeo::IrtGeo::SetReadoutIDToPositionLambda() { - m_irtDetector->m_ReadoutIDToPosition = [ - &m_log = this->m_log, // capture logger by reference - // capture instance members by value, so those owned by `this` are not mutable here - cell_mask = this->m_irtDetector->GetReadoutCellMask(), - converter = this->m_converter, - sensor_info = this->m_sensor_info - ] (auto cell_id) { - // decode cell ID to get the sensor ID and pixel volume centroid - auto sensor_id = cell_id & cell_mask; - auto pixel_volume_centroid = (1/dd4hep::mm) * converter->position(cell_id); - // get sensor info - auto sensor_info_it = sensor_info.find(sensor_id); - if(sensor_info_it == sensor_info.end()) { - m_log->warn("cannot find sensor ID {} in IrtGeo; using pixel volume centroid instead",sensor_id); - return TVector3( pixel_volume_centroid.x(), pixel_volume_centroid.y(), pixel_volume_centroid.z()); - } - auto sensor_obj = sensor_info_it->second; - // get pixel surface centroid, given sensor surface offset w.r.t centroid - auto pixel_surface_centroid = pixel_volume_centroid + sensor_obj.surface_offset; - // cross check: make sure pixel and sensor surface centroids are close enough - auto dist = sqrt((pixel_surface_centroid - sensor_obj.surface_centroid).Mag2()); - if( dist > sensor_obj.size / sqrt(2) ) - m_log->warn("dist(pixel,sensor) is too large: {} mm",dist); - return TVector3( pixel_surface_centroid.x(), pixel_surface_centroid.y(), pixel_surface_centroid.z()); - }; - + m_irtDetector->m_ReadoutIDToPosition = + [&m_log = this->m_log, // capture logger by reference + // capture instance members by value, so those owned by `this` are not mutable here + cell_mask = this->m_irtDetector->GetReadoutCellMask(), converter = this->m_converter, + sensor_info = this->m_sensor_info](auto cell_id) { + // decode cell ID to get the sensor ID and pixel volume centroid + auto sensor_id = cell_id & cell_mask; + auto pixel_volume_centroid = (1 / dd4hep::mm) * converter->position(cell_id); + // get sensor info + auto sensor_info_it = sensor_info.find(sensor_id); + if (sensor_info_it == sensor_info.end()) { + m_log->warn("cannot find sensor ID {} in IrtGeo; using pixel volume centroid instead", + sensor_id); + return TVector3(pixel_volume_centroid.x(), pixel_volume_centroid.y(), + pixel_volume_centroid.z()); + } + auto sensor_obj = sensor_info_it->second; + // get pixel surface centroid, given sensor surface offset w.r.t centroid + auto pixel_surface_centroid = pixel_volume_centroid + sensor_obj.surface_offset; + // cross check: make sure pixel and sensor surface centroids are close enough + auto dist = sqrt((pixel_surface_centroid - sensor_obj.surface_centroid).Mag2()); + if (dist > sensor_obj.size / sqrt(2)) + m_log->warn("dist(pixel,sensor) is too large: {} mm", dist); + return TVector3(pixel_surface_centroid.x(), pixel_surface_centroid.y(), + pixel_surface_centroid.z()); + }; } // ------------------------------------------------ // fill table of refractive indices void richgeo::IrtGeo::SetRefractiveIndexTable() { - m_log->debug("{:-^60}"," Refractive Index Tables "); - for(auto rad_obj : m_irtDetector->Radiators()) { + m_log->debug("{:-^60}", " Refractive Index Tables "); + for (auto rad_obj : m_irtDetector->Radiators()) { m_log->debug("{}:", rad_obj.first.Data()); - auto *const rad = rad_obj.second; - const auto *rindex_matrix = m_det->material(rad->GetAlternativeMaterialName()).property("RINDEX"); - for(unsigned row=0; rowGetRows(); row++) { - auto energy = rindex_matrix->Get(row,0) / dd4hep::eV; - auto rindex = rindex_matrix->Get(row,1); + auto* const rad = rad_obj.second; + const auto* rindex_matrix = + m_det->material(rad->GetAlternativeMaterialName()).property("RINDEX"); + for (unsigned row = 0; row < rindex_matrix->GetRows(); row++) { + auto energy = rindex_matrix->Get(row, 0) / dd4hep::eV; + auto rindex = rindex_matrix->Get(row, 1); m_log->debug(" {:>5} eV {:<}", energy, rindex); - rad->m_ri_lookup_table.emplace_back(energy,rindex); + rad->m_ri_lookup_table.emplace_back(energy, rindex); } } } diff --git a/src/services/geometry/richgeo/IrtGeo.h b/src/services/geometry/richgeo/IrtGeo.h index 8d930b081e..802f1e1c50 100644 --- a/src/services/geometry/richgeo/IrtGeo.h +++ b/src/services/geometry/richgeo/IrtGeo.h @@ -23,50 +23,51 @@ #include "RichGeo.h" namespace richgeo { - class IrtGeo { - public: +class IrtGeo { +public: + // constructor: creates IRT-DD4hep bindings using main `Detector` handle `*det_` + IrtGeo(std::string detName_, gsl::not_null det_, + gsl::not_null conv_, + std::shared_ptr log_); + virtual ~IrtGeo(); - // constructor: creates IRT-DD4hep bindings using main `Detector` handle `*det_` - IrtGeo(std::string detName_, gsl::not_null det_, gsl::not_null conv_, std::shared_ptr log_); - virtual ~IrtGeo(); + // access the full IRT geometry + CherenkovDetectorCollection* GetIrtDetectorCollection() { return m_irtDetectorCollection; } - // access the full IRT geometry - CherenkovDetectorCollection *GetIrtDetectorCollection() { return m_irtDetectorCollection; } +protected: + // protected methods + virtual void DD4hep_to_IRT() = 0; // given DD4hep geometry, produce IRT geometry + void + SetReadoutIDToPositionLambda(); // define the `cell ID -> pixel position` converter, correcting to sensor surface + void SetRefractiveIndexTable(); // fill table of refractive indices + // read `VariantParameters` for a vector + template + VecT GetVectorFromVariantParameters(dd4hep::rec::VariantParameters* pars, std::string key) { + return VecT(pars->get(key + "_x"), pars->get(key + "_y"), + pars->get(key + "_z")); + } - protected: + // inputs + std::string m_detName; - // protected methods - virtual void DD4hep_to_IRT() = 0; // given DD4hep geometry, produce IRT geometry - void SetReadoutIDToPositionLambda(); // define the `cell ID -> pixel position` converter, correcting to sensor surface - void SetRefractiveIndexTable(); // fill table of refractive indices - // read `VariantParameters` for a vector - template - VecT GetVectorFromVariantParameters(dd4hep::rec::VariantParameters *pars, std::string key) { - return VecT(pars->get(key+"_x"), pars->get(key+"_y"), pars->get(key+"_z")); - } + // DD4hep geometry handles + gsl::not_null m_det; + dd4hep::DetElement m_detRich; + dd4hep::Position m_posRich; - // inputs - std::string m_detName; + // cell ID conversion + gsl::not_null m_converter; + std::unordered_map m_sensor_info; // sensor ID -> sensor info - // DD4hep geometry handles - gsl::not_null m_det; - dd4hep::DetElement m_detRich; - dd4hep::Position m_posRich; + // IRT geometry handles + CherenkovDetectorCollection* m_irtDetectorCollection; + CherenkovDetector* m_irtDetector; - // cell ID conversion - gsl::not_null m_converter; - std::unordered_map m_sensor_info; // sensor ID -> sensor info + // logger + std::shared_ptr m_log; - // IRT geometry handles - CherenkovDetectorCollection *m_irtDetectorCollection; - CherenkovDetector *m_irtDetector; - - // logger - std::shared_ptr m_log; - - private: - - // set all geometry handles - void Bind(); - }; -} +private: + // set all geometry handles + void Bind(); +}; +} // namespace richgeo diff --git a/src/services/geometry/richgeo/IrtGeoDRICH.cc b/src/services/geometry/richgeo/IrtGeoDRICH.cc index d6f4cf1848..e21fc1901d 100644 --- a/src/services/geometry/richgeo/IrtGeoDRICH.cc +++ b/src/services/geometry/richgeo/IrtGeoDRICH.cc @@ -36,31 +36,31 @@ void richgeo::IrtGeoDRICH::DD4hep_to_IRT() { auto vesselZmin = m_det->constant("DRICH_zmin") / dd4hep::mm; auto vesselWindowThickness = m_det->constant("DRICH_window_thickness") / dd4hep::mm; auto gasvolMaterial = m_det->constant("DRICH_gasvol_material"); - TVector3 normX(1, 0, 0); // normal vectors + TVector3 normX(1, 0, 0); // normal vectors TVector3 normY(0, -1, 0); - m_surfEntrance = new FlatSurface(TVector3(0, 0, vesselZmin + vesselWindowThickness), normX, normY); - for (int isec=0; isecSetContainerVolume( + m_surfEntrance = + new FlatSurface(TVector3(0, 0, vesselZmin + vesselWindowThickness), normX, normY); + for (int isec = 0; isec < nSectors; isec++) { + auto* cv = m_irtDetectorCollection->SetContainerVolume( m_irtDetector, // Cherenkov detector RadiatorName(kGas).c_str(), // name isec, // path (G4LogicalVolume*)(0x0), // G4LogicalVolume (inaccessible? use an integer instead) nullptr, // G4RadiatorMaterial (inaccessible?) m_surfEntrance // surface - ); + ); cv->SetAlternativeMaterialName(gasvolMaterial.c_str()); } // photon detector // - FIXME: args (G4Solid,G4Material) inaccessible? - auto cellMask = uint64_t(std::stoull(m_det->constant("DRICH_cell_mask"))); + auto cellMask = uint64_t(std::stoull(m_det->constant("DRICH_cell_mask"))); m_irtPhotonDetector = new CherenkovPhotonDetector(nullptr, nullptr); m_irtDetector->SetReadoutCellMask(cellMask); - m_irtDetectorCollection->AddPhotonDetector( - m_irtDetector, // Cherenkov detector - nullptr, // G4LogicalVolume (inaccessible?) - m_irtPhotonDetector // photon detector - ); + m_irtDetectorCollection->AddPhotonDetector(m_irtDetector, // Cherenkov detector + nullptr, // G4LogicalVolume (inaccessible?) + m_irtPhotonDetector // photon detector + ); m_log->debug("cellMask = {:#X}", cellMask); // aerogel + filter @@ -76,9 +76,9 @@ void richgeo::IrtGeoDRICH::DD4hep_to_IRT() { auto filterThickness = m_det->constant("DRICH_filter_thickness") / dd4hep::mm; auto filterMaterial = m_det->constant("DRICH_filter_material"); m_aerogelFlatSurface = new FlatSurface(TVector3(0, 0, aerogelZpos), normX, normY); - m_filterFlatSurface = new FlatSurface(TVector3(0, 0, filterZpos), normX, normY); + m_filterFlatSurface = new FlatSurface(TVector3(0, 0, filterZpos), normX, normY); for (int isec = 0; isec < nSectors; isec++) { - auto *aerogelFlatRadiator = m_irtDetectorCollection->AddFlatRadiator( + auto* aerogelFlatRadiator = m_irtDetectorCollection->AddFlatRadiator( m_irtDetector, // Cherenkov detector RadiatorName(kAerogel).c_str(), // name isec, // path @@ -86,8 +86,8 @@ void richgeo::IrtGeoDRICH::DD4hep_to_IRT() { nullptr, // G4RadiatorMaterial m_aerogelFlatSurface, // surface aerogelThickness // surface thickness - ); - auto *filterFlatRadiator = m_irtDetectorCollection->AddFlatRadiator( + ); + auto* filterFlatRadiator = m_irtDetectorCollection->AddFlatRadiator( m_irtDetector, // Cherenkov detector "Filter", // name isec, // path @@ -95,7 +95,7 @@ void richgeo::IrtGeoDRICH::DD4hep_to_IRT() { nullptr, // G4RadiatorMaterial m_filterFlatSurface, // surface filterThickness // surface thickness - ); + ); aerogelFlatRadiator->SetAlternativeMaterialName(aerogelMaterial.c_str()); filterFlatRadiator->SetAlternativeMaterialName(filterMaterial.c_str()); } @@ -110,15 +110,15 @@ void richgeo::IrtGeoDRICH::DD4hep_to_IRT() { // mirrors auto mirrorRadius = m_det->constant("DRICH_mirror_radius") / dd4hep::mm; dd4hep::Position mirrorCenter( - m_det->constant("DRICH_mirror_center_x_"+secName) / dd4hep::mm, - m_det->constant("DRICH_mirror_center_y_"+secName) / dd4hep::mm, - m_det->constant("DRICH_mirror_center_z_"+secName) / dd4hep::mm - ); - m_mirrorSphericalSurface = new SphericalSurface(TVector3(mirrorCenter.x(), mirrorCenter.y(), mirrorCenter.z()), mirrorRadius); - m_mirrorOpticalBoundary = new OpticalBoundary( - m_irtDetector->GetContainerVolume(), // CherenkovRadiator radiator - m_mirrorSphericalSurface, // surface - false // bool refractive + m_det->constant("DRICH_mirror_center_x_" + secName) / dd4hep::mm, + m_det->constant("DRICH_mirror_center_y_" + secName) / dd4hep::mm, + m_det->constant("DRICH_mirror_center_z_" + secName) / dd4hep::mm); + m_mirrorSphericalSurface = new SphericalSurface( + TVector3(mirrorCenter.x(), mirrorCenter.y(), mirrorCenter.z()), mirrorRadius); + m_mirrorOpticalBoundary = + new OpticalBoundary(m_irtDetector->GetContainerVolume(), // CherenkovRadiator radiator + m_mirrorSphericalSurface, // surface + false // bool refractive ); m_irtDetector->AddOpticalBoundary(isec, m_mirrorOpticalBoundary); m_log->debug(""); @@ -130,58 +130,60 @@ void richgeo::IrtGeoDRICH::DD4hep_to_IRT() { // complete the radiator volume description; this is the rear side of the container gas volume auto rad = m_irtDetector->GetRadiator(RadiatorName(kGas).c_str()); - if(rad) rad->m_Borders[isec].second = m_mirrorSphericalSurface; - else throw std::runtime_error("Gas radiator not built in IrtGeo"); + if (rad) + rad->m_Borders[isec].second = m_mirrorSphericalSurface; + else + throw std::runtime_error("Gas radiator not built in IrtGeo"); // sensor modules: search the detector tree for sensors for this sector m_log->trace(" SENSORS:"); - m_log->trace("--------------------------------------------------------------------------------------"); - m_log->trace("name ID sector pos_x pos_y pos_z normX_x normX_y normX_z normY_x normY_y normY_z"); - m_log->trace("--------------------------------------------------------------------------------------"); + m_log->trace( + "--------------------------------------------------------------------------------------"); + m_log->trace( + "name ID sector pos_x pos_y pos_z normX_x normX_y normX_z normY_x normY_y normY_z"); + m_log->trace( + "--------------------------------------------------------------------------------------"); auto sensorThickness = m_det->constant("DRICH_sensor_thickness") / dd4hep::mm; auto sensorSize = m_det->constant("DRICH_sensor_size") / dd4hep::mm; - for(auto const& [de_name, detSensor] : m_detRich.children()) { - if(de_name.find("sensor_de_"+secName)!=std::string::npos) { + for (auto const& [de_name, detSensor] : m_detRich.children()) { + if (de_name.find("sensor_de_" + secName) != std::string::npos) { // get sensor info const auto sensorID = detSensor.id(); const auto detSensorPars = detSensor.extension(true); - if(detSensorPars==nullptr) - throw std::runtime_error(fmt::format("sensor '{}' does not have VariantParameters", de_name)); + if (detSensorPars == nullptr) + throw std::runtime_error( + fmt::format("sensor '{}' does not have VariantParameters", de_name)); // - sensor surface position - auto posSensor = GetVectorFromVariantParameters(detSensorPars, "pos") / dd4hep::mm; + auto posSensor = + GetVectorFromVariantParameters(detSensorPars, "pos") / dd4hep::mm; // - sensor orientation auto normXdir = GetVectorFromVariantParameters(detSensorPars, "normX"); auto normYdir = GetVectorFromVariantParameters(detSensorPars, "normY"); auto normZdir = normXdir.Cross(normYdir); // sensor surface normal // - surface offset, used to convert sensor volume centroid to sensor surface centroid - auto surfaceOffset = normZdir.Unit() * (0.5*sensorThickness); + auto surfaceOffset = normZdir.Unit() * (0.5 * sensorThickness); // add sensor info to `m_sensor_info` map richgeo::Sensor sensor_info; sensor_info.size = sensorSize; sensor_info.surface_centroid = posSensor; sensor_info.surface_offset = surfaceOffset; - m_sensor_info.insert({ sensorID, sensor_info }); + m_sensor_info.insert({sensorID, sensor_info}); // create the optical surface - m_sensorFlatSurface = new FlatSurface( - TVector3(posSensor.x(), posSensor.y(), posSensor.z()), - TVector3(normXdir.x(), normXdir.y(), normXdir.z()), - TVector3(normYdir.x(), normYdir.y(), normYdir.z()) - ); - m_irtDetector->CreatePhotonDetectorInstance( - isec, // sector - m_irtPhotonDetector, // CherenkovPhotonDetector - sensorID, // copy number - m_sensorFlatSurface // surface - ); - m_log->trace( - "{} {:#X} {} {:5.2f} {:5.2f} {:5.2f} {:5.2f} {:5.2f} {:5.2f} {:5.2f} {:5.2f} {:5.2f}", - de_name, sensorID, isec, - posSensor.x(), posSensor.y(), posSensor.z(), - normXdir.x(), normXdir.y(), normXdir.z(), - normYdir.x(), normYdir.y(), normYdir.z() - ); + m_sensorFlatSurface = new FlatSurface(TVector3(posSensor.x(), posSensor.y(), posSensor.z()), + TVector3(normXdir.x(), normXdir.y(), normXdir.z()), + TVector3(normYdir.x(), normYdir.y(), normYdir.z())); + m_irtDetector->CreatePhotonDetectorInstance(isec, // sector + m_irtPhotonDetector, // CherenkovPhotonDetector + sensorID, // copy number + m_sensorFlatSurface // surface + ); + m_log->trace("{} {:#X} {} {:5.2f} {:5.2f} {:5.2f} {:5.2f} {:5.2f} {:5.2f} {:5.2f} " + "{:5.2f} {:5.2f}", + de_name, sensorID, isec, posSensor.x(), posSensor.y(), posSensor.z(), + normXdir.x(), normXdir.y(), normXdir.z(), normYdir.x(), normYdir.y(), + normYdir.z()); } } // search for sensors @@ -189,9 +191,9 @@ void richgeo::IrtGeoDRICH::DD4hep_to_IRT() { // set reference refractive indices // NOTE: numbers may be overridden externally std::map rIndices; - rIndices.insert({RadiatorName(kGas), 1.00076}); + rIndices.insert({RadiatorName(kGas), 1.00076}); rIndices.insert({RadiatorName(kAerogel), 1.0190}); - rIndices.insert({"Filter", 1.5017}); + rIndices.insert({"Filter", 1.5017}); for (auto const& [rName, rIndex] : rIndices) { auto rad = m_irtDetector->GetRadiator(rName.c_str()); if (rad) @@ -204,20 +206,19 @@ void richgeo::IrtGeoDRICH::DD4hep_to_IRT() { // define the `cell ID -> pixel position` converter SetReadoutIDToPositionLambda(); } -TVector3 richgeo::IrtGeoDRICH::GetSensorSurfaceNorm(CellIDType id){ +TVector3 richgeo::IrtGeoDRICH::GetSensorSurfaceNorm(CellIDType id) { TVector3 sensorNorm; - auto cellMask = uint64_t(std::stoull(m_det->constant("DRICH_cell_mask"))); - auto sensor_info = this->m_sensor_info; - auto sID = id & cellMask; + auto cellMask = uint64_t(std::stoull(m_det->constant("DRICH_cell_mask"))); + auto sensor_info = this->m_sensor_info; + auto sID = id & cellMask; auto sensor_info_it = sensor_info.find(sID); - if(sensor_info_it!=sensor_info.end()){ + if (sensor_info_it != sensor_info.end()) { auto sensor_obj = sensor_info_it->second; - auto normZdir = sensor_obj.surface_offset.Unit(); + auto normZdir = sensor_obj.surface_offset.Unit(); sensorNorm.SetX(static_cast(normZdir.x())); sensorNorm.SetY(static_cast(normZdir.y())); sensorNorm.SetZ(static_cast(normZdir.z())); - } - else{ + } else { m_log->error("Cannot find sensor {} in IrtGeoDRICH::GetSensorSurface", id); throw std::runtime_error("sensor not found in IrtGeoDRIC::GetSensorSurfaceNormal"); } diff --git a/src/services/geometry/richgeo/IrtGeoDRICH.h b/src/services/geometry/richgeo/IrtGeoDRICH.h index 23d86f37c5..22433c8e2e 100644 --- a/src/services/geometry/richgeo/IrtGeoDRICH.h +++ b/src/services/geometry/richgeo/IrtGeoDRICH.h @@ -18,25 +18,29 @@ #include "services/geometry/richgeo/RichGeo.h" namespace richgeo { - class IrtGeoDRICH : public IrtGeo { +class IrtGeoDRICH : public IrtGeo { - public: - IrtGeoDRICH(gsl::not_null det_, gsl::not_null conv_, std::shared_ptr log_) : - IrtGeo("DRICH",det_,conv_,log_) { DD4hep_to_IRT(); } - ~IrtGeoDRICH(); - TVector3 GetSensorSurfaceNorm(CellIDType); - protected: - void DD4hep_to_IRT() override; +public: + IrtGeoDRICH(gsl::not_null det_, + gsl::not_null conv_, + std::shared_ptr log_) + : IrtGeo("DRICH", det_, conv_, log_) { + DD4hep_to_IRT(); + } + ~IrtGeoDRICH(); + TVector3 GetSensorSurfaceNorm(CellIDType); - private: - // FIXME: should be smart pointers, but IRT methods sometimes assume ownership of such raw pointers - FlatSurface* m_surfEntrance; - CherenkovPhotonDetector* m_irtPhotonDetector; - FlatSurface* m_aerogelFlatSurface; - FlatSurface* m_filterFlatSurface; - SphericalSurface* m_mirrorSphericalSurface; - OpticalBoundary* m_mirrorOpticalBoundary; - FlatSurface* m_sensorFlatSurface; +protected: + void DD4hep_to_IRT() override; - }; -} +private: + // FIXME: should be smart pointers, but IRT methods sometimes assume ownership of such raw pointers + FlatSurface* m_surfEntrance; + CherenkovPhotonDetector* m_irtPhotonDetector; + FlatSurface* m_aerogelFlatSurface; + FlatSurface* m_filterFlatSurface; + SphericalSurface* m_mirrorSphericalSurface; + OpticalBoundary* m_mirrorOpticalBoundary; + FlatSurface* m_sensorFlatSurface; +}; +} // namespace richgeo diff --git a/src/services/geometry/richgeo/IrtGeoPFRICH.cc b/src/services/geometry/richgeo/IrtGeoPFRICH.cc index 55dde3d8eb..a69ee107d0 100644 --- a/src/services/geometry/richgeo/IrtGeoPFRICH.cc +++ b/src/services/geometry/richgeo/IrtGeoPFRICH.cc @@ -37,44 +37,43 @@ void richgeo::IrtGeoPFRICH::DD4hep_to_IRT() { */ auto vesselZmin = m_det->constant("PFRICH_zmin") / dd4hep::mm; auto gasvolMaterial = m_det->constant("PFRICH_gasvol_material"); - TVector3 normX(1, 0, 0); // normal vectors + TVector3 normX(1, 0, 0); // normal vectors TVector3 normY(0, 1, 0); m_surfEntrance = new FlatSurface(TVector3(0, 0, vesselZmin), normX, normY); - auto cv = m_irtDetectorCollection->SetContainerVolume( + auto cv = m_irtDetectorCollection->SetContainerVolume( m_irtDetector, // Cherenkov detector RadiatorName(kGas).c_str(), // name 0, // path (G4LogicalVolume*)(0x0), // G4LogicalVolume (inaccessible? use an integer instead) nullptr, // G4RadiatorMaterial (inaccessible?) m_surfEntrance // surface - ); + ); cv->SetAlternativeMaterialName(gasvolMaterial.c_str()); // photon detector // - FIXME: args (G4Solid,G4Material) inaccessible? - auto cellMask = uint64_t(std::stoull(m_det->constant("PFRICH_cell_mask"))); + auto cellMask = uint64_t(std::stoull(m_det->constant("PFRICH_cell_mask"))); m_irtPhotonDetector = new CherenkovPhotonDetector(nullptr, nullptr); m_irtDetector->SetReadoutCellMask(cellMask); - m_irtDetectorCollection->AddPhotonDetector( - m_irtDetector, // Cherenkov detector - nullptr, // G4LogicalVolume (inaccessible?) - m_irtPhotonDetector // photon detector - ); + m_irtDetectorCollection->AddPhotonDetector(m_irtDetector, // Cherenkov detector + nullptr, // G4LogicalVolume (inaccessible?) + m_irtPhotonDetector // photon detector + ); m_log->debug("cellMask = {:#X}", cellMask); // aerogel + filter /* AddFlatRadiator will create a pair of flat refractive surfaces internally; * FIXME: should make a small gas gap at the upstream end of the gas volume; */ - auto aerogelZpos = m_det->constant("PFRICH_aerogel_zpos") / dd4hep::mm; - auto aerogelThickness = m_det->constant("PFRICH_aerogel_thickness") / dd4hep::mm; - auto aerogelMaterial = m_det->constant("PFRICH_aerogel_material"); - auto filterZpos = m_det->constant("PFRICH_filter_zpos") / dd4hep::mm; - auto filterThickness = m_det->constant("PFRICH_filter_thickness") / dd4hep::mm; - auto filterMaterial = m_det->constant("PFRICH_filter_material"); - m_aerogelFlatSurface = new FlatSurface(TVector3(0, 0, aerogelZpos), normX, normY); - m_filterFlatSurface = new FlatSurface(TVector3(0, 0, filterZpos), normX, normY); - auto *aerogelFlatRadiator = m_irtDetectorCollection->AddFlatRadiator( + auto aerogelZpos = m_det->constant("PFRICH_aerogel_zpos") / dd4hep::mm; + auto aerogelThickness = m_det->constant("PFRICH_aerogel_thickness") / dd4hep::mm; + auto aerogelMaterial = m_det->constant("PFRICH_aerogel_material"); + auto filterZpos = m_det->constant("PFRICH_filter_zpos") / dd4hep::mm; + auto filterThickness = m_det->constant("PFRICH_filter_thickness") / dd4hep::mm; + auto filterMaterial = m_det->constant("PFRICH_filter_material"); + m_aerogelFlatSurface = new FlatSurface(TVector3(0, 0, aerogelZpos), normX, normY); + m_filterFlatSurface = new FlatSurface(TVector3(0, 0, filterZpos), normX, normY); + auto* aerogelFlatRadiator = m_irtDetectorCollection->AddFlatRadiator( m_irtDetector, // Cherenkov detector RadiatorName(kAerogel).c_str(), // name 0, // path @@ -82,8 +81,8 @@ void richgeo::IrtGeoPFRICH::DD4hep_to_IRT() { nullptr, // G4RadiatorMaterial m_aerogelFlatSurface, // surface aerogelThickness // surface thickness - ); - auto *filterFlatRadiator = m_irtDetectorCollection->AddFlatRadiator( + ); + auto* filterFlatRadiator = m_irtDetectorCollection->AddFlatRadiator( m_irtDetector, // Cherenkov detector "Filter", // name 0, // path @@ -91,7 +90,7 @@ void richgeo::IrtGeoPFRICH::DD4hep_to_IRT() { nullptr, // G4RadiatorMaterial m_filterFlatSurface, // surface filterThickness // surface thickness - ); + ); aerogelFlatRadiator->SetAlternativeMaterialName(aerogelMaterial.c_str()); filterFlatRadiator->SetAlternativeMaterialName(filterMaterial.c_str()); m_log->debug("aerogelZpos = {:f} mm", aerogelZpos); @@ -100,32 +99,36 @@ void richgeo::IrtGeoPFRICH::DD4hep_to_IRT() { m_log->debug("filter thickness = {:f} mm", filterThickness); // sensor modules: search the detector tree for sensors - auto sensorThickness = m_det->constant("PFRICH_sensor_thickness") / dd4hep::mm; - auto sensorSize = m_det->constant("PFRICH_sensor_size") / dd4hep::mm; - bool firstSensor = true; - for(auto const& [de_name, detSensor] : m_detRich.children()) { - if(de_name.find("sensor_de")!=std::string::npos) { + auto sensorThickness = m_det->constant("PFRICH_sensor_thickness") / dd4hep::mm; + auto sensorSize = m_det->constant("PFRICH_sensor_size") / dd4hep::mm; + bool firstSensor = true; + for (auto const& [de_name, detSensor] : m_detRich.children()) { + if (de_name.find("sensor_de") != std::string::npos) { // get sensor info auto imod = detSensor.id(); // - get sensor centroid position auto pvSensor = detSensor.placement(); - auto posSensor = (1/dd4hep::mm) * (m_posRich + pvSensor.position()); + auto posSensor = (1 / dd4hep::mm) * (m_posRich + pvSensor.position()); // - get sensor surface position - dd4hep::Direction sensorNorm(0,0,1); // FIXME: generalize; this assumes planar layout, with norm along +z axis (toward IP) - auto surfaceOffset = sensorNorm.Unit() * (0.5*sensorThickness); + dd4hep::Direction sensorNorm( + 0, 0, + 1); // FIXME: generalize; this assumes planar layout, with norm along +z axis (toward IP) + auto surfaceOffset = sensorNorm.Unit() * (0.5 * sensorThickness); auto posSensorSurface = posSensor + surfaceOffset; // - add to `m_sensor_info` map richgeo::Sensor sensor_info; sensor_info.size = sensorSize; sensor_info.surface_centroid = posSensorSurface; sensor_info.surface_offset = surfaceOffset; - m_sensor_info.insert({ imod, sensor_info }); + m_sensor_info.insert({imod, sensor_info}); // - get surface normal and in-plane vectors double sensorLocalNormX[3] = {1.0, 0.0, 0.0}; double sensorLocalNormY[3] = {0.0, 1.0, 0.0}; double sensorGlobalNormX[3], sensorGlobalNormY[3]; - pvSensor.ptr()->LocalToMasterVect(sensorLocalNormX, sensorGlobalNormX); // ignore vessel transformation, since it is a pure translation + pvSensor.ptr()->LocalToMasterVect( + sensorLocalNormX, + sensorGlobalNormX); // ignore vessel transformation, since it is a pure translation pvSensor.ptr()->LocalToMasterVect(sensorLocalNormY, sensorGlobalNormY); // validate sensor position and normal @@ -133,43 +136,39 @@ void richgeo::IrtGeoPFRICH::DD4hep_to_IRT() { dd4hep::Direction normXdir, normYdir; normXdir.SetCoordinates(sensorGlobalNormX); normYdir.SetCoordinates(sensorGlobalNormY); - auto normZdir = normXdir.Cross(normYdir); // sensor surface normal, given derived GlobalNormX,Y - auto testOrtho = normXdir.Dot(normYdir); // should be zero, if normX and normY are orthogonal - auto testRadial = sensorNorm.Cross(normZdir).Mag2(); // should be zero, if sensor surface normal is as expected - if(abs(testOrtho)>1e-6 || abs(testRadial)>1e-6) { + auto normZdir = + normXdir.Cross(normYdir); // sensor surface normal, given derived GlobalNormX,Y + auto testOrtho = normXdir.Dot(normYdir); // should be zero, if normX and normY are orthogonal + auto testRadial = sensorNorm.Cross(normZdir) + .Mag2(); // should be zero, if sensor surface normal is as expected + if (abs(testOrtho) > 1e-6 || abs(testRadial) > 1e-6) { m_log->error( "sensor normal is wrong: normX.normY = {:f} |sensorNorm x normZdir|^2 = {:f}", - testOrtho, - testRadial - ); + testOrtho, testRadial); return; } // create the optical surface m_sensorFlatSurface = new FlatSurface( TVector3(posSensorSurface.x(), posSensorSurface.y(), posSensorSurface.z()), - TVector3(sensorGlobalNormX), - TVector3(sensorGlobalNormY) - ); - m_irtDetector->CreatePhotonDetectorInstance( - 0, // sector - m_irtPhotonDetector, // CherenkovPhotonDetector - imod, // copy number - m_sensorFlatSurface // surface - ); - m_log->trace( - "sensor: id={:#08X} pos=({:5.2f}, {:5.2f}, {:5.2f}) normX=({:5.2f}, {:5.2f}, {:5.2f}) normY=({:5.2f}, {:5.2f}, {:5.2f})", - imod, - posSensorSurface.x(), posSensorSurface.y(), posSensorSurface.z(), - normXdir.x(), normXdir.y(), normXdir.z(), - normYdir.x(), normYdir.y(), normYdir.z() - ); + TVector3(sensorGlobalNormX), TVector3(sensorGlobalNormY)); + m_irtDetector->CreatePhotonDetectorInstance(0, // sector + m_irtPhotonDetector, // CherenkovPhotonDetector + imod, // copy number + m_sensorFlatSurface // surface + ); + m_log->trace("sensor: id={:#08X} pos=({:5.2f}, {:5.2f}, {:5.2f}) normX=({:5.2f}, {:5.2f}, " + "{:5.2f}) normY=({:5.2f}, {:5.2f}, {:5.2f})", + imod, posSensorSurface.x(), posSensorSurface.y(), posSensorSurface.z(), + normXdir.x(), normXdir.y(), normXdir.z(), normYdir.x(), normYdir.y(), + normYdir.z()); // complete the radiator volume description; this is the rear side of the container gas volume // Yes, since there are no mirrors in this detector, just close the gas radiator volume by hand (once), // assuming that all the sensors will be sitting at roughly the same location along the beam line anyway; - if(firstSensor) { - m_irtDetector->GetRadiator(RadiatorName(kGas).c_str())->m_Borders[0].second = dynamic_cast(m_sensorFlatSurface); + if (firstSensor) { + m_irtDetector->GetRadiator(RadiatorName(kGas).c_str())->m_Borders[0].second = + dynamic_cast(m_sensorFlatSurface); firstSensor = false; } @@ -178,9 +177,9 @@ void richgeo::IrtGeoPFRICH::DD4hep_to_IRT() { // set reference refractive indices // NOTE: numbers may be overridden externally std::map rIndices; - rIndices.insert({RadiatorName(kGas).c_str(), 1.0013}); + rIndices.insert({RadiatorName(kGas).c_str(), 1.0013}); rIndices.insert({RadiatorName(kAerogel).c_str(), 1.0190}); - rIndices.insert({"Filter", 1.5017}); + rIndices.insert({"Filter", 1.5017}); for (auto const& [rName, rIndex] : rIndices) { auto rad = m_irtDetector->GetRadiator(rName); if (rad) diff --git a/src/services/geometry/richgeo/IrtGeoPFRICH.h b/src/services/geometry/richgeo/IrtGeoPFRICH.h index 35aa449b73..0592d572c3 100644 --- a/src/services/geometry/richgeo/IrtGeoPFRICH.h +++ b/src/services/geometry/richgeo/IrtGeoPFRICH.h @@ -15,22 +15,26 @@ #include "IrtGeo.h" namespace richgeo { - class IrtGeoPFRICH : public IrtGeo { +class IrtGeoPFRICH : public IrtGeo { - public: - IrtGeoPFRICH(gsl::not_null det_, gsl::not_null conv_, std::shared_ptr log_) : - IrtGeo("PFRICH",det_,conv_,log_) { DD4hep_to_IRT(); } - ~IrtGeoPFRICH(); +public: + IrtGeoPFRICH(gsl::not_null det_, + gsl::not_null conv_, + std::shared_ptr log_) + : IrtGeo("PFRICH", det_, conv_, log_) { + DD4hep_to_IRT(); + } + ~IrtGeoPFRICH(); - protected: - void DD4hep_to_IRT() override; +protected: + void DD4hep_to_IRT() override; - private: - // FIXME: should be smart pointers, but IRT methods sometimes assume ownership of such raw pointers - FlatSurface* m_surfEntrance; - CherenkovPhotonDetector* m_irtPhotonDetector; - FlatSurface* m_aerogelFlatSurface; - FlatSurface* m_filterFlatSurface; - FlatSurface* m_sensorFlatSurface; - }; -} +private: + // FIXME: should be smart pointers, but IRT methods sometimes assume ownership of such raw pointers + FlatSurface* m_surfEntrance; + CherenkovPhotonDetector* m_irtPhotonDetector; + FlatSurface* m_aerogelFlatSurface; + FlatSurface* m_filterFlatSurface; + FlatSurface* m_sensorFlatSurface; +}; +} // namespace richgeo diff --git a/src/services/geometry/richgeo/ReadoutGeo.cc b/src/services/geometry/richgeo/ReadoutGeo.cc index 0bdebc13ad..36c239f578 100644 --- a/src/services/geometry/richgeo/ReadoutGeo.cc +++ b/src/services/geometry/richgeo/ReadoutGeo.cc @@ -24,9 +24,10 @@ #include "services/geometry/richgeo/RichGeo.h" // constructor -richgeo::ReadoutGeo::ReadoutGeo(std::string detName_, gsl::not_null det_, gsl::not_null conv_, std::shared_ptr log_) - : m_detName(detName_), m_det(det_), m_conv(conv_), m_log(log_) -{ +richgeo::ReadoutGeo::ReadoutGeo(std::string detName_, gsl::not_null det_, + gsl::not_null conv_, + std::shared_ptr log_) + : m_detName(detName_), m_det(det_), m_conv(conv_), m_log(log_) { // capitalize m_detName std::transform(m_detName.begin(), m_detName.end(), m_detName.begin(), ::toupper); @@ -34,18 +35,18 @@ richgeo::ReadoutGeo::ReadoutGeo(std::string detName_, gsl::not_null lambda) { return; }; + m_loopCellIDs = [](std::function lambda) { return; }; // default (empty) cellID rng generator - m_rngCellIDs = [] (std::function lambda, float p) { return; }; + m_rngCellIDs = [](std::function lambda, float p) { return; }; // common objects - m_readoutCoder = m_det->readout(m_detName+"Hits").idSpec().decoder(); + m_readoutCoder = m_det->readout(m_detName + "Hits").idSpec().decoder(); m_detRich = m_det->detector(m_detName); m_systemID = m_detRich.id(); // dRICH readout -------------------------------------------------------------------- - if(m_detName=="DRICH") { + if (m_detName == "DRICH") { // get constants from geometry m_num_sec = m_det->constant("DRICH_num_sectors"); @@ -55,12 +56,12 @@ richgeo::ReadoutGeo::ReadoutGeo(std::string detName_, gsl::not_nullconstant("DRICH_pixel_size") / dd4hep::mm; // define cellID looper - m_loopCellIDs = [this] (std::function lambda) { + m_loopCellIDs = [this](std::function lambda) { m_log->trace("call VisitAllReadoutPixels for systemID = {} = {}", m_systemID, m_detName); // loop over sensors (for all sectors) - for(auto const& [deName, detSensor] : m_detRich.children()) { - if(deName.find("sensor_de_sec")!=std::string::npos) { + for (auto const& [deName, detSensor] : m_detRich.children()) { + if (deName.find("sensor_de_sec") != std::string::npos) { // decode `sensorID` to module number and sector number auto sensorID = detSensor.id(); @@ -84,17 +85,17 @@ richgeo::ReadoutGeo::ReadoutGeo(std::string detName_, gsl::not_null lambda, float p) { + m_rngCellIDs = [this](std::function lambda, float p) { m_log->trace("call RngReadoutPixels for systemID = {} = {}", m_systemID, m_detName); int k = p * m_num_sec * m_num_pdus * m_num_sipms_per_pdu * m_num_px * m_num_px; for (int i = 0; i < k; i++) { - int isec = m_random.Uniform(0., m_num_sec); - int ipdu = m_random.Uniform(0., m_num_pdus); + int isec = m_random.Uniform(0., m_num_sec); + int ipdu = m_random.Uniform(0., m_num_pdus); int isipm = m_random.Uniform(0., m_num_sipms_per_pdu); - int x = m_random.Uniform(0., m_num_px); - int y = m_random.Uniform(0., m_num_px); + int x = m_random.Uniform(0., m_num_px); + int y = m_random.Uniform(0., m_num_px); auto cellID = cellIDEncoding(isec, ipdu, isipm, x, y); @@ -105,32 +106,31 @@ richgeo::ReadoutGeo::ReadoutGeo(std::string detName_, gsl::not_nullerror("TODO: pfRICH readout bindings have not yet been implemented"); } // ------------------------------------------------------------------------------------------------ - else m_log->error("ReadoutGeo is not defined for detector '{}'",m_detName); - + else + m_log->error("ReadoutGeo is not defined for detector '{}'", m_detName); } - // pixel gap mask // FIXME: generalize; this assumes the segmentation is `CartesianGridXY` bool richgeo::ReadoutGeo::PixelGapMask(CellIDType cellID, dd4hep::Position pos_hit_global) { auto pos_pixel_global = m_conv->position(cellID); auto pos_pixel_local = GetSensorLocalPosition(cellID, pos_pixel_global); auto pos_hit_local = GetSensorLocalPosition(cellID, pos_hit_global); - return ! ( - std::abs( pos_hit_local.x()/dd4hep::mm - pos_pixel_local.x()/dd4hep::mm ) > m_pixel_size/2 || - std::abs( pos_hit_local.y()/dd4hep::mm - pos_pixel_local.y()/dd4hep::mm ) > m_pixel_size/2 - ); + return !(std::abs(pos_hit_local.x() / dd4hep::mm - pos_pixel_local.x() / dd4hep::mm) > + m_pixel_size / 2 || + std::abs(pos_hit_local.y() / dd4hep::mm - pos_pixel_local.y() / dd4hep::mm) > + m_pixel_size / 2); } - // transform global position `pos` to sensor `cellID` frame position // IMPORTANT NOTE: this has only been tested for the dRICH; if you use it, test it carefully... -dd4hep::Position richgeo::ReadoutGeo::GetSensorLocalPosition(CellIDType cellID, dd4hep::Position pos) { +dd4hep::Position richgeo::ReadoutGeo::GetSensorLocalPosition(CellIDType cellID, + dd4hep::Position pos) { // get the VolumeManagerContext for this sensitive detector auto context = m_conv->findContext(cellID); diff --git a/src/services/geometry/richgeo/ReadoutGeo.h b/src/services/geometry/richgeo/ReadoutGeo.h index 00c952a10e..e0976b1bc9 100644 --- a/src/services/geometry/richgeo/ReadoutGeo.h +++ b/src/services/geometry/richgeo/ReadoutGeo.h @@ -24,70 +24,69 @@ #include "RichGeo.h" namespace richgeo { - class ReadoutGeo { - public: - - // constructor - ReadoutGeo(std::string detName_, gsl::not_null det_, gsl::not_null conv_, std::shared_ptr log_); - ~ReadoutGeo() {} - - // define cellID encoding - CellIDType cellIDEncoding(int isec, int ipdu, int isipm, int x, int y) - { - // encode cellID - dd4hep::rec::CellID cellID_dd4hep; - m_readoutCoder->set(cellID_dd4hep, "system", m_systemID); - m_readoutCoder->set(cellID_dd4hep, "sector", isec); - m_readoutCoder->set(cellID_dd4hep, "pdu", ipdu); - m_readoutCoder->set(cellID_dd4hep, "sipm", isipm); - m_readoutCoder->set(cellID_dd4hep, "x", x); - m_readoutCoder->set(cellID_dd4hep, "y", y); - CellIDType cellID(cellID_dd4hep); // in case DD4hep CellID type differs from EDM type - return cellID; - // m_log->trace(" x={:<2} y={:<2} => cellID={:#018X}", x, y, cellID); - } - - // loop over readout pixels, executing `lambda(cellID)` on each - void VisitAllReadoutPixels(std::function lambda) { m_loopCellIDs(lambda); } - - // generated k rng cell IDs, executing `lambda(cellID)` on each - void VisitAllRngPixels(std::function lambda, float p) { m_rngCellIDs(lambda, p); } - - // pixel gap mask - bool PixelGapMask(CellIDType cellID, dd4hep::Position pos_hit_global); - - // transform global position `pos` to sensor `id` frame position - // IMPORTANT NOTE: this has only been tested for the dRICH; if you use it, test it carefully... - dd4hep::Position GetSensorLocalPosition(CellIDType id, dd4hep::Position pos); - - // set RNG seed - void SetSeed(unsigned long seed) { m_random.SetSeed(seed); } - - protected: - - // common objects - std::shared_ptr m_log; - std::string m_detName; - gsl::not_null m_det; - gsl::not_null m_conv; - dd4hep::DetElement m_detRich; - dd4hep::BitFieldCoder* m_readoutCoder; - int m_systemID; - int m_num_sec; - int m_num_pdus; - int m_num_sipms_per_pdu; - int m_num_px; - double m_pixel_size; - - // local function to loop over cellIDs; defined in initialization and called by `VisitAllReadoutPixels` - std::function< void(std::function) > m_loopCellIDs; - // local function to generate rng cellIDs; defined in initialization and called by `VisitAllRngPixels` - std::function< void(std::function, float) > m_rngCellIDs; - - private: - - // random number generators - TRandomMixMax m_random; - - }; -} +class ReadoutGeo { +public: + // constructor + ReadoutGeo(std::string detName_, gsl::not_null det_, + gsl::not_null conv_, + std::shared_ptr log_); + ~ReadoutGeo() {} + + // define cellID encoding + CellIDType cellIDEncoding(int isec, int ipdu, int isipm, int x, int y) { + // encode cellID + dd4hep::rec::CellID cellID_dd4hep; + m_readoutCoder->set(cellID_dd4hep, "system", m_systemID); + m_readoutCoder->set(cellID_dd4hep, "sector", isec); + m_readoutCoder->set(cellID_dd4hep, "pdu", ipdu); + m_readoutCoder->set(cellID_dd4hep, "sipm", isipm); + m_readoutCoder->set(cellID_dd4hep, "x", x); + m_readoutCoder->set(cellID_dd4hep, "y", y); + CellIDType cellID(cellID_dd4hep); // in case DD4hep CellID type differs from EDM type + return cellID; + // m_log->trace(" x={:<2} y={:<2} => cellID={:#018X}", x, y, cellID); + } + + // loop over readout pixels, executing `lambda(cellID)` on each + void VisitAllReadoutPixels(std::function lambda) { m_loopCellIDs(lambda); } + + // generated k rng cell IDs, executing `lambda(cellID)` on each + void VisitAllRngPixels(std::function lambda, float p) { + m_rngCellIDs(lambda, p); + } + + // pixel gap mask + bool PixelGapMask(CellIDType cellID, dd4hep::Position pos_hit_global); + + // transform global position `pos` to sensor `id` frame position + // IMPORTANT NOTE: this has only been tested for the dRICH; if you use it, test it carefully... + dd4hep::Position GetSensorLocalPosition(CellIDType id, dd4hep::Position pos); + + // set RNG seed + void SetSeed(unsigned long seed) { m_random.SetSeed(seed); } + +protected: + // common objects + std::shared_ptr m_log; + std::string m_detName; + gsl::not_null m_det; + gsl::not_null m_conv; + dd4hep::DetElement m_detRich; + dd4hep::BitFieldCoder* m_readoutCoder; + int m_systemID; + int m_num_sec; + int m_num_pdus; + int m_num_sipms_per_pdu; + int m_num_px; + double m_pixel_size; + + // local function to loop over cellIDs; defined in initialization and called by `VisitAllReadoutPixels` + std::function)> m_loopCellIDs; + // local function to generate rng cellIDs; defined in initialization and called by `VisitAllRngPixels` + std::function, float)> m_rngCellIDs; + +private: + // random number generators + TRandomMixMax m_random; +}; +} // namespace richgeo diff --git a/src/services/geometry/richgeo/RichGeo.h b/src/services/geometry/richgeo/RichGeo.h index f8f38d7d02..25776e5e69 100644 --- a/src/services/geometry/richgeo/RichGeo.h +++ b/src/services/geometry/richgeo/RichGeo.h @@ -11,69 +11,79 @@ namespace richgeo { - using CellIDType = decltype(edm4hep::SimTrackerHitData::cellID); +using CellIDType = decltype(edm4hep::SimTrackerHitData::cellID); - // sensors - // ----------------------------------------------------------------------- - /* keep track of information for a sensor +// sensors +// ----------------------------------------------------------------------- +/* keep track of information for a sensor */ - class Sensor { - public: - Sensor() {}; - ~Sensor() {}; - double size; - dd4hep::Position surface_centroid; - dd4hep::Direction surface_offset; // surface centroid = volume centroid + `surface_offset` - }; +class Sensor { +public: + Sensor(){}; + ~Sensor(){}; + double size; + dd4hep::Position surface_centroid; + dd4hep::Direction surface_offset; // surface centroid = volume centroid + `surface_offset` +}; - // radiators - // ----------------------------------------------------------------------- - /* in many places in the reconstruction, we need to track which radiator +// radiators +// ----------------------------------------------------------------------- +/* in many places in the reconstruction, we need to track which radiator * we are referring to; these are common methods to enumerate them */ - enum radiator_enum { - kAerogel, - kGas, - nRadiators - }; +enum radiator_enum { kAerogel, kGas, nRadiators }; - // return radiator name associated with index - static std::string RadiatorName(int num, std::shared_ptr m_log = nullptr) { - if(num==kAerogel) return "Aerogel"; - else if(num==kGas) return "Gas"; - else { - if (m_log) m_log->error("unknown radiator number {}", num); - else std::cerr << "ERROR: unknown radiator number " << num << std::endl; - return "UNKNOWN_RADIATOR"; - } +// return radiator name associated with index +static std::string RadiatorName(int num, std::shared_ptr m_log = nullptr) { + if (num == kAerogel) + return "Aerogel"; + else if (num == kGas) + return "Gas"; + else { + if (m_log) + m_log->error("unknown radiator number {}", num); + else + std::cerr << "ERROR: unknown radiator number " << num << std::endl; + return "UNKNOWN_RADIATOR"; } +} - // return radiator index associated with name - static int RadiatorNum(std::string name, std::shared_ptr m_log = nullptr) { - if(name=="Aerogel") return kAerogel; - else if(name=="Gas") return kGas; - else { - if (m_log) m_log->error("unknown radiator name {}", name); - else std::cerr << "ERROR: unknown radiator name " << name << std::endl; - return -1; - } +// return radiator index associated with name +static int RadiatorNum(std::string name, std::shared_ptr m_log = nullptr) { + if (name == "Aerogel") + return kAerogel; + else if (name == "Gas") + return kGas; + else { + if (m_log) + m_log->error("unknown radiator name {}", name); + else + std::cerr << "ERROR: unknown radiator name " << name << std::endl; + return -1; } +} - static int RadiatorNum(const char * name, std::shared_ptr m_log = nullptr) { - return RadiatorNum(std::string(name), m_log); - } +static int RadiatorNum(const char* name, std::shared_ptr m_log = nullptr) { + return RadiatorNum(std::string(name), m_log); +} - // search string `input` for a radiator name; return corresponding index - static int ParseRadiatorName(std::string input, std::shared_ptr m_log = nullptr) { - if (input.find("aerogel")!=std::string::npos) return kAerogel; - else if (input.find("Aerogel")!=std::string::npos) return kAerogel; - else if (input.find("gas")!=std::string::npos) return kGas; - else if (input.find("Gas")!=std::string::npos) return kGas; - else { - if (m_log) m_log->error("failed to parse '{}' for radiator name", input); - else std::cerr << "ERROR: failed to parse '" << input << "' for radiator name" << std::endl; - return -1; - } +// search string `input` for a radiator name; return corresponding index +static int ParseRadiatorName(std::string input, std::shared_ptr m_log = nullptr) { + if (input.find("aerogel") != std::string::npos) + return kAerogel; + else if (input.find("Aerogel") != std::string::npos) + return kAerogel; + else if (input.find("gas") != std::string::npos) + return kGas; + else if (input.find("Gas") != std::string::npos) + return kGas; + else { + if (m_log) + m_log->error("failed to parse '{}' for radiator name", input); + else + std::cerr << "ERROR: failed to parse '" << input << "' for radiator name" << std::endl; + return -1; } - } + +} // namespace richgeo diff --git a/src/services/geometry/richgeo/RichGeo_service.cc b/src/services/geometry/richgeo/RichGeo_service.cc index 0f8ac714b9..747b3e65df 100644 --- a/src/services/geometry/richgeo/RichGeo_service.cc +++ b/src/services/geometry/richgeo/RichGeo_service.cc @@ -21,40 +21,44 @@ #include "services/log/Log_service.h" // Services ---------------------------------------------------------- -void RichGeo_service::acquire_services(JServiceLocator *srv_locator) { +void RichGeo_service::acquire_services(JServiceLocator* srv_locator) { // logging service - auto log_service = srv_locator->get(); - m_log = log_service->logger("richgeo"); + auto log_service = srv_locator->get(); + m_log = log_service->logger("richgeo"); std::string log_level_str = "info"; m_app->SetDefaultParameter("richgeo:LogLevel", log_level_str, "Log level for RichGeo_service"); m_log->set_level(eicrecon::ParseLogLevel(log_level_str)); - m_log->debug("RichGeo log level is set to {} ({})", log_level_str, fmt::underlying(m_log->level())); + m_log->debug("RichGeo log level is set to {} ({})", log_level_str, + fmt::underlying(m_log->level())); // DD4Hep geometry service auto dd4hep_service = srv_locator->get(); - m_dd4hepGeo = dd4hep_service->detector(); - m_converter = dd4hep_service->converter(); + m_dd4hepGeo = dd4hep_service->detector(); + m_converter = dd4hep_service->converter(); } // IrtGeo ----------------------------------------------------------- -richgeo::IrtGeo *RichGeo_service::GetIrtGeo(std::string detector_name) { +richgeo::IrtGeo* RichGeo_service::GetIrtGeo(std::string detector_name) { // initialize, if not yet initialized try { m_log->debug("Call RichGeo_service::GetIrtGeo initializer"); - auto initialize = [this,&detector_name] () { - if(!m_dd4hepGeo) throw JException("RichGeo_service m_dd4hepGeo==null which should never be!"); + auto initialize = [this, &detector_name]() { + if (!m_dd4hepGeo) + throw JException("RichGeo_service m_dd4hepGeo==null which should never be!"); // instantiate IrtGeo-derived object, depending on detector auto which_rich = detector_name; std::transform(which_rich.begin(), which_rich.end(), which_rich.begin(), ::toupper); - if ( which_rich=="DRICH" ) m_irtGeo = new richgeo::IrtGeoDRICH(m_dd4hepGeo, m_converter, m_log); - else if( which_rich=="PFRICH" ) m_irtGeo = new richgeo::IrtGeoPFRICH(m_dd4hepGeo, m_converter, m_log); - else throw JException(fmt::format("IrtGeo is not defined for detector '{}'",detector_name)); + if (which_rich == "DRICH") + m_irtGeo = new richgeo::IrtGeoDRICH(m_dd4hepGeo, m_converter, m_log); + else if (which_rich == "PFRICH") + m_irtGeo = new richgeo::IrtGeoPFRICH(m_dd4hepGeo, m_converter, m_log); + else + throw JException(fmt::format("IrtGeo is not defined for detector '{}'", detector_name)); }; std::call_once(m_init_irt, initialize); - } - catch (std::exception &ex) { + } catch (std::exception& ex) { throw JException(ex.what()); } @@ -62,17 +66,17 @@ richgeo::IrtGeo *RichGeo_service::GetIrtGeo(std::string detector_name) { } // ActsGeo ----------------------------------------------------------- -richgeo::ActsGeo *RichGeo_service::GetActsGeo(std::string detector_name) { +richgeo::ActsGeo* RichGeo_service::GetActsGeo(std::string detector_name) { // initialize, if not yet initialized try { m_log->debug("Call RichGeo_service::GetActsGeo initializer"); - auto initialize = [this,&detector_name] () { - if(!m_dd4hepGeo) throw JException("RichGeo_service m_dd4hepGeo==null which should never be!"); + auto initialize = [this, &detector_name]() { + if (!m_dd4hepGeo) + throw JException("RichGeo_service m_dd4hepGeo==null which should never be!"); m_actsGeo = new richgeo::ActsGeo(detector_name, m_dd4hepGeo, m_log); }; std::call_once(m_init_acts, initialize); - } - catch (std::exception &ex) { + } catch (std::exception& ex) { throw JException(ex.what()); } return m_actsGeo; @@ -83,13 +87,14 @@ std::shared_ptr RichGeo_service::GetReadoutGeo(std::string // initialize, if not yet initialized try { m_log->debug("Call RichGeo_service::GetReadoutGeo initializer"); - auto initialize = [this,&detector_name] () { - if(!m_dd4hepGeo) throw JException("RichGeo_service m_dd4hepGeo==null which should never be!"); - m_readoutGeo = std::make_shared(detector_name, m_dd4hepGeo, m_converter, m_log); + auto initialize = [this, &detector_name]() { + if (!m_dd4hepGeo) + throw JException("RichGeo_service m_dd4hepGeo==null which should never be!"); + m_readoutGeo = + std::make_shared(detector_name, m_dd4hepGeo, m_converter, m_log); }; std::call_once(m_init_readout, initialize); - } - catch (std::exception &ex) { + } catch (std::exception& ex) { throw JException(ex.what()); } return m_readoutGeo; @@ -100,5 +105,6 @@ RichGeo_service::~RichGeo_service() { try { delete m_irtGeo; delete m_actsGeo; - } catch (...) {} + } catch (...) { + } } diff --git a/src/services/geometry/richgeo/RichGeo_service.h b/src/services/geometry/richgeo/RichGeo_service.h index 1cb7c04551..0d920b70bb 100644 --- a/src/services/geometry/richgeo/RichGeo_service.h +++ b/src/services/geometry/richgeo/RichGeo_service.h @@ -18,31 +18,31 @@ #include "ReadoutGeo.h" class RichGeo_service : public JService { - public: - RichGeo_service(JApplication *app) : m_app(app) {} - virtual ~RichGeo_service(); - - // return pointer to the main DD4hep Detector - virtual const dd4hep::Detector* GetDD4hepGeo() { return m_dd4hepGeo; }; - - // return pointers to geometry bindings; initializes the bindings upon the first time called - virtual richgeo::IrtGeo *GetIrtGeo(std::string detector_name); - virtual richgeo::ActsGeo *GetActsGeo(std::string detector_name); - virtual std::shared_ptr GetReadoutGeo(std::string detector_name); - - private: - RichGeo_service() = default; - void acquire_services(JServiceLocator *) override; - - std::once_flag m_init_irt; - std::once_flag m_init_acts; - std::once_flag m_init_readout; - JApplication *m_app = nullptr; - const dd4hep::Detector* m_dd4hepGeo = nullptr; - const dd4hep::rec::CellIDPositionConverter* m_converter = nullptr; - richgeo::IrtGeo *m_irtGeo = nullptr; - richgeo::ActsGeo *m_actsGeo = nullptr; - std::shared_ptr m_readoutGeo; - - std::shared_ptr m_log; +public: + RichGeo_service(JApplication* app) : m_app(app) {} + virtual ~RichGeo_service(); + + // return pointer to the main DD4hep Detector + virtual const dd4hep::Detector* GetDD4hepGeo() { return m_dd4hepGeo; }; + + // return pointers to geometry bindings; initializes the bindings upon the first time called + virtual richgeo::IrtGeo* GetIrtGeo(std::string detector_name); + virtual richgeo::ActsGeo* GetActsGeo(std::string detector_name); + virtual std::shared_ptr GetReadoutGeo(std::string detector_name); + +private: + RichGeo_service() = default; + void acquire_services(JServiceLocator*) override; + + std::once_flag m_init_irt; + std::once_flag m_init_acts; + std::once_flag m_init_readout; + JApplication* m_app = nullptr; + const dd4hep::Detector* m_dd4hepGeo = nullptr; + const dd4hep::rec::CellIDPositionConverter* m_converter = nullptr; + richgeo::IrtGeo* m_irtGeo = nullptr; + richgeo::ActsGeo* m_actsGeo = nullptr; + std::shared_ptr m_readoutGeo; + + std::shared_ptr m_log; }; diff --git a/src/services/geometry/richgeo/richgeo.cc b/src/services/geometry/richgeo/richgeo.cc index da7a90f7aa..aeb1d22585 100644 --- a/src/services/geometry/richgeo/richgeo.cc +++ b/src/services/geometry/richgeo/richgeo.cc @@ -9,8 +9,8 @@ #include "RichGeo_service.h" extern "C" { - void InitPlugin(JApplication *app) { - InitJANAPlugin(app); - app->ProvideService(std::make_shared(app) ); - } +void InitPlugin(JApplication* app) { + InitJANAPlugin(app); + app->ProvideService(std::make_shared(app)); +} } diff --git a/src/services/io/podio/JEventProcessorPODIO.cc b/src/services/io/podio/JEventProcessorPODIO.cc index 80b43c428e..03f5f16824 100644 --- a/src/services/io/podio/JEventProcessorPODIO.cc +++ b/src/services/io/podio/JEventProcessorPODIO.cc @@ -13,425 +13,302 @@ #include "services/log/Log_service.h" - JEventProcessorPODIO::JEventProcessorPODIO() { - SetTypeName(NAME_OF_THIS); // Provide JANA with this class's name - - japp->SetDefaultParameter( - "podio:output_file", - m_output_file, - "Name of EDM4hep/podio output file to write to. Setting this will cause the output file to be created and written to." - ); - - // Allow user to set PODIO:OUTPUT_FILE to "1" to specify using the default name. - if( m_output_file == "1" ){ - auto param = japp->GetJParameterManager()->FindParameter("podio:output_file" ); - if(param) { - param->SetValue( param->GetDefault() ); - m_output_file = param->GetDefault(); - } + SetTypeName(NAME_OF_THIS); // Provide JANA with this class's name + + japp->SetDefaultParameter("podio:output_file", m_output_file, + "Name of EDM4hep/podio output file to write to. Setting this will " + "cause the output file to be created and written to."); + + // Allow user to set PODIO:OUTPUT_FILE to "1" to specify using the default name. + if (m_output_file == "1") { + auto param = japp->GetJParameterManager()->FindParameter("podio:output_file"); + if (param) { + param->SetValue(param->GetDefault()); + m_output_file = param->GetDefault(); } - - // Get the output directory path for creating a second copy of the output file at the end of processing. - // (this is duplicating similar functionality in Juggler/Gaudi so assume it is useful). - japp->SetDefaultParameter( - "podio:output_file_copy_dir", - m_output_file_copy_dir, - "Directory name to make an additional copy of the output file to. Copy will be done at end of processing. Default is empty string which means do not make a copy. No check is made on path existing." - ); - - // Get the list of output collections to include/exclude - std::vector output_include_collections={ - // Header and other metadata - "EventHeader", - - // Truth record - "MCParticles", - "BeamElectrons", - "BeamProtons", - - // All tracking hits combined - "CentralTrackingRecHits", - "CentralTrackSeedingResults", - "CentralTrackerMeasurements", - - // Si tracker hits - "SiBarrelTrackerRecHits", - "SiBarrelVertexRecHits", - "SiEndcapTrackerRecHits", - - "SiBarrelRawHits", - "SiBarrelVertexRawHits", - "SiEndcapTrackerRawHits", - - "SiBarrelHits", - "VertexBarrelHits", - "TrackerEndcapHits", - - // TOF - "TOFBarrelRecHit", - "TOFEndcapRecHits", - - "TOFBarrelRawHit", - "TOFEndcapRawHits", - - "TOFBarrelHits", - "TOFEndcapHits", - // DRICH - "DRICHRawHits", - "DRICHRawHitsAssociations", - "DRICHAerogelTracks", - "DRICHGasTracks", - "DRICHAerogelIrtCherenkovParticleID", - "DRICHGasIrtCherenkovParticleID", - - // MPGD - "MPGDBarrelRecHits", - "MPGDDIRCRecHits", - "OuterMPGDBarrelRecHits", - "BackwardMPGDEndcapRecHits", - "ForwardMPGDEndcapRecHits", - - "MPGDBarrelRawHits", - "MPGDDIRCRawHits", - "OuterMPGDBarrelRawHits", - "BackwardMPGDEndcapRawHits", - "ForwardMPGDEndcapRawHits", - - "MPGDBarrelHits", - "MPGDDIRCHits", - "OuterMPGDBarrelHits", - "BackwardMPGDEndcapHits", - "ForwardMPGDEndcapHits", - // LOWQ2 hits - "TaggerTrackerRawHits", - - // Forward & Far forward hits - "B0TrackerRecHits", - "B0TrackerRawHits", - "B0TrackerHits", - "ForwardRomanPotRecHits", - "ForwardOffMTrackerRecHits", - // - "ForwardRomanPotRecParticles", - "ForwardOffMRecParticles", - - // Reconstructed data - "GeneratedParticles", - "ReconstructedParticles", - "ReconstructedParticleAssociations", - "ReconstructedChargedParticles", - "ReconstructedChargedParticleAssociations", - "ReconstructedSeededChargedParticles", - "ReconstructedSeededChargedParticleAssociations", - "ReconstructedChargedParticleIDs", - "ReconstructedBreitFrameParticles", - "CentralTrackSegments", - "CentralTrackVertices", - "CentralCKFTrajectories", - "CentralCKFTracks", - "CentralCKFTrackParameters", - "CentralCKFSeededTrajectories", - "CentralCKFSeededTracks", - "CentralCKFSeededTrackParameters", - "InclusiveKinematicsDA", - "InclusiveKinematicsJB", - "InclusiveKinematicsSigma", - "InclusiveKinematicseSigma", - "InclusiveKinematicsElectron", - "InclusiveKinematicsTruth", - "GeneratedJets", - "GeneratedChargedJets", - "ReconstructedJets", - "ReconstructedChargedJets", - "ReconstructedElectrons", - "ScatteredElectronsTruth", - "ScatteredElectronsEMinusPz", - - // Track projections - "CalorimeterTrackProjections", - - // Ecal stuff - "EcalEndcapNRawHits", - "EcalEndcapNRecHits", - "EcalEndcapNTruthClusters", - "EcalEndcapNTruthClusterAssociations", - "EcalEndcapNClusters", - "EcalEndcapNClusterAssociations", - "EcalEndcapPRawHits", - "EcalEndcapPRecHits", - "EcalEndcapPTruthClusters", - "EcalEndcapPTruthClusterAssociations", - "EcalEndcapPClusters", - "EcalEndcapPClusterAssociations", - "EcalEndcapPInsertRawHits", - "EcalEndcapPInsertRecHits", - "EcalEndcapPInsertTruthClusters", - "EcalEndcapPInsertTruthClusterAssociations", - "EcalEndcapPInsertClusters", - "EcalEndcapPInsertClusterAssociations", - "EcalBarrelClusters", - "EcalBarrelClusterAssociations", - "EcalBarrelTruthClusters", - "EcalBarrelTruthClusterAssociations", - "EcalBarrelImagingRawHits", - "EcalBarrelImagingRecHits", - "EcalBarrelImagingClusters", - "EcalBarrelImagingClusterAssociations", - "EcalBarrelScFiRawHits", - "EcalBarrelScFiRecHits", - "EcalBarrelScFiClusters", - "EcalBarrelScFiClusterAssociations", - "EcalLumiSpecRawHits", - "EcalLumiSpecRecHits", - "EcalLumiSpecTruthClusters", - "EcalLumiSpecTruthClusterAssociations", - "EcalLumiSpecClusters", - "EcalLumiSpecClusterAssociations", - "HcalEndcapNRawHits", - "HcalEndcapNRecHits", - "HcalEndcapNMergedHits", - "HcalEndcapNClusters", - "HcalEndcapNClusterAssociations", - "HcalEndcapPInsertRawHits", - "HcalEndcapPInsertRecHits", - "HcalEndcapPInsertMergedHits", - "HcalEndcapPInsertClusters", - "HcalEndcapPInsertClusterAssociations", - "LFHCALRawHits", - "LFHCALRecHits", - "LFHCALClusters", - "LFHCALClusterAssociations", - "HcalBarrelRawHits", - "HcalBarrelRecHits", - "HcalBarrelClusters", - "HcalBarrelClusterAssociations", - "B0ECalRawHits", - "B0ECalRecHits", - "B0ECalClusters", - "B0ECalClusterAssociations", - "HcalEndcapNTruthClusters", - "HcalEndcapNTruthClusterAssociations", - "HcalBarrelTruthClusters", - "HcalBarrelTruthClusterAssociations", - "B0ECalRecHits", - "B0ECalClusters", - "B0ECalClusterAssociations", - - //ZDC Ecal - "EcalFarForwardZDCRawHits", - "EcalFarForwardZDCRecHits", - "EcalFarForwardZDCClusters", - "EcalFarForwardZDCClusterAssociations", - "EcalFarForwardZDCTruthClusters", - "EcalFarForwardZDCTruthClusterAssociations", - - //ZDC HCal - "HcalFarForwardZDCRawHits", - "HcalFarForwardZDCRecHits", - "HcalFarForwardZDCSubcellHits", - "HcalFarForwardZDCClusters", - "HcalFarForwardZDCClusterAssociations", - "HcalFarForwardZDCClustersBaseline", - "HcalFarForwardZDCClusterAssociationsBaseline", - "HcalFarForwardZDCTruthClusters", - "HcalFarForwardZDCTruthClusterAssociations", - - - // DIRC - "DIRCRawHits" - }; - std::vector output_exclude_collections; // need to get as vector, then convert to set - japp->SetDefaultParameter( - "podio:output_include_collections", - output_include_collections, - "Comma separated list of collection names to write out. If not set, all collections will be written (including ones from input file). Don't set this and use PODIO:OUTPUT_EXCLUDE_COLLECTIONS to write everything except a selection." - ); - japp->SetDefaultParameter( - "podio:output_exclude_collections", - output_exclude_collections, - "Comma separated list of collection names to not write out." - ); - japp->SetDefaultParameter( - "podio:print_collections", - m_collections_to_print, - "Comma separated list of collection names to print to screen, e.g. for debugging." - ); - - m_output_include_collections = std::set(output_include_collections.begin(), - output_include_collections.end()); - m_output_exclude_collections = std::set(output_exclude_collections.begin(), - output_exclude_collections.end()); - + } + + // Get the output directory path for creating a second copy of the output file at the end of processing. + // (this is duplicating similar functionality in Juggler/Gaudi so assume it is useful). + japp->SetDefaultParameter("podio:output_file_copy_dir", m_output_file_copy_dir, + "Directory name to make an additional copy of the output file to. Copy " + "will be done at end of processing. Default is empty string which " + "means do not make a copy. No check is made on path existing."); + + // Get the list of output collections to include/exclude + std::vector output_include_collections = { + // Header and other metadata + "EventHeader", + + // Truth record + "MCParticles", "BeamElectrons", "BeamProtons", + + // All tracking hits combined + "CentralTrackingRecHits", "CentralTrackSeedingResults", "CentralTrackerMeasurements", + + // Si tracker hits + "SiBarrelTrackerRecHits", "SiBarrelVertexRecHits", "SiEndcapTrackerRecHits", + + "SiBarrelRawHits", "SiBarrelVertexRawHits", "SiEndcapTrackerRawHits", + + "SiBarrelHits", "VertexBarrelHits", "TrackerEndcapHits", + + // TOF + "TOFBarrelRecHit", "TOFEndcapRecHits", + + "TOFBarrelRawHit", "TOFEndcapRawHits", + + "TOFBarrelHits", "TOFEndcapHits", + // DRICH + "DRICHRawHits", "DRICHRawHitsAssociations", "DRICHAerogelTracks", "DRICHGasTracks", + "DRICHAerogelIrtCherenkovParticleID", "DRICHGasIrtCherenkovParticleID", + + // MPGD + "MPGDBarrelRecHits", "MPGDDIRCRecHits", "OuterMPGDBarrelRecHits", "BackwardMPGDEndcapRecHits", + "ForwardMPGDEndcapRecHits", + + "MPGDBarrelRawHits", "MPGDDIRCRawHits", "OuterMPGDBarrelRawHits", "BackwardMPGDEndcapRawHits", + "ForwardMPGDEndcapRawHits", + + "MPGDBarrelHits", "MPGDDIRCHits", "OuterMPGDBarrelHits", "BackwardMPGDEndcapHits", + "ForwardMPGDEndcapHits", + // LOWQ2 hits + "TaggerTrackerRawHits", + + // Forward & Far forward hits + "B0TrackerRecHits", "B0TrackerRawHits", "B0TrackerHits", "ForwardRomanPotRecHits", + "ForwardOffMTrackerRecHits", + // + "ForwardRomanPotRecParticles", "ForwardOffMRecParticles", + + // Reconstructed data + "GeneratedParticles", "ReconstructedParticles", "ReconstructedParticleAssociations", + "ReconstructedChargedParticles", "ReconstructedChargedParticleAssociations", + "ReconstructedSeededChargedParticles", "ReconstructedSeededChargedParticleAssociations", + "ReconstructedChargedParticleIDs", "ReconstructedBreitFrameParticles", "CentralTrackSegments", + "CentralTrackVertices", "CentralCKFTrajectories", "CentralCKFTracks", + "CentralCKFTrackParameters", "CentralCKFSeededTrajectories", "CentralCKFSeededTracks", + "CentralCKFSeededTrackParameters", "InclusiveKinematicsDA", "InclusiveKinematicsJB", + "InclusiveKinematicsSigma", "InclusiveKinematicseSigma", "InclusiveKinematicsElectron", + "InclusiveKinematicsTruth", "GeneratedJets", "GeneratedChargedJets", "ReconstructedJets", + "ReconstructedChargedJets", "ReconstructedElectrons", "ScatteredElectronsTruth", + "ScatteredElectronsEMinusPz", + + // Track projections + "CalorimeterTrackProjections", + + // Ecal stuff + "EcalEndcapNRawHits", "EcalEndcapNRecHits", "EcalEndcapNTruthClusters", + "EcalEndcapNTruthClusterAssociations", "EcalEndcapNClusters", + "EcalEndcapNClusterAssociations", "EcalEndcapPRawHits", "EcalEndcapPRecHits", + "EcalEndcapPTruthClusters", "EcalEndcapPTruthClusterAssociations", "EcalEndcapPClusters", + "EcalEndcapPClusterAssociations", "EcalEndcapPInsertRawHits", "EcalEndcapPInsertRecHits", + "EcalEndcapPInsertTruthClusters", "EcalEndcapPInsertTruthClusterAssociations", + "EcalEndcapPInsertClusters", "EcalEndcapPInsertClusterAssociations", "EcalBarrelClusters", + "EcalBarrelClusterAssociations", "EcalBarrelTruthClusters", + "EcalBarrelTruthClusterAssociations", "EcalBarrelImagingRawHits", "EcalBarrelImagingRecHits", + "EcalBarrelImagingClusters", "EcalBarrelImagingClusterAssociations", "EcalBarrelScFiRawHits", + "EcalBarrelScFiRecHits", "EcalBarrelScFiClusters", "EcalBarrelScFiClusterAssociations", + "EcalLumiSpecRawHits", "EcalLumiSpecRecHits", "EcalLumiSpecTruthClusters", + "EcalLumiSpecTruthClusterAssociations", "EcalLumiSpecClusters", + "EcalLumiSpecClusterAssociations", "HcalEndcapNRawHits", "HcalEndcapNRecHits", + "HcalEndcapNMergedHits", "HcalEndcapNClusters", "HcalEndcapNClusterAssociations", + "HcalEndcapPInsertRawHits", "HcalEndcapPInsertRecHits", "HcalEndcapPInsertMergedHits", + "HcalEndcapPInsertClusters", "HcalEndcapPInsertClusterAssociations", "LFHCALRawHits", + "LFHCALRecHits", "LFHCALClusters", "LFHCALClusterAssociations", "HcalBarrelRawHits", + "HcalBarrelRecHits", "HcalBarrelClusters", "HcalBarrelClusterAssociations", "B0ECalRawHits", + "B0ECalRecHits", "B0ECalClusters", "B0ECalClusterAssociations", "HcalEndcapNTruthClusters", + "HcalEndcapNTruthClusterAssociations", "HcalBarrelTruthClusters", + "HcalBarrelTruthClusterAssociations", "B0ECalRecHits", "B0ECalClusters", + "B0ECalClusterAssociations", + + //ZDC Ecal + "EcalFarForwardZDCRawHits", "EcalFarForwardZDCRecHits", "EcalFarForwardZDCClusters", + "EcalFarForwardZDCClusterAssociations", "EcalFarForwardZDCTruthClusters", + "EcalFarForwardZDCTruthClusterAssociations", + + //ZDC HCal + "HcalFarForwardZDCRawHits", "HcalFarForwardZDCRecHits", "HcalFarForwardZDCSubcellHits", + "HcalFarForwardZDCClusters", "HcalFarForwardZDCClusterAssociations", + "HcalFarForwardZDCClustersBaseline", "HcalFarForwardZDCClusterAssociationsBaseline", + "HcalFarForwardZDCTruthClusters", "HcalFarForwardZDCTruthClusterAssociations", + + // DIRC + "DIRCRawHits"}; + std::vector output_exclude_collections; // need to get as vector, then convert to set + japp->SetDefaultParameter( + "podio:output_include_collections", output_include_collections, + "Comma separated list of collection names to write out. If not set, all collections will be " + "written (including ones from input file). Don't set this and use " + "PODIO:OUTPUT_EXCLUDE_COLLECTIONS to write everything except a selection."); + japp->SetDefaultParameter("podio:output_exclude_collections", output_exclude_collections, + "Comma separated list of collection names to not write out."); + japp->SetDefaultParameter( + "podio:print_collections", m_collections_to_print, + "Comma separated list of collection names to print to screen, e.g. for debugging."); + + m_output_include_collections = + std::set(output_include_collections.begin(), output_include_collections.end()); + m_output_exclude_collections = + std::set(output_exclude_collections.begin(), output_exclude_collections.end()); } - void JEventProcessorPODIO::Init() { - auto *app = GetApplication(); - m_log = app->GetService()->logger("JEventProcessorPODIO"); - m_log->set_level(spdlog::level::debug); - m_writer = std::make_unique(m_output_file); - // TODO: NWB: Verify that output file is writable NOW, rather than after event processing completes. - // I definitely don't trust PODIO to do this for me. - + auto* app = GetApplication(); + m_log = app->GetService()->logger("JEventProcessorPODIO"); + m_log->set_level(spdlog::level::debug); + m_writer = std::make_unique(m_output_file); + // TODO: NWB: Verify that output file is writable NOW, rather than after event processing completes. + // I definitely don't trust PODIO to do this for me. } - void JEventProcessorPODIO::FindCollectionsToWrite(const std::shared_ptr& event) { - // Set up the set of collections_to_write. - std::vector all_collections = event->GetAllCollectionNames(); + // Set up the set of collections_to_write. + std::vector all_collections = event->GetAllCollectionNames(); - if (m_output_include_collections.empty()) { - // User has not specified an include list, so we include _all_ PODIO collections present in the first event. - for (const std::string& col : all_collections) { - if (m_output_exclude_collections.find(col) == m_output_exclude_collections.end()) { - m_collections_to_write.push_back(col); - m_log->info("Persisting collection '{}'", col); - } - } + if (m_output_include_collections.empty()) { + // User has not specified an include list, so we include _all_ PODIO collections present in the first event. + for (const std::string& col : all_collections) { + if (m_output_exclude_collections.find(col) == m_output_exclude_collections.end()) { + m_collections_to_write.push_back(col); + m_log->info("Persisting collection '{}'", col); + } } - else { - m_log->debug("Persisting podio types from includes list"); - m_user_included_collections = true; - - // We match up the include list with what is actually present in the event - std::set all_collections_set = std::set(all_collections.begin(), all_collections.end()); - - for (const auto& col : m_output_include_collections) { - if (m_output_exclude_collections.find(col) == m_output_exclude_collections.end()) { - // Included and not excluded - if (all_collections_set.find(col) == all_collections_set.end()) { - // Included, but not a valid PODIO type - m_log->warn("Explicitly included collection '{}' not present in factory set, omitting.", col); - } - else { - // Included, not excluded, and a valid PODIO type - m_collections_to_write.push_back(col); - m_log->info("Persisting collection '{}'", col); - } - } + } else { + m_log->debug("Persisting podio types from includes list"); + m_user_included_collections = true; + + // We match up the include list with what is actually present in the event + std::set all_collections_set = + std::set(all_collections.begin(), all_collections.end()); + + for (const auto& col : m_output_include_collections) { + if (m_output_exclude_collections.find(col) == m_output_exclude_collections.end()) { + // Included and not excluded + if (all_collections_set.find(col) == all_collections_set.end()) { + // Included, but not a valid PODIO type + m_log->warn("Explicitly included collection '{}' not present in factory set, omitting.", + col); + } else { + // Included, not excluded, and a valid PODIO type + m_collections_to_write.push_back(col); + m_log->info("Persisting collection '{}'", col); } + } } - + } } -void JEventProcessorPODIO::Process(const std::shared_ptr &event) { - - std::lock_guard lock(m_mutex); - if (m_is_first_event) { - FindCollectionsToWrite(event); - } - - // Trigger all collections once to fix the collection IDs - // TODO: WDC: This should not be necessary, but while we await collection IDs - // that are determined by hash, we have to ensure they are reproducible - // even if the collections are filled in unpredictable order (or not at - // all). See also below, at "TODO: NWB:". - for (const auto& coll_name : m_collections_to_write) { - try { - [[maybe_unused]] - const auto* coll_ptr = event->GetCollectionBase(coll_name); - } - catch(std::exception &e) { - // chomp - } +void JEventProcessorPODIO::Process(const std::shared_ptr& event) { + + std::lock_guard lock(m_mutex); + if (m_is_first_event) { + FindCollectionsToWrite(event); + } + + // Trigger all collections once to fix the collection IDs + // TODO: WDC: This should not be necessary, but while we await collection IDs + // that are determined by hash, we have to ensure they are reproducible + // even if the collections are filled in unpredictable order (or not at + // all). See also below, at "TODO: NWB:". + for (const auto& coll_name : m_collections_to_write) { + try { + [[maybe_unused]] + const auto* coll_ptr = event->GetCollectionBase(coll_name); + } catch (std::exception& e) { + // chomp } - - // Print the contents of some collections, just for debugging purposes - // Do this before writing just in case writing crashes - if (!m_collections_to_print.empty()) { - LOG << "========================================" << LOG_END; - LOG << "JEventProcessorPODIO: Event " << event->GetEventNumber() << LOG_END; + } + + // Print the contents of some collections, just for debugging purposes + // Do this before writing just in case writing crashes + if (!m_collections_to_print.empty()) { + LOG << "========================================" << LOG_END; + LOG << "JEventProcessorPODIO: Event " << event->GetEventNumber() << LOG_END; + } + for (const auto& coll_name : m_collections_to_print) { + LOG << "------------------------------" << LOG_END; + LOG << coll_name << LOG_END; + try { + const auto* coll_ptr = event->GetCollectionBase(coll_name); + if (coll_ptr == nullptr) { + LOG << "missing" << LOG_END; + } else { + coll_ptr->print(); + } + } catch (std::exception& e) { + LOG << "missing" << LOG_END; } - for (const auto& coll_name : m_collections_to_print) { - LOG << "------------------------------" << LOG_END; - LOG << coll_name << LOG_END; - try { - const auto* coll_ptr = event->GetCollectionBase(coll_name); - if (coll_ptr == nullptr) { - LOG << "missing" << LOG_END; - } else { - coll_ptr->print(); - } - } - catch(std::exception &e) { - LOG << "missing" << LOG_END; + } + + m_log->trace("=================================="); + m_log->trace("Event #{}", event->GetEventNumber()); + + // Make sure that all factories get called that need to be written into the frame. + // We need to do this for _all_ factories unless we've constrained it by using includes/excludes. + // Note that all collections need to be present in the first event, as podio::RootFrameWriter constrains us to write one event at a time, so there + // is no way to add a new branch after the first event. + + // If we get an exception below while trying to add a factory for any + // reason then mark that factory as bad and don't try running it again. + // This is motivated by trying to write EcalBarrelSciGlass objects for + // data simulated using the imaging calorimeter. In that case, it will + // always throw an exception, but DD4hep also prints its own error message. + // Thus, to prevent that error message every event, we must avoid calling + // it. + + // Activate factories. + // TODO: NWB: For now we run every factory every time, swallowing exceptions if necessary. + // We do this so that we always have the same collections created in the same order. + // This means that the collection IDs are stable so the writer doesn't segfault. + // The better fix is to maintain a map of collection IDs, or just wait for PODIO to fix the bug. + std::vector successful_collections; + static std::set failed_collections; + for (const std::string& coll : m_collections_to_write) { + try { + m_log->trace("Ensuring factory for collection '{}' has been called.", coll); + const auto* coll_ptr = event->GetCollectionBase(coll); + if (coll_ptr == nullptr) { + // If a collection is missing from the frame, the podio root writer will segfault. + // To avoid this, we treat this as a failing collection and omit from this point onwards. + // However, this code path is expected to be unreachable because any missing collection will be + // replaced with an empty collection in JFactoryPodioTFixed::Create. + if (failed_collections.count(coll) == 0) { + m_log->error("Omitting PODIO collection '{}' because it is null", coll); + failed_collections.insert(coll); } + } else { + m_log->trace("Including PODIO collection '{}'", coll); + successful_collections.push_back(coll); + } + } catch (std::exception& e) { + // Limit printing warning to just once per factory + if (failed_collections.count(coll) == 0) { + m_log->error("Omitting PODIO collection '{}' due to exception: {}.", coll, e.what()); + failed_collections.insert(coll); + } } + } + m_collections_to_write = successful_collections; - m_log->trace("=================================="); - m_log->trace("Event #{}", event->GetEventNumber()); - - - // Make sure that all factories get called that need to be written into the frame. - // We need to do this for _all_ factories unless we've constrained it by using includes/excludes. - // Note that all collections need to be present in the first event, as podio::RootFrameWriter constrains us to write one event at a time, so there - // is no way to add a new branch after the first event. - - // If we get an exception below while trying to add a factory for any - // reason then mark that factory as bad and don't try running it again. - // This is motivated by trying to write EcalBarrelSciGlass objects for - // data simulated using the imaging calorimeter. In that case, it will - // always throw an exception, but DD4hep also prints its own error message. - // Thus, to prevent that error message every event, we must avoid calling - // it. - - // Activate factories. - // TODO: NWB: For now we run every factory every time, swallowing exceptions if necessary. - // We do this so that we always have the same collections created in the same order. - // This means that the collection IDs are stable so the writer doesn't segfault. - // The better fix is to maintain a map of collection IDs, or just wait for PODIO to fix the bug. - std::vector successful_collections; - static std::set failed_collections; - for (const std::string& coll : m_collections_to_write) { - try { - m_log->trace("Ensuring factory for collection '{}' has been called.", coll); - const auto* coll_ptr = event->GetCollectionBase(coll); - if (coll_ptr == nullptr) { - // If a collection is missing from the frame, the podio root writer will segfault. - // To avoid this, we treat this as a failing collection and omit from this point onwards. - // However, this code path is expected to be unreachable because any missing collection will be - // replaced with an empty collection in JFactoryPodioTFixed::Create. - if (failed_collections.count(coll) == 0) { - m_log->error("Omitting PODIO collection '{}' because it is null", coll); - failed_collections.insert(coll); - } - } - else { - m_log->trace("Including PODIO collection '{}'", coll); - successful_collections.push_back(coll); - } - } - catch(std::exception &e) { - // Limit printing warning to just once per factory - if (failed_collections.count(coll) == 0) { - m_log->error("Omitting PODIO collection '{}' due to exception: {}.", coll, e.what()); - failed_collections.insert(coll); - } - } - } - m_collections_to_write = successful_collections; - - // Frame will contain data from all Podio factories that have been triggered, - // including by the `event->GetCollectionBase(coll);` above. - // Note that collections MUST be present in frame. If a collection is null, the writer will segfault. - const auto* frame = event->GetSingle(); + // Frame will contain data from all Podio factories that have been triggered, + // including by the `event->GetCollectionBase(coll);` above. + // Note that collections MUST be present in frame. If a collection is null, the writer will segfault. + const auto* frame = event->GetSingle(); - // TODO: NWB: We need to actively stabilize podio collections. Until then, keep this around in case - // the writer starts segfaulting, so we can quickly see whether the problem is unstable collection IDs. - /* + // TODO: NWB: We need to actively stabilize podio collections. Until then, keep this around in case + // the writer starts segfaulting, so we can quickly see whether the problem is unstable collection IDs. + /* m_log->info("Event {}: Writing {} collections", event->GetEventNumber(), m_collections_to_write.size()); for (const std::string& collname : m_collections_to_write) { m_log->info("Writing collection '{}' with id {}", collname, frame->get(collname)->getID()); } */ - m_writer->writeFrame(*frame, "events", m_collections_to_write); - m_is_first_event = false; - + m_writer->writeFrame(*frame, "events", m_collections_to_write); + m_is_first_event = false; } -void JEventProcessorPODIO::Finish() { - m_writer->finish(); -} +void JEventProcessorPODIO::Finish() { m_writer->finish(); } diff --git a/src/services/io/podio/JEventProcessorPODIO.h b/src/services/io/podio/JEventProcessorPODIO.h index 4ab126a140..a2de0be64a 100644 --- a/src/services/io/podio/JEventProcessorPODIO.h +++ b/src/services/io/podio/JEventProcessorPODIO.h @@ -11,31 +11,28 @@ #include #include - class JEventProcessorPODIO : public JEventProcessor { public: - - JEventProcessorPODIO(); - virtual ~JEventProcessorPODIO() = default; - - void Init() override; - void Process(const std::shared_ptr& event) override; - void Finish() override; - - void FindCollectionsToWrite(const std::shared_ptr& event); - - std::unique_ptr m_writer; - std::mutex m_mutex; - bool m_is_first_event = true; - bool m_user_included_collections = false; - std::shared_ptr m_log; - - std::string m_output_file = "podio_output.root"; - std::string m_output_file_copy_dir = ""; - std::set m_output_include_collections; // config. parameter - std::set m_output_exclude_collections; // config. parameter - std::vector m_collections_to_write; // derived from above config. parameters - std::vector m_collections_to_print; - + JEventProcessorPODIO(); + virtual ~JEventProcessorPODIO() = default; + + void Init() override; + void Process(const std::shared_ptr& event) override; + void Finish() override; + + void FindCollectionsToWrite(const std::shared_ptr& event); + + std::unique_ptr m_writer; + std::mutex m_mutex; + bool m_is_first_event = true; + bool m_user_included_collections = false; + std::shared_ptr m_log; + + std::string m_output_file = "podio_output.root"; + std::string m_output_file_copy_dir = ""; + std::set m_output_include_collections; // config. parameter + std::set m_output_exclude_collections; // config. parameter + std::vector m_collections_to_write; // derived from above config. parameters + std::vector m_collections_to_print; }; diff --git a/src/services/io/podio/JEventSourcePODIO.cc b/src/services/io/podio/JEventSourcePODIO.cc index 1d60140ff2..30074f186d 100644 --- a/src/services/io/podio/JEventSourcePODIO.cc +++ b/src/services/io/podio/JEventSourcePODIO.cc @@ -33,7 +33,6 @@ #include "services/io/podio/datamodel_glue.h" #include "services/io/podio/datamodel_includes.h" // IWYU pragma: keep - //------------------------------------------------------------------------------ // InsertingVisitor // @@ -46,20 +45,19 @@ /// \param collection_name name of the collection which will be used as the factory tag for these objects //------------------------------------------------------------------------------ struct InsertingVisitor { - JEvent& m_event; - const std::string& m_collection_name; + JEvent& m_event; + const std::string& m_collection_name; - InsertingVisitor(JEvent& event, const std::string& collection_name) : m_event(event), m_collection_name(collection_name){}; + InsertingVisitor(JEvent& event, const std::string& collection_name) + : m_event(event), m_collection_name(collection_name){}; - template - void operator() (const T& collection) { + template void operator()(const T& collection) { - using ContentsT = decltype(collection[0]); - m_event.InsertCollectionAlreadyInFrame(&collection, m_collection_name); - } + using ContentsT = decltype(collection[0]); + m_event.InsertCollectionAlreadyInFrame(&collection, m_collection_name); + } }; - //------------------------------------------------------------------------------ // Constructor // @@ -67,30 +65,25 @@ struct InsertingVisitor { /// \param resource_name Name of root file to open (n.b. file is not opened until Open() is called) /// \param app JApplication //------------------------------------------------------------------------------ -JEventSourcePODIO::JEventSourcePODIO(std::string resource_name, JApplication* app) : JEventSource(resource_name, app) { - SetTypeName(NAME_OF_THIS); // Provide JANA with class name +JEventSourcePODIO::JEventSourcePODIO(std::string resource_name, JApplication* app) + : JEventSource(resource_name, app) { + SetTypeName(NAME_OF_THIS); // Provide JANA with class name - // Tell JANA that we want it to call the FinishEvent() method. - // EnableFinishEvent(); + // Tell JANA that we want it to call the FinishEvent() method. + // EnableFinishEvent(); - // Allow user to specify to recycle events forever - GetApplication()->SetDefaultParameter( - "podio:run_forever", - m_run_forever, - "set to true to recycle through events continuously" - ); + // Allow user to specify to recycle events forever + GetApplication()->SetDefaultParameter("podio:run_forever", m_run_forever, + "set to true to recycle through events continuously"); - bool print_type_table = false; - GetApplication()->SetDefaultParameter( - "podio:print_type_table", - print_type_table, - "Print list of collection names and their types" - ); + bool print_type_table = false; + GetApplication()->SetDefaultParameter("podio:print_type_table", print_type_table, + "Print list of collection names and their types"); - // Hopefully we won't need to reimplement background event merging. Using podio frames, it looks like we would - // have to do a deep copy of all data in order to insert it into the same frame, which would probably be - // quite inefficient. - /* + // Hopefully we won't need to reimplement background event merging. Using podio frames, it looks like we would + // have to do a deep copy of all data in order to insert it into the same frame, which would probably be + // quite inefficient. + /* std::string background_filename; GetApplication()->SetDefaultParameter( "podio:background_filename", @@ -111,7 +104,7 @@ JEventSourcePODIO::JEventSourcePODIO(std::string resource_name, JApplication* ap // Destructor //------------------------------------------------------------------------------ JEventSourcePODIO::~JEventSourcePODIO() { - LOG << "Closing Event Source for " << GetResourceName() << LOG_END; + LOG << "Closing Event Source for " << GetResourceName() << LOG_END; } //------------------------------------------------------------------------------ @@ -121,48 +114,51 @@ JEventSourcePODIO::~JEventSourcePODIO() { //------------------------------------------------------------------------------ void JEventSourcePODIO::Open() { - bool print_type_table = GetApplication()->GetParameterValue("podio:print_type_table"); - // std::string background_filename = GetApplication()->GetParameterValue("podio:background_filename");; - // int num_background_events = GetApplication()->GetParameterValue("podio:num_background_events");; - - // Open primary events file - try { - - // Verify file exists - if( ! std::filesystem::exists(GetResourceName()) ){ - // Here we go against the standard practice of throwing an error and print - // the message and exit immediately. This is because we want the last message - // on the screen to be that the file doesn't exist. - auto mess = fmt::format(fmt::emphasis::bold | fg(fmt::color::red),"ERROR: "); - mess += fmt::format(fmt::emphasis::bold, "file: {} does not exist!", GetResourceName()); - std::cerr << std::endl << std::endl << mess << std::endl << std::endl; - std::_Exit(EXIT_FAILURE); - } - - m_reader.openFile( GetResourceName() ); - - auto version = m_reader.currentFileVersion(); - bool version_mismatch = version.major > podio::version::build_version.major; - version_mismatch |= (version.major == podio::version::build_version.major) && (version.minor>podio::version::build_version.minor); - if( version_mismatch ) { - std::stringstream ss; - ss << "Mismatch in PODIO versions! " << version << " > " << podio::version::build_version; - // FIXME: The podio ROOTReader is somehow failing to read in the correct version numbers from the file -// throw JException(ss.str()); - } - - LOG << "PODIO version: file=" << version << " (executable=" << podio::version::build_version << ")" << LOG_END; - - Nevents_in_file = m_reader.getEntries("events"); - LOG << "Opened PODIO Frame file \"" << GetResourceName() << "\" with " << Nevents_in_file << " events" << LOG_END; - - if( print_type_table ) PrintCollectionTypeTable(); - - }catch (std::exception &e ){ - LOG_ERROR(default_cerr_logger) << e.what() << LOG_END; - throw JException( fmt::format( "Problem opening file \"{}\"", GetResourceName() ) ); + bool print_type_table = GetApplication()->GetParameterValue("podio:print_type_table"); + // std::string background_filename = GetApplication()->GetParameterValue("podio:background_filename");; + // int num_background_events = GetApplication()->GetParameterValue("podio:num_background_events");; + + // Open primary events file + try { + + // Verify file exists + if (!std::filesystem::exists(GetResourceName())) { + // Here we go against the standard practice of throwing an error and print + // the message and exit immediately. This is because we want the last message + // on the screen to be that the file doesn't exist. + auto mess = fmt::format(fmt::emphasis::bold | fg(fmt::color::red), "ERROR: "); + mess += fmt::format(fmt::emphasis::bold, "file: {} does not exist!", GetResourceName()); + std::cerr << std::endl << std::endl << mess << std::endl << std::endl; + std::_Exit(EXIT_FAILURE); + } + + m_reader.openFile(GetResourceName()); + + auto version = m_reader.currentFileVersion(); + bool version_mismatch = version.major > podio::version::build_version.major; + version_mismatch |= (version.major == podio::version::build_version.major) && + (version.minor > podio::version::build_version.minor); + if (version_mismatch) { + std::stringstream ss; + ss << "Mismatch in PODIO versions! " << version << " > " << podio::version::build_version; + // FIXME: The podio ROOTReader is somehow failing to read in the correct version numbers from the file + // throw JException(ss.str()); } + LOG << "PODIO version: file=" << version << " (executable=" << podio::version::build_version + << ")" << LOG_END; + + Nevents_in_file = m_reader.getEntries("events"); + LOG << "Opened PODIO Frame file \"" << GetResourceName() << "\" with " << Nevents_in_file + << " events" << LOG_END; + + if (print_type_table) + PrintCollectionTypeTable(); + + } catch (std::exception& e) { + LOG_ERROR(default_cerr_logger) << e.what() << LOG_END; + throw JException(fmt::format("Problem opening file \"{}\"", GetResourceName())); + } } //------------------------------------------------------------------------------ @@ -173,11 +169,10 @@ void JEventSourcePODIO::Open() { /// \param event //------------------------------------------------------------------------------ void JEventSourcePODIO::Close() { - // m_reader.close(); - // TODO: ROOTFrameReader does not appear to have a close() method. + // m_reader.close(); + // TODO: ROOTFrameReader does not appear to have a close() method. } - //------------------------------------------------------------------------------ // GetEvent // @@ -187,40 +182,42 @@ void JEventSourcePODIO::Close() { //------------------------------------------------------------------------------ void JEventSourcePODIO::GetEvent(std::shared_ptr event) { - /// Calls to GetEvent are synchronized with each other, which means they can - /// read and write state on the JEventSource without causing race conditions. - - // Check if we have exhausted events from file - if( Nevents_read >= Nevents_in_file ) { - if( m_run_forever ){ - Nevents_read = 0; - }else{ - // m_reader.close(); - // TODO:: ROOTFrameReader does not appear to have a close() method. - throw RETURN_STATUS::kNO_MORE_EVENTS; - } - } - - auto frame_data = m_reader.readEntry("events", Nevents_read); - auto frame = std::make_unique(std::move(frame_data)); - - const auto& event_headers = frame->get("EventHeader"); // TODO: What is the collection name? - if (event_headers.size() != 1) { - throw JException("Bad event headers: Entry %d contains %d items, but 1 expected.", Nevents_read, event_headers.size()); - } - event->SetEventNumber(event_headers[0].getEventNumber()); - event->SetRunNumber(event_headers[0].getRunNumber()); - - // Insert contents odf frame into JFactories - VisitPodioCollection visit; - for (const std::string& coll_name : frame->getAvailableCollections()) { - const podio::CollectionBase* collection = frame->get(coll_name); - InsertingVisitor visitor(*event, coll_name); - visit(visitor, *collection); + /// Calls to GetEvent are synchronized with each other, which means they can + /// read and write state on the JEventSource without causing race conditions. + + // Check if we have exhausted events from file + if (Nevents_read >= Nevents_in_file) { + if (m_run_forever) { + Nevents_read = 0; + } else { + // m_reader.close(); + // TODO:: ROOTFrameReader does not appear to have a close() method. + throw RETURN_STATUS::kNO_MORE_EVENTS; } - - event->Insert(frame.release()); // Transfer ownership from unique_ptr to JFactoryT - Nevents_read += 1; + } + + auto frame_data = m_reader.readEntry("events", Nevents_read); + auto frame = std::make_unique(std::move(frame_data)); + + const auto& event_headers = frame->get( + "EventHeader"); // TODO: What is the collection name? + if (event_headers.size() != 1) { + throw JException("Bad event headers: Entry %d contains %d items, but 1 expected.", Nevents_read, + event_headers.size()); + } + event->SetEventNumber(event_headers[0].getEventNumber()); + event->SetRunNumber(event_headers[0].getRunNumber()); + + // Insert contents odf frame into JFactories + VisitPodioCollection visit; + for (const std::string& coll_name : frame->getAvailableCollections()) { + const podio::CollectionBase* collection = frame->get(coll_name); + InsertingVisitor visitor(*event, coll_name); + visit(visitor, *collection); + } + + event->Insert(frame.release()); // Transfer ownership from unique_ptr to JFactoryT + Nevents_read += 1; } //------------------------------------------------------------------------------ @@ -228,8 +225,8 @@ void JEventSourcePODIO::GetEvent(std::shared_ptr event) { //------------------------------------------------------------------------------ std::string JEventSourcePODIO::GetDescription() { - /// GetDescription() helps JANA explain to the user what is going on - return "PODIO root file (Frames, podio >= v0.16.3)"; + /// GetDescription() helps JANA explain to the user what is going on + return "PODIO root file (Frames, podio >= v0.16.3)"; } //------------------------------------------------------------------------------ @@ -247,20 +244,23 @@ std::string JEventSourcePODIO::GetDescription() { template <> double JEventSourceGeneratorT::CheckOpenable(std::string resource_name) { - // PODIO Frame reader gets slightly higher precedence than PODIO Legacy reader, but only if the file - // contains a 'podio_metadata' TTree. If the file doesn't exist, this will return 0. The "file not found" - // error will hopefully be generated by the PODIO legacy reader instead. - if (resource_name.find(".root") == std::string::npos ) return 0.0; - - // PODIO FrameReader segfaults on legacy input files, so we use ROOT to validate beforehand. Of course, - // we can't validate if ROOT can't read the file. - std::unique_ptr file = std::make_unique(resource_name.c_str()); - if (!file || file->IsZombie()) return 0.0; - - // We test the format the same way that PODIO's python API does. See python/podio/reading.py - TObject* tree = file->Get("podio_metadata"); - if (tree == nullptr) return 0.0; - return 0.03; + // PODIO Frame reader gets slightly higher precedence than PODIO Legacy reader, but only if the file + // contains a 'podio_metadata' TTree. If the file doesn't exist, this will return 0. The "file not found" + // error will hopefully be generated by the PODIO legacy reader instead. + if (resource_name.find(".root") == std::string::npos) + return 0.0; + + // PODIO FrameReader segfaults on legacy input files, so we use ROOT to validate beforehand. Of course, + // we can't validate if ROOT can't read the file. + std::unique_ptr file = std::make_unique(resource_name.c_str()); + if (!file || file->IsZombie()) + return 0.0; + + // We test the format the same way that PODIO's python API does. See python/podio/reading.py + TObject* tree = file->Get("podio_metadata"); + if (tree == nullptr) + return 0.0; + return 0.03; } //------------------------------------------------------------------------------ @@ -272,35 +272,36 @@ double JEventSourceGeneratorT::CheckOpenable(std::string reso //------------------------------------------------------------------------------ void JEventSourcePODIO::PrintCollectionTypeTable(void) { - // Read the zeroth entry. This assumes that m_reader has already been initialized with a valid filename - auto frame_data = m_reader.readEntry("events", 0); - auto frame = std::make_unique(std::move(frame_data)); - - std::map collectionNames; - size_t max_name_len = 0; - size_t max_type_len = 0; - - // Record all (collection name, value type name) pairs - // Record the maximum length of both strings so that we can print nicely aligned columns. - for (const std::string& name : frame->getAvailableCollections()) { - const podio::CollectionBase* coll = frame->get(name); - const auto type = coll->getTypeName(); - max_name_len = std::max(max_name_len, name.length()); - max_type_len = std::max(max_type_len, type.length()); - collectionNames[name] = std::string(type); - } - - // Print table - std::cout << std::endl; - std::cout << "Available Collections" << std::endl; - std::cout << std::endl; - std::cout << "Collection Name" << std::string(max_name_len + 2 - std::string("Collection Name").length(), ' ') - << "Data Type" << std::endl; - std::cout << std::string(max_name_len, '-') << " " << std::string(max_name_len, '-') << std::endl; - for (auto &[name, type] : collectionNames) { - std::cout << name + std::string(max_name_len + 2 - name.length(), ' '); - std::cout << type << std::endl; - } - std::cout << std::endl; - + // Read the zeroth entry. This assumes that m_reader has already been initialized with a valid filename + auto frame_data = m_reader.readEntry("events", 0); + auto frame = std::make_unique(std::move(frame_data)); + + std::map collectionNames; + size_t max_name_len = 0; + size_t max_type_len = 0; + + // Record all (collection name, value type name) pairs + // Record the maximum length of both strings so that we can print nicely aligned columns. + for (const std::string& name : frame->getAvailableCollections()) { + const podio::CollectionBase* coll = frame->get(name); + const auto type = coll->getTypeName(); + max_name_len = std::max(max_name_len, name.length()); + max_type_len = std::max(max_type_len, type.length()); + collectionNames[name] = std::string(type); + } + + // Print table + std::cout << std::endl; + std::cout << "Available Collections" << std::endl; + std::cout << std::endl; + std::cout << "Collection Name" + << std::string(max_name_len + 2 - std::string("Collection Name").length(), ' ') + << "Data Type" << std::endl; + std::cout << std::string(max_name_len, '-') << " " << std::string(max_name_len, '-') + << std::endl; + for (auto& [name, type] : collectionNames) { + std::cout << name + std::string(max_name_len + 2 - name.length(), ' '); + std::cout << type << std::endl; + } + std::cout << std::endl; } diff --git a/src/services/io/podio/JEventSourcePODIO.h b/src/services/io/podio/JEventSourcePODIO.h index 21dc45c999..013caf1268 100644 --- a/src/services/io/podio/JEventSourcePODIO.h +++ b/src/services/io/podio/JEventSourcePODIO.h @@ -17,32 +17,30 @@ class JEventSourcePODIO : public JEventSource { public: - JEventSourcePODIO(std::string resource_name, JApplication* app); + JEventSourcePODIO(std::string resource_name, JApplication* app); - virtual ~JEventSourcePODIO(); + virtual ~JEventSourcePODIO(); - void Open() override; + void Open() override; - void Close() override; + void Close() override; - void GetEvent(std::shared_ptr) override; + void GetEvent(std::shared_ptr) override; - static std::string GetDescription(); + static std::string GetDescription(); - void PrintCollectionTypeTable(void); + void PrintCollectionTypeTable(void); protected: - podio::ROOTFrameReader m_reader; - size_t Nevents_in_file = 0; - size_t Nevents_read = 0; - - std::string m_include_collections_str; - std::string m_exclude_collections_str; - std::set m_INPUT_INCLUDE_COLLECTIONS; - std::set m_INPUT_EXCLUDE_COLLECTIONS; - bool m_run_forever=false; - + podio::ROOTFrameReader m_reader; + size_t Nevents_in_file = 0; + size_t Nevents_read = 0; + + std::string m_include_collections_str; + std::string m_exclude_collections_str; + std::set m_INPUT_INCLUDE_COLLECTIONS; + std::set m_INPUT_EXCLUDE_COLLECTIONS; + bool m_run_forever = false; }; -template <> -double JEventSourceGeneratorT::CheckOpenable(std::string); +template <> double JEventSourceGeneratorT::CheckOpenable(std::string); diff --git a/src/services/io/podio/datamodel_LinkDef.h b/src/services/io/podio/datamodel_LinkDef.h index 1dba35ae28..2d90c4b2ba 100644 --- a/src/services/io/podio/datamodel_LinkDef.h +++ b/src/services/io/podio/datamodel_LinkDef.h @@ -6,7 +6,6 @@ // the vector types like "vector". // - #include #ifdef __ROOTCLING__ diff --git a/src/services/io/podio/podio.cc b/src/services/io/podio/podio.cc index 829527f104..96465e03a6 100644 --- a/src/services/io/podio/podio.cc +++ b/src/services/io/podio/podio.cc @@ -9,21 +9,20 @@ #include "JEventProcessorPODIO.h" #include "JEventSourcePODIO.h" - // Make this a JANA plugin extern "C" { -void InitPlugin(JApplication *app) { - InitJANAPlugin(app); - app->Add(new JEventSourceGeneratorT()); +void InitPlugin(JApplication* app) { + InitJANAPlugin(app); + app->Add(new JEventSourceGeneratorT()); - // Disable this behavior for now so one can run eicrecon with only the - // input file as an argument. - // Only add a EICRootWriter if the user has specified a configuration parameter relevant to writing -// if( app->GetJParameterManager()->Exists("podio:output_file") -// || app->GetJParameterManager()->Exists("podio:output_file_copy_dir") -// || app->GetJParameterManager()->Exists("podio:output_include_collections") -// || app->GetJParameterManager()->Exists("podio:output_exclude_collections") ){ - app->Add(new JEventProcessorPODIO()); -// } + // Disable this behavior for now so one can run eicrecon with only the + // input file as an argument. + // Only add a EICRootWriter if the user has specified a configuration parameter relevant to writing + // if( app->GetJParameterManager()->Exists("podio:output_file") + // || app->GetJParameterManager()->Exists("podio:output_file_copy_dir") + // || app->GetJParameterManager()->Exists("podio:output_include_collections") + // || app->GetJParameterManager()->Exists("podio:output_exclude_collections") ){ + app->Add(new JEventProcessorPODIO()); + // } } } diff --git a/src/services/log/Log_service.cc b/src/services/log/Log_service.cc index fd83730ed9..796a93b6d8 100644 --- a/src/services/log/Log_service.cc +++ b/src/services/log/Log_service.cc @@ -10,51 +10,55 @@ #include "extensions/spdlog/SpdlogExtensions.h" +Log_service::Log_service(JApplication* app) { + // Here one could add centralized documentation for spdlog::default_logger() + // All subsequent loggers are cloned from the spdlog::default_logger() + m_application = app; -Log_service::Log_service(JApplication *app) { - // Here one could add centralized documentation for spdlog::default_logger() - // All subsequent loggers are cloned from the spdlog::default_logger() - m_application = app; + m_log_level_str = "info"; + m_application->SetDefaultParameter("eicrecon:LogLevel", m_log_level_str, + "log_level: trace, debug, info, warn, error, critical, off"); + spdlog::default_logger()->set_level(eicrecon::ParseLogLevel(m_log_level_str)); - m_log_level_str = "info"; - m_application->SetDefaultParameter("eicrecon:LogLevel", m_log_level_str, "log_level: trace, debug, info, warn, error, critical, off"); - spdlog::default_logger()->set_level(eicrecon::ParseLogLevel(m_log_level_str)); - - m_log_format_str = "[%n] [%^%l%$] %v"; - m_application->SetDefaultParameter("eicrecon:LogFormat", m_log_level_str, "spdlog pattern string"); - spdlog::set_pattern(m_log_format_str); + m_log_format_str = "[%n] [%^%l%$] %v"; + m_application->SetDefaultParameter("eicrecon:LogFormat", m_log_level_str, + "spdlog pattern string"); + spdlog::set_pattern(m_log_format_str); } - // Virtual destructor implementation to pin vtable and typeinfo to this // translation unit -Log_service::~Log_service() {}; - +Log_service::~Log_service(){}; -std::shared_ptr Log_service::logger(const std::string &name) { +std::shared_ptr Log_service::logger(const std::string& name) { - try { - std::lock_guard locker(m_lock); + try { + std::lock_guard locker(m_lock); - // Try to get existing logger - auto logger = spdlog::get(name); - if(!logger) { - // or create a new one with current configuration - logger = spdlog::default_logger()->clone(name); + // Try to get existing logger + auto logger = spdlog::get(name); + if (!logger) { + // or create a new one with current configuration + logger = spdlog::default_logger()->clone(name); - // Set log level for this named logger allowing user to specify as config. parameter - // e.g. EcalEndcapPRecHits:LogLevel - std::string log_level_str = m_log_level_str; - m_application->SetDefaultParameter(name+":LogLevel", log_level_str, "log_level for "+name+": trace, debug, info, warn, error, critical, off"); - logger->set_level(eicrecon::ParseLogLevel(log_level_str)); - } - return logger; - } - catch(const std::exception & exception) { - throw JException(exception.what()); + // Set log level for this named logger allowing user to specify as config. parameter + // e.g. EcalEndcapPRecHits:LogLevel + std::string log_level_str = m_log_level_str; + m_application->SetDefaultParameter(name + ":LogLevel", log_level_str, + "log_level for " + name + + ": trace, debug, info, warn, error, critical, off"); + logger->set_level(eicrecon::ParseLogLevel(log_level_str)); } + return logger; + } catch (const std::exception& exception) { + throw JException(exception.what()); + } } -spdlog::level::level_enum Log_service::getDefaultLevel() {return spdlog::default_logger()->level();} +spdlog::level::level_enum Log_service::getDefaultLevel() { + return spdlog::default_logger()->level(); +} -std::string Log_service::getDefaultLevelStr() {return eicrecon::LogLevelToString(getDefaultLevel());} +std::string Log_service::getDefaultLevelStr() { + return eicrecon::LogLevelToString(getDefaultLevel()); +} diff --git a/src/services/log/Log_service.h b/src/services/log/Log_service.h index 0ec1440a4d..7faa7780b3 100644 --- a/src/services/log/Log_service.h +++ b/src/services/log/Log_service.h @@ -1,6 +1,5 @@ #pragma once - #include #include #include @@ -12,28 +11,25 @@ /** * The Service centralizes use of spdlog */ -class Log_service : public JService -{ +class Log_service : public JService { public: - explicit Log_service(JApplication *app); - ~Log_service(); + explicit Log_service(JApplication* app); + ~Log_service(); - virtual std::shared_ptr logger(const std::string &name); + virtual std::shared_ptr logger(const std::string& name); - /** Gets the default level for all loggers + /** Gets the default level for all loggers * The log level is set from user parameters or is 'info'**/ - virtual spdlog::level::level_enum getDefaultLevel(); - - /** Gets std::string version of the default log level **/ - virtual std::string getDefaultLevelStr(); + virtual spdlog::level::level_enum getDefaultLevel(); + /** Gets std::string version of the default log level **/ + virtual std::string getDefaultLevelStr(); private: + Log_service() = default; - Log_service()=default; - - std::recursive_mutex m_lock; - JApplication* m_application; - std::string m_log_level_str; - std::string m_log_format_str; + std::recursive_mutex m_lock; + JApplication* m_application; + std::string m_log_level_str; + std::string m_log_format_str; }; diff --git a/src/services/log/log.cc b/src/services/log/log.cc index b1f6db3d37..42a34160dc 100644 --- a/src/services/log/log.cc +++ b/src/services/log/log.cc @@ -8,10 +8,9 @@ #include "Log_service.h" - extern "C" { -void InitPlugin(JApplication *app) { - InitJANAPlugin(app); - app->ProvideService(std::make_shared(app) ); +void InitPlugin(JApplication* app) { + InitJANAPlugin(app); + app->ProvideService(std::make_shared(app)); } } diff --git a/src/services/rootfile/RootFile_service.h b/src/services/rootfile/RootFile_service.h index ab80456c2a..cefbbd9275 100644 --- a/src/services/rootfile/RootFile_service.h +++ b/src/services/rootfile/RootFile_service.h @@ -1,6 +1,5 @@ #pragma once - #include #include #include @@ -16,90 +15,88 @@ /** * This Service centralizes creation of a root file for histograms */ -class RootFile_service : public JService -{ +class RootFile_service : public JService { public: - explicit RootFile_service(JApplication *app ):m_app(app){} - ~RootFile_service() override { CloseHistFile(); } + explicit RootFile_service(JApplication* app) : m_app(app) {} + ~RootFile_service() override { CloseHistFile(); } - void acquire_services(JServiceLocator *locater) override { - auto log_service = m_app->GetService(); - m_log = log_service->logger("RootFile"); - } + void acquire_services(JServiceLocator* locater) override { + auto log_service = m_app->GetService(); + m_log = log_service->logger("RootFile"); + } - /// This will return a pointer to the top-level directory of the - /// common output root file for histograms. If create_if_needed - /// is true and the root file has not already been created, then - /// one will be created. If create_if_needed is false, the pointer - /// to the existing file will be returned or nullptr if it does - /// not already exist. - /// - /// NOTE: This should only be called by a thread already holding - /// the global root lock. The root lock will already be held if - /// calling from JEventProcessorSequentialRoot. For pretty much - /// everyplace else, the lock should be acquired manually. - /// e.g. - /// - /// auto rootfile_service = japp->GetService(); - /// auto globalRootLock = japp->GetService(); - /// globalRootLock->acquire_write_lock(); - /// auto rootfile = rootfile_service->GetHistFile(); - /// globalWriteLock->release_lock(); - /// - /// \param create_if_needed create file if not already created - /// \return - TDirectory* GetHistFile(bool create_if_needed=true){ + /// This will return a pointer to the top-level directory of the + /// common output root file for histograms. If create_if_needed + /// is true and the root file has not already been created, then + /// one will be created. If create_if_needed is false, the pointer + /// to the existing file will be returned or nullptr if it does + /// not already exist. + /// + /// NOTE: This should only be called by a thread already holding + /// the global root lock. The root lock will already be held if + /// calling from JEventProcessorSequentialRoot. For pretty much + /// everyplace else, the lock should be acquired manually. + /// e.g. + /// + /// auto rootfile_service = japp->GetService(); + /// auto globalRootLock = japp->GetService(); + /// globalRootLock->acquire_write_lock(); + /// auto rootfile = rootfile_service->GetHistFile(); + /// globalWriteLock->release_lock(); + /// + /// \param create_if_needed create file if not already created + /// \return + TDirectory* GetHistFile(bool create_if_needed = true) { - if( create_if_needed ) { - std::call_once(init_flag, &RootFile_service::CreateHistFile, this); - } - return m_histfile; + if (create_if_needed) { + std::call_once(init_flag, &RootFile_service::CreateHistFile, this); } + return m_histfile; + } - /// Close the histogram file. If no histogram file was opened, - /// then this does nothing. - /// - /// This should generally never be called by anything other than - /// the destructor so that it is - /// automatically closed when the service is destructed at - /// the end of processing. This is only here for use in - /// execptional circumstances like the program is suffering - /// a fatal crash and we want to try and save the work by - /// closing the file cleanly. - void CloseHistFile(){ - if( m_histfile){ - std::string filename = m_histfile->GetName(); - m_histfile->Write(); - delete m_histfile; - m_log->info("Closed user histogram file: {}" , filename); - } - m_histfile = nullptr; + /// Close the histogram file. If no histogram file was opened, + /// then this does nothing. + /// + /// This should generally never be called by anything other than + /// the destructor so that it is + /// automatically closed when the service is destructed at + /// the end of processing. This is only here for use in + /// execptional circumstances like the program is suffering + /// a fatal crash and we want to try and save the work by + /// closing the file cleanly. + void CloseHistFile() { + if (m_histfile) { + std::string filename = m_histfile->GetName(); + m_histfile->Write(); + delete m_histfile; + m_log->info("Closed user histogram file: {}", filename); } + m_histfile = nullptr; + } private: - - /// Create the output rootfile. This will be called only once - /// which will happen the first time GetHistFile is called. - void CreateHistFile(){ - // Get root file name - std::string filename = "eicrecon.root"; - m_app->SetDefaultParameter("histsfile", filename, - "Name of root file to be created for plugin histograms/trees"); - if (!m_histfile) { - try { - m_histfile = new TFile(filename.c_str(), "RECREATE", "user histograms/trees"); - m_log->info("Created file: {} for user histograms", filename); - } catch (std::exception &ex) { - m_log->error("Problem opening root file for histograms: {}", ex.what()); - throw ex; - } - } + /// Create the output rootfile. This will be called only once + /// which will happen the first time GetHistFile is called. + void CreateHistFile() { + // Get root file name + std::string filename = "eicrecon.root"; + m_app->SetDefaultParameter("histsfile", filename, + "Name of root file to be created for plugin histograms/trees"); + if (!m_histfile) { + try { + m_histfile = new TFile(filename.c_str(), "RECREATE", "user histograms/trees"); + m_log->info("Created file: {} for user histograms", filename); + } catch (std::exception& ex) { + m_log->error("Problem opening root file for histograms: {}", ex.what()); + throw ex; + } } + } - RootFile_service()=default; + RootFile_service() = default; - JApplication *m_app=nullptr; - std::shared_ptr m_log; - TFile *m_histfile = nullptr; - std::once_flag init_flag; + JApplication* m_app = nullptr; + std::shared_ptr m_log; + TFile* m_histfile = nullptr; + std::once_flag init_flag; }; diff --git a/src/services/rootfile/rootfile.cc b/src/services/rootfile/rootfile.cc index 01499013cd..67919280e7 100644 --- a/src/services/rootfile/rootfile.cc +++ b/src/services/rootfile/rootfile.cc @@ -8,10 +8,9 @@ #include "RootFile_service.h" - extern "C" { -void InitPlugin(JApplication *app) { - InitJANAPlugin(app); - app->ProvideService(std::make_shared(app) ); +void InitPlugin(JApplication* app) { + InitJANAPlugin(app); + app->ProvideService(std::make_shared(app)); } } diff --git a/src/tests/algorithms_test/algorithmsInit.cc b/src/tests/algorithms_test/algorithmsInit.cc index 0eeccdbf8f..a42307ed5d 100644 --- a/src/tests/algorithms_test/algorithmsInit.cc +++ b/src/tests/algorithms_test/algorithmsInit.cc @@ -32,14 +32,12 @@ class algorithmsInitListener : public Catch::EventListenerBase { detector->add(readout); m_detector = std::move(detector); - auto& serviceSvc = algorithms::ServiceSvc::instance(); + auto& serviceSvc = algorithms::ServiceSvc::instance(); [[maybe_unused]] auto& geoSvc = algorithms::GeoSvc::instance(); - serviceSvc.setInit([this](auto&& g) { - g.init(this->m_detector.get()); - }); + serviceSvc.setInit([this](auto&& g) { g.init(this->m_detector.get()); }); [[maybe_unused]] auto& randomSvc = algorithms::RandomSvc::instance(); - auto seed = Catch::Generators::Detail::getSeed(); + auto seed = Catch::Generators::Detail::getSeed(); serviceSvc.setInit([seed](auto&& r) { r.setProperty("seed", static_cast(seed)); r.init(); diff --git a/src/tests/algorithms_test/calorimetry_CalorimeterHitDigi.cc b/src/tests/algorithms_test/calorimetry_CalorimeterHitDigi.cc index 74c7f78666..80a918ecb3 100644 --- a/src/tests/algorithms_test/calorimetry_CalorimeterHitDigi.cc +++ b/src/tests/algorithms_test/calorimetry_CalorimeterHitDigi.cc @@ -24,60 +24,60 @@ using eicrecon::CalorimeterHitDigi; using eicrecon::CalorimeterHitDigiConfig; -TEST_CASE( "the clustering algorithm runs", "[CalorimeterHitDigi]" ) { +TEST_CASE("the clustering algorithm runs", "[CalorimeterHitDigi]") { std::shared_ptr logger = spdlog::default_logger()->clone("CalorimeterHitDigi"); logger->set_level(spdlog::level::trace); auto detector = algorithms::GeoSvc::instance().detector(); - auto id_desc = detector->readout("MockCalorimeterHits").idSpec(); + auto id_desc = detector->readout("MockCalorimeterHits").idSpec(); CalorimeterHitDigi algo("test"); CalorimeterHitDigiConfig cfg; - cfg.threshold = 0. /* GeV */; + cfg.threshold = 0. /* GeV */; cfg.corrMeanScale = 1.; // Keep smearing parameters at zero cfg.pedSigmaADC = 0; - cfg.tRes = 0. * dd4hep::ns; - cfg.eRes = {0. * sqrt(dd4hep::GeV), 0., 0. * dd4hep::GeV}; - cfg.readout = "MockCalorimeterHits"; + cfg.tRes = 0. * dd4hep::ns; + cfg.eRes = {0. * sqrt(dd4hep::GeV), 0., 0. * dd4hep::GeV}; + cfg.readout = "MockCalorimeterHits"; - SECTION( "single hit with couple contributions" ) { - cfg.capADC = 555; - cfg.dyRangeADC = 5.0 /* GeV */; - cfg.pedMeanADC = 123; + SECTION("single hit with couple contributions") { + cfg.capADC = 555; + cfg.dyRangeADC = 5.0 /* GeV */; + cfg.pedMeanADC = 123; cfg.resolutionTDC = 1.0 * dd4hep::ns; algo.level(algorithms::LogLevel(spdlog::level::trace)); algo.applyConfig(cfg); algo.init(); auto calohits = std::make_unique(); - auto simhits = std::make_unique(); - auto mhit = simhits->create( - id_desc.encode({{"system", 255}, {"x", 0}, {"y", 0}}), // std::uint64_t cellID, - 1.0 /* GeV */, // float energy - edm4hep::Vector3f({0. /* mm */, 0. /* mm */, 0. /* mm */}) // edm4hep::Vector3f position + auto simhits = std::make_unique(); + auto mhit = simhits->create( + id_desc.encode({{"system", 255}, {"x", 0}, {"y", 0}}), // std::uint64_t cellID, + 1.0 /* GeV */, // float energy + edm4hep::Vector3f({0. /* mm */, 0. /* mm */, 0. /* mm */}) // edm4hep::Vector3f position ); mhit.addToContributions(calohits->create( - 0, // std::int32_t PDG - 0.5 /* GeV */, // float energy - 7.0 /* ns */, // float time - edm4hep::Vector3f({0. /* mm */, 0. /* mm */, 0. /* mm */}) // edm4hep::Vector3f stepPosition - )); + 0, // std::int32_t PDG + 0.5 /* GeV */, // float energy + 7.0 /* ns */, // float time + edm4hep::Vector3f({0. /* mm */, 0. /* mm */, 0. /* mm */}) // edm4hep::Vector3f stepPosition + )); mhit.addToContributions(calohits->create( - 0, // std::int32_t PDG - 0.5 /* GeV */, // float energy - 9.0 /* ns */, // float time - edm4hep::Vector3f({0. /* mm */, 0. /* mm */, 0. /* mm */}) // edm4hep::Vector3f stepPosition - )); + 0, // std::int32_t PDG + 0.5 /* GeV */, // float energy + 9.0 /* ns */, // float time + edm4hep::Vector3f({0. /* mm */, 0. /* mm */, 0. /* mm */}) // edm4hep::Vector3f stepPosition + )); auto rawhits = std::make_unique(); algo.process({simhits.get()}, {rawhits.get()}); - REQUIRE( (*rawhits).size() == 1 ); - REQUIRE( (*rawhits)[0].getCellID() == id_desc.encode({{"system", 255}, {"x", 0}, {"y", 0}})); - REQUIRE( (*rawhits)[0].getAmplitude() == 123 + 111 ); - REQUIRE( (*rawhits)[0].getTimeStamp() == 7 ); // currently, earliest contribution is returned + REQUIRE((*rawhits).size() == 1); + REQUIRE((*rawhits)[0].getCellID() == id_desc.encode({{"system", 255}, {"x", 0}, {"y", 0}})); + REQUIRE((*rawhits)[0].getAmplitude() == 123 + 111); + REQUIRE((*rawhits)[0].getTimeStamp() == 7); // currently, earliest contribution is returned } } diff --git a/src/tests/algorithms_test/calorimetry_CalorimeterIslandCluster.cc b/src/tests/algorithms_test/calorimetry_CalorimeterIslandCluster.cc index cd4d59eafe..ec3c1e21e8 100644 --- a/src/tests/algorithms_test/calorimetry_CalorimeterIslandCluster.cc +++ b/src/tests/algorithms_test/calorimetry_CalorimeterIslandCluster.cc @@ -29,129 +29,128 @@ using eicrecon::CalorimeterIslandCluster; using eicrecon::CalorimeterIslandClusterConfig; -TEST_CASE( "the clustering algorithm runs", "[CalorimeterIslandCluster]" ) { +TEST_CASE("the clustering algorithm runs", "[CalorimeterIslandCluster]") { CalorimeterIslandCluster algo("CalorimeterIslandCluster"); - std::shared_ptr logger = spdlog::default_logger()->clone("CalorimeterIslandCluster"); + std::shared_ptr logger = + spdlog::default_logger()->clone("CalorimeterIslandCluster"); logger->set_level(spdlog::level::trace); CalorimeterIslandClusterConfig cfg; - cfg.minClusterHitEdep = 0. * dd4hep::GeV; + cfg.minClusterHitEdep = 0. * dd4hep::GeV; cfg.minClusterCenterEdep = 0. * dd4hep::GeV; auto detector = algorithms::GeoSvc::instance().detector(); - auto id_desc = detector->readout("MockCalorimeterHits").idSpec(); + auto id_desc = detector->readout("MockCalorimeterHits").idSpec(); - SECTION( "without splitting" ) { + SECTION("without splitting") { bool use_adjacencyMatrix = GENERATE(false, true); - cfg.splitCluster = false; + cfg.splitCluster = false; if (use_adjacencyMatrix) { cfg.adjacencyMatrix = "abs(x_1 - x_2) + abs(y_1 - y_2) == 1"; - cfg.readout = "MockCalorimeterHits"; + cfg.readout = "MockCalorimeterHits"; } else { cfg.localDistXY = {1 * dd4hep::mm, 1 * dd4hep::mm}; } algo.applyConfig(cfg); algo.init(); - SECTION( "on a single cell" ) { + SECTION("on a single cell") { edm4eic::CalorimeterHitCollection hits_coll; hits_coll.create( - id_desc.encode({{"system", 255}, {"x", 0}, {"y", 0}}), // std::uint64_t cellID, - 5.0, // float energy, - 0.0, // float energyError, - 0.0, // float time, - 0.0, // float timeError, - edm4hep::Vector3f(0.0, 0.0, 0.0), // edm4hep::Vector3f position, - edm4hep::Vector3f(0.0, 0.0, 0.0), // edm4hep::Vector3f dimension, - 0, // std::int32_t sector, - 0, // std::int32_t layer, - edm4hep::Vector3f(0.0, 0.0, 0.0) // edm4hep::Vector3f local + id_desc.encode({{"system", 255}, {"x", 0}, {"y", 0}}), // std::uint64_t cellID, + 5.0, // float energy, + 0.0, // float energyError, + 0.0, // float time, + 0.0, // float timeError, + edm4hep::Vector3f(0.0, 0.0, 0.0), // edm4hep::Vector3f position, + edm4hep::Vector3f(0.0, 0.0, 0.0), // edm4hep::Vector3f dimension, + 0, // std::int32_t sector, + 0, // std::int32_t layer, + edm4hep::Vector3f(0.0, 0.0, 0.0) // edm4hep::Vector3f local ); auto protoclust_coll = std::make_unique(); algo.process({&hits_coll}, {protoclust_coll.get()}); - REQUIRE( (*protoclust_coll).size() == 1 ); - REQUIRE( (*protoclust_coll)[0].hits_size() == 1 ); - REQUIRE( (*protoclust_coll)[0].weights_size() == 1 ); + REQUIRE((*protoclust_coll).size() == 1); + REQUIRE((*protoclust_coll)[0].hits_size() == 1); + REQUIRE((*protoclust_coll)[0].weights_size() == 1); } - SECTION( "on two separated cells" ) { + SECTION("on two separated cells") { edm4eic::CalorimeterHitCollection hits_coll; - hits_coll.create( - 0, // std::uint64_t cellID, - 5.0, // float energy, - 0.0, // float energyError, - 0.0, // float time, - 0.0, // float timeError, - edm4hep::Vector3f(0.0, 0.0, 0.0), // edm4hep::Vector3f position, - edm4hep::Vector3f(1.0, 1.0, 0.0), // edm4hep::Vector3f dimension, - 0, // std::int32_t sector, - 0, // std::int32_t layer, - edm4hep::Vector3f(0.0, 0.0, 0.0) // edm4hep::Vector3f local + hits_coll.create(0, // std::uint64_t cellID, + 5.0, // float energy, + 0.0, // float energyError, + 0.0, // float time, + 0.0, // float timeError, + edm4hep::Vector3f(0.0, 0.0, 0.0), // edm4hep::Vector3f position, + edm4hep::Vector3f(1.0, 1.0, 0.0), // edm4hep::Vector3f dimension, + 0, // std::int32_t sector, + 0, // std::int32_t layer, + edm4hep::Vector3f(0.0, 0.0, 0.0) // edm4hep::Vector3f local ); - hits_coll.create( - 1, // std::uint64_t cellID, - 6.0, // float energy, - 0.0, // float energyError, - 0.0, // float time, - 0.0, // float timeError, - edm4hep::Vector3f(0.0, 0.0, 0.0), // edm4hep::Vector3f position, - edm4hep::Vector3f(1.0, 1.0, 0.0), // edm4hep::Vector3f dimension, - 0, // std::int32_t sector, - 0, // std::int32_t layer, - edm4hep::Vector3f(1.1 /* mm */, 1.1 /* mm */, 0.0) // edm4hep::Vector3f local + hits_coll.create(1, // std::uint64_t cellID, + 6.0, // float energy, + 0.0, // float energyError, + 0.0, // float time, + 0.0, // float timeError, + edm4hep::Vector3f(0.0, 0.0, 0.0), // edm4hep::Vector3f position, + edm4hep::Vector3f(1.0, 1.0, 0.0), // edm4hep::Vector3f dimension, + 0, // std::int32_t sector, + 0, // std::int32_t layer, + edm4hep::Vector3f(1.1 /* mm */, 1.1 /* mm */, 0.0) // edm4hep::Vector3f local ); auto protoclust_coll = std::make_unique(); algo.process({&hits_coll}, {protoclust_coll.get()}); - REQUIRE( (*protoclust_coll).size() == 2 ); - REQUIRE( (*protoclust_coll)[0].hits_size() == 1 ); - REQUIRE( (*protoclust_coll)[0].weights_size() == 1 ); - REQUIRE( (*protoclust_coll)[1].hits_size() == 1 ); - REQUIRE( (*protoclust_coll)[1].weights_size() == 1 ); + REQUIRE((*protoclust_coll).size() == 2); + REQUIRE((*protoclust_coll)[0].hits_size() == 1); + REQUIRE((*protoclust_coll)[0].weights_size() == 1); + REQUIRE((*protoclust_coll)[1].hits_size() == 1); + REQUIRE((*protoclust_coll)[1].weights_size() == 1); } - SECTION( "on two adjacent cells" ) { + SECTION("on two adjacent cells") { edm4eic::CalorimeterHitCollection hits_coll; hits_coll.create( - id_desc.encode({{"system", 255}, {"x", 0}, {"y", 0}}), // std::uint64_t cellID, - 5.0, // float energy, - 0.0, // float energyError, - 0.0, // float time, - 0.0, // float timeError, - edm4hep::Vector3f(0.0, 0.0, 0.0), // edm4hep::Vector3f position, - edm4hep::Vector3f(1.0, 1.0, 0.0), // edm4hep::Vector3f dimension, - 0, // std::int32_t sector, - 0, // std::int32_t layer, - edm4hep::Vector3f(0.0, 0.0, 0.0) // edm4hep::Vector3f local + id_desc.encode({{"system", 255}, {"x", 0}, {"y", 0}}), // std::uint64_t cellID, + 5.0, // float energy, + 0.0, // float energyError, + 0.0, // float time, + 0.0, // float timeError, + edm4hep::Vector3f(0.0, 0.0, 0.0), // edm4hep::Vector3f position, + edm4hep::Vector3f(1.0, 1.0, 0.0), // edm4hep::Vector3f dimension, + 0, // std::int32_t sector, + 0, // std::int32_t layer, + edm4hep::Vector3f(0.0, 0.0, 0.0) // edm4hep::Vector3f local ); hits_coll.create( - id_desc.encode({{"system", 255}, {"x", 1}, {"y", 0}}), // std::uint64_t cellID, - 6.0, // float energy, - 0.0, // float energyError, - 0.0, // float time, - 0.0, // float timeError, - edm4hep::Vector3f(0.0, 0.0, 0.0), // edm4hep::Vector3f position, - edm4hep::Vector3f(1.0, 1.0, 0.0), // edm4hep::Vector3f dimension, - 0, // std::int32_t sector, - 0, // std::int32_t layer, - edm4hep::Vector3f(0.9 /* mm */, 0.9 /* mm */, 0.0) // edm4hep::Vector3f local + id_desc.encode({{"system", 255}, {"x", 1}, {"y", 0}}), // std::uint64_t cellID, + 6.0, // float energy, + 0.0, // float energyError, + 0.0, // float time, + 0.0, // float timeError, + edm4hep::Vector3f(0.0, 0.0, 0.0), // edm4hep::Vector3f position, + edm4hep::Vector3f(1.0, 1.0, 0.0), // edm4hep::Vector3f dimension, + 0, // std::int32_t sector, + 0, // std::int32_t layer, + edm4hep::Vector3f(0.9 /* mm */, 0.9 /* mm */, 0.0) // edm4hep::Vector3f local ); auto protoclust_coll = std::make_unique(); algo.process({&hits_coll}, {protoclust_coll.get()}); - REQUIRE( (*protoclust_coll).size() == 1 ); - REQUIRE( (*protoclust_coll)[0].hits_size() == 2 ); - REQUIRE( (*protoclust_coll)[0].weights_size() == 2 ); + REQUIRE((*protoclust_coll).size() == 1); + REQUIRE((*protoclust_coll)[0].hits_size() == 2); + REQUIRE((*protoclust_coll)[0].weights_size() == 2); } } - SECTION( "run on three adjacent cells" ) { + SECTION("run on three adjacent cells") { bool use_adjacencyMatrix = GENERATE(false, true); if (use_adjacencyMatrix) { cfg.adjacencyMatrix = "abs(x_1 - x_2) + abs(y_1 - y_2) == 1"; - cfg.readout = "MockCalorimeterHits"; + cfg.readout = "MockCalorimeterHits"; } else { cfg.localDistXY = {1 * dd4hep::mm, 1 * dd4hep::mm}; } @@ -159,70 +158,70 @@ TEST_CASE( "the clustering algorithm runs", "[CalorimeterIslandCluster]" ) { cfg.splitCluster = GENERATE(false, true); if (cfg.splitCluster) { cfg.transverseEnergyProfileMetric = "localDistXY"; - cfg.transverseEnergyProfileScale = std::numeric_limits::infinity(); + cfg.transverseEnergyProfileScale = + std::numeric_limits::infinity(); } cfg.localDistXY = {1 * dd4hep::mm, 1 * dd4hep::mm}; algo.applyConfig(cfg); algo.init(); edm4eic::CalorimeterHitCollection hits_coll; - hits_coll.create( - id_desc.encode({{"system", 255}, {"x", 0}, {"y", 0}}), // std::uint64_t cellID, - 5.0, // float energy, - 0.0, // float energyError, - 0.0, // float time, - 0.0, // float timeError, - edm4hep::Vector3f(0.0, 0.0, 0.0), // edm4hep::Vector3f position, - edm4hep::Vector3f(1.0, 1.0, 0.0), // edm4hep::Vector3f dimension, - 0, // std::int32_t sector, - 0, // std::int32_t layer, - edm4hep::Vector3f(0.0, 0.0, 0.0) // edm4hep::Vector3f local + hits_coll.create(id_desc.encode({{"system", 255}, {"x", 0}, {"y", 0}}), // std::uint64_t cellID, + 5.0, // float energy, + 0.0, // float energyError, + 0.0, // float time, + 0.0, // float timeError, + edm4hep::Vector3f(0.0, 0.0, 0.0), // edm4hep::Vector3f position, + edm4hep::Vector3f(1.0, 1.0, 0.0), // edm4hep::Vector3f dimension, + 0, // std::int32_t sector, + 0, // std::int32_t layer, + edm4hep::Vector3f(0.0, 0.0, 0.0) // edm4hep::Vector3f local ); - hits_coll.create( - id_desc.encode({{"system", 255}, {"x", 1}, {"y", 0}}), // std::uint64_t cellID, - 1.0, // float energy, - 0.0, // float energyError, - 0.0, // float time, - 0.0, // float timeError, - edm4hep::Vector3f(0.0, 0.0, 0.0), // edm4hep::Vector3f position, - edm4hep::Vector3f(1.0, 1.0, 0.0), // edm4hep::Vector3f dimension, - 0, // std::int32_t sector, - 0, // std::int32_t layer, - edm4hep::Vector3f(0.9 /* mm */, 0.9 /* mm */, 0.0) // edm4hep::Vector3f local + hits_coll.create(id_desc.encode({{"system", 255}, {"x", 1}, {"y", 0}}), // std::uint64_t cellID, + 1.0, // float energy, + 0.0, // float energyError, + 0.0, // float time, + 0.0, // float timeError, + edm4hep::Vector3f(0.0, 0.0, 0.0), // edm4hep::Vector3f position, + edm4hep::Vector3f(1.0, 1.0, 0.0), // edm4hep::Vector3f dimension, + 0, // std::int32_t sector, + 0, // std::int32_t layer, + edm4hep::Vector3f(0.9 /* mm */, 0.9 /* mm */, 0.0) // edm4hep::Vector3f local ); - hits_coll.create( - id_desc.encode({{"system", 255}, {"x", 2}, {"y", 0}}), // std::uint64_t cellID, - 6.0, // float energy, - 0.0, // float energyError, - 0.0, // float time, - 0.0, // float timeError, - edm4hep::Vector3f(0.0, 0.0, 0.0), // edm4hep::Vector3f position, - edm4hep::Vector3f(1.0, 1.0, 0.0), // edm4hep::Vector3f dimension, - 0, // std::int32_t sector, - 0, // std::int32_t layer, - edm4hep::Vector3f(1.8 /* mm */, 1.8 /* mm */, 0.0) // edm4hep::Vector3f local + hits_coll.create(id_desc.encode({{"system", 255}, {"x", 2}, {"y", 0}}), // std::uint64_t cellID, + 6.0, // float energy, + 0.0, // float energyError, + 0.0, // float time, + 0.0, // float timeError, + edm4hep::Vector3f(0.0, 0.0, 0.0), // edm4hep::Vector3f position, + edm4hep::Vector3f(1.0, 1.0, 0.0), // edm4hep::Vector3f dimension, + 0, // std::int32_t sector, + 0, // std::int32_t layer, + edm4hep::Vector3f(1.8 /* mm */, 1.8 /* mm */, 0.0) // edm4hep::Vector3f local ); auto protoclust_coll = std::make_unique(); algo.process({&hits_coll}, {protoclust_coll.get()}); if (cfg.splitCluster) { - REQUIRE( (*protoclust_coll).size() == 2 ); - REQUIRE( (*protoclust_coll)[0].hits_size() == 3 ); - REQUIRE( (*protoclust_coll)[0].weights_size() == 3 ); + REQUIRE((*protoclust_coll).size() == 2); + REQUIRE((*protoclust_coll)[0].hits_size() == 3); + REQUIRE((*protoclust_coll)[0].weights_size() == 3); for (double weight : (*protoclust_coll)[0].getWeights()) { - double energy_fraction = hits_coll[0].getEnergy() / (hits_coll[0].getEnergy() + hits_coll[2].getEnergy()); - REQUIRE_THAT( weight, Catch::Matchers::WithinAbs(energy_fraction, 1e-5) ); + double energy_fraction = + hits_coll[0].getEnergy() / (hits_coll[0].getEnergy() + hits_coll[2].getEnergy()); + REQUIRE_THAT(weight, Catch::Matchers::WithinAbs(energy_fraction, 1e-5)); } - REQUIRE( (*protoclust_coll)[1].hits_size() == 3 ); - REQUIRE( (*protoclust_coll)[1].weights_size() == 3 ); + REQUIRE((*protoclust_coll)[1].hits_size() == 3); + REQUIRE((*protoclust_coll)[1].weights_size() == 3); for (double weight : (*protoclust_coll)[1].getWeights()) { - double energy_fraction = hits_coll[2].getEnergy() / (hits_coll[0].getEnergy() + hits_coll[2].getEnergy()); - REQUIRE_THAT( weight, Catch::Matchers::WithinAbs(energy_fraction, 1e-5) ); + double energy_fraction = + hits_coll[2].getEnergy() / (hits_coll[0].getEnergy() + hits_coll[2].getEnergy()); + REQUIRE_THAT(weight, Catch::Matchers::WithinAbs(energy_fraction, 1e-5)); } } else { - REQUIRE( (*protoclust_coll).size() == 1 ); - REQUIRE( (*protoclust_coll)[0].hits_size() == 3 ); - REQUIRE( (*protoclust_coll)[0].weights_size() == 3 ); + REQUIRE((*protoclust_coll).size() == 1); + REQUIRE((*protoclust_coll)[0].hits_size() == 3); + REQUIRE((*protoclust_coll)[0].weights_size() == 3); } } } diff --git a/src/tests/algorithms_test/calorimetry_HEXPLIT.cc b/src/tests/algorithms_test/calorimetry_HEXPLIT.cc index 911de1f8ef..9ee0717009 100644 --- a/src/tests/algorithms_test/calorimetry_HEXPLIT.cc +++ b/src/tests/algorithms_test/calorimetry_HEXPLIT.cc @@ -1,50 +1,50 @@ // SPDX-License-Identifier: LGPL-3.0-or-later // Copyright (C) 2024, Sebouh Paul -#include // for Detector -#include // for IDDescriptor -#include // for Readout -#include // for MeV, mm, keV, ns +#include // for Detector +#include // for IDDescriptor +#include // for Readout +#include // for MeV, mm, keV, ns #include -#include // for AssertionHandler, operator""_catch_sr, StringRef, REQUIRE, operator<, operator==, operator>, TEST_CASE -#include // for CalorimeterHitCollection, MutableCalorimeterHit, CalorimeterHitMutableCollectionIterator -#include // for Vector3f -#include // for level_enum -#include // for logger -#include // for default_logger -#include // for size_t -#include // for array -#include // for sqrt, abs +#include // for AssertionHandler, operator""_catch_sr, StringRef, REQUIRE, operator<, operator==, operator>, TEST_CASE +#include // for CalorimeterHitCollection, MutableCalorimeterHit, CalorimeterHitMutableCollectionIterator +#include // for Vector3f +#include // for level_enum +#include // for logger +#include // for default_logger +#include // for size_t +#include // for array +#include // for sqrt, abs #include -#include // for allocator, unique_ptr, make_unique, shared_ptr, __shared_ptr_access -#include // for pair +#include // for allocator, unique_ptr, make_unique, shared_ptr, __shared_ptr_access +#include // for pair -#include "algorithms/calorimetry/HEXPLIT.h" // for HEXPLIT -#include "algorithms/calorimetry/HEXPLITConfig.h" // for HEXPLITConfig +#include "algorithms/calorimetry/HEXPLIT.h" // for HEXPLIT +#include "algorithms/calorimetry/HEXPLITConfig.h" // for HEXPLITConfig using eicrecon::HEXPLIT; using eicrecon::HEXPLITConfig; -TEST_CASE( "the subcell-splitting algorithm runs", "[HEXPLIT]" ) { +TEST_CASE("the subcell-splitting algorithm runs", "[HEXPLIT]") { HEXPLIT algo("HEXPLIT"); std::shared_ptr logger = spdlog::default_logger()->clone("HEXPLIT"); logger->set_level(spdlog::level::trace); HEXPLITConfig cfg; - cfg.MIP = 472. * dd4hep::keV; + cfg.MIP = 472. * dd4hep::keV; cfg.tmax = 1000. * dd4hep::ns; auto detector = algorithms::GeoSvc::instance().detector(); - auto id_desc = detector->readout("MockCalorimeterHits").idSpec(); + auto id_desc = detector->readout("MockCalorimeterHits").idSpec(); //create a geometry for the fake detector. - double side_length=31.3*dd4hep::mm; - double layer_spacing=25.1*dd4hep::mm; - double thickness=3*dd4hep::mm; + double side_length = 31.3 * dd4hep::mm; + double layer_spacing = 25.1 * dd4hep::mm; + double thickness = 3 * dd4hep::mm; //dimension of a cell - auto dimension = edm4hep::Vector3f(2*side_length, sqrt(3)*side_length, thickness); + auto dimension = edm4hep::Vector3f(2 * side_length, sqrt(3) * side_length, thickness); algo.applyConfig(cfg); algo.init(); @@ -53,48 +53,47 @@ TEST_CASE( "the subcell-splitting algorithm runs", "[HEXPLIT]" ) { //create a set of 5 hits in consecutive layers, all of which overlap in a single rhombus, // centered at (3/8, sqrt(3)/8)*side_length - std::array layer={0,1,2,3,4}; - std::array x={0,0.75*side_length,0,0.75*side_length,0}; - std::array y={sqrt(3)/2*side_length,-0.25*sqrt(3)*side_length,0,0.25*sqrt(3)*side_length,sqrt(3)/2*side_length}; - std::array E={50*dd4hep::MeV,50*dd4hep::MeV,50*dd4hep::MeV,50*dd4hep::MeV,50*dd4hep::MeV}; - for(size_t i=0; i<5; i++){ + std::array layer = {0, 1, 2, 3, 4}; + std::array x = {0, 0.75 * side_length, 0, 0.75 * side_length, 0}; + std::array y = {sqrt(3) / 2 * side_length, -0.25 * sqrt(3) * side_length, 0, + 0.25 * sqrt(3) * side_length, sqrt(3) / 2 * side_length}; + std::array E = {50 * dd4hep::MeV, 50 * dd4hep::MeV, 50 * dd4hep::MeV, 50 * dd4hep::MeV, + 50 * dd4hep::MeV}; + for (size_t i = 0; i < 5; i++) { hits_coll.create( - id_desc.encode({{"system", 255}, {"x", 0}, {"y", 0}}), // std::uint64_t cellID, - E[i], // float energy, - 0.0, // float energyError, - 0.0, // float time, - 0.0, // float timeError, - edm4hep::Vector3f(x[i], y[i], layer[i]*layer_spacing), // edm4hep::Vector3f position, - dimension, // edm4hep::Vector3f dimension, - 0, // std::int32_t sector, - layer[i], // std::int32_t layer, - edm4hep::Vector3f(x[i], y[i], layer[i]*layer_spacing) // edm4hep::Vector3f local - ); + id_desc.encode({{"system", 255}, {"x", 0}, {"y", 0}}), // std::uint64_t cellID, + E[i], // float energy, + 0.0, // float energyError, + 0.0, // float time, + 0.0, // float timeError, + edm4hep::Vector3f(x[i], y[i], layer[i] * layer_spacing), // edm4hep::Vector3f position, + dimension, // edm4hep::Vector3f dimension, + 0, // std::int32_t sector, + layer[i], // std::int32_t layer, + edm4hep::Vector3f(x[i], y[i], layer[i] * layer_spacing) // edm4hep::Vector3f local + ); } auto subcellhits_coll = std::make_unique(); algo.process({&hits_coll}, {subcellhits_coll.get()}); - //the number of subcell hits should be equal to the //number of subcells per cell (12) times the number of cells (5) - REQUIRE( (*subcellhits_coll).size() == 60); + REQUIRE((*subcellhits_coll).size() == 60); //next check that the sum of the hit energies equals the energy that I gave the hits - double tol=0.001; - double Esum=0; - int i=0; - for (auto subcell : *subcellhits_coll){ - Esum+=subcell.getEnergy(); + double tol = 0.001; + double Esum = 0; + int i = 0; + for (auto subcell : *subcellhits_coll) { + Esum += subcell.getEnergy(); i++; - if (i%12==0){ - REQUIRE(abs(Esum-E[i/12-1])/E[i/12-1]0.95); - - + REQUIRE((*subcellhits_coll)[35].getEnergy() / E[2] > 0.95); } diff --git a/src/tests/algorithms_test/pid_MergeParticleID.cc b/src/tests/algorithms_test/pid_MergeParticleID.cc index 1a19fac787..85873925f8 100644 --- a/src/tests/algorithms_test/pid_MergeParticleID.cc +++ b/src/tests/algorithms_test/pid_MergeParticleID.cc @@ -33,7 +33,7 @@ TEST_CASE("the PID MergeParticleID algorithm runs", "[MergeParticleID]") { * since `MergeParticleID` matches tracks by ID */ auto tracks = std::make_unique(); - for(int i=0; i<2; i++) + for (int i = 0; i < 2; i++) tracks->create(); // Cherenkov PID inputs @@ -42,7 +42,7 @@ TEST_CASE("the PID MergeParticleID algorithm runs", "[MergeParticleID]") { * 2 or 3 possible PID hypotheses for each */ - edm4eic::MutableCherenkovParticleID pid; + edm4eic::MutableCherenkovParticleID pid; edm4eic::CherenkovParticleIDHypothesis pid_hyp; // collection 1 ------ @@ -61,8 +61,8 @@ TEST_CASE("the PID MergeParticleID algorithm runs", "[MergeParticleID]") { pid_hyp.npe = 8; pid_hyp.weight = 80; pid.addToHypotheses(pid_hyp); - for(int i=0; i<=pid.getNpe(); i++) - pid.addToThetaPhiPhotons(edm4hep::Vector2f{M_PI/4, 0}); + for (int i = 0; i <= pid.getNpe(); i++) + pid.addToThetaPhiPhotons(edm4hep::Vector2f{M_PI / 4, 0}); pid = coll_cherenkov_1->create(); pid.setChargedParticle(tracks->at(1)); @@ -77,8 +77,8 @@ TEST_CASE("the PID MergeParticleID algorithm runs", "[MergeParticleID]") { pid_hyp.npe = 10; pid_hyp.weight = 80; pid.addToHypotheses(pid_hyp); - for(int i=0; i<=pid.getNpe(); i++) - pid.addToThetaPhiPhotons(edm4hep::Vector2f{-M_PI/4, 0}); + for (int i = 0; i <= pid.getNpe(); i++) + pid.addToThetaPhiPhotons(edm4hep::Vector2f{-M_PI / 4, 0}); // collection 2 ------ auto coll_cherenkov_2 = std::make_unique(); @@ -96,8 +96,8 @@ TEST_CASE("the PID MergeParticleID algorithm runs", "[MergeParticleID]") { pid_hyp.npe = 2; pid_hyp.weight = 90; pid.addToHypotheses(pid_hyp); - for(int i=0; i<=pid.getNpe(); i++) - pid.addToThetaPhiPhotons(edm4hep::Vector2f{M_PI/4, 0}); + for (int i = 0; i <= pid.getNpe(); i++) + pid.addToThetaPhiPhotons(edm4hep::Vector2f{M_PI / 4, 0}); pid = coll_cherenkov_2->create(); pid.setChargedParticle(tracks->at(0)); @@ -116,25 +116,24 @@ TEST_CASE("the PID MergeParticleID algorithm runs", "[MergeParticleID]") { pid_hyp.npe = 1; pid_hyp.weight = 60; pid.addToHypotheses(pid_hyp); - for(int i=0; i<=pid.getNpe(); i++) - pid.addToThetaPhiPhotons(edm4hep::Vector2f{-M_PI/4, 0}); + for (int i = 0; i <= pid.getNpe(); i++) + pid.addToThetaPhiPhotons(edm4hep::Vector2f{-M_PI / 4, 0}); // Cherenkov PID tests //---------------------------------------------------------- std::vector> coll_cherenkov_list = { - coll_cherenkov_1.get(), - coll_cherenkov_2.get() - }; + coll_cherenkov_1.get(), coll_cherenkov_2.get()}; - auto find_cherenkov_pid_for_track = [] (const auto& coll, auto trk) { - for(auto obj : *coll) { - if(obj.getChargedParticle().id() == trk.id()) + auto find_cherenkov_pid_for_track = [](const auto& coll, auto trk) { + for (auto obj : *coll) { + if (obj.getChargedParticle().id() == trk.id()) return obj; } FAIL("ERROR: cannot find CherenkovParticleID given track"); - if(coll->size() == 0) - throw std::runtime_error("empty collection used in pid_MergeParticleID::find_cherenkov_pid_for_track"); + if (coll->size() == 0) + throw std::runtime_error( + "empty collection used in pid_MergeParticleID::find_cherenkov_pid_for_track"); return coll->at(0); }; @@ -149,54 +148,57 @@ TEST_CASE("the PID MergeParticleID algorithm runs", "[MergeParticleID]") { auto result = std::make_unique(); algo.process({coll_cherenkov_list}, {result.get()}); - auto pid_0 = find_cherenkov_pid_for_track(result, tracks->at(0)); - auto pid_1 = find_cherenkov_pid_for_track(result, tracks->at(1)); + auto pid_0 = find_cherenkov_pid_for_track(result, tracks->at(0)); + auto pid_1 = find_cherenkov_pid_for_track(result, tracks->at(1)); - REQUIRE_THAT( pid_0.getNpe(), Catch::Matchers::WithinAbs(10+6, EPSILON) ); - REQUIRE_THAT( pid_1.getNpe(), Catch::Matchers::WithinAbs(11+4, EPSILON) ); + REQUIRE_THAT(pid_0.getNpe(), Catch::Matchers::WithinAbs(10 + 6, EPSILON)); + REQUIRE_THAT(pid_1.getNpe(), Catch::Matchers::WithinAbs(11 + 4, EPSILON)); - REQUIRE_THAT( pid_0.getRefractiveIndex(), Catch::Matchers::WithinAbs((10*1.05+6*1.3)/(10+6), EPSILON) ); - REQUIRE_THAT( pid_1.getRefractiveIndex(), Catch::Matchers::WithinAbs((11*1.06+4*1.5)/(11+4), EPSILON) ); + REQUIRE_THAT(pid_0.getRefractiveIndex(), + Catch::Matchers::WithinAbs((10 * 1.05 + 6 * 1.3) / (10 + 6), EPSILON)); + REQUIRE_THAT(pid_1.getRefractiveIndex(), + Catch::Matchers::WithinAbs((11 * 1.06 + 4 * 1.5) / (11 + 4), EPSILON)); - REQUIRE_THAT( pid_0.getPhotonEnergy(), Catch::Matchers::WithinAbs((10*3e-9+6*4e-9)/(10+6), EPSILON) ); - REQUIRE_THAT( pid_1.getPhotonEnergy(), Catch::Matchers::WithinAbs((11*4e-9+4*3e-9)/(11+4), EPSILON) ); + REQUIRE_THAT(pid_0.getPhotonEnergy(), + Catch::Matchers::WithinAbs((10 * 3e-9 + 6 * 4e-9) / (10 + 6), EPSILON)); + REQUIRE_THAT(pid_1.getPhotonEnergy(), + Catch::Matchers::WithinAbs((11 * 4e-9 + 4 * 3e-9) / (11 + 4), EPSILON)); REQUIRE(pid_0.hypotheses_size() == 3); - for(auto hyp : pid_0.getHypotheses()) { - switch(hyp.PDG) { - case 211: - REQUIRE_THAT( hyp.npe, Catch::Matchers::WithinAbs(10+1, EPSILON) ); - REQUIRE_THAT( hyp.weight, Catch::Matchers::WithinAbs(100+80, EPSILON) ); - break; - case 321: - REQUIRE_THAT( hyp.npe, Catch::Matchers::WithinAbs(8+4, EPSILON) ); - REQUIRE_THAT( hyp.weight, Catch::Matchers::WithinAbs(80+70, EPSILON) ); - break; - case 11: - REQUIRE_THAT( hyp.npe, Catch::Matchers::WithinAbs(1, EPSILON) ); - REQUIRE_THAT( hyp.weight, Catch::Matchers::WithinAbs(60, EPSILON) ); - break; - default: - FAIL("untested PDG hypothesis"); + for (auto hyp : pid_0.getHypotheses()) { + switch (hyp.PDG) { + case 211: + REQUIRE_THAT(hyp.npe, Catch::Matchers::WithinAbs(10 + 1, EPSILON)); + REQUIRE_THAT(hyp.weight, Catch::Matchers::WithinAbs(100 + 80, EPSILON)); + break; + case 321: + REQUIRE_THAT(hyp.npe, Catch::Matchers::WithinAbs(8 + 4, EPSILON)); + REQUIRE_THAT(hyp.weight, Catch::Matchers::WithinAbs(80 + 70, EPSILON)); + break; + case 11: + REQUIRE_THAT(hyp.npe, Catch::Matchers::WithinAbs(1, EPSILON)); + REQUIRE_THAT(hyp.weight, Catch::Matchers::WithinAbs(60, EPSILON)); + break; + default: + FAIL("untested PDG hypothesis"); } } REQUIRE(pid_1.hypotheses_size() == 2); - for(auto hyp : pid_1.getHypotheses()) { - switch(hyp.PDG) { - case 211: - REQUIRE_THAT( hyp.npe, Catch::Matchers::WithinAbs(10+3, EPSILON) ); - REQUIRE_THAT( hyp.weight, Catch::Matchers::WithinAbs(80+200, EPSILON) ); - break; - case 321: - REQUIRE_THAT( hyp.npe, Catch::Matchers::WithinAbs(10+2, EPSILON) ); - REQUIRE_THAT( hyp.weight, Catch::Matchers::WithinAbs(100+90, EPSILON) ); - break; - default: - FAIL("untested PDG hypothesis"); + for (auto hyp : pid_1.getHypotheses()) { + switch (hyp.PDG) { + case 211: + REQUIRE_THAT(hyp.npe, Catch::Matchers::WithinAbs(10 + 3, EPSILON)); + REQUIRE_THAT(hyp.weight, Catch::Matchers::WithinAbs(80 + 200, EPSILON)); + break; + case 321: + REQUIRE_THAT(hyp.npe, Catch::Matchers::WithinAbs(10 + 2, EPSILON)); + REQUIRE_THAT(hyp.weight, Catch::Matchers::WithinAbs(100 + 90, EPSILON)); + break; + default: + FAIL("untested PDG hypothesis"); } } - } // multiplicative weights @@ -214,52 +216,54 @@ TEST_CASE("the PID MergeParticleID algorithm runs", "[MergeParticleID]") { auto result = std::make_unique(); algo.process({coll_cherenkov_list}, {result.get()}); - auto pid_0 = find_cherenkov_pid_for_track(result, tracks->at(0)); - auto pid_1 = find_cherenkov_pid_for_track(result, tracks->at(1)); - - REQUIRE_THAT( pid_0.getNpe(), Catch::Matchers::WithinAbs(10+6, EPSILON) ); - REQUIRE_THAT( pid_1.getNpe(), Catch::Matchers::WithinAbs(11+4, EPSILON) ); - - REQUIRE_THAT( pid_0.getRefractiveIndex(), Catch::Matchers::WithinAbs((10*1.05+6*1.3)/(10+6), EPSILON) ); - REQUIRE_THAT( pid_1.getRefractiveIndex(), Catch::Matchers::WithinAbs((11*1.06+4*1.5)/(11+4), EPSILON) ); - - REQUIRE_THAT( pid_0.getPhotonEnergy(), Catch::Matchers::WithinAbs((10*3e-9+6*4e-9)/(10+6), EPSILON) ); - REQUIRE_THAT( pid_1.getPhotonEnergy(), Catch::Matchers::WithinAbs((11*4e-9+4*3e-9)/(11+4), EPSILON) ); - - for(auto hyp : pid_0.getHypotheses()) { - switch(hyp.PDG) { - case 211: - REQUIRE_THAT( hyp.npe, Catch::Matchers::WithinAbs(10+1, EPSILON) ); - REQUIRE_THAT( hyp.weight, Catch::Matchers::WithinAbs(100*80, EPSILON) ); - break; - case 321: - REQUIRE_THAT( hyp.npe, Catch::Matchers::WithinAbs(8+4, EPSILON) ); - REQUIRE_THAT( hyp.weight, Catch::Matchers::WithinAbs(80*70, EPSILON) ); - break; - case 11: - REQUIRE_THAT( hyp.npe, Catch::Matchers::WithinAbs(1, EPSILON) ); - REQUIRE_THAT( hyp.weight, Catch::Matchers::WithinAbs(60, EPSILON) ); - break; - default: - FAIL("untested PDG hypothesis"); + auto pid_0 = find_cherenkov_pid_for_track(result, tracks->at(0)); + auto pid_1 = find_cherenkov_pid_for_track(result, tracks->at(1)); + + REQUIRE_THAT(pid_0.getNpe(), Catch::Matchers::WithinAbs(10 + 6, EPSILON)); + REQUIRE_THAT(pid_1.getNpe(), Catch::Matchers::WithinAbs(11 + 4, EPSILON)); + + REQUIRE_THAT(pid_0.getRefractiveIndex(), + Catch::Matchers::WithinAbs((10 * 1.05 + 6 * 1.3) / (10 + 6), EPSILON)); + REQUIRE_THAT(pid_1.getRefractiveIndex(), + Catch::Matchers::WithinAbs((11 * 1.06 + 4 * 1.5) / (11 + 4), EPSILON)); + + REQUIRE_THAT(pid_0.getPhotonEnergy(), + Catch::Matchers::WithinAbs((10 * 3e-9 + 6 * 4e-9) / (10 + 6), EPSILON)); + REQUIRE_THAT(pid_1.getPhotonEnergy(), + Catch::Matchers::WithinAbs((11 * 4e-9 + 4 * 3e-9) / (11 + 4), EPSILON)); + + for (auto hyp : pid_0.getHypotheses()) { + switch (hyp.PDG) { + case 211: + REQUIRE_THAT(hyp.npe, Catch::Matchers::WithinAbs(10 + 1, EPSILON)); + REQUIRE_THAT(hyp.weight, Catch::Matchers::WithinAbs(100 * 80, EPSILON)); + break; + case 321: + REQUIRE_THAT(hyp.npe, Catch::Matchers::WithinAbs(8 + 4, EPSILON)); + REQUIRE_THAT(hyp.weight, Catch::Matchers::WithinAbs(80 * 70, EPSILON)); + break; + case 11: + REQUIRE_THAT(hyp.npe, Catch::Matchers::WithinAbs(1, EPSILON)); + REQUIRE_THAT(hyp.weight, Catch::Matchers::WithinAbs(60, EPSILON)); + break; + default: + FAIL("untested PDG hypothesis"); } } - for(auto hyp : pid_1.getHypotheses()) { - switch(hyp.PDG) { - case 211: - REQUIRE_THAT( hyp.npe, Catch::Matchers::WithinAbs(10+3, EPSILON) ); - REQUIRE_THAT( hyp.weight, Catch::Matchers::WithinAbs(80*200, EPSILON) ); - break; - case 321: - REQUIRE_THAT( hyp.npe, Catch::Matchers::WithinAbs(10+2, EPSILON) ); - REQUIRE_THAT( hyp.weight, Catch::Matchers::WithinAbs(100*90, EPSILON) ); - break; - default: - FAIL("untested PDG hypothesis"); + for (auto hyp : pid_1.getHypotheses()) { + switch (hyp.PDG) { + case 211: + REQUIRE_THAT(hyp.npe, Catch::Matchers::WithinAbs(10 + 3, EPSILON)); + REQUIRE_THAT(hyp.weight, Catch::Matchers::WithinAbs(80 * 200, EPSILON)); + break; + case 321: + REQUIRE_THAT(hyp.npe, Catch::Matchers::WithinAbs(10 + 2, EPSILON)); + REQUIRE_THAT(hyp.weight, Catch::Matchers::WithinAbs(100 * 90, EPSILON)); + break; + default: + FAIL("untested PDG hypothesis"); } } - } - } diff --git a/src/tests/algorithms_test/pid_MergeTracks.cc b/src/tests/algorithms_test/pid_MergeTracks.cc index 1bf10a8c09..3dd05ee3be 100644 --- a/src/tests/algorithms_test/pid_MergeTracks.cc +++ b/src/tests/algorithms_test/pid_MergeTracks.cc @@ -32,12 +32,12 @@ TEST_CASE("the PID MergeTracks algorithm runs", "[MergeTracks]") { struct Point { decltype(edm4eic::TrackPoint::position) position; decltype(edm4eic::TrackPoint::momentum) momentum; - decltype(edm4eic::TrackPoint::time) time; + decltype(edm4eic::TrackPoint::time) time; }; - auto make_track = [] (auto& coll, std::vector points) { + auto make_track = [](auto& coll, std::vector points) { auto trk = coll->create(); - for(auto& point : points) { + for (auto& point : points) { edm4eic::TrackPoint trk_point; trk_point.position = point.position; trk_point.momentum = point.momentum; @@ -46,14 +46,11 @@ TEST_CASE("the PID MergeTracks algorithm runs", "[MergeTracks]") { } }; - auto track_length = [] (auto trk) { + auto track_length = [](auto trk) { auto a = trk.getPoints(0); - auto b = trk.getPoints(trk.points_size()-1); - return std::hypot( - a.position.x - b.position.x, - a.position.y - b.position.y, - a.position.z - b.position.z - ); + auto b = trk.getPoints(trk.points_size() - 1); + return std::hypot(a.position.x - b.position.x, a.position.y - b.position.y, + a.position.z - b.position.z); }; // inputs @@ -73,112 +70,101 @@ TEST_CASE("the PID MergeTracks algorithm runs", "[MergeTracks]") { auto collection2 = std::make_unique(); // track0 - make_track(collection0, { // horizontal - { {0, 0, 0}, {1, 0, 0}, 1 }, // { position, momentum, time } - { {1, 0, 0}, {1, 0, 0}, 2 } - }); - make_track(collection1, { // horizontal - { {2, 0, 0}, {1, 0, 0}, 3 }, - { {3, 0, 0}, {1, 0, 0}, 4 } - }); - make_track(collection2, { // horizontal - { {4, 0, 0}, {1, 0, 0}, 5 }, - { {5, 0, 0}, {1, 0, 0}, 6 } - }); + make_track(collection0, { // horizontal + {{0, 0, 0}, {1, 0, 0}, 1}, // { position, momentum, time } + {{1, 0, 0}, {1, 0, 0}, 2}}); + make_track(collection1, {// horizontal + {{2, 0, 0}, {1, 0, 0}, 3}, + {{3, 0, 0}, {1, 0, 0}, 4}}); + make_track(collection2, {// horizontal + {{4, 0, 0}, {1, 0, 0}, 5}, + {{5, 0, 0}, {1, 0, 0}, 6}}); // track1 - make_track(collection0, { // horizontal - { {0, 0, 0}, {1, 0, 0}, 1 }, - { {1, 0, 0}, {1, 0, 0}, 2 } - }); - make_track(collection1, { // empty - { } - }); - make_track(collection2, { // one point - { {2, 0, 0}, {1, 0, 0}, 3 } - }); + make_track(collection0, {// horizontal + {{0, 0, 0}, {1, 0, 0}, 1}, + {{1, 0, 0}, {1, 0, 0}, 2}}); + make_track(collection1, {// empty + {}}); + make_track(collection2, {// one point + {{2, 0, 0}, {1, 0, 0}, 3}}); // track2 - make_track(collection0, { // vertical - { {0, 0, 0}, {0, 1, 0}, 1 }, - { {0, 1, 0}, {0, 1, 0}, 2 } - }); - make_track(collection1, { // horizontal - { {0, 1, 0}, {1, 0, 0}, 3 }, - { {1, 1, 0}, {1, 0, 0}, 4 } - }); - make_track(collection2, { // vertical - { {1, 1, 0}, {0, 1, 0}, 5 }, - { {1, 2, 0}, {0, 1, 0}, 6 } - }); + make_track(collection0, {// vertical + {{0, 0, 0}, {0, 1, 0}, 1}, + {{0, 1, 0}, {0, 1, 0}, 2}}); + make_track(collection1, {// horizontal + {{0, 1, 0}, {1, 0, 0}, 3}, + {{1, 1, 0}, {1, 0, 0}, 4}}); + make_track(collection2, {// vertical + {{1, 1, 0}, {0, 1, 0}, 5}, + {{1, 2, 0}, {0, 1, 0}, 6}}); // track3 - make_track(collection0, { // horizontal - { {1, 0, 0}, {1, 0, 0}, 2 }, - { {0, 0, 0}, {1, 0, 0}, 1 } - }); - make_track(collection1, { // horizontal - { {3, 0, 0}, {1, 0, 0}, 4 }, - { {4, 0, 0}, {1, 0, 0}, 5 } - }); - make_track(collection2, { // horizontal - { {5, 0, 0}, {1, 0, 0}, 6 }, - { {2, 0, 0}, {1, 0, 0}, 3 } - }); + make_track(collection0, {// horizontal + {{1, 0, 0}, {1, 0, 0}, 2}, + {{0, 0, 0}, {1, 0, 0}, 1}}); + make_track(collection1, {// horizontal + {{3, 0, 0}, {1, 0, 0}, 4}, + {{4, 0, 0}, {1, 0, 0}, 5}}); + make_track(collection2, {// horizontal + {{5, 0, 0}, {1, 0, 0}, 6}, + {{2, 0, 0}, {1, 0, 0}, 3}}); // tests //---------------------------------------------------------- SECTION("merge tracks from 1 collection") { // run algorithm - std::vector> colls = { collection0.get() }; + std::vector> colls = {collection0.get()}; // create output collection auto trks = std::make_unique(); algo.process({colls}, {trks.get()}); // input collection(s) size == output collection size REQUIRE(trks->size() == colls.front()->size()); // track length: from endpoints - REQUIRE_THAT( track_length(trks->at(0)), Catch::Matchers::WithinAbs(1, EPSILON) ); - REQUIRE_THAT( track_length(trks->at(1)), Catch::Matchers::WithinAbs(1, EPSILON) ); - REQUIRE_THAT( track_length(trks->at(2)), Catch::Matchers::WithinAbs(1, EPSILON) ); - REQUIRE_THAT( track_length(trks->at(3)), Catch::Matchers::WithinAbs(1, EPSILON) ); + REQUIRE_THAT(track_length(trks->at(0)), Catch::Matchers::WithinAbs(1, EPSILON)); + REQUIRE_THAT(track_length(trks->at(1)), Catch::Matchers::WithinAbs(1, EPSILON)); + REQUIRE_THAT(track_length(trks->at(2)), Catch::Matchers::WithinAbs(1, EPSILON)); + REQUIRE_THAT(track_length(trks->at(3)), Catch::Matchers::WithinAbs(1, EPSILON)); // track length: from algorithm // FIXME when implemented in `MergeTracks` - for(const auto& trk : *trks) - REQUIRE_THAT( trk.getLength(), Catch::Matchers::WithinAbs(0, EPSILON) ); + for (const auto& trk : *trks) + REQUIRE_THAT(trk.getLength(), Catch::Matchers::WithinAbs(0, EPSILON)); } SECTION("merge tracks from 2 collections") { // run algorithm - std::vector> colls = { collection0.get(), collection1.get() }; + std::vector> colls = {collection0.get(), + collection1.get()}; auto trks = std::make_unique(); algo.process({colls}, {trks.get()}); // input collection(s) size == output collection size REQUIRE(trks->size() == colls.front()->size()); // track length: from endpoints - REQUIRE_THAT( track_length(trks->at(0)), Catch::Matchers::WithinAbs(3, EPSILON) ); - REQUIRE_THAT( track_length(trks->at(1)), Catch::Matchers::WithinAbs(1, EPSILON) ); - REQUIRE_THAT( track_length(trks->at(2)), Catch::Matchers::WithinAbs(std::hypot(1,1), EPSILON) ); - REQUIRE_THAT( track_length(trks->at(3)), Catch::Matchers::WithinAbs(4, EPSILON) ); + REQUIRE_THAT(track_length(trks->at(0)), Catch::Matchers::WithinAbs(3, EPSILON)); + REQUIRE_THAT(track_length(trks->at(1)), Catch::Matchers::WithinAbs(1, EPSILON)); + REQUIRE_THAT(track_length(trks->at(2)), Catch::Matchers::WithinAbs(std::hypot(1, 1), EPSILON)); + REQUIRE_THAT(track_length(trks->at(3)), Catch::Matchers::WithinAbs(4, EPSILON)); // track length: from algorithm // FIXME when implemented in `MergeTracks` - for(const auto& trk : *trks) - REQUIRE_THAT( trk.getLength(), Catch::Matchers::WithinAbs(0, EPSILON) ); + for (const auto& trk : *trks) + REQUIRE_THAT(trk.getLength(), Catch::Matchers::WithinAbs(0, EPSILON)); } SECTION("merge tracks from 3 collections") { // run algorithm - std::vector> colls = { collection0.get(), collection1.get(), collection2.get() }; + std::vector> colls = { + collection0.get(), collection1.get(), collection2.get()}; auto trks = std::make_unique(); algo.process({colls}, {trks.get()}); // input collection(s) size == output collection size REQUIRE(trks->size() == colls.front()->size()); // track length: from endpoints - REQUIRE_THAT( track_length(trks->at(0)), Catch::Matchers::WithinAbs(5, EPSILON) ); - REQUIRE_THAT( track_length(trks->at(1)), Catch::Matchers::WithinAbs(2, EPSILON) ); - REQUIRE_THAT( track_length(trks->at(2)), Catch::Matchers::WithinAbs(std::hypot(1,2), EPSILON) ); - REQUIRE_THAT( track_length(trks->at(3)), Catch::Matchers::WithinAbs(5, EPSILON) ); + REQUIRE_THAT(track_length(trks->at(0)), Catch::Matchers::WithinAbs(5, EPSILON)); + REQUIRE_THAT(track_length(trks->at(1)), Catch::Matchers::WithinAbs(2, EPSILON)); + REQUIRE_THAT(track_length(trks->at(2)), Catch::Matchers::WithinAbs(std::hypot(1, 2), EPSILON)); + REQUIRE_THAT(track_length(trks->at(3)), Catch::Matchers::WithinAbs(5, EPSILON)); // track length: from algorithm // FIXME when implemented in `MergeTracks` - for(const auto& trk : *trks) - REQUIRE_THAT( trk.getLength(), Catch::Matchers::WithinAbs(0, EPSILON) ); + for (const auto& trk : *trks) + REQUIRE_THAT(trk.getLength(), Catch::Matchers::WithinAbs(0, EPSILON)); } - } diff --git a/src/tests/geometry_navigation_test/GeometryNavigationSteps_processor.cc b/src/tests/geometry_navigation_test/GeometryNavigationSteps_processor.cc index 6d15ec1e97..d1f6591083 100644 --- a/src/tests/geometry_navigation_test/GeometryNavigationSteps_processor.cc +++ b/src/tests/geometry_navigation_test/GeometryNavigationSteps_processor.cc @@ -8,42 +8,33 @@ #include "services/geometry/acts/ACTSGeo_service.h" #include "services/rootfile/RootFile_service.h" -GeometryNavigationSteps_processor::GeometryNavigationSteps_processor(JApplication *app) : - JEventProcessor(app) -{ -} - -void GeometryNavigationSteps_processor::Init() -{ - std::string plugin_name=("geometry_navigation_test"); +GeometryNavigationSteps_processor::GeometryNavigationSteps_processor(JApplication* app) + : JEventProcessor(app) {} - // Get JANA application - auto *app = GetApplication(); +void GeometryNavigationSteps_processor::Init() { + std::string plugin_name = ("geometry_navigation_test"); - // Ask service locator a file to write histograms to - auto root_file_service = app->GetService(); + // Get JANA application + auto* app = GetApplication(); - // Get TDirectory for histograms root file - auto globalRootLock = app->GetService(); - globalRootLock->acquire_write_lock(); - auto *file = root_file_service->GetHistFile(); - globalRootLock->release_lock(); + // Ask service locator a file to write histograms to + auto root_file_service = app->GetService(); - // Create a directory for this plugin. And subdirectories for series of histograms - m_dir_main = file->mkdir(plugin_name.c_str()); + // Get TDirectory for histograms root file + auto globalRootLock = app->GetService(); + globalRootLock->acquire_write_lock(); + auto* file = root_file_service->GetHistFile(); + globalRootLock->release_lock(); - // Get log level from user parameter or default - InitLogger(app, plugin_name); + // Create a directory for this plugin. And subdirectories for series of histograms + m_dir_main = file->mkdir(plugin_name.c_str()); - auto acts_service = GetApplication()->GetService(); + // Get log level from user parameter or default + InitLogger(app, plugin_name); + auto acts_service = GetApplication()->GetService(); } +void GeometryNavigationSteps_processor::Process(const std::shared_ptr& event) {} -void GeometryNavigationSteps_processor::Process(const std::shared_ptr& event) -{ -} - -void GeometryNavigationSteps_processor::Finish() -{ -} +void GeometryNavigationSteps_processor::Finish() {} diff --git a/src/tests/geometry_navigation_test/GeometryNavigationSteps_processor.h b/src/tests/geometry_navigation_test/GeometryNavigationSteps_processor.h index 26cbbeeec0..2f115d2793 100644 --- a/src/tests/geometry_navigation_test/GeometryNavigationSteps_processor.h +++ b/src/tests/geometry_navigation_test/GeometryNavigationSteps_processor.h @@ -11,46 +11,44 @@ #include "extensions/spdlog/SpdlogMixin.h" -class GeometryNavigationSteps_processor: - public JEventProcessor, - public eicrecon::SpdlogMixin // this automates proper log initialization +class GeometryNavigationSteps_processor + : public JEventProcessor, + public eicrecon::SpdlogMixin // this automates proper log initialization { public: - explicit GeometryNavigationSteps_processor(JApplication *); - ~GeometryNavigationSteps_processor() override = default; - - //---------------------------- - // Init - // - // This is called once before the first call to the Process method - // below. You may, for example, want to open an output file here. - // Only one thread will call this. - void Init() override; - - //---------------------------- - // Process - // - // This is called for every event. Multiple threads may call this - // simultaneously. If you write something to an output file here - // then make sure to protect it with a mutex or similar mechanism. - // Minimize what is done while locked since that directly affects - // the multi-threaded performance. - void Process(const std::shared_ptr& event) override; - - //---------------------------- - // Finish - // - // This is called once after all events have been processed. You may, - // for example, want to close an output file here. - // Only one thread will call this. - void Finish() override; + explicit GeometryNavigationSteps_processor(JApplication*); + ~GeometryNavigationSteps_processor() override = default; + + //---------------------------- + // Init + // + // This is called once before the first call to the Process method + // below. You may, for example, want to open an output file here. + // Only one thread will call this. + void Init() override; + + //---------------------------- + // Process + // + // This is called for every event. Multiple threads may call this + // simultaneously. If you write something to an output file here + // then make sure to protect it with a mutex or similar mechanism. + // Minimize what is done while locked since that directly affects + // the multi-threaded performance. + void Process(const std::shared_ptr& event) override; + + //---------------------------- + // Finish + // + // This is called once after all events have been processed. You may, + // for example, want to close an output file here. + // Only one thread will call this. + void Finish() override; private: - - /// Directory to store histograms to - TDirectory *m_dir_main{}; - Acts::GeometryContext m_geoContext; - Acts::MagneticFieldContext m_fieldContext; - std::shared_ptr m_log; - + /// Directory to store histograms to + TDirectory* m_dir_main{}; + Acts::GeometryContext m_geoContext; + Acts::MagneticFieldContext m_fieldContext; + std::shared_ptr m_log; }; diff --git a/src/tests/geometry_navigation_test/geometry_navigation_test.cc b/src/tests/geometry_navigation_test/geometry_navigation_test.cc index e451412ee9..b378ed0d59 100644 --- a/src/tests/geometry_navigation_test/geometry_navigation_test.cc +++ b/src/tests/geometry_navigation_test/geometry_navigation_test.cc @@ -7,14 +7,13 @@ #include "GeometryNavigationSteps_processor.h" - extern "C" { - void InitPlugin(JApplication *app) { +void InitPlugin(JApplication* app) { - // Initializes this plugin - InitJANAPlugin(app); + // Initializes this plugin + InitJANAPlugin(app); - // Adds our processor to JANA2 to execute - app->Add(new GeometryNavigationSteps_processor(app)); - } + // Adds our processor to JANA2 to execute + app->Add(new GeometryNavigationSteps_processor(app)); +} } diff --git a/src/tests/omnifactory_test/JOmniFactoryTests.cc b/src/tests/omnifactory_test/JOmniFactoryTests.cc index 91ec196c0c..1d15ca5cab 100644 --- a/src/tests/omnifactory_test/JOmniFactoryTests.cc +++ b/src/tests/omnifactory_test/JOmniFactoryTests.cc @@ -21,401 +21,414 @@ #include "extensions/jana/JOmniFactoryGeneratorT.h" struct BasicTestAlgConfig { - int bucket_count = 42; - double threshold = 7.6; + int bucket_count = 42; + double threshold = 7.6; }; struct BasicTestAlg : public JOmniFactory { - PodioOutput output_hits_left {this, "output_hits_left"}; - PodioOutput output_hits_right {this, "output_hits_right"}; - Output output_vechits {this, "output_vechits"}; - - ParameterRef bucket_count {this, "bucket_count", config().bucket_count, "The total number of buckets [dimensionless]"}; - ParameterRef threshold {this, "threshold", config().threshold, "The max cutoff threshold [V * A * kg^-1 * m^-2 * sec^-3]"}; - - std::vector GetOutputs() { return this->m_outputs; } - - int m_init_call_count = 0; - int m_changerun_call_count = 0; - int m_process_call_count = 0; - - void Configure() { - m_init_call_count++; - logger()->info("Calling BasicTestAlg::Configure"); - } - - void ChangeRun(int64_t run_number) { - m_changerun_call_count++; - logger()->info("Calling BasicTestAlg::ChangeRun"); - } - - // NOLINTNEXTLINE(bugprone-easily-swappable-parameters) - void Process(int64_t run_number, uint64_t event_number) { - m_process_call_count++; - logger()->info("Calling BasicTestAlg::Process with bucket_count={}, threshold={}", config().bucket_count, config().threshold); - // Provide empty collections (as opposed to nulls) so that PODIO doesn't crash - // TODO: NWB: I though multifactories already took care of this under the hood somewhere - output_hits_left() = std::make_unique(); - output_hits_right() = std::make_unique(); - output_vechits().push_back(new edm4hep::SimCalorimeterHit()); - } + PodioOutput output_hits_left{this, "output_hits_left"}; + PodioOutput output_hits_right{this, "output_hits_right"}; + Output output_vechits{this, "output_vechits"}; + + ParameterRef bucket_count{this, "bucket_count", config().bucket_count, + "The total number of buckets [dimensionless]"}; + ParameterRef threshold{this, "threshold", config().threshold, + "The max cutoff threshold [V * A * kg^-1 * m^-2 * sec^-3]"}; + + std::vector GetOutputs() { return this->m_outputs; } + + int m_init_call_count = 0; + int m_changerun_call_count = 0; + int m_process_call_count = 0; + + void Configure() { + m_init_call_count++; + logger()->info("Calling BasicTestAlg::Configure"); + } + + void ChangeRun(int64_t run_number) { + m_changerun_call_count++; + logger()->info("Calling BasicTestAlg::ChangeRun"); + } + + // NOLINTNEXTLINE(bugprone-easily-swappable-parameters) + void Process(int64_t run_number, uint64_t event_number) { + m_process_call_count++; + logger()->info("Calling BasicTestAlg::Process with bucket_count={}, threshold={}", + config().bucket_count, config().threshold); + // Provide empty collections (as opposed to nulls) so that PODIO doesn't crash + // TODO: NWB: I though multifactories already took care of this under the hood somewhere + output_hits_left() = std::make_unique(); + output_hits_right() = std::make_unique(); + output_vechits().push_back(new edm4hep::SimCalorimeterHit()); + } }; template MultifactoryT* RetrieveMultifactory(JFactorySet* facset, std::string output_collection_name) { - auto fac = facset->GetFactory(output_collection_name); - REQUIRE(fac != nullptr); - auto helper = dynamic_cast*>(fac); - REQUIRE(helper != nullptr); - auto multifactory = helper->GetMultifactory(); - REQUIRE(multifactory != nullptr); - auto typed = dynamic_cast(multifactory); - REQUIRE(typed != nullptr); - return typed; + auto fac = facset->GetFactory(output_collection_name); + REQUIRE(fac != nullptr); + auto helper = dynamic_cast*>(fac); + REQUIRE(helper != nullptr); + auto multifactory = helper->GetMultifactory(); + REQUIRE(multifactory != nullptr); + auto typed = dynamic_cast(multifactory); + REQUIRE(typed != nullptr); + return typed; } TEST_CASE("Registering Podio outputs works") { - BasicTestAlg alg; - REQUIRE(alg.GetOutputs().size() == 3); - REQUIRE(alg.GetOutputs()[0]->collection_names[0] == "output_hits_left"); - REQUIRE(alg.GetOutputs()[0]->type_name == "edm4hep::SimCalorimeterHit"); - REQUIRE(alg.GetOutputs()[1]->collection_names[0] == "output_hits_right"); - REQUIRE(alg.GetOutputs()[1]->type_name == "edm4hep::SimCalorimeterHit"); - REQUIRE(alg.GetOutputs()[2]->collection_names[0] == "output_vechits"); - REQUIRE(alg.GetOutputs()[2]->type_name == "edm4hep::SimCalorimeterHit"); + BasicTestAlg alg; + REQUIRE(alg.GetOutputs().size() == 3); + REQUIRE(alg.GetOutputs()[0]->collection_names[0] == "output_hits_left"); + REQUIRE(alg.GetOutputs()[0]->type_name == "edm4hep::SimCalorimeterHit"); + REQUIRE(alg.GetOutputs()[1]->collection_names[0] == "output_hits_right"); + REQUIRE(alg.GetOutputs()[1]->type_name == "edm4hep::SimCalorimeterHit"); + REQUIRE(alg.GetOutputs()[2]->collection_names[0] == "output_vechits"); + REQUIRE(alg.GetOutputs()[2]->type_name == "edm4hep::SimCalorimeterHit"); } TEST_CASE("Configuration object is correctly wired from untyped wiring data") { - JApplication app; - app.AddPlugin("log"); - app.Initialize(); - JOmniFactoryGeneratorT facgen (&app); - facgen.AddWiring("ECalTestAlg", {}, {"ECalLeftHits", "ECalRightHits", "ECalVecHits"}, {{"threshold", "6.1"}, {"bucket_count", "22"}}); + JApplication app; + app.AddPlugin("log"); + app.Initialize(); + JOmniFactoryGeneratorT facgen(&app); + facgen.AddWiring("ECalTestAlg", {}, {"ECalLeftHits", "ECalRightHits", "ECalVecHits"}, + {{"threshold", "6.1"}, {"bucket_count", "22"}}); - JFactorySet facset; - facgen.GenerateFactories(&facset); - // for (auto* fac : facset.GetAllFactories()) { - // std::cout << "typename=" << fac->GetFactoryName() << ", tag=" << fac->GetTag() << std::endl; - // } + JFactorySet facset; + facgen.GenerateFactories(&facset); + // for (auto* fac : facset.GetAllFactories()) { + // std::cout << "typename=" << fac->GetFactoryName() << ", tag=" << fac->GetTag() << std::endl; + // } - auto basictestalg = RetrieveMultifactory(&facset, "ECalLeftHits"); + auto basictestalg = + RetrieveMultifactory(&facset, "ECalLeftHits"); - REQUIRE(basictestalg->threshold() == 6.1); - REQUIRE(basictestalg->bucket_count() == 22); + REQUIRE(basictestalg->threshold() == 6.1); + REQUIRE(basictestalg->bucket_count() == 22); - REQUIRE(basictestalg->config().threshold == 6.1); - REQUIRE(basictestalg->config().bucket_count == 22); + REQUIRE(basictestalg->config().threshold == 6.1); + REQUIRE(basictestalg->config().bucket_count == 22); - REQUIRE(basictestalg->m_init_call_count == 0); + REQUIRE(basictestalg->m_init_call_count == 0); } TEST_CASE("Multiple configuration objects are correctly wired from untyped wiring data") { - JApplication app; - app.AddPlugin("log"); - app.Initialize(); - JOmniFactoryGeneratorT facgen (&app); - facgen.AddWiring("BCalTestAlg", {}, {"BCalLeftHits", "BCalRightHits", "BCalVecHits"}, {{"threshold", "6.1"}, {"bucket_count", "22"}}); - facgen.AddWiring("CCalTestAlg", {}, {"CCalLeftHits", "CCalRightHits", "CCalVecHits"}, {{"threshold", "9.0"}, {"bucket_count", "27"}}); - facgen.AddWiring("ECalTestAlg", {}, {"ECalLeftHits", "ECalRightHits", "ECalVecHits"}, {{"threshold", "16.25"}, {"bucket_count", "49"}}); - - JFactorySet facset; - facgen.GenerateFactories(&facset); - // for (auto* fac : facset.GetAllFactories()) { - // std::cout << "typename=" << fac->GetFactoryName() << ", tag=" << fac->GetTag() << std::endl; - // } - auto b = RetrieveMultifactory(&facset, "BCalLeftHits"); - auto c = RetrieveMultifactory(&facset, "CCalLeftHits"); - auto e = RetrieveMultifactory(&facset, "ECalLeftHits"); - - REQUIRE(b->threshold() == 6.1); - REQUIRE(b->bucket_count() == 22); - REQUIRE(b->config().threshold == 6.1); - REQUIRE(b->config().bucket_count == 22); - - REQUIRE(c->threshold() == 9.0); - REQUIRE(c->bucket_count() == 27); - REQUIRE(c->config().threshold == 9.0); - REQUIRE(c->config().bucket_count == 27); - - REQUIRE(e->threshold() == 16.25); - REQUIRE(e->bucket_count() == 49); - REQUIRE(e->config().threshold == 16.25); - REQUIRE(e->config().bucket_count == 49); - - REQUIRE(b->m_init_call_count == 0); - REQUIRE(c->m_init_call_count == 0); - REQUIRE(e->m_init_call_count == 0); + JApplication app; + app.AddPlugin("log"); + app.Initialize(); + JOmniFactoryGeneratorT facgen(&app); + facgen.AddWiring("BCalTestAlg", {}, {"BCalLeftHits", "BCalRightHits", "BCalVecHits"}, + {{"threshold", "6.1"}, {"bucket_count", "22"}}); + facgen.AddWiring("CCalTestAlg", {}, {"CCalLeftHits", "CCalRightHits", "CCalVecHits"}, + {{"threshold", "9.0"}, {"bucket_count", "27"}}); + facgen.AddWiring("ECalTestAlg", {}, {"ECalLeftHits", "ECalRightHits", "ECalVecHits"}, + {{"threshold", "16.25"}, {"bucket_count", "49"}}); + + JFactorySet facset; + facgen.GenerateFactories(&facset); + // for (auto* fac : facset.GetAllFactories()) { + // std::cout << "typename=" << fac->GetFactoryName() << ", tag=" << fac->GetTag() << std::endl; + // } + auto b = RetrieveMultifactory(&facset, "BCalLeftHits"); + auto c = RetrieveMultifactory(&facset, "CCalLeftHits"); + auto e = RetrieveMultifactory(&facset, "ECalLeftHits"); + + REQUIRE(b->threshold() == 6.1); + REQUIRE(b->bucket_count() == 22); + REQUIRE(b->config().threshold == 6.1); + REQUIRE(b->config().bucket_count == 22); + + REQUIRE(c->threshold() == 9.0); + REQUIRE(c->bucket_count() == 27); + REQUIRE(c->config().threshold == 9.0); + REQUIRE(c->config().bucket_count == 27); + + REQUIRE(e->threshold() == 16.25); + REQUIRE(e->bucket_count() == 49); + REQUIRE(e->config().threshold == 16.25); + REQUIRE(e->config().bucket_count == 49); + + REQUIRE(b->m_init_call_count == 0); + REQUIRE(c->m_init_call_count == 0); + REQUIRE(e->m_init_call_count == 0); } -TEST_CASE("JParameterManager correctly understands which values are defaulted and which are overridden") { - JApplication app; - app.AddPlugin("log"); +TEST_CASE( + "JParameterManager correctly understands which values are defaulted and which are overridden") { + JApplication app; + app.AddPlugin("log"); - auto facgen = new JOmniFactoryGeneratorT(&app); - facgen->AddWiring("FunTest", {}, {"BCalLeftHits", "BCalRightHits", "BCalVecHits"}, {{"threshold", "6.1"}, {"bucket_count", "22"}}); - app.Add(facgen); + auto facgen = new JOmniFactoryGeneratorT(&app); + facgen->AddWiring("FunTest", {}, {"BCalLeftHits", "BCalRightHits", "BCalVecHits"}, + {{"threshold", "6.1"}, {"bucket_count", "22"}}); + app.Add(facgen); - app.GetJParameterManager()->SetParameter("FunTest:threshold", 12.0); - app.Initialize(); + app.GetJParameterManager()->SetParameter("FunTest:threshold", 12.0); + app.Initialize(); - auto event = std::make_shared(); - app.GetService()->configure_event(*event); + auto event = std::make_shared(); + app.GetService()->configure_event(*event); - // for (auto* fac : event->GetFactorySet()->GetAllFactories()) { - // std::cout << "typename=" << fac->GetFactoryName() << ", tag=" << fac->GetTag() << std::endl; - // } + // for (auto* fac : event->GetFactorySet()->GetAllFactories()) { + // std::cout << "typename=" << fac->GetFactoryName() << ", tag=" << fac->GetTag() << std::endl; + // } - // Retrieve multifactory - auto b = RetrieveMultifactory(event->GetFactorySet(), "BCalLeftHits"); + // Retrieve multifactory + auto b = RetrieveMultifactory(event->GetFactorySet(), + "BCalLeftHits"); - // Overrides won't happen until factory gets Init()ed. However, defaults will be applied immediately - REQUIRE(b->threshold() == 6.1); - REQUIRE(b->config().threshold == 6.1); + // Overrides won't happen until factory gets Init()ed. However, defaults will be applied immediately + REQUIRE(b->threshold() == 6.1); + REQUIRE(b->config().threshold == 6.1); - // Trigger JMF::Execute(), in order to trigger Init(), in order to Configure()s all Parameter fields... - auto lefthits = event->Get("BCalLeftHits"); + // Trigger JMF::Execute(), in order to trigger Init(), in order to Configure()s all Parameter fields... + auto lefthits = event->Get("BCalLeftHits"); - REQUIRE(b->threshold() == 12.0); - REQUIRE(b->config().threshold == 12.0); + REQUIRE(b->threshold() == 12.0); + REQUIRE(b->config().threshold == 12.0); - std::cout << "Showing the full table of config parameters" << std::endl; - app.GetJParameterManager()->PrintParameters(true, false, true); + std::cout << "Showing the full table of config parameters" << std::endl; + app.GetJParameterManager()->PrintParameters(true, false, true); - std::cout << "Showing only overridden config parameters" << std::endl; - app.GetJParameterManager()->PrintParameters(false, false, true); + std::cout << "Showing only overridden config parameters" << std::endl; + app.GetJParameterManager()->PrintParameters(false, false, true); } TEST_CASE("Wiring itself is correctly defaulted") { - JApplication app; - app.AddPlugin("log"); + JApplication app; + app.AddPlugin("log"); - auto facgen = new JOmniFactoryGeneratorT(&app); - facgen->AddWiring("FunTest", {}, {"BCalLeftHits", "BCalRightHits", "BCalVecHits"}, {{"threshold", "6.1"}}); - app.Add(facgen); - app.Initialize(); + auto facgen = new JOmniFactoryGeneratorT(&app); + facgen->AddWiring("FunTest", {}, {"BCalLeftHits", "BCalRightHits", "BCalVecHits"}, + {{"threshold", "6.1"}}); + app.Add(facgen); + app.Initialize(); - auto event = std::make_shared(); - app.GetService()->configure_event(*event); + auto event = std::make_shared(); + app.GetService()->configure_event(*event); - // Retrieve multifactory - auto b = RetrieveMultifactory(event->GetFactorySet(), "BCalLeftHits"); + // Retrieve multifactory + auto b = RetrieveMultifactory(event->GetFactorySet(), + "BCalLeftHits"); - // Overrides won't happen until factory gets Init()ed. However, defaults will be applied immediately - REQUIRE(b->bucket_count() == 42); // Not provided by wiring - REQUIRE(b->config().bucket_count == 42); // Not provided by wiring + // Overrides won't happen until factory gets Init()ed. However, defaults will be applied immediately + REQUIRE(b->bucket_count() == 42); // Not provided by wiring + REQUIRE(b->config().bucket_count == 42); // Not provided by wiring - REQUIRE(b->threshold() == 6.1); // Provided by wiring - REQUIRE(b->config().threshold == 6.1); // Provided by wiring + REQUIRE(b->threshold() == 6.1); // Provided by wiring + REQUIRE(b->config().threshold == 6.1); // Provided by wiring - // Trigger JMF::Execute(), in order to trigger Init(), in order to Configure()s all Parameter fields... - auto lefthits = event->Get("BCalLeftHits"); + // Trigger JMF::Execute(), in order to trigger Init(), in order to Configure()s all Parameter fields... + auto lefthits = event->Get("BCalLeftHits"); - // We didn't override the config values via the parameter manager, so all of these should be the same - REQUIRE(b->bucket_count() == 42); // Not provided by wiring - REQUIRE(b->config().bucket_count == 42); // Not provided by wiring + // We didn't override the config values via the parameter manager, so all of these should be the same + REQUIRE(b->bucket_count() == 42); // Not provided by wiring + REQUIRE(b->config().bucket_count == 42); // Not provided by wiring - REQUIRE(b->threshold() == 6.1); // Provided by wiring - REQUIRE(b->config().threshold == 6.1); // Provided by wiring + REQUIRE(b->threshold() == 6.1); // Provided by wiring + REQUIRE(b->config().threshold == 6.1); // Provided by wiring + b->logger()->info("Showing the full table of config parameters"); + app.GetJParameterManager()->PrintParameters(true, false, true); - b->logger()->info("Showing the full table of config parameters"); - app.GetJParameterManager()->PrintParameters(true, false, true); - - b->logger()->info("Showing only overridden config parameters"); - // Should be empty because everything is defaulted - app.GetJParameterManager()->PrintParameters(false, false, true); + b->logger()->info("Showing only overridden config parameters"); + // Should be empty because everything is defaulted + app.GetJParameterManager()->PrintParameters(false, false, true); } struct VariadicTestAlg : public JOmniFactory { - PodioInput m_hits_in {this}; - VariadicPodioInput m_variadic_hits_in {this}; - PodioOutput m_hits_out {this}; - - std::vector GetOutputs() { return this->m_outputs; } - - int m_init_call_count = 0; - int m_changerun_call_count = 0; - int m_process_call_count = 0; - - void Configure() { - m_init_call_count++; - logger()->info("Calling VariadicTestAlg::Configure"); - } - - void ChangeRun(int64_t run_number) { - m_changerun_call_count++; - logger()->info("Calling VariadicTestAlg::ChangeRun"); - } - - // NOLINTNEXTLINE(bugprone-easily-swappable-parameters) - void Process(int64_t run_number, uint64_t event_number) { - m_process_call_count++; - logger()->info("Calling VariadicTestAlg::Process with bucket_count={}, threshold={}", config().bucket_count, config().threshold); - - REQUIRE(m_hits_in()->size() == 3); - REQUIRE(m_variadic_hits_in().size() == 2); - REQUIRE(m_variadic_hits_in()[0]->size() == 1); - REQUIRE(m_variadic_hits_in()[1]->size() == 2); - - m_hits_out() = std::make_unique(); - m_hits_out()->push_back(edm4hep::SimCalorimeterHit()); - m_hits_out()->push_back(edm4hep::SimCalorimeterHit()); - m_hits_out()->push_back(edm4hep::SimCalorimeterHit()); - m_hits_out()->push_back(edm4hep::SimCalorimeterHit()); - } + PodioInput m_hits_in{this}; + VariadicPodioInput m_variadic_hits_in{this}; + PodioOutput m_hits_out{this}; + + std::vector GetOutputs() { return this->m_outputs; } + + int m_init_call_count = 0; + int m_changerun_call_count = 0; + int m_process_call_count = 0; + + void Configure() { + m_init_call_count++; + logger()->info("Calling VariadicTestAlg::Configure"); + } + + void ChangeRun(int64_t run_number) { + m_changerun_call_count++; + logger()->info("Calling VariadicTestAlg::ChangeRun"); + } + + // NOLINTNEXTLINE(bugprone-easily-swappable-parameters) + void Process(int64_t run_number, uint64_t event_number) { + m_process_call_count++; + logger()->info("Calling VariadicTestAlg::Process with bucket_count={}, threshold={}", + config().bucket_count, config().threshold); + + REQUIRE(m_hits_in()->size() == 3); + REQUIRE(m_variadic_hits_in().size() == 2); + REQUIRE(m_variadic_hits_in()[0]->size() == 1); + REQUIRE(m_variadic_hits_in()[1]->size() == 2); + + m_hits_out() = std::make_unique(); + m_hits_out()->push_back(edm4hep::SimCalorimeterHit()); + m_hits_out()->push_back(edm4hep::SimCalorimeterHit()); + m_hits_out()->push_back(edm4hep::SimCalorimeterHit()); + m_hits_out()->push_back(edm4hep::SimCalorimeterHit()); + } }; TEST_CASE("VariadicOmniFactoryTests") { - VariadicTestAlg alg; - JApplication app; - app.AddPlugin("log"); + VariadicTestAlg alg; + JApplication app; + app.AddPlugin("log"); - auto facgen = new JOmniFactoryGeneratorT("VariadicTest", {"main_hits","fun_hits","funner_hits"}, {"processed_hits"}, &app); - app.Add(facgen); - app.Initialize(); + auto facgen = new JOmniFactoryGeneratorT( + "VariadicTest", {"main_hits", "fun_hits", "funner_hits"}, {"processed_hits"}, &app); + app.Add(facgen); + app.Initialize(); - auto event = std::make_shared(); - app.GetService()->configure_event(*event); + auto event = std::make_shared(); + app.GetService()->configure_event(*event); - edm4hep::SimCalorimeterHitCollection mains; - edm4hep::SimCalorimeterHitCollection funs; - edm4hep::SimCalorimeterHitCollection funners; + edm4hep::SimCalorimeterHitCollection mains; + edm4hep::SimCalorimeterHitCollection funs; + edm4hep::SimCalorimeterHitCollection funners; - mains.push_back(edm4hep::SimCalorimeterHit()); - mains.push_back(edm4hep::SimCalorimeterHit()); - mains.push_back(edm4hep::SimCalorimeterHit()); + mains.push_back(edm4hep::SimCalorimeterHit()); + mains.push_back(edm4hep::SimCalorimeterHit()); + mains.push_back(edm4hep::SimCalorimeterHit()); - funs.push_back(edm4hep::SimCalorimeterHit()); - funners.push_back(edm4hep::SimCalorimeterHit()); - funners.push_back(edm4hep::SimCalorimeterHit()); + funs.push_back(edm4hep::SimCalorimeterHit()); + funners.push_back(edm4hep::SimCalorimeterHit()); + funners.push_back(edm4hep::SimCalorimeterHit()); - event->InsertCollection(std::move(mains), "main_hits"); - event->InsertCollection(std::move(funs), "fun_hits"); - event->InsertCollection(std::move(funners), "funner_hits"); + event->InsertCollection(std::move(mains), "main_hits"); + event->InsertCollection(std::move(funs), "fun_hits"); + event->InsertCollection(std::move(funners), "funner_hits"); - auto processed = event->GetCollection("processed_hits"); - REQUIRE(processed->size() == 4); + auto processed = event->GetCollection("processed_hits"); + REQUIRE(processed->size() == 4); } struct SubsetTestAlg : public JOmniFactory { - VariadicPodioInput m_left_hits_in {this}; - PodioInput m_center_hits_in {this}; - VariadicPodioInput m_right_hits_in {this}; - PodioOutput m_hits_out {this}; + VariadicPodioInput m_left_hits_in{this}; + PodioInput m_center_hits_in{this}; + VariadicPodioInput m_right_hits_in{this}; + PodioOutput m_hits_out{this}; - std::vector GetOutputs() { return this->m_outputs; } + std::vector GetOutputs() { return this->m_outputs; } - void Configure() {} + void Configure() {} - void ChangeRun(int64_t run_number) {} + void ChangeRun(int64_t run_number) {} - // NOLINTNEXTLINE(bugprone-easily-swappable-parameters) - void Process(int64_t run_number, uint64_t event_number) { + // NOLINTNEXTLINE(bugprone-easily-swappable-parameters) + void Process(int64_t run_number, uint64_t event_number) { - // Variadic collection count constrained to be same size - REQUIRE(m_left_hits_in().size() == 1); - REQUIRE(m_right_hits_in().size() == 1); + // Variadic collection count constrained to be same size + REQUIRE(m_left_hits_in().size() == 1); + REQUIRE(m_right_hits_in().size() == 1); - REQUIRE(m_left_hits_in()[0]->size() == 2); - REQUIRE(m_right_hits_in()[0]->size() == 1); + REQUIRE(m_left_hits_in()[0]->size() == 2); + REQUIRE(m_right_hits_in()[0]->size() == 1); - REQUIRE(m_center_hits_in()->size() == 3); + REQUIRE(m_center_hits_in()->size() == 3); - m_hits_out() = std::make_unique(); - m_hits_out()->setSubsetCollection(); + m_hits_out() = std::make_unique(); + m_hits_out()->setSubsetCollection(); - auto* lhi = m_left_hits_in()[0]; - for (const auto& hit : *lhi) { - m_hits_out()->push_back(hit); - } - for (const auto& hit : *m_center_hits_in()) { - m_hits_out()->push_back(hit); - } + auto* lhi = m_left_hits_in()[0]; + for (const auto& hit : *lhi) { + m_hits_out()->push_back(hit); + } + for (const auto& hit : *m_center_hits_in()) { + m_hits_out()->push_back(hit); } + } }; - TEST_CASE("SubsetOmniFactoryTests") { - JApplication app; - app.AddPlugin("log"); + JApplication app; + app.AddPlugin("log"); - auto facgen = new JOmniFactoryGeneratorT("SubsetTest", {"left","center","right"}, {"processed_hits"}, &app); - app.Add(facgen); - app.Initialize(); + auto facgen = new JOmniFactoryGeneratorT("SubsetTest", {"left", "center", "right"}, + {"processed_hits"}, &app); + app.Add(facgen); + app.Initialize(); - auto event = std::make_shared(); - app.GetService()->configure_event(*event); + auto event = std::make_shared(); + app.GetService()->configure_event(*event); - edm4hep::SimCalorimeterHitCollection left; - edm4hep::SimCalorimeterHitCollection center; - edm4hep::SimCalorimeterHitCollection right; + edm4hep::SimCalorimeterHitCollection left; + edm4hep::SimCalorimeterHitCollection center; + edm4hep::SimCalorimeterHitCollection right; - left.push_back(edm4hep::SimCalorimeterHit()); - left.push_back(edm4hep::SimCalorimeterHit()); - right.push_back(edm4hep::SimCalorimeterHit()); + left.push_back(edm4hep::SimCalorimeterHit()); + left.push_back(edm4hep::SimCalorimeterHit()); + right.push_back(edm4hep::SimCalorimeterHit()); - center.push_back(edm4hep::SimCalorimeterHit()); - center.push_back(edm4hep::SimCalorimeterHit()); - center.push_back(edm4hep::SimCalorimeterHit()); + center.push_back(edm4hep::SimCalorimeterHit()); + center.push_back(edm4hep::SimCalorimeterHit()); + center.push_back(edm4hep::SimCalorimeterHit()); - event->InsertCollection(std::move(left), "left"); - event->InsertCollection(std::move(center), "center"); - event->InsertCollection(std::move(right), "right"); + event->InsertCollection(std::move(left), "left"); + event->InsertCollection(std::move(center), "center"); + event->InsertCollection(std::move(right), "right"); - auto processed = event->GetCollection("processed_hits"); - REQUIRE(processed->size() == 5); + auto processed = event->GetCollection("processed_hits"); + REQUIRE(processed->size() == 5); } struct VariadicOutputTestAlg : public JOmniFactory { - PodioInput m_hits_in {this}; + PodioInput m_hits_in{this}; - VariadicPodioOutput m_hits_out {this}; + VariadicPodioOutput m_hits_out{this}; - void Configure() {} - void ChangeRun(int64_t run_number) {} + void Configure() {} + void ChangeRun(int64_t run_number) {} - // NOLINTNEXTLINE(bugprone-easily-swappable-parameters) - void Process(int64_t run_number, uint64_t event_number) { + // NOLINTNEXTLINE(bugprone-easily-swappable-parameters) + void Process(int64_t run_number, uint64_t event_number) { - REQUIRE(m_hits_out().size() == 2); - m_hits_out()[0]->setSubsetCollection(); - m_hits_out()[1]->setSubsetCollection(); + REQUIRE(m_hits_out().size() == 2); + m_hits_out()[0]->setSubsetCollection(); + m_hits_out()[1]->setSubsetCollection(); - int i = 0; - for (const auto& hit : *(m_hits_in())) { - m_hits_out()[i]->push_back(hit); - i = (i == 1) ? 0 : 1; - } + int i = 0; + for (const auto& hit : *(m_hits_in())) { + m_hits_out()[i]->push_back(hit); + i = (i == 1) ? 0 : 1; } + } }; - - TEST_CASE("VariadicPodioOutputTests") { - JApplication app; - app.AddPlugin("log"); + JApplication app; + app.AddPlugin("log"); - auto facgen = new JOmniFactoryGeneratorT("VariadicOutputTest", {"all_hits"}, {"left_hits", "right_hits"}, &app); - app.Add(facgen); - app.Initialize(); + auto facgen = new JOmniFactoryGeneratorT( + "VariadicOutputTest", {"all_hits"}, {"left_hits", "right_hits"}, &app); + app.Add(facgen); + app.Initialize(); - auto event = std::make_shared(); - app.GetService()->configure_event(*event); + auto event = std::make_shared(); + app.GetService()->configure_event(*event); - edm4hep::SimCalorimeterHitCollection all_hits; + edm4hep::SimCalorimeterHitCollection all_hits; - all_hits.push_back(edm4hep::SimCalorimeterHit()); - all_hits.push_back(edm4hep::SimCalorimeterHit()); - all_hits.push_back(edm4hep::SimCalorimeterHit()); + all_hits.push_back(edm4hep::SimCalorimeterHit()); + all_hits.push_back(edm4hep::SimCalorimeterHit()); + all_hits.push_back(edm4hep::SimCalorimeterHit()); - event->InsertCollection(std::move(all_hits), "all_hits"); + event->InsertCollection(std::move(all_hits), "all_hits"); - auto left_hits = event->GetCollection("left_hits"); - auto right_hits = event->GetCollection("right_hits"); - REQUIRE(left_hits->size() == 2); - REQUIRE(right_hits->size() == 1); + auto left_hits = event->GetCollection("left_hits"); + auto right_hits = event->GetCollection("right_hits"); + REQUIRE(left_hits->size() == 2); + REQUIRE(right_hits->size() == 1); } diff --git a/src/tests/reco_test/GlobalReconstructionTest_processor.cc b/src/tests/reco_test/GlobalReconstructionTest_processor.cc index 7b50bc3563..3db8f54b2f 100644 --- a/src/tests/reco_test/GlobalReconstructionTest_processor.cc +++ b/src/tests/reco_test/GlobalReconstructionTest_processor.cc @@ -26,105 +26,105 @@ using namespace fmt; //------------------ // OccupancyAnalysis (Constructor) //------------------ -GlobalReconstructionTest_processor::GlobalReconstructionTest_processor(JApplication *app) : - JEventProcessor(app) -{ -} +GlobalReconstructionTest_processor::GlobalReconstructionTest_processor(JApplication* app) + : JEventProcessor(app) {} //------------------ // Init //------------------ -void GlobalReconstructionTest_processor::Init() -{ - std::string plugin_name=("reco_test"); - - // Get JANA application - auto *app = GetApplication(); - - // Ask service locator a file to write histograms to - auto root_file_service = app->GetService(); - - // Get TDirectory for histograms root file - auto globalRootLock = app->GetService(); - globalRootLock->acquire_write_lock(); - auto *file = root_file_service->GetHistFile(); - globalRootLock->release_lock(); - - // Create a directory for this plugin. And subdirectories for series of histograms - m_dir_main = file->mkdir(plugin_name.c_str()); - - // Get log level from user parameter or default - std::string log_level_str = "info"; - m_log = app->GetService()->logger(plugin_name); - app->SetDefaultParameter(plugin_name + ":LogLevel", log_level_str, "LogLevel: trace, debug, info, warn, err, critical, off"); - m_log->set_level(eicrecon::ParseLogLevel(log_level_str)); - for(auto pair: app->GetJParameterManager()->GetAllParameters()) { - m_log->info("{:<20} | {}", pair.first, pair.second->GetDescription()); - } +void GlobalReconstructionTest_processor::Init() { + std::string plugin_name = ("reco_test"); + + // Get JANA application + auto* app = GetApplication(); + + // Ask service locator a file to write histograms to + auto root_file_service = app->GetService(); + + // Get TDirectory for histograms root file + auto globalRootLock = app->GetService(); + globalRootLock->acquire_write_lock(); + auto* file = root_file_service->GetHistFile(); + globalRootLock->release_lock(); + + // Create a directory for this plugin. And subdirectories for series of histograms + m_dir_main = file->mkdir(plugin_name.c_str()); + + // Get log level from user parameter or default + std::string log_level_str = "info"; + m_log = app->GetService()->logger(plugin_name); + app->SetDefaultParameter(plugin_name + ":LogLevel", log_level_str, + "LogLevel: trace, debug, info, warn, err, critical, off"); + m_log->set_level(eicrecon::ParseLogLevel(log_level_str)); + for (auto pair : app->GetJParameterManager()->GetAllParameters()) { + m_log->info("{:<20} | {}", pair.first, pair.second->GetDescription()); + } } - //------------------ // Process //------------------ -void GlobalReconstructionTest_processor::Process(const std::shared_ptr& event) -{ - using namespace ROOT; - - m_log->debug("----------- GlobalReconstructionTest_processor {}-----------", event->GetEventNumber()); - - /** RECONSTRUCTED PARTICLES **/ - auto reco_particles = event->Get("ReconstructedParticles"); - printRecoParticles(reco_particles, std::string("ReconstructedParticles")); - - /** GENERATED PARTICLES **/ - auto gen_particles = event->Get("GeneratedParticles"); - printRecoParticles(gen_particles, std::string("GeneratedParticles")); - - /** MC PARTICLES **/ - auto mc_particles = event->Get("MCParticles"); - m_log->debug("MC particles N={}: ", mc_particles.size()); - m_log->debug(" {:<5} {:<6} {:<7} {:>8} {:>8} {:>8} {:>8}","[i]", "status", "[PDG]", "[px]", "[py]", "[pz]", "[P]"); - for(size_t i=0; i < mc_particles.size(); i++) { - - const auto *particle=mc_particles[i]; - - if(particle->getGeneratorStatus() != 1) continue; -// - double px = particle->getMomentum().x; - double py = particle->getMomentum().y; - double pz = particle->getMomentum().z; - ROOT::Math::PxPyPzM4D p4v(px, py, pz, particle->getMass()); - ROOT::Math::Cartesian3D p(px, py, pz); - if(p.R()<1) continue; - - m_log->debug(" {:<5} {:<6} {:<7} {:>8.2f} {:>8.2f} {:>8.2f} {:>8.2f}", i, particle->getGeneratorStatus(), particle->getPDG(), px, py, pz, p.R()); - } +void GlobalReconstructionTest_processor::Process(const std::shared_ptr& event) { + using namespace ROOT; + + m_log->debug("----------- GlobalReconstructionTest_processor {}-----------", + event->GetEventNumber()); + + /** RECONSTRUCTED PARTICLES **/ + auto reco_particles = event->Get("ReconstructedParticles"); + printRecoParticles(reco_particles, std::string("ReconstructedParticles")); + + /** GENERATED PARTICLES **/ + auto gen_particles = event->Get("GeneratedParticles"); + printRecoParticles(gen_particles, std::string("GeneratedParticles")); + + /** MC PARTICLES **/ + auto mc_particles = event->Get("MCParticles"); + m_log->debug("MC particles N={}: ", mc_particles.size()); + m_log->debug(" {:<5} {:<6} {:<7} {:>8} {:>8} {:>8} {:>8}", "[i]", "status", "[PDG]", "[px]", + "[py]", "[pz]", "[P]"); + for (size_t i = 0; i < mc_particles.size(); i++) { + + const auto* particle = mc_particles[i]; + + if (particle->getGeneratorStatus() != 1) + continue; + // + double px = particle->getMomentum().x; + double py = particle->getMomentum().y; + double pz = particle->getMomentum().z; + ROOT::Math::PxPyPzM4D p4v(px, py, pz, particle->getMass()); + ROOT::Math::Cartesian3D p(px, py, pz); + if (p.R() < 1) + continue; + + m_log->debug(" {:<5} {:<6} {:<7} {:>8.2f} {:>8.2f} {:>8.2f} {:>8.2f}", i, + particle->getGeneratorStatus(), particle->getPDG(), px, py, pz, p.R()); + } } - //------------------ // Finish //------------------ -void GlobalReconstructionTest_processor::Finish() -{ - fmt::print("GlobalReconstructionTest_processor::Finish() called\n"); - +void GlobalReconstructionTest_processor::Finish() { + fmt::print("GlobalReconstructionTest_processor::Finish() called\n"); } -void GlobalReconstructionTest_processor::printRecoParticles(std::vector reco_particles, const std::string &title) { - m_log->debug("{} N={}: ", title, reco_particles.size()); - m_log->debug(" {:<5} {:>8} {:>8} {:>8} {:>8} {:>8}","[i]", "[px]", "[py]", "[pz]", "[P]", "[P*3]"); - - - for(size_t i=0; i < reco_particles.size(); i++) { - const auto *particle = reco_particles[i]; - - double px = particle->getMomentum().x; - double py = particle->getMomentum().y; - double pz = particle->getMomentum().z; - // ROOT::Math::PxPyPzM4D p4v(px, py, pz, particle.getMass()); - ROOT::Math::Cartesian3D p(px, py, pz); - m_log->debug(" {:<5} {:>8.2f} {:>8.2f} {:>8.2f} {:>8.2f} {:>8.2f}", i, px, py, pz, p.R(), p.R()*3); - } +void GlobalReconstructionTest_processor::printRecoParticles( + std::vector reco_particles, const std::string& title) { + m_log->debug("{} N={}: ", title, reco_particles.size()); + m_log->debug(" {:<5} {:>8} {:>8} {:>8} {:>8} {:>8}", "[i]", "[px]", "[py]", "[pz]", "[P]", + "[P*3]"); + + for (size_t i = 0; i < reco_particles.size(); i++) { + const auto* particle = reco_particles[i]; + + double px = particle->getMomentum().x; + double py = particle->getMomentum().y; + double pz = particle->getMomentum().z; + // ROOT::Math::PxPyPzM4D p4v(px, py, pz, particle.getMass()); + ROOT::Math::Cartesian3D p(px, py, pz); + m_log->debug(" {:<5} {:>8.2f} {:>8.2f} {:>8.2f} {:>8.2f} {:>8.2f}", i, px, py, pz, p.R(), + p.R() * 3); + } } diff --git a/src/tests/reco_test/GlobalReconstructionTest_processor.h b/src/tests/reco_test/GlobalReconstructionTest_processor.h index b979c5b5f5..29ead344e7 100644 --- a/src/tests/reco_test/GlobalReconstructionTest_processor.h +++ b/src/tests/reco_test/GlobalReconstructionTest_processor.h @@ -10,43 +10,41 @@ #include #include -class GlobalReconstructionTest_processor:public JEventProcessor -{ +class GlobalReconstructionTest_processor : public JEventProcessor { public: - explicit GlobalReconstructionTest_processor(JApplication *); - ~GlobalReconstructionTest_processor() override = default; - - //---------------------------- - // Init - // - // This is called once before the first call to the Process method - // below. You may, for example, want to open an output file here. - // Only one thread will call this. - void Init() override; - - //---------------------------- - // Process - // - // This is called for every event. Multiple threads may call this - // simultaneously. If you write something to an output file here - // then make sure to protect it with a mutex or similar mechanism. - // Minimize what is done while locked since that directly affects - // the multi-threaded performance. - void Process(const std::shared_ptr& event) override; - - //---------------------------- - // Finish - // - // This is called once after all events have been processed. You may, - // for example, want to close an output file here. - // Only one thread will call this. - void Finish() override; + explicit GlobalReconstructionTest_processor(JApplication*); + ~GlobalReconstructionTest_processor() override = default; + + //---------------------------- + // Init + // + // This is called once before the first call to the Process method + // below. You may, for example, want to open an output file here. + // Only one thread will call this. + void Init() override; + + //---------------------------- + // Process + // + // This is called for every event. Multiple threads may call this + // simultaneously. If you write something to an output file here + // then make sure to protect it with a mutex or similar mechanism. + // Minimize what is done while locked since that directly affects + // the multi-threaded performance. + void Process(const std::shared_ptr& event) override; + + //---------------------------- + // Finish + // + // This is called once after all events have been processed. You may, + // for example, want to close an output file here. + // Only one thread will call this. + void Finish() override; private: + std::shared_ptr m_log; + TDirectory* m_dir_main; - - std::shared_ptr m_log; - TDirectory *m_dir_main; - - void printRecoParticles(std::vector reco_particles, const std::string &title); + void printRecoParticles(std::vector reco_particles, + const std::string& title); }; diff --git a/src/tests/reco_test/reco_test.cc b/src/tests/reco_test/reco_test.cc index 447f119a5a..cb52439a99 100644 --- a/src/tests/reco_test/reco_test.cc +++ b/src/tests/reco_test/reco_test.cc @@ -10,10 +10,10 @@ //#include "JFactory_RawCalorimeterHit_EcalBarrelRawCalorimeterHits.h.bck" extern "C" { - void InitPlugin(JApplication *app) { - InitJANAPlugin(app); - app->Add(new GlobalReconstructionTest_processor(app)); - //app->Add(new JFactoryGeneratorT()); - //app->Add(new JFactoryGeneratorT()); - } +void InitPlugin(JApplication* app) { + InitJANAPlugin(app); + app->Add(new GlobalReconstructionTest_processor(app)); + //app->Add(new JFactoryGeneratorT()); + //app->Add(new JFactoryGeneratorT()); +} } diff --git a/src/tests/track_propagation_test/TrackPropagationTest_processor.cc b/src/tests/track_propagation_test/TrackPropagationTest_processor.cc index b275ee5c4e..7fdc7bc544 100644 --- a/src/tests/track_propagation_test/TrackPropagationTest_processor.cc +++ b/src/tests/track_propagation_test/TrackPropagationTest_processor.cc @@ -24,106 +24,95 @@ #include "services/geometry/acts/ACTSGeo_service.h" #include "services/rootfile/RootFile_service.h" - - - //------------------ // OccupancyAnalysis (Constructor) //------------------ -TrackPropagationTest_processor::TrackPropagationTest_processor(JApplication *app) : - JEventProcessor(app) -{ -} +TrackPropagationTest_processor::TrackPropagationTest_processor(JApplication* app) + : JEventProcessor(app) {} //------------------ // Init //------------------ -void TrackPropagationTest_processor::Init() -{ - std::string plugin_name=("track_propagation_test"); +void TrackPropagationTest_processor::Init() { + std::string plugin_name = ("track_propagation_test"); - // Get JANA application - auto *app = GetApplication(); + // Get JANA application + auto* app = GetApplication(); - // Ask service locator a file to write histograms to - auto root_file_service = app->GetService(); + // Ask service locator a file to write histograms to + auto root_file_service = app->GetService(); - // Get TDirectory for histograms root file - auto globalRootLock = app->GetService(); - globalRootLock->acquire_write_lock(); - auto *file = root_file_service->GetHistFile(); - globalRootLock->release_lock(); + // Get TDirectory for histograms root file + auto globalRootLock = app->GetService(); + globalRootLock->acquire_write_lock(); + auto* file = root_file_service->GetHistFile(); + globalRootLock->release_lock(); - // Create a directory for this plugin. And subdirectories for series of histograms - m_dir_main = file->mkdir(plugin_name.c_str()); + // Create a directory for this plugin. And subdirectories for series of histograms + m_dir_main = file->mkdir(plugin_name.c_str()); - // Get log level from user parameter or default - InitLogger(app, plugin_name); + // Get log level from user parameter or default + InitLogger(app, plugin_name); - auto acts_service = GetApplication()->GetService(); + auto acts_service = GetApplication()->GetService(); - auto detector = dd4hep::Detector::make_unique(""); + auto detector = dd4hep::Detector::make_unique(""); - m_propagation_algo.init(detector.get(), acts_service->actsGeoProvider(), logger()); + m_propagation_algo.init(detector.get(), acts_service->actsGeoProvider(), logger()); - // Create HCal surface that will be used for propagation - auto transform = Acts::Transform3::Identity(); + // Create HCal surface that will be used for propagation + auto transform = Acts::Transform3::Identity(); - // make a reference disk to mimic electron-endcap HCal - const auto hcalEndcapNZ = -3322.; - const auto hcalEndcapNMinR = 83.01; - const auto hcalEndcapNMaxR = 950; - auto hcalEndcapNBounds = std::make_shared(hcalEndcapNMinR, hcalEndcapNMaxR); - auto hcalEndcapNTrf = transform * Acts::Translation3(Acts::Vector3(0, 0, hcalEndcapNZ)); - m_hcal_surface = Acts::Surface::makeShared(hcalEndcapNTrf, hcalEndcapNBounds); + // make a reference disk to mimic electron-endcap HCal + const auto hcalEndcapNZ = -3322.; + const auto hcalEndcapNMinR = 83.01; + const auto hcalEndcapNMaxR = 950; + auto hcalEndcapNBounds = std::make_shared(hcalEndcapNMinR, hcalEndcapNMaxR); + auto hcalEndcapNTrf = transform * Acts::Translation3(Acts::Vector3(0, 0, hcalEndcapNZ)); + m_hcal_surface = Acts::Surface::makeShared(hcalEndcapNTrf, hcalEndcapNBounds); } - //------------------ // Process //------------------ // This function is called every event -void TrackPropagationTest_processor::Process(const std::shared_ptr& event) -{ - m_log->trace("TrackPropagationTest_processor event"); - - // Get trajectories from tracking - auto trajectories = event->Get("CentralCKFTrajectories"); - - // Iterate over trajectories - m_log->debug("Propagating through {} trajectories", trajectories.size()); - for (size_t traj_index = 0; traj_index < trajectories.size(); traj_index++) { - auto &trajectory = trajectories[traj_index]; - m_log->trace(" -- trajectory {} --", traj_index); - - std::unique_ptr projection_point; - try { - // >>> try to propagate to surface <<< - projection_point = m_propagation_algo.propagate(trajectory, m_hcal_surface); - } - catch(std::exception &e) { - throw JException(e.what()); - } - - if(!projection_point) { - m_log->trace(" could not propagate!", traj_index); - continue; - } - - // Now go through reconstructed tracks points - - auto pos = projection_point->position; - auto length = projection_point->pathlength; - m_log->trace(" {:>10} {:>10.2f} {:>10.2f} {:>10.2f} {:>10.2f}", traj_index, pos.x, pos.y, pos.z, length); +void TrackPropagationTest_processor::Process(const std::shared_ptr& event) { + m_log->trace("TrackPropagationTest_processor event"); + + // Get trajectories from tracking + auto trajectories = event->Get("CentralCKFTrajectories"); + + // Iterate over trajectories + m_log->debug("Propagating through {} trajectories", trajectories.size()); + for (size_t traj_index = 0; traj_index < trajectories.size(); traj_index++) { + auto& trajectory = trajectories[traj_index]; + m_log->trace(" -- trajectory {} --", traj_index); + + std::unique_ptr projection_point; + try { + // >>> try to propagate to surface <<< + projection_point = m_propagation_algo.propagate(trajectory, m_hcal_surface); + } catch (std::exception& e) { + throw JException(e.what()); } -} + if (!projection_point) { + m_log->trace(" could not propagate!", traj_index); + continue; + } + + // Now go through reconstructed tracks points + + auto pos = projection_point->position; + auto length = projection_point->pathlength; + m_log->trace(" {:>10} {:>10.2f} {:>10.2f} {:>10.2f} {:>10.2f}", traj_index, pos.x, pos.y, + pos.z, length); + } +} //------------------ // Finish //------------------ -void TrackPropagationTest_processor::Finish() -{ -// m_log->trace("TrackPropagationTest_processor finished\n"); - +void TrackPropagationTest_processor::Finish() { + // m_log->trace("TrackPropagationTest_processor finished\n"); } diff --git a/src/tests/track_propagation_test/TrackPropagationTest_processor.h b/src/tests/track_propagation_test/TrackPropagationTest_processor.h index 0a54647352..e589665050 100644 --- a/src/tests/track_propagation_test/TrackPropagationTest_processor.h +++ b/src/tests/track_propagation_test/TrackPropagationTest_processor.h @@ -10,48 +10,47 @@ #include "algorithms/tracking/TrackPropagation.h" #include "extensions/spdlog/SpdlogMixin.h" -class TrackPropagationTest_processor: - public JEventProcessor, - public eicrecon::SpdlogMixin // this automates proper log initialization +class TrackPropagationTest_processor + : public JEventProcessor, + public eicrecon::SpdlogMixin // this automates proper log initialization { public: - explicit TrackPropagationTest_processor(JApplication *); - ~TrackPropagationTest_processor() override = default; - - //---------------------------- - // Init - // - // This is called once before the first call to the Process method - // below. You may, for example, want to open an output file here. - // Only one thread will call this. - void Init() override; - - //---------------------------- - // Process - // - // This is called for every event. Multiple threads may call this - // simultaneously. If you write something to an output file here - // then make sure to protect it with a mutex or similar mechanism. - // Minimize what is done while locked since that directly affects - // the multi-threaded performance. - void Process(const std::shared_ptr& event) override; - - //---------------------------- - // Finish - // - // This is called once after all events have been processed. You may, - // for example, want to close an output file here. - // Only one thread will call this. - void Finish() override; + explicit TrackPropagationTest_processor(JApplication*); + ~TrackPropagationTest_processor() override = default; + + //---------------------------- + // Init + // + // This is called once before the first call to the Process method + // below. You may, for example, want to open an output file here. + // Only one thread will call this. + void Init() override; + + //---------------------------- + // Process + // + // This is called for every event. Multiple threads may call this + // simultaneously. If you write something to an output file here + // then make sure to protect it with a mutex or similar mechanism. + // Minimize what is done while locked since that directly affects + // the multi-threaded performance. + void Process(const std::shared_ptr& event) override; + + //---------------------------- + // Finish + // + // This is called once after all events have been processed. You may, + // for example, want to close an output file here. + // Only one thread will call this. + void Finish() override; private: + /// Directory to store histograms to + TDirectory* m_dir_main{}; - /// Directory to store histograms to - TDirectory *m_dir_main{}; + /// Tracking propagation algorithm + eicrecon::TrackPropagation m_propagation_algo; - /// Tracking propagation algorithm - eicrecon::TrackPropagation m_propagation_algo; - - /// A surface to propagate to - std::shared_ptr m_hcal_surface; + /// A surface to propagate to + std::shared_ptr m_hcal_surface; }; diff --git a/src/tests/track_propagation_test/track_propagation_test.cc b/src/tests/track_propagation_test/track_propagation_test.cc index d43b59a782..a4e3006fb6 100644 --- a/src/tests/track_propagation_test/track_propagation_test.cc +++ b/src/tests/track_propagation_test/track_propagation_test.cc @@ -7,14 +7,13 @@ #include "TrackPropagationTest_processor.h" - extern "C" { - void InitPlugin(JApplication *app) { +void InitPlugin(JApplication* app) { - // Initializes this plugin - InitJANAPlugin(app); + // Initializes this plugin + InitJANAPlugin(app); - // Adds our processor to JANA2 to execute - app->Add(new TrackPropagationTest_processor(app)); - } + // Adds our processor to JANA2 to execute + app->Add(new TrackPropagationTest_processor(app)); +} } diff --git a/src/tests/tracking_test/TrackingTest_processor.cc b/src/tests/tracking_test/TrackingTest_processor.cc index 3a0bf6f806..0ae38f8bc9 100644 --- a/src/tests/tracking_test/TrackingTest_processor.cc +++ b/src/tests/tracking_test/TrackingTest_processor.cc @@ -30,141 +30,139 @@ using namespace fmt; //------------------ // OccupancyAnalysis (Constructor) //------------------ -TrackingTest_processor::TrackingTest_processor(JApplication *app) : - JEventProcessor(app) -{ -} +TrackingTest_processor::TrackingTest_processor(JApplication* app) : JEventProcessor(app) {} //------------------ // Init //------------------ -void TrackingTest_processor::Init() -{ - std::string plugin_name=("tracking_test"); - - // Get JANA application - auto *app = GetApplication(); - - // Ask service locator a file to write histograms to - auto root_file_service = app->GetService(); - - // Get TDirectory for histograms root file - auto globalRootLock = app->GetService(); - globalRootLock->acquire_write_lock(); - auto *file = root_file_service->GetHistFile(); - globalRootLock->release_lock(); - - // Create a directory for this plugin. And subdirectories for series of histograms - m_dir_main = file->mkdir(plugin_name.c_str()); - - // Get log level from user parameter or default - std::string log_level_str = "info"; - m_log = app->GetService()->logger(plugin_name); - app->SetDefaultParameter(plugin_name + ":LogLevel", log_level_str, "LogLevel: trace, debug, info, warn, err, critical, off"); - m_log->set_level(eicrecon::ParseLogLevel(log_level_str)); - for(auto pair: app->GetJParameterManager()->GetAllParameters()) { - m_log->info("{:<20} | {}", pair.first, pair.second->GetDescription()); - } +void TrackingTest_processor::Init() { + std::string plugin_name = ("tracking_test"); + + // Get JANA application + auto* app = GetApplication(); + + // Ask service locator a file to write histograms to + auto root_file_service = app->GetService(); + + // Get TDirectory for histograms root file + auto globalRootLock = app->GetService(); + globalRootLock->acquire_write_lock(); + auto* file = root_file_service->GetHistFile(); + globalRootLock->release_lock(); + + // Create a directory for this plugin. And subdirectories for series of histograms + m_dir_main = file->mkdir(plugin_name.c_str()); + + // Get log level from user parameter or default + std::string log_level_str = "info"; + m_log = app->GetService()->logger(plugin_name); + app->SetDefaultParameter(plugin_name + ":LogLevel", log_level_str, + "LogLevel: trace, debug, info, warn, err, critical, off"); + m_log->set_level(eicrecon::ParseLogLevel(log_level_str)); + for (auto pair : app->GetJParameterManager()->GetAllParameters()) { + m_log->info("{:<20} | {}", pair.first, pair.second->GetDescription()); + } } - //------------------ // Process //------------------ -void TrackingTest_processor::Process(const std::shared_ptr& event) -{ - m_log->debug("---- TrackingTest_processor {} ----", event->GetEventNumber()); +void TrackingTest_processor::Process(const std::shared_ptr& event) { + m_log->debug("---- TrackingTest_processor {} ----", event->GetEventNumber()); - ProcessTrackingMatching(event); + ProcessTrackingMatching(event); } - //------------------ // Finish //------------------ -void TrackingTest_processor::Finish() -{ - fmt::print("OccupancyAnalysis::Finish() called\n"); - +void TrackingTest_processor::Finish() { fmt::print("OccupancyAnalysis::Finish() called\n"); } + +void TrackingTest_processor::ProcessTrackingResults(const std::shared_ptr& event) { + const auto* reco_particles = + event->GetCollection("outputParticles"); + + m_log->debug("Tracking reconstructed particles N={}: ", reco_particles->size()); + m_log->debug(" {:<5} {:>8} {:>8} {:>8} {:>8} {:>8}", "[i]", "[px]", "[py]", "[pz]", "[P]", + "[P*3]"); + + for (size_t i = 0; i < reco_particles->size(); i++) { + auto particle = (*reco_particles)[i]; + + double px = particle.getMomentum().x; + double py = particle.getMomentum().y; + double pz = particle.getMomentum().z; + // ROOT::Math::PxPyPzM4D p4v(px, py, pz, particle.getMass()); + ROOT::Math::Cartesian3D p(px, py, pz); + m_log->debug(" {:<5} {:>8.2f} {:>8.2f} {:>8.2f} {:>8.2f} {:>8.2f}", i, px, py, pz, p.R(), + p.R() * 3); + } + + auto mc_particles = event->Get("MCParticles"); + + m_log->debug("MC particles N={}: ", mc_particles.size()); + m_log->debug(" {:<5} {:<6} {:<7} {:>8} {:>8} {:>8} {:>8}", "[i]", "status", "[PDG]", "[px]", + "[py]", "[pz]", "[P]"); + for (size_t i = 0; i < mc_particles.size(); i++) { + + const auto* particle = mc_particles[i]; + + if (particle->getGeneratorStatus() != 1) + continue; + // + double px = particle->getMomentum().x; + double py = particle->getMomentum().y; + double pz = particle->getMomentum().z; + ROOT::Math::PxPyPzM4D p4v(px, py, pz, particle->getMass()); + ROOT::Math::Cartesian3D p(px, py, pz); + if (p.R() < 1) + continue; + + m_log->debug(" {:<5} {:<6} {:<7} {:>8.2f} {:>8.2f} {:>8.2f} {:>8.2f}", i, + particle->getGeneratorStatus(), particle->getPDG(), px, py, pz, p.R()); + } } -void TrackingTest_processor::ProcessTrackingResults(const std::shared_ptr &event) { - const auto *reco_particles = event->GetCollection("outputParticles"); - - m_log->debug("Tracking reconstructed particles N={}: ", reco_particles->size()); - m_log->debug(" {:<5} {:>8} {:>8} {:>8} {:>8} {:>8}","[i]", "[px]", "[py]", "[pz]", "[P]", "[P*3]"); - - for(size_t i=0; i < reco_particles->size(); i++) { - auto particle = (*reco_particles)[i]; - - double px = particle.getMomentum().x; - double py = particle.getMomentum().y; - double pz = particle.getMomentum().z; - // ROOT::Math::PxPyPzM4D p4v(px, py, pz, particle.getMass()); - ROOT::Math::Cartesian3D p(px, py, pz); - m_log->debug(" {:<5} {:>8.2f} {:>8.2f} {:>8.2f} {:>8.2f} {:>8.2f}", i, px, py, pz, p.R(), p.R()*3); - } - - auto mc_particles = event->Get("MCParticles"); - - m_log->debug("MC particles N={}: ", mc_particles.size()); - m_log->debug(" {:<5} {:<6} {:<7} {:>8} {:>8} {:>8} {:>8}","[i]", "status", "[PDG]", "[px]", "[py]", "[pz]", "[P]"); - for(size_t i=0; i < mc_particles.size(); i++) { - - const auto *particle=mc_particles[i]; - - if(particle->getGeneratorStatus() != 1) continue; -// - double px = particle->getMomentum().x; - double py = particle->getMomentum().y; - double pz = particle->getMomentum().z; - ROOT::Math::PxPyPzM4D p4v(px, py, pz, particle->getMass()); - ROOT::Math::Cartesian3D p(px, py, pz); - if(p.R()<1) continue; - - m_log->debug(" {:<5} {:<6} {:<7} {:>8.2f} {:>8.2f} {:>8.2f} {:>8.2f}", i, particle->getGeneratorStatus(), particle->getPDG(), px, py, pz, p.R()); - } - +void TrackingTest_processor::ProcessTrackingMatching(const std::shared_ptr& event) { + m_log->debug("Associations [simId] [recID] [simE] [recE] [simPDG] [recPDG]"); + + const auto* associations = event->GetCollection( + "ReconstructedChargedParticleAssociations"); + + for (auto assoc : *associations) { + auto sim = assoc.getSim(); + auto rec = assoc.getRec(); + + m_log->debug(" {:<6} {:<6} {:>8d} {:>8d}", assoc.getSim().getObjectID().index, + assoc.getRec().getObjectID().index, sim.getPDG(), rec.getPDG()); + } + + // m_log->debug("Particles [objID] [PDG] [simE] [recE] [simPDG] [recPDG]"); + // auto prt_with_assoc = event->GetSingle("ChargedParticlesWithAssociations"); + // for(auto part: prt_with_assoc->particles()) { + // + // // auto sim = assoc->getSim(); + // // auto rec = assoc->getRec(); + // + // m_log->debug(" {:<6} {:<6} {:>8.2f} {:>8.2f}", part->getObjectID().index, part->getPDG(), part->getCharge(), part->getEnergy()); + // + // } + // + // + // m_log->debug("ReconstructedChargedParticles [objID] [PDG] [charge] [energy]"); + // auto reco_charged_particles = event->Get("ReconstructedChargedParticles"); + // for(auto part: reco_charged_particles) { + // m_log->debug(" {:<6} {:<6} {:>8.2f} {:>8.2f}", part->getObjectID().index, part->getPDG(), part->getCharge(), part->getEnergy()); + // } } -void TrackingTest_processor::ProcessTrackingMatching(const std::shared_ptr &event) { - m_log->debug("Associations [simId] [recID] [simE] [recE] [simPDG] [recPDG]"); - - const auto *associations = event->GetCollection("ReconstructedChargedParticleAssociations"); - - for(auto assoc: *associations) { - auto sim = assoc.getSim(); - auto rec = assoc.getRec(); - - m_log->debug(" {:<6} {:<6} {:>8d} {:>8d}", assoc.getSim().getObjectID().index, assoc.getRec().getObjectID().index, sim.getPDG(), rec.getPDG()); - } - -// m_log->debug("Particles [objID] [PDG] [simE] [recE] [simPDG] [recPDG]"); -// auto prt_with_assoc = event->GetSingle("ChargedParticlesWithAssociations"); -// for(auto part: prt_with_assoc->particles()) { -// -// // auto sim = assoc->getSim(); -// // auto rec = assoc->getRec(); -// -// m_log->debug(" {:<6} {:<6} {:>8.2f} {:>8.2f}", part->getObjectID().index, part->getPDG(), part->getCharge(), part->getEnergy()); -// -// } -// -// -// m_log->debug("ReconstructedChargedParticles [objID] [PDG] [charge] [energy]"); -// auto reco_charged_particles = event->Get("ReconstructedChargedParticles"); -// for(auto part: reco_charged_particles) { -// m_log->debug(" {:<6} {:<6} {:>8.2f} {:>8.2f}", part->getObjectID().index, part->getPDG(), part->getCharge(), part->getEnergy()); -// } - -} - -void TrackingTest_processor::ProcessGloablMatching(const std::shared_ptr &event) { - - m_log->debug("ReconstructedParticles (FINAL) [objID] [PDG] [charge] [energy]"); - auto final_reco_particles = event->Get("ReconstructedParticlesWithAssoc"); - for(const auto *part: final_reco_particles) { - m_log->debug(" {:<6} {:<6} {:>8.2f} {:>8.2f}", part->getObjectID().index, part->getPDG(), part->getCharge(), part->getEnergy()); - } +void TrackingTest_processor::ProcessGloablMatching(const std::shared_ptr& event) { + m_log->debug("ReconstructedParticles (FINAL) [objID] [PDG] [charge] [energy]"); + auto final_reco_particles = + event->Get("ReconstructedParticlesWithAssoc"); + for (const auto* part : final_reco_particles) { + m_log->debug(" {:<6} {:<6} {:>8.2f} {:>8.2f}", part->getObjectID().index, part->getPDG(), + part->getCharge(), part->getEnergy()); + } } diff --git a/src/tests/tracking_test/TrackingTest_processor.h b/src/tests/tracking_test/TrackingTest_processor.h index 6abcf13859..250f152eff 100644 --- a/src/tests/tracking_test/TrackingTest_processor.h +++ b/src/tests/tracking_test/TrackingTest_processor.h @@ -7,49 +7,46 @@ #include #include -class TrackingTest_processor:public JEventProcessor -{ +class TrackingTest_processor : public JEventProcessor { public: - explicit TrackingTest_processor(JApplication *); - ~TrackingTest_processor() override = default; - - //---------------------------- - // Init - // - // This is called once before the first call to the Process method - // below. You may, for example, want to open an output file here. - // Only one thread will call this. - void Init() override; - - //---------------------------- - // Process - // - // This is called for every event. Multiple threads may call this - // simultaneously. If you write something to an output file here - // then make sure to protect it with a mutex or similar mechanism. - // Minimize what is done while locked since that directly affects - // the multi-threaded performance. - void Process(const std::shared_ptr& event) override; - - //---------------------------- - // Finish - // - // This is called once after all events have been processed. You may, - // for example, want to close an output file here. - // Only one thread will call this. - void Finish() override; + explicit TrackingTest_processor(JApplication*); + ~TrackingTest_processor() override = default; + + //---------------------------- + // Init + // + // This is called once before the first call to the Process method + // below. You may, for example, want to open an output file here. + // Only one thread will call this. + void Init() override; + + //---------------------------- + // Process + // + // This is called for every event. Multiple threads may call this + // simultaneously. If you write something to an output file here + // then make sure to protect it with a mutex or similar mechanism. + // Minimize what is done while locked since that directly affects + // the multi-threaded performance. + void Process(const std::shared_ptr& event) override; + + //---------------------------- + // Finish + // + // This is called once after all events have been processed. You may, + // for example, want to close an output file here. + // Only one thread will call this. + void Finish() override; private: + //---------------------------- + // Test imminent tracking output + void ProcessTrackingResults(const std::shared_ptr& event); - //---------------------------- - // Test imminent tracking output - void ProcessTrackingResults(const std::shared_ptr& event); + void ProcessTrackingMatching(const std::shared_ptr& event); - void ProcessTrackingMatching(const std::shared_ptr& event); + void ProcessGloablMatching(const std::shared_ptr& event); - void ProcessGloablMatching(const std::shared_ptr& event); - - - std::shared_ptr m_log; - TDirectory *m_dir_main; + std::shared_ptr m_log; + TDirectory* m_dir_main; }; diff --git a/src/tests/tracking_test/tracking_test.cc b/src/tests/tracking_test/tracking_test.cc index d81de9dfcf..9664cbbc92 100644 --- a/src/tests/tracking_test/tracking_test.cc +++ b/src/tests/tracking_test/tracking_test.cc @@ -10,10 +10,10 @@ //#include "JFactory_RawCalorimeterHit_EcalBarrelRawCalorimeterHits.h.bck" extern "C" { - void InitPlugin(JApplication *app) { - InitJANAPlugin(app); - app->Add(new TrackingTest_processor(app)); - //app->Add(new JFactoryGeneratorT()); - //app->Add(new JFactoryGeneratorT()); - } +void InitPlugin(JApplication* app) { + InitJANAPlugin(app); + app->Add(new TrackingTest_processor(app)); + //app->Add(new JFactoryGeneratorT()); + //app->Add(new JFactoryGeneratorT()); +} } diff --git a/src/utilities/dump_flags/DumpFlags_processor.cc b/src/utilities/dump_flags/DumpFlags_processor.cc index a0c03b7f1f..0ab2eeae9a 100644 --- a/src/utilities/dump_flags/DumpFlags_processor.cc +++ b/src/utilities/dump_flags/DumpFlags_processor.cc @@ -12,139 +12,124 @@ #include #include - using namespace fmt; //------------------ // DefaultFlags_processor (Constructor) //------------------ -DumpFlags_processor::DumpFlags_processor(JApplication *app) : - JEventProcessor(app) -{ -} +DumpFlags_processor::DumpFlags_processor(JApplication* app) : JEventProcessor(app) {} //------------------ // Init //------------------ -void DumpFlags_processor::Init() -{ - // Ask service locator a file to write to - - auto *app = GetApplication(); - app->SetDefaultParameter("dump_flags:python", m_python_file_name, "If not empty, a python file to generate"); - app->SetDefaultParameter("dump_flags:markdown", m_markdown_file_name, "If not empty, a markdown file to generate"); - app->SetDefaultParameter("dump_flags:json", m_json_file_name, "If not empty, a json file to generate"); - app->SetDefaultParameter("dump_flags:screen", m_print_to_screen, "If not empty, print summary to screen at end of job"); - - - InitLogger(app, "dump_flags", "info"); +void DumpFlags_processor::Init() { + // Ask service locator a file to write to + + auto* app = GetApplication(); + app->SetDefaultParameter("dump_flags:python", m_python_file_name, + "If not empty, a python file to generate"); + app->SetDefaultParameter("dump_flags:markdown", m_markdown_file_name, + "If not empty, a markdown file to generate"); + app->SetDefaultParameter("dump_flags:json", m_json_file_name, + "If not empty, a json file to generate"); + app->SetDefaultParameter("dump_flags:screen", m_print_to_screen, + "If not empty, print summary to screen at end of job"); + + InitLogger(app, "dump_flags", "info"); } - //------------------ // Process //------------------ -void DumpFlags_processor::Process(const std::shared_ptr& event) -{ - -} - +void DumpFlags_processor::Process(const std::shared_ptr& event) {} //------------------ // Finish //------------------ -void DumpFlags_processor::Finish() -{ - auto *pm = GetApplication()->GetJParameterManager(); - - // Find longest strings in names and values - size_t max_name_len = 0; - size_t max_default_val_len = 0; - for(auto [name,param]: pm->GetAllParameters()) { - if(max_name_len < strlen(name.c_str())) { - max_name_len = strlen(name.c_str()); - } - - if(max_default_val_len < strlen(param->GetDefault().c_str())) { - max_default_val_len = strlen(param->GetDefault().c_str()); - } +void DumpFlags_processor::Finish() { + auto* pm = GetApplication()->GetJParameterManager(); + + // Find longest strings in names and values + size_t max_name_len = 0; + size_t max_default_val_len = 0; + for (auto [name, param] : pm->GetAllParameters()) { + if (max_name_len < strlen(name.c_str())) { + max_name_len = strlen(name.c_str()); } - // Found longest values? - spdlog::info("max_name_len={} max_default_val_len={}", max_name_len, max_default_val_len); - - // Start generating - std::string python_content ="# format [ (flag_name, default_val, description), ...]\neicrecon_flags=[\n"; - std::string json_content = "[\n"; - - // iterate over parameters - size_t line_num = 0; - for(auto [name,param]: pm->GetAllParameters()) - { - // form python content string - std::string python_escaped_descr = param->GetDescription(); - std::replace(python_escaped_descr.begin(), python_escaped_descr.end(), '\'', '`'); - python_content += fmt::format(" ({:{}} {:{}} '{}'),\n", - fmt::format("'{}',", param->GetKey()), - max_name_len + 3, - fmt::format("'{}',", param->GetDefault()), - max_default_val_len + 3, - python_escaped_descr - ); - - // form json content string - std::string json_escaped_descr = param->GetDescription(); - std::replace(json_escaped_descr.begin(), json_escaped_descr.end(), '"', '\''); - json_content += fmt::format(" {}[\"{}\", \"{}\", \"{}\", \"{}\"]\n", - line_num++==0?' ': ',', - param->GetKey(), - param->GetValue(), - param->GetDefault(), - json_escaped_descr); - - // Print on screen - if( m_print_to_screen ) fmt::print(" {:{}} : {}\n", param->GetKey(), max_name_len + 3, param->GetValue()); + if (max_default_val_len < strlen(param->GetDefault().c_str())) { + max_default_val_len = strlen(param->GetDefault().c_str()); } - - // Finalizing - python_content+="]\n\n"; - json_content+="]\n\n"; - - // Save python file - if(!m_python_file_name.empty()) { - try{ - std::ofstream ofs(m_python_file_name); - ofs << python_content; - m_log->info("Created python file with flags: '{}'", m_python_file_name); - } - catch(std::exception ex) { - m_log->error("Can't open file '{}' for write", m_python_file_name); // TODO personal logger - throw JException(ex.what()); - } + } + + // Found longest values? + spdlog::info("max_name_len={} max_default_val_len={}", max_name_len, max_default_val_len); + + // Start generating + std::string python_content = + "# format [ (flag_name, default_val, description), ...]\neicrecon_flags=[\n"; + std::string json_content = "[\n"; + + // iterate over parameters + size_t line_num = 0; + for (auto [name, param] : pm->GetAllParameters()) { + // form python content string + std::string python_escaped_descr = param->GetDescription(); + std::replace(python_escaped_descr.begin(), python_escaped_descr.end(), '\'', '`'); + python_content += fmt::format( + " ({:{}} {:{}} '{}'),\n", fmt::format("'{}',", param->GetKey()), max_name_len + 3, + fmt::format("'{}',", param->GetDefault()), max_default_val_len + 3, python_escaped_descr); + + // form json content string + std::string json_escaped_descr = param->GetDescription(); + std::replace(json_escaped_descr.begin(), json_escaped_descr.end(), '"', '\''); + json_content += + fmt::format(" {}[\"{}\", \"{}\", \"{}\", \"{}\"]\n", line_num++ == 0 ? ' ' : ',', + param->GetKey(), param->GetValue(), param->GetDefault(), json_escaped_descr); + + // Print on screen + if (m_print_to_screen) + fmt::print(" {:{}} : {}\n", param->GetKey(), max_name_len + 3, param->GetValue()); + } + + // Finalizing + python_content += "]\n\n"; + json_content += "]\n\n"; + + // Save python file + if (!m_python_file_name.empty()) { + try { + std::ofstream ofs(m_python_file_name); + ofs << python_content; + m_log->info("Created python file with flags: '{}'", m_python_file_name); + } catch (std::exception ex) { + m_log->error("Can't open file '{}' for write", m_python_file_name); // TODO personal logger + throw JException(ex.what()); } - - // Save json file - if(!m_json_file_name.empty()) { - try{ - std::ofstream ofs(m_json_file_name); - ofs << json_content; - m_log->info("Created json file with flags: '{}'", m_json_file_name); - m_log->info("Json records format is: [name, value, default-value, comment]", m_json_file_name); - } - catch(std::exception ex) { - m_log->error("Can't open file '{}' for write", m_json_file_name); // TODO personal logger - throw JException(ex.what()); - } + } + + // Save json file + if (!m_json_file_name.empty()) { + try { + std::ofstream ofs(m_json_file_name); + ofs << json_content; + m_log->info("Created json file with flags: '{}'", m_json_file_name); + m_log->info("Json records format is: [name, value, default-value, comment]", + m_json_file_name); + } catch (std::exception ex) { + m_log->error("Can't open file '{}' for write", m_json_file_name); // TODO personal logger + throw JException(ex.what()); } - - // Save JANA simple key-value file - if(!m_janaconfig_file_name.empty()) { - try{ - pm->WriteConfigFile(m_janaconfig_file_name); - } - catch(std::exception ex) { - m_log->error("Can't open file '{}' for write", m_janaconfig_file_name); // TODO personal logger - throw JException(ex.what()); - } + } + + // Save JANA simple key-value file + if (!m_janaconfig_file_name.empty()) { + try { + pm->WriteConfigFile(m_janaconfig_file_name); + } catch (std::exception ex) { + m_log->error("Can't open file '{}' for write", + m_janaconfig_file_name); // TODO personal logger + throw JException(ex.what()); } + } } diff --git a/src/utilities/dump_flags/DumpFlags_processor.h b/src/utilities/dump_flags/DumpFlags_processor.h index 27fd20500e..29ef89310a 100644 --- a/src/utilities/dump_flags/DumpFlags_processor.h +++ b/src/utilities/dump_flags/DumpFlags_processor.h @@ -11,121 +11,112 @@ #include "extensions/spdlog/SpdlogMixin.h" -class DumpFlags_processor: public JEventProcessor, public eicrecon::SpdlogMixin -{ +class DumpFlags_processor : public JEventProcessor, public eicrecon::SpdlogMixin { public: - explicit DumpFlags_processor(JApplication *); - ~DumpFlags_processor() override = default; - - //---------------------------- - // Init - // - // This is called once before the first call to the Process method - // below. You may, for example, want to open an output file here. - // Only one thread will call this. - void Init() override; - - //---------------------------- - // Process - // - // This is called for every event. Multiple threads may call this - // simultaneously. If you write something to an output file here - // then make sure to protect it with a mutex or similar mechanism. - // Minimize what is done while locked since that directly affects - // the multi-threaded performance. - void Process(const std::shared_ptr& event) override; - - //---------------------------- - // Finish - // - // This is called once after all events have been processed. You may, - // for example, want to close an output file here. - // Only one thread will call this. - void Finish() override; + explicit DumpFlags_processor(JApplication*); + ~DumpFlags_processor() override = default; + + //---------------------------- + // Init + // + // This is called once before the first call to the Process method + // below. You may, for example, want to open an output file here. + // Only one thread will call this. + void Init() override; + + //---------------------------- + // Process + // + // This is called for every event. Multiple threads may call this + // simultaneously. If you write something to an output file here + // then make sure to protect it with a mutex or similar mechanism. + // Minimize what is done while locked since that directly affects + // the multi-threaded performance. + void Process(const std::shared_ptr& event) override; + + //---------------------------- + // Finish + // + // This is called once after all events have been processed. You may, + // for example, want to close an output file here. + // Only one thread will call this. + void Finish() override; private: - /// If not empty, a python eicrecon run file is created - std::string m_python_file_name = ""; - - /// If not null, such markdown file is created - std::string m_markdown_file_name = ""; - - /// If not null, such json file is created - std::string m_json_file_name = ""; - - /// If not null, such jana configuration file is created - std::string m_janaconfig_file_name = "jana.conf"; - - /// Print parameter summary to screen at end of job - bool m_print_to_screen = true; - - /// Print only reconstruction flags - bool m_only_reco = true; - - /// Prefixes of flags that belongs to reconstruction parameters - std::vector m_reco_prefixes = { - "B0TRK", - "BEMC", - "DRICH", - "BTRK", - "BVTX", - "ECTRK", - "EEMC", - "FOFFMTRK", - "HCAL", - "MPGD", - "RPOTS", - "LOWQ2", - "ZDC", - "Tracking", - "Reco", - "Digi", - "Calorimetry" - }; - - /// Checks if flags starts with one of m_reco_prefixes - bool isReconstructionFlag(std::string flag_name) { // (!) copy value is important here! don't do const& NOLINT(performance-unnecessary-value-param) - - // convert flag_name to lower - std::transform(flag_name.begin(), flag_name.end(), flag_name.begin(), static_cast(&std::tolower)); - - for(auto subsystem: m_reco_prefixes) { // (!) copy value is important here! don't do auto& - - // Convert subsystem to lower - std::transform(subsystem.begin(), subsystem.end(), subsystem.begin(), static_cast(&std::tolower)); - - // if not sure, read this - // https://stackoverflow.com/questions/1878001/how-do-i-check-if-a-c-stdstring-starts-with-a-certain-string-and-convert-a - if (flag_name.rfind(subsystem, 0) == 0) { // pos=0 limits the search to the prefix - // s starts with prefix - return true; - } - } - - // flag prefix is not in list - return false; + /// If not empty, a python eicrecon run file is created + std::string m_python_file_name = ""; + + /// If not null, such markdown file is created + std::string m_markdown_file_name = ""; + + /// If not null, such json file is created + std::string m_json_file_name = ""; + + /// If not null, such jana configuration file is created + std::string m_janaconfig_file_name = "jana.conf"; + + /// Print parameter summary to screen at end of job + bool m_print_to_screen = true; + + /// Print only reconstruction flags + bool m_only_reco = true; + + /// Prefixes of flags that belongs to reconstruction parameters + std::vector m_reco_prefixes = { + "B0TRK", "BEMC", "DRICH", "BTRK", "BVTX", "ECTRK", "EEMC", "FOFFMTRK", "HCAL", + "MPGD", "RPOTS", "LOWQ2", "ZDC", "Tracking", "Reco", "Digi", "Calorimetry"}; + + /// Checks if flags starts with one of m_reco_prefixes + bool isReconstructionFlag( + std::string + flag_name) { // (!) copy value is important here! don't do const& NOLINT(performance-unnecessary-value-param) + + // convert flag_name to lower + std::transform(flag_name.begin(), flag_name.end(), flag_name.begin(), + static_cast(&std::tolower)); + + for (auto subsystem : m_reco_prefixes) { // (!) copy value is important here! don't do auto& + + // Convert subsystem to lower + std::transform(subsystem.begin(), subsystem.end(), subsystem.begin(), + static_cast(&std::tolower)); + + // if not sure, read this + // https://stackoverflow.com/questions/1878001/how-do-i-check-if-a-c-stdstring-starts-with-a-certain-string-and-convert-a + if (flag_name.rfind(subsystem, 0) == 0) { // pos=0 limits the search to the prefix + // s starts with prefix + return true; + } } - std::string findCategory(std::string flag_name) { // (!) copy value is important here! don't do const& NOLINT(performance-unnecessary-value-param) + // flag prefix is not in list + return false; + } - // convert flag_name to lower - std::transform(flag_name.begin(), flag_name.end(), flag_name.begin(), static_cast(&std::tolower)); + std::string findCategory( + std::string + flag_name) { // (!) copy value is important here! don't do const& NOLINT(performance-unnecessary-value-param) - for(auto subsystem: m_reco_prefixes) { // (!) copy value is important here! don't do auto& + // convert flag_name to lower + std::transform(flag_name.begin(), flag_name.end(), flag_name.begin(), + static_cast(&std::tolower)); - // Convert subsystem to lower - std::string original_subsystem_name = subsystem; - std::transform(subsystem.begin(), subsystem.end(), subsystem.begin(), static_cast(&std::tolower)); + for (auto subsystem : m_reco_prefixes) { // (!) copy value is important here! don't do auto& - // if not sure, read this - // https://stackoverflow.com/questions/1878001/how-do-i-check-if-a-c-stdstring-starts-with-a-certain-string-and-convert-a - if (flag_name.rfind(subsystem, 0) == 0) { // pos=0 limits the search to the prefix - // s starts with prefix - return original_subsystem_name; - } - } + // Convert subsystem to lower + std::string original_subsystem_name = subsystem; + std::transform(subsystem.begin(), subsystem.end(), subsystem.begin(), + static_cast(&std::tolower)); - // flag prefix is not in list - return ""; + // if not sure, read this + // https://stackoverflow.com/questions/1878001/how-do-i-check-if-a-c-stdstring-starts-with-a-certain-string-and-convert-a + if (flag_name.rfind(subsystem, 0) == 0) { // pos=0 limits the search to the prefix + // s starts with prefix + return original_subsystem_name; + } } + + // flag prefix is not in list + return ""; + } }; diff --git a/src/utilities/dump_flags/dump_flags.cc b/src/utilities/dump_flags/dump_flags.cc index a5fec81ee2..4189b87563 100644 --- a/src/utilities/dump_flags/dump_flags.cc +++ b/src/utilities/dump_flags/dump_flags.cc @@ -7,10 +7,9 @@ #include "DumpFlags_processor.h" - extern "C" { - void InitPlugin(JApplication *app) { - InitJANAPlugin(app); - app->Add(new DumpFlags_processor(app)); - } +void InitPlugin(JApplication* app) { + InitJANAPlugin(app); + app->Add(new DumpFlags_processor(app)); +} } diff --git a/src/utilities/eicrecon/eicrecon.cc b/src/utilities/eicrecon/eicrecon.cc index b19e43381b..e652178c26 100644 --- a/src/utilities/eicrecon/eicrecon.cc +++ b/src/utilities/eicrecon/eicrecon.cc @@ -13,56 +13,31 @@ /// Add new default plugin names here and the main() will do JApplication::AddPlugin() for you. std::vector EICRECON_DEFAULT_PLUGINS = { - "log", - "dd4hep", - "acts", - "algorithms_init", - "richgeo", - "rootfile", - "beam", - "reco", - "tracking", - "pid", - "EEMC", - "BEMC", - "FEMC", - "EHCAL", - "BHCAL", - "FHCAL", - "B0ECAL", - "ZDC", - "BTRK", - "BVTX", - "DIRC", - "DRICH", - "ECTRK", - "MPGD", - "B0TRK", - "RPOTS", - "FOFFMTRK", - "BTOF", - "ECTOF", - "LOWQ2", - "LUMISPECCAL", - "podio", - "janatop", + "log", "dd4hep", "acts", "algorithms_init", + "richgeo", "rootfile", "beam", "reco", + "tracking", "pid", "EEMC", "BEMC", + "FEMC", "EHCAL", "BHCAL", "FHCAL", + "B0ECAL", "ZDC", "BTRK", "BVTX", + "DIRC", "DRICH", "ECTRK", "MPGD", + "B0TRK", "RPOTS", "FOFFMTRK", "BTOF", + "ECTOF", "LOWQ2", "LUMISPECCAL", "podio", + "janatop", }; -int main( int narg, char **argv) -{ - std::vector default_plugins = EICRECON_DEFAULT_PLUGINS; +int main(int narg, char** argv) { + std::vector default_plugins = EICRECON_DEFAULT_PLUGINS; - auto options = jana::GetCliOptions(narg, argv, false); + auto options = jana::GetCliOptions(narg, argv, false); - if (jana::HasPrintOnlyCliOptions(options, default_plugins)) - return -1; + if (jana::HasPrintOnlyCliOptions(options, default_plugins)) + return -1; - AddAvailablePluginsToOptionParams(options, default_plugins); + AddAvailablePluginsToOptionParams(options, default_plugins); - japp = jana::CreateJApplication(options); + japp = jana::CreateJApplication(options); - auto exit_code = jana::Execute(japp, options); + auto exit_code = jana::Execute(japp, options); - delete japp; - return exit_code; + delete japp; + return exit_code; } diff --git a/src/utilities/eicrecon/eicrecon_cli.cpp b/src/utilities/eicrecon/eicrecon_cli.cpp index bcbce93fdc..ebe46e591c 100644 --- a/src/utilities/eicrecon/eicrecon_cli.cpp +++ b/src/utilities/eicrecon/eicrecon_cli.cpp @@ -29,508 +29,509 @@ #define STR(macro) QUOTE(macro) #ifndef EICRECON_APP_VERSION -# define EICRECON_APP_VERSION Error +#define EICRECON_APP_VERSION Error #endif #define EICRECON_APP_VERSION_STR STR(EICRECON_APP_VERSION) - namespace jana { - void PrintUsageOptions() { - std::cout << "Options:" << std::endl; - std::cout << " -h --help Display this message" << std::endl; - std::cout << " -v --version Display version information" << std::endl; - std::cout << " -j --janaversion Display JANA version information" << std::endl; - std::cout << " -c --configs Display configuration parameters" << std::endl; - std::cout << " -l --loadconfigs Load configuration parameters from file" << std::endl; - std::cout << " -d --dumpconfigs Dump configuration parameters to file" << std::endl; - std::cout << " -b --benchmark Run in benchmark mode" << std::endl; - std::cout << " -L --list-factories List all the factories without running" << std::endl; - std::cout << " -Pkey=value Specify a configuration parameter" << std::endl; - std::cout << " -Pplugin:param=value Specify a parameter value for a plugin" << std::endl; - std::cout << std::endl; - - std::cout << " --list-default-plugins List all the default plugins" << std::endl; - std::cout << " --list-available-plugins List plugins at $JANA_PLUGIN_PATH and $EICrecon_MY" << std::endl; - std::cout << std::endl << std::endl; - } - - void PrintUsageExample() { - - std::cout << "Example:" << std::endl; - std::cout << " eicrecon -Pplugins=plugin1,plugin2,plugin3 -Pnthreads=8 infile.root" << std::endl; - std::cout << " eicrecon -Ppodio:print_type_table=1 infile.root" << std::endl << std::endl; - std::cout << std::endl << std::endl; - } - - void PrintUsage() { - /// Prints jana.cc command-line options to stdout, for use by the CLI. - /// This does not include JANA parameters, which come from - /// JParameterManager::PrintParameters() instead. - - std::cout << std::endl; - std::cout << "Usage:" << std::endl; - std::cout << " eicrecon [options] source1 source2 ..." << std::endl; - std::cout << std::endl; - - std::cout << "Description:" << std::endl; - std::cout << " Command-line interface for running JANA plugins. This can be used to" << std::endl; - std::cout << " read in events and process them. Command-line flags control configuration" << std::endl; - std::cout << " while additional arguments denote input files, which are to be loaded and" << std::endl; - std::cout << " processed by the appropriate EventSource plugin." << std::endl; - std::cout << std::endl; - - PrintUsageOptions(); - PrintUsageExample(); - } - - void PrintVersion() { - std::cout << "EICrecon version: " << EICRECON_APP_VERSION_STR << std::endl; - } - - void PrintJANAVersion() { - std::cout << "JANA version: " << JVersion::GetVersion() << std::endl; - } +void PrintUsageOptions() { + std::cout << "Options:" << std::endl; + std::cout << " -h --help Display this message" << std::endl; + std::cout << " -v --version Display version information" << std::endl; + std::cout << " -j --janaversion Display JANA version information" << std::endl; + std::cout << " -c --configs Display configuration parameters" << std::endl; + std::cout << " -l --loadconfigs Load configuration parameters from file" + << std::endl; + std::cout << " -d --dumpconfigs Dump configuration parameters to file" << std::endl; + std::cout << " -b --benchmark Run in benchmark mode" << std::endl; + std::cout << " -L --list-factories List all the factories without running" + << std::endl; + std::cout << " -Pkey=value Specify a configuration parameter" << std::endl; + std::cout << " -Pplugin:param=value Specify a parameter value for a plugin" + << std::endl; + std::cout << std::endl; + + std::cout << " --list-default-plugins List all the default plugins" << std::endl; + std::cout << " --list-available-plugins List plugins at $JANA_PLUGIN_PATH and $EICrecon_MY" + << std::endl; + std::cout << std::endl << std::endl; +} - void PrintDefaultPlugins(std::vector const& default_plugins) { - std::cout << "\n List default plugins:\n\n"; - printPluginNames(default_plugins); - std::cout << std::endl << std::endl; - } +void PrintUsageExample() { - void GetPluginNamesInDir(std::set & plugin_names, std::string dir_str) { - // Edge case handler: taking care of invalid and empty dirs - if (std::filesystem::is_directory(dir_str) == false) - return; - if (std::filesystem::is_empty(dir_str)) - return; - - std::string full_path, filename; - for (const auto & entry : std::filesystem::directory_iterator(dir_str)) { - full_path = std::string(entry.path()); // Example: "/usr/local/plugins/Tutorial.so" - filename = full_path.substr(full_path.find_last_of("/") + 1); // Example: "Tutorial.so" - if (filename.substr(filename.size() - 3) == ".so") { - std::string s = filename.substr(0, filename.size() - 3); -// std::cout << filename << "==> " << s << std::endl; - plugin_names.insert(s); - } - } - } + std::cout << "Example:" << std::endl; + std::cout << " eicrecon -Pplugins=plugin1,plugin2,plugin3 -Pnthreads=8 infile.root" + << std::endl; + std::cout << " eicrecon -Ppodio:print_type_table=1 infile.root" << std::endl << std::endl; + std::cout << std::endl << std::endl; +} - /// Get the plugin names by searching for files named as *.so under $JANA_PLUGIN_PATH and $EICrecon_MY/plugins. - /// @note It does not guarantee any effectiveness of the plugins. - void GetPluginNamesFromEnvPath(std::set & plugin_names, const char* env_var) { - std::string dir_path, paths; - - const char* env_p = getenv(env_var); - if (env_p) { - if (strcmp(env_var, "EICrecon_MY") == 0) { - paths = std::string(env_p) + "/plugins"; - } - else { - paths = std::string(env_p); - } - - std::stringstream envvar_ss(paths); - while (getline(envvar_ss, dir_path, ':')) { - GetPluginNamesInDir(plugin_names, dir_path); - } - } - } +void PrintUsage() { + /// Prints jana.cc command-line options to stdout, for use by the CLI. + /// This does not include JANA parameters, which come from + /// JParameterManager::PrintParameters() instead. + + std::cout << std::endl; + std::cout << "Usage:" << std::endl; + std::cout << " eicrecon [options] source1 source2 ..." << std::endl; + std::cout << std::endl; + + std::cout << "Description:" << std::endl; + std::cout << " Command-line interface for running JANA plugins. This can be used to" + << std::endl; + std::cout << " read in events and process them. Command-line flags control configuration" + << std::endl; + std::cout << " while additional arguments denote input files, which are to be loaded and" + << std::endl; + std::cout << " processed by the appropriate EventSource plugin." << std::endl; + std::cout << std::endl; + + PrintUsageOptions(); + PrintUsageExample(); +} - std::vector GetAvailablePluginNames(std::vector const& default_plugins) { - // Use set to remove duplicates. - /// @note The plugins will be override if you use the same plugin name at different paths. - std::set set_plugin_name; - for (std::string s : default_plugins) - set_plugin_name.insert(s); +void PrintVersion() { std::cout << "EICrecon version: " << EICRECON_APP_VERSION_STR << std::endl; } - jana::GetPluginNamesFromEnvPath(set_plugin_name, "JANA_PLUGIN_PATH"); - jana::GetPluginNamesFromEnvPath(set_plugin_name, "EICrecon_MY"); +void PrintJANAVersion() { std::cout << "JANA version: " << JVersion::GetVersion() << std::endl; } - std::vector plugin_names(set_plugin_name.begin(), set_plugin_name.end()); - return plugin_names; - } +void PrintDefaultPlugins(std::vector const& default_plugins) { + std::cout << "\n List default plugins:\n\n"; + printPluginNames(default_plugins); + std::cout << std::endl << std::endl; +} - void PrintAvailablePlugins(std::vector const& default_plugins) { - std::cout << "\n List available plugins:\n\n"; - printPluginNames(GetAvailablePluginNames(default_plugins)); - std::cout << std::endl << std::endl; +void GetPluginNamesInDir(std::set& plugin_names, std::string dir_str) { + // Edge case handler: taking care of invalid and empty dirs + if (std::filesystem::is_directory(dir_str) == false) + return; + if (std::filesystem::is_empty(dir_str)) + return; + + std::string full_path, filename; + for (const auto& entry : std::filesystem::directory_iterator(dir_str)) { + full_path = std::string(entry.path()); // Example: "/usr/local/plugins/Tutorial.so" + filename = full_path.substr(full_path.find_last_of("/") + 1); // Example: "Tutorial.so" + if (filename.substr(filename.size() - 3) == ".so") { + std::string s = filename.substr(0, filename.size() - 3); + // std::cout << filename << "==> " << s << std::endl; + plugin_names.insert(s); } + } +} - bool HasPrintOnlyCliOptions(UserOptions& options, std::vector const& default_plugins) { - if (options.flags[jana::ShowUsage]) { - jana::PrintUsage(); - return true; - } - if (options.flags[jana::ShowVersion]) { - jana::PrintVersion(); - return true; - } - if (options.flags[jana::ShowJANAVersion]) { - jana::PrintJANAVersion(); - return true; - } - if (options.flags[jana::ShowDefaultPlugins]) { - jana::PrintDefaultPlugins(default_plugins); - return true; - } - if (options.flags[jana::ShowAvailablePlugins]) { - jana::PrintAvailablePlugins(default_plugins); - return true; - } - return false; +/// Get the plugin names by searching for files named as *.so under $JANA_PLUGIN_PATH and $EICrecon_MY/plugins. +/// @note It does not guarantee any effectiveness of the plugins. +void GetPluginNamesFromEnvPath(std::set& plugin_names, const char* env_var) { + std::string dir_path, paths; + + const char* env_p = getenv(env_var); + if (env_p) { + if (strcmp(env_var, "EICrecon_MY") == 0) { + paths = std::string(env_p) + "/plugins"; + } else { + paths = std::string(env_p); } - /// Detect whether the cli params @param options.params contain "-Pplugins_to_ignore=......". - /// If true, delete @param erase_str from the original cli string "-Pplugins_to_ignore". - bool HasExcludeDefaultPluginsInCliParams(UserOptions& options, const std::string erase_str) { - auto has_ignore_plugins = options.params.find("plugins_to_ignore"); - if (has_ignore_plugins == options.params.end()) - return false; - - // Has cli option "-Pplugins_to_ignore". Look for @param erase_str - size_t pos = has_ignore_plugins->second.find(erase_str); - if (pos == std::string::npos) // does not contain @param erase_str - return false; - - // Detect @param flag_str. Delete flag_str from the original cli option. - std::string ignore_str; - if (erase_str.length() + pos == has_ignore_plugins->second.length()) { // @param flag_str is at the end - ignore_str = has_ignore_plugins->second.erase(pos, erase_str.length()); - } else { // erase "," from "-Pplugins_to_ignore". - ignore_str = has_ignore_plugins->second.erase(pos, erase_str.length() + 1); - } - options.params["plugins_to_ignore"] = ignore_str; - return true; + std::stringstream envvar_ss(paths); + while (getline(envvar_ss, dir_path, ':')) { + GetPluginNamesInDir(plugin_names, dir_path); } + } +} - void AddAvailablePluginsToOptionParams(UserOptions& options, std::vector const& default_plugins) { - - std::set set_plugins; - // Add the plugins at $EICrecon_MY/plugins. -// jana::GetPluginNamesFromEnvPath(set_plugins, "EICrecon_MY"); // disabled as we do not want to automatically add these - - std::string plugins_str; // the complete plugins list - for (std::string s : set_plugins) - plugins_str += s + ","; - - // Add the default plugins into the plugin set if there is no - // "-Pplugins_to_ignore=default (exclude all default plugins)" option - if (HasExcludeDefaultPluginsInCliParams(options, "default") == false) - /// @note: The sequence of adding the default plugins matters. - /// Have to keep the original sequence to not causing troubles. - for (std::string s : default_plugins) { - plugins_str += s + ","; - } - - // Insert other plugins in cli option "-Pplugins=pl1,pl2,..." - auto has_cli_plugin_params = options.params.find("plugins"); - if (has_cli_plugin_params != options.params.end()) { - plugins_str += has_cli_plugin_params->second; - options.params["plugins"] = plugins_str; - } else { - options.params["plugins"] = plugins_str.substr(0, plugins_str.size() - 1); // exclude last "," - } - } +std::vector GetAvailablePluginNames(std::vector const& default_plugins) { + // Use set to remove duplicates. + /// @note The plugins will be override if you use the same plugin name at different paths. + std::set set_plugin_name; + for (std::string s : default_plugins) + set_plugin_name.insert(s); - JApplication* CreateJApplication(UserOptions& options) { + jana::GetPluginNamesFromEnvPath(set_plugin_name, "JANA_PLUGIN_PATH"); + jana::GetPluginNamesFromEnvPath(set_plugin_name, "EICrecon_MY"); - auto *para_mgr = new JParameterManager(); // JApplication owns params_copy, does not own eventSources + std::vector plugin_names(set_plugin_name.begin(), set_plugin_name.end()); + return plugin_names; +} - // Add the cli options based on the user inputs - for (auto pair : options.params) { - para_mgr->SetParameter(pair.first, pair.second); - } +void PrintAvailablePlugins(std::vector const& default_plugins) { + std::cout << "\n List available plugins:\n\n"; + printPluginNames(GetAvailablePluginNames(default_plugins)); + std::cout << std::endl << std::endl; +} - // Shut down the [INFO] msg of adding plugins, printing cpu info - if (options.flags[ListFactories]) { - para_mgr->SetParameter( - "log:off", - "JPluginLoader,JArrowProcessingController,JArrow" - ); - } +bool HasPrintOnlyCliOptions(UserOptions& options, std::vector const& default_plugins) { + if (options.flags[jana::ShowUsage]) { + jana::PrintUsage(); + return true; + } + if (options.flags[jana::ShowVersion]) { + jana::PrintVersion(); + return true; + } + if (options.flags[jana::ShowJANAVersion]) { + jana::PrintJANAVersion(); + return true; + } + if (options.flags[jana::ShowDefaultPlugins]) { + jana::PrintDefaultPlugins(default_plugins); + return true; + } + if (options.flags[jana::ShowAvailablePlugins]) { + jana::PrintAvailablePlugins(default_plugins); + return true; + } + return false; +} - if (options.flags[LoadConfigs]) { - // If the user specified an external config file, we should definitely use that - try { - para_mgr->ReadConfigFile(options.load_config_file); - } - catch (JException &e) { - std::cout << "Problem loading config file '" << options.load_config_file << "'. Exiting." << std::endl - << std::endl; - exit(-1); - } - std::cout << "Loaded config file '" << options.load_config_file << "'." << std::endl << std::endl; - } +/// Detect whether the cli params @param options.params contain "-Pplugins_to_ignore=......". +/// If true, delete @param erase_str from the original cli string "-Pplugins_to_ignore". +bool HasExcludeDefaultPluginsInCliParams(UserOptions& options, const std::string erase_str) { + auto has_ignore_plugins = options.params.find("plugins_to_ignore"); + if (has_ignore_plugins == options.params.end()) + return false; + + // Has cli option "-Pplugins_to_ignore". Look for @param erase_str + size_t pos = has_ignore_plugins->second.find(erase_str); + if (pos == std::string::npos) // does not contain @param erase_str + return false; + + // Detect @param flag_str. Delete flag_str from the original cli option. + std::string ignore_str; + if (erase_str.length() + pos == + has_ignore_plugins->second.length()) { // @param flag_str is at the end + ignore_str = has_ignore_plugins->second.erase(pos, erase_str.length()); + } else { // erase "," from "-Pplugins_to_ignore". + ignore_str = has_ignore_plugins->second.erase(pos, erase_str.length() + 1); + } + options.params["plugins_to_ignore"] = ignore_str; + return true; +} - // If the user hasn't specified a timeout (on cmd line or in config file), set the timeout to something reasonably high - if (para_mgr->FindParameter("jana:timeout") == nullptr) { - para_mgr->SetParameter("jana:timeout", 180); // seconds - para_mgr->SetParameter("jana:warmup_timeout", 180); // seconds - } +void AddAvailablePluginsToOptionParams(UserOptions& options, + std::vector const& default_plugins) { - auto *app = new JApplication(para_mgr); + std::set set_plugins; + // Add the plugins at $EICrecon_MY/plugins. + // jana::GetPluginNamesFromEnvPath(set_plugins, "EICrecon_MY"); // disabled as we do not want to automatically add these - const char* env_p = getenv("EICrecon_MY"); - if( env_p ){ - app->AddPluginPath( std::string(env_p) + "/plugins" ); - } + std::string plugins_str; // the complete plugins list + for (std::string s : set_plugins) + plugins_str += s + ","; - for (auto event_src : options.eventSources) { - app->Add(event_src); - } - return app; + // Add the default plugins into the plugin set if there is no + // "-Pplugins_to_ignore=default (exclude all default plugins)" option + if (HasExcludeDefaultPluginsInCliParams(options, "default") == false) + /// @note: The sequence of adding the default plugins matters. + /// Have to keep the original sequence to not causing troubles. + for (std::string s : default_plugins) { + plugins_str += s + ","; } - void AddDefaultPluginsToJApplication(JApplication* app, std::vector const& default_plugins) { - for (std::string s : default_plugins) - app->AddPlugin(s); - } + // Insert other plugins in cli option "-Pplugins=pl1,pl2,..." + auto has_cli_plugin_params = options.params.find("plugins"); + if (has_cli_plugin_params != options.params.end()) { + plugins_str += has_cli_plugin_params->second; + options.params["plugins"] = plugins_str; + } else { + options.params["plugins"] = plugins_str.substr(0, plugins_str.size() - 1); // exclude last "," + } +} - void PrintFactories(JApplication* app) { - std::cout << std::endl << "List all the factories:" << std::endl << std::endl; - printFactoryTable(app->GetComponentSummary()); - std::cout << std::endl; +JApplication* CreateJApplication(UserOptions& options) { + + auto* para_mgr = + new JParameterManager(); // JApplication owns params_copy, does not own eventSources + + // Add the cli options based on the user inputs + for (auto pair : options.params) { + para_mgr->SetParameter(pair.first, pair.second); + } + + // Shut down the [INFO] msg of adding plugins, printing cpu info + if (options.flags[ListFactories]) { + para_mgr->SetParameter("log:off", "JPluginLoader,JArrowProcessingController,JArrow"); + } + + if (options.flags[LoadConfigs]) { + // If the user specified an external config file, we should definitely use that + try { + para_mgr->ReadConfigFile(options.load_config_file); + } catch (JException& e) { + std::cout << "Problem loading config file '" << options.load_config_file << "'. Exiting." + << std::endl + << std::endl; + exit(-1); } + std::cout << "Loaded config file '" << options.load_config_file << "'." << std::endl + << std::endl; + } + + // If the user hasn't specified a timeout (on cmd line or in config file), set the timeout to something reasonably high + if (para_mgr->FindParameter("jana:timeout") == nullptr) { + para_mgr->SetParameter("jana:timeout", 180); // seconds + para_mgr->SetParameter("jana:warmup_timeout", 180); // seconds + } + + auto* app = new JApplication(para_mgr); + + const char* env_p = getenv("EICrecon_MY"); + if (env_p) { + app->AddPluginPath(std::string(env_p) + "/plugins"); + } + + for (auto event_src : options.eventSources) { + app->Add(event_src); + } + return app; +} - void PrintPodioCollections(JApplication* app) { - if (app->GetJParameterManager()->Exists("PODIO:PRINT_TYPE_TABLE")) { - bool print_type_table = app->GetParameterValue("podio:print_type_table"); - - // cli criteria: Ppodio:print_type_table=1 - if (print_type_table) { - auto event_sources = app->GetService()->get_evt_srces(); - for (auto *event_source : event_sources) { -// std::cout << event_source->GetPluginName() << std::endl; // podio.so -// std::cout << event_source->GetResourceName() << std::endl; - if (event_source->GetPluginName().find("podio") != std::string::npos) - event_source->DoInitialize(); - } - } - - } - } +void AddDefaultPluginsToJApplication(JApplication* app, + std::vector const& default_plugins) { + for (std::string s : default_plugins) + app->AddPlugin(s); +} - void PrintConfigParameters(JApplication* app){ - /// Print a table of the currently defined configuration parameters. - /// n.b. this mostly duplicates a call to app->GetJParameterManager()->PrintParameters() - /// but avoids the issue it has of setting the values column to same - /// width for all parameters. (That leads to lots of whitespace being - /// printed due to the very long podio:output_include_collections param. - - // Determine column widths - auto params = app->GetJParameterManager()->GetAllParameters(); - size_t max_key_length = 0; - size_t max_val_length = 0; - size_t max_max_val_length = 32; // maximum width allowed for column. - for( auto &[key, p] : params ){ - if( key.length() > max_key_length ) max_key_length = key.length(); - if( p->GetValue().length() > max_val_length ){ - if( p->GetValue().length() <= max_max_val_length ) max_val_length = p->GetValue().length(); - } - } +void PrintFactories(JApplication* app) { + std::cout << std::endl << "List all the factories:" << std::endl << std::endl; + printFactoryTable(app->GetComponentSummary()); + std::cout << std::endl; +} - std::cout << "\nConfiguration Parameters:" << std::endl; - std::cout << "Name" + std::string(std::max(max_key_length, size_t(4)) - 4, ' ') << " : "; - std::cout << "Value" + std::string(std::max(max_val_length, size_t(5)) - 5, ' ') << " : "; - std::cout << "Description" << std::endl; - std::cout << std::string(max_key_length+max_val_length+20, '-') << std::endl; - for( auto &[key, p] : params ){ - std::stringstream ss; - int key_length_diff = max_key_length - key.length(); - if( key_length_diff>0 ) ss << std::string(key_length_diff, ' '); - ss << key; - ss << " | "; - - int val_length_diff = max_val_length - p->GetValue().length(); - if( val_length_diff>0 ) ss << std::string(val_length_diff, ' '); - ss << p->GetValue(); - ss << " | "; - ss << p->GetDescription(); - - std::cout << ss.str() << std::endl; - } - std::cout << std::string(max_key_length+max_val_length+20, '-') << std::endl; +void PrintPodioCollections(JApplication* app) { + if (app->GetJParameterManager()->Exists("PODIO:PRINT_TYPE_TABLE")) { + bool print_type_table = app->GetParameterValue("podio:print_type_table"); + + // cli criteria: Ppodio:print_type_table=1 + if (print_type_table) { + auto event_sources = app->GetService()->get_evt_srces(); + for (auto* event_source : event_sources) { + // std::cout << event_source->GetPluginName() << std::endl; // podio.so + // std::cout << event_source->GetResourceName() << std::endl; + if (event_source->GetPluginName().find("podio") != std::string::npos) + event_source->DoInitialize(); + } } + } +} - int Execute(JApplication* app, UserOptions &options) { +void PrintConfigParameters(JApplication* app) { + /// Print a table of the currently defined configuration parameters. + /// n.b. this mostly duplicates a call to app->GetJParameterManager()->PrintParameters() + /// but avoids the issue it has of setting the values column to same + /// width for all parameters. (That leads to lots of whitespace being + /// printed due to the very long podio:output_include_collections param. + + // Determine column widths + auto params = app->GetJParameterManager()->GetAllParameters(); + size_t max_key_length = 0; + size_t max_val_length = 0; + size_t max_max_val_length = 32; // maximum width allowed for column. + for (auto& [key, p] : params) { + if (key.length() > max_key_length) + max_key_length = key.length(); + if (p->GetValue().length() > max_val_length) { + if (p->GetValue().length() <= max_max_val_length) + max_val_length = p->GetValue().length(); + } + } + + std::cout << "\nConfiguration Parameters:" << std::endl; + std::cout << "Name" + std::string(std::max(max_key_length, size_t(4)) - 4, ' ') << " : "; + std::cout << "Value" + std::string(std::max(max_val_length, size_t(5)) - 5, ' ') << " : "; + std::cout << "Description" << std::endl; + std::cout << std::string(max_key_length + max_val_length + 20, '-') << std::endl; + for (auto& [key, p] : params) { + std::stringstream ss; + int key_length_diff = max_key_length - key.length(); + if (key_length_diff > 0) + ss << std::string(key_length_diff, ' '); + ss << key; + ss << " | "; + + int val_length_diff = max_val_length - p->GetValue().length(); + if (val_length_diff > 0) + ss << std::string(val_length_diff, ' '); + ss << p->GetValue(); + ss << " | "; + ss << p->GetDescription(); + + std::cout << ss.str() << std::endl; + } + std::cout << std::string(max_key_length + max_val_length + 20, '-') << std::endl; +} - std::cout << std::endl; +int Execute(JApplication* app, UserOptions& options) { - // std::cout << "JANA " << JVersion::GetVersion() << " [" << JVersion::GetRevision() << "]" << std::endl; + std::cout << std::endl; - if (options.flags[ShowConfigs]) { - // Load all plugins, collect all parameters, exit without running anything - app->Initialize(); - if (options.flags[Benchmark]) { - JBenchmarker benchmarker(app); // Show benchmarking configs only if benchmarking mode specified - } -// app->GetJParameterManager()->PrintParameters(true); - PrintConfigParameters(app); - } - else if (options.flags[DumpConfigs]) { - // Load all plugins, dump parameters to file, exit without running anything - app->Initialize(); - std::cout << std::endl << "Writing configuration options to file: " << options.dump_config_file - << std::endl; - app->GetJParameterManager()->WriteConfigFile(options.dump_config_file); - } - else if (options.flags[Benchmark]) { - JSignalHandler::register_handlers(app); - // Run JANA in benchmark mode - JBenchmarker benchmarker(app); // Benchmarking params override default params - benchmarker.RunUntilFinished(); // Benchmarker will control JApp Run/Stop - } - else if (options.flags[ListFactories]) { - app->Initialize(); - PrintFactories(app); + // std::cout << "JANA " << JVersion::GetVersion() << " [" << JVersion::GetRevision() << "]" << std::endl; - // TODO: more elegant processing here - PrintPodioCollections(app); - } - else { - // Run JANA in normal mode - try { - printJANAHeaderIMG(); - JSignalHandler::register_handlers(app); - app->Run(); - } - catch (JException& e) { - std::cout << "----------------------------------------------------------" << std::endl; - std::cout << e << std::endl; - app->SetExitCode(EXIT_FAILURE); - } - catch (std::runtime_error& e) { - std::cout << "----------------------------------------------------------" << std::endl; - std::cout << "Exception: " << e.what() << std::endl; - app->SetExitCode(EXIT_FAILURE); - } - } - return (int) app->GetExitCode(); + if (options.flags[ShowConfigs]) { + // Load all plugins, collect all parameters, exit without running anything + app->Initialize(); + if (options.flags[Benchmark]) { + JBenchmarker benchmarker( + app); // Show benchmarking configs only if benchmarking mode specified + } + // app->GetJParameterManager()->PrintParameters(true); + PrintConfigParameters(app); + } else if (options.flags[DumpConfigs]) { + // Load all plugins, dump parameters to file, exit without running anything + app->Initialize(); + std::cout << std::endl + << "Writing configuration options to file: " << options.dump_config_file << std::endl; + app->GetJParameterManager()->WriteConfigFile(options.dump_config_file); + } else if (options.flags[Benchmark]) { + JSignalHandler::register_handlers(app); + // Run JANA in benchmark mode + JBenchmarker benchmarker(app); // Benchmarking params override default params + benchmarker.RunUntilFinished(); // Benchmarker will control JApp Run/Stop + } else if (options.flags[ListFactories]) { + app->Initialize(); + PrintFactories(app); + + // TODO: more elegant processing here + PrintPodioCollections(app); + } else { + // Run JANA in normal mode + try { + printJANAHeaderIMG(); + JSignalHandler::register_handlers(app); + app->Run(); + } catch (JException& e) { + std::cout << "----------------------------------------------------------" << std::endl; + std::cout << e << std::endl; + app->SetExitCode(EXIT_FAILURE); + } catch (std::runtime_error& e) { + std::cout << "----------------------------------------------------------" << std::endl; + std::cout << "Exception: " << e.what() << std::endl; + app->SetExitCode(EXIT_FAILURE); } + } + return (int)app->GetExitCode(); +} +UserOptions GetCliOptions(int nargs, char* argv[], bool expect_extra) { + + UserOptions options; + + std::map tokenizer; + tokenizer["-h"] = ShowUsage; + tokenizer["--help"] = ShowUsage; + tokenizer["-v"] = ShowVersion; + tokenizer["--version"] = ShowVersion; + tokenizer["-j"] = ShowJANAVersion; + tokenizer["--janaversion"] = ShowJANAVersion; + tokenizer["-c"] = ShowConfigs; + tokenizer["--configs"] = ShowConfigs; + tokenizer["-l"] = LoadConfigs; + tokenizer["--loadconfigs"] = LoadConfigs; + tokenizer["-d"] = DumpConfigs; + tokenizer["--dumpconfigs"] = DumpConfigs; + tokenizer["-b"] = Benchmark; + tokenizer["--benchmark"] = Benchmark; + tokenizer["-L"] = ListFactories; + tokenizer["--list-factories"] = ListFactories; + tokenizer["--list-default-plugins"] = ShowDefaultPlugins; + tokenizer["--list-available-plugins"] = ShowAvailablePlugins; + + // `eicrecon` has the same effect with `eicrecon -h` + if (nargs == 1) { + options.flags[ShowUsage] = true; + } + + for (int i = 1; i < nargs; i++) { + + std::string arg = argv[i]; + // std::cout << "Found arg " << arg << std::endl; + + if (argv[i][0] != '-') { + options.eventSources.push_back(arg); + continue; + } - UserOptions GetCliOptions(int nargs, char *argv[], bool expect_extra) { - - UserOptions options; - - std::map tokenizer; - tokenizer["-h"] = ShowUsage; - tokenizer["--help"] = ShowUsage; - tokenizer["-v"] = ShowVersion; - tokenizer["--version"] = ShowVersion; - tokenizer["-j"] = ShowJANAVersion; - tokenizer["--janaversion"] = ShowJANAVersion; - tokenizer["-c"] = ShowConfigs; - tokenizer["--configs"] = ShowConfigs; - tokenizer["-l"] = LoadConfigs; - tokenizer["--loadconfigs"] = LoadConfigs; - tokenizer["-d"] = DumpConfigs; - tokenizer["--dumpconfigs"] = DumpConfigs; - tokenizer["-b"] = Benchmark; - tokenizer["--benchmark"] = Benchmark; - tokenizer["-L"] = ListFactories; - tokenizer["--list-factories"] = ListFactories; - tokenizer["--list-default-plugins"] = ShowDefaultPlugins; - tokenizer["--list-available-plugins"] = ShowAvailablePlugins; - - // `eicrecon` has the same effect with `eicrecon -h` - if (nargs == 1) { - options.flags[ShowUsage] = true; + switch (tokenizer[arg]) { + + case Benchmark: + options.flags[Benchmark] = true; + break; + + case ShowUsage: + options.flags[ShowUsage] = true; + break; + + case ShowVersion: + options.flags[ShowVersion] = true; + break; + + case ShowJANAVersion: + options.flags[ShowJANAVersion] = true; + break; + + case ShowConfigs: + options.flags[ShowConfigs] = true; + break; + + case LoadConfigs: + options.flags[LoadConfigs] = true; + if (i + 1 < nargs && argv[i + 1][0] != '-') { + options.load_config_file = argv[i + 1]; + i += 1; + } else { + options.load_config_file = "jana.config"; + } + break; + + case DumpConfigs: + options.flags[DumpConfigs] = true; + if (i + 1 < nargs && argv[i + 1][0] != '-') { + options.dump_config_file = argv[i + 1]; + i += 1; + } else { + options.dump_config_file = "jana.config"; + } + break; + + case ListFactories: + options.flags[ListFactories] = true; + break; + + case ShowDefaultPlugins: + options.flags[ShowDefaultPlugins] = true; + break; + + case ShowAvailablePlugins: + options.flags[ShowAvailablePlugins] = true; + break; + + // TODO: add exclude plugin options + case Unknown: + if (argv[i][0] == '-' && argv[i][1] == 'P') { + + size_t pos = arg.find("="); + if ((pos != std::string::npos) && (pos > 2)) { + std::string key = arg.substr(2, pos - 2); + std::string val = arg.substr(pos + 1); + if (options.params.find(key) != options.params.end()) { + std::cout << "Duplicate parameter '" << arg << "' ignored" << std::endl; + } else { + options.params.insert({key, val}); + } + } else { + std::cout << "Invalid JANA parameter '" << arg << "': Expected format -Pkey=value" + << std::endl; + options.flags[ShowConfigs] = true; } - - for (int i = 1; i < nargs; i++) { - - std::string arg = argv[i]; - // std::cout << "Found arg " << arg << std::endl; - - if (argv[i][0] != '-') { - options.eventSources.push_back(arg); - continue; - } - - switch (tokenizer[arg]) { - - case Benchmark: - options.flags[Benchmark] = true; - break; - - case ShowUsage: - options.flags[ShowUsage] = true; - break; - - case ShowVersion: - options.flags[ShowVersion] = true; - break; - - case ShowJANAVersion: - options.flags[ShowJANAVersion] = true; - break; - - case ShowConfigs: - options.flags[ShowConfigs] = true; - break; - - case LoadConfigs: - options.flags[LoadConfigs] = true; - if (i + 1 < nargs && argv[i + 1][0] != '-') { - options.load_config_file = argv[i + 1]; - i += 1; - } else { - options.load_config_file = "jana.config"; - } - break; - - case DumpConfigs: - options.flags[DumpConfigs] = true; - if (i + 1 < nargs && argv[i + 1][0] != '-') { - options.dump_config_file = argv[i + 1]; - i += 1; - } else { - options.dump_config_file = "jana.config"; - } - break; - - case ListFactories: - options.flags[ListFactories] = true; - break; - - case ShowDefaultPlugins: - options.flags[ShowDefaultPlugins] = true; - break; - - case ShowAvailablePlugins: - options.flags[ShowAvailablePlugins] = true; - break; - - // TODO: add exclude plugin options - case Unknown: - if (argv[i][0] == '-' && argv[i][1] == 'P') { - - size_t pos = arg.find("="); - if ((pos != std::string::npos) && (pos > 2)) { - std::string key = arg.substr(2, pos - 2); - std::string val = arg.substr(pos + 1); - if (options.params.find(key) != options.params.end()) { - std::cout << "Duplicate parameter '" << arg << "' ignored" << std::endl; - } else { - options.params.insert({key, val}); - } - } else { - std::cout << "Invalid JANA parameter '" << arg - << "': Expected format -Pkey=value" << std::endl; - options.flags[ShowConfigs] = true; - } - } else { - if (!expect_extra) { - std::cout << "Invalid command line flag '" << arg << "'" << std::endl; - options.flags[ShowUsage] = true; - } - } - } + } else { + if (!expect_extra) { + std::cout << "Invalid command line flag '" << arg << "'" << std::endl; + options.flags[ShowUsage] = true; } - return options; + } } + } + return options; } +} // namespace jana diff --git a/src/utilities/eicrecon/eicrecon_cli.h b/src/utilities/eicrecon/eicrecon_cli.h index 6909c2cd4a..1af8896b13 100644 --- a/src/utilities/eicrecon/eicrecon_cli.h +++ b/src/utilities/eicrecon/eicrecon_cli.h @@ -16,70 +16,72 @@ namespace jana { - enum Flag { - Unknown, - ShowUsage, - ShowVersion, - ShowJANAVersion, - ShowDefaultPlugins, - ShowAvailablePlugins, - ShowConfigs, - LoadConfigs, - DumpConfigs, - Benchmark, - ListFactories - }; - - struct UserOptions { - /// Code representation of all user options. - /// This lets us cleanly separate args parsing from execution. - - std::map flags; - std::map params; - std::vector eventSources; - std::string load_config_file; - std::string dump_config_file; - }; - - /// Read the user options from the command line and initialize @param options. - /// If there are certain flags, mark them as true. - /// Push the event source strings to @param options.eventSources. - /// Push the parameter strings to @param options.params as key-value pairs. - /// If the user option is to load or dump a config file, initialize @param options.load/dump_config_file - UserOptions GetCliOptions(int nargs, char *argv[], bool expect_extra=true); - - /// If the user option contains print only flags, print the info ann return true; otherwise return false. - /// The print only flags include: "-v", "-h", "-L", "--list_default_plugins", "--list_available_plugins". - /// When the info is shown, the application will exit immediately. - bool HasPrintOnlyCliOptions(UserOptions& options, std::vector const& default_plugins); - - void PrintUsage(); - void PrintVersion(); - - /// List the @param default_plugins in a table. - /// @param default_plugins is given at the top of the eicrecon.cc. - void PrintDefaultPlugins(std::vector const& default_plugins); - - /// List all the available plugins at @env_var $JANA_PLUGIN_PATH and @env_var $EICrecon_MY/plugins. - /// @note Does not guarantee the effectiveness of the plugins. - /// @note The plugins can be override if they use the same name under different locations. - void PrintAvailablePlugins(std::vector const& default_plugins); - - /// Add the default plugins and the plugins at $EICrecon_MY/plugins to @param options.params. - /// It comes before creating the @class JApplication. - void AddAvailablePluginsToOptionParams(UserOptions& options, std::vector const& default_plugins); - - void AddDefaultPluginsToJApplication(JApplication* app, std::vector const& default_plugins); - - void PrintFactories(JApplication* app); - void PrintPodioCollections(JApplication* app); - - /// Copy the @param options params (from the cli or the config file) to a JParameterManager @var para_mgr. - /// Create an empty JApplication @var app. - /// Add the event sources got from the cli input to @var app, and then return. - /// @note The cli -Pkey=value pairs are not processed when the function returns. They are processed, - /// or, added to @var app at calling JApplication::Initialize(). - JApplication* CreateJApplication(UserOptions& options); - int Execute(JApplication* app, UserOptions& options); - -} +enum Flag { + Unknown, + ShowUsage, + ShowVersion, + ShowJANAVersion, + ShowDefaultPlugins, + ShowAvailablePlugins, + ShowConfigs, + LoadConfigs, + DumpConfigs, + Benchmark, + ListFactories +}; + +struct UserOptions { + /// Code representation of all user options. + /// This lets us cleanly separate args parsing from execution. + + std::map flags; + std::map params; + std::vector eventSources; + std::string load_config_file; + std::string dump_config_file; +}; + +/// Read the user options from the command line and initialize @param options. +/// If there are certain flags, mark them as true. +/// Push the event source strings to @param options.eventSources. +/// Push the parameter strings to @param options.params as key-value pairs. +/// If the user option is to load or dump a config file, initialize @param options.load/dump_config_file +UserOptions GetCliOptions(int nargs, char* argv[], bool expect_extra = true); + +/// If the user option contains print only flags, print the info ann return true; otherwise return false. +/// The print only flags include: "-v", "-h", "-L", "--list_default_plugins", "--list_available_plugins". +/// When the info is shown, the application will exit immediately. +bool HasPrintOnlyCliOptions(UserOptions& options, std::vector const& default_plugins); + +void PrintUsage(); +void PrintVersion(); + +/// List the @param default_plugins in a table. +/// @param default_plugins is given at the top of the eicrecon.cc. +void PrintDefaultPlugins(std::vector const& default_plugins); + +/// List all the available plugins at @env_var $JANA_PLUGIN_PATH and @env_var $EICrecon_MY/plugins. +/// @note Does not guarantee the effectiveness of the plugins. +/// @note The plugins can be override if they use the same name under different locations. +void PrintAvailablePlugins(std::vector const& default_plugins); + +/// Add the default plugins and the plugins at $EICrecon_MY/plugins to @param options.params. +/// It comes before creating the @class JApplication. +void AddAvailablePluginsToOptionParams(UserOptions& options, + std::vector const& default_plugins); + +void AddDefaultPluginsToJApplication(JApplication* app, + std::vector const& default_plugins); + +void PrintFactories(JApplication* app); +void PrintPodioCollections(JApplication* app); + +/// Copy the @param options params (from the cli or the config file) to a JParameterManager @var para_mgr. +/// Create an empty JApplication @var app. +/// Add the event sources got from the cli input to @var app, and then return. +/// @note The cli -Pkey=value pairs are not processed when the function returns. They are processed, +/// or, added to @var app at calling JApplication::Initialize(). +JApplication* CreateJApplication(UserOptions& options); +int Execute(JApplication* app, UserOptions& options); + +} // namespace jana diff --git a/src/utilities/eicrecon/print_info.h b/src/utilities/eicrecon/print_info.h index 4060d4b9fb..2d9516334c 100644 --- a/src/utilities/eicrecon/print_info.h +++ b/src/utilities/eicrecon/print_info.h @@ -9,41 +9,43 @@ #include void printFactoryTable(JComponentSummary const& cs) { - JTablePrinter factory_table; - factory_table.AddColumn("Plugin"); - factory_table.AddColumn("Object name"); - factory_table.AddColumn("Tag"); - for (const auto& factory : cs.factories) { - factory_table | factory.plugin_name | factory.object_name | factory.factory_tag; - } + JTablePrinter factory_table; + factory_table.AddColumn("Plugin"); + factory_table.AddColumn("Object name"); + factory_table.AddColumn("Tag"); + for (const auto& factory : cs.factories) { + factory_table | factory.plugin_name | factory.object_name | factory.factory_tag; + } - std::ostringstream ss; - factory_table.Render(ss); - std::cout << ss.str() << std::endl; + std::ostringstream ss; + factory_table.Render(ss); + std::cout << ss.str() << std::endl; } void printPluginNames(std::vector const& plugin_names) { - JTablePrinter plugin_table; - plugin_table.AddColumn("Plugin name"); - for (const auto& plugin_name : plugin_names) { - plugin_table | plugin_name; - } + JTablePrinter plugin_table; + plugin_table.AddColumn("Plugin name"); + for (const auto& plugin_name : plugin_names) { + plugin_table | plugin_name; + } - std::ostringstream ss; - plugin_table.Render(ss); - std::cout << ss.str() << std::endl; + std::ostringstream ss; + plugin_table.Render(ss); + std::cout << ss.str() << std::endl; } void printJANAHeaderIMG() { - std::cout << " ____ _ ___ ___ _ \n" - " `MM' dM. `MM\\ `M' dM. \n" - " MM ,MMb MMM\\ M ,MMb \n" - " MM d'YM. M\\MM\\ M d'YM. ____ \n" - " MM ,P `Mb M \\MM\\ M ,P `Mb 6MMMMb \n" - " MM d' YM. M \\MM\\ M d' YM. MM' `Mb \n" - " MM ,P `Mb M \\MM\\ M ,P `Mb ,MM \n" - " MM d' YM. M \\MM\\M d' YM. ,MM' \n" - "(8) MM ,MMMMMMMMb M \\MMM ,MMMMMMMMb ,M' \n" - "(( ,M9 d' YM. M \\MM d' YM. ,M' \n" - " YMMMM9 _dM_ _dMM_M_ \\M _dM_ _dMM_MMMMMMMM " << std::endl << std::endl; + std::cout << " ____ _ ___ ___ _ \n" + " `MM' dM. `MM\\ `M' dM. \n" + " MM ,MMb MMM\\ M ,MMb \n" + " MM d'YM. M\\MM\\ M d'YM. ____ \n" + " MM ,P `Mb M \\MM\\ M ,P `Mb 6MMMMb \n" + " MM d' YM. M \\MM\\ M d' YM. MM' `Mb \n" + " MM ,P `Mb M \\MM\\ M ,P `Mb ,MM \n" + " MM d' YM. M \\MM\\M d' YM. ,MM' \n" + "(8) MM ,MMMMMMMMb M \\MMM ,MMMMMMMMb ,M' \n" + "(( ,M9 d' YM. M \\MM d' YM. ,M' \n" + " YMMMM9 _dM_ _dMM_M_ \\M _dM_ _dMM_MMMMMMMM " + << std::endl + << std::endl; } diff --git a/src/utilities/janatop/JEventProcessorJANATOP.h b/src/utilities/janatop/JEventProcessorJANATOP.h index 70311ef301..1b8a274baa 100644 --- a/src/utilities/janatop/JEventProcessorJANATOP.h +++ b/src/utilities/janatop/JEventProcessorJANATOP.h @@ -6,258 +6,253 @@ #include #include -class JEventProcessorJANATOP : public JEventProcessor -{ - private: - enum node_type { - kDefault, - kProcessor, - kFactory, - kCache, - kSource - }; - - class CallLink { - public: - std::string caller_name; - std::string caller_tag; - std::string callee_name; - std::string callee_tag; - - bool operator<(const CallLink &link) const { - if (this->caller_name != link.caller_name) - return this->caller_name < link.caller_name; - if (this->callee_name != link.callee_name) - return this->callee_name < link.callee_name; - if (this->caller_tag != link.caller_tag) - return this->caller_tag < link.caller_tag; - return this->callee_tag < link.callee_tag; - } - }; - - class CallStats { - public: - CallStats(void) { - from_cache_ms = 0; - from_source_ms = 0; - from_factory_ms = 0; - data_not_available_ms = 0; - Nfrom_cache = 0; - Nfrom_source = 0; - Nfrom_factory = 0; - Ndata_not_available = 0; - } - double from_cache_ms; - double from_source_ms; - double from_factory_ms; - double data_not_available_ms; - unsigned int Nfrom_cache; - unsigned int Nfrom_source; - unsigned int Nfrom_factory; - unsigned int Ndata_not_available; - }; +class JEventProcessorJANATOP : public JEventProcessor { +private: + enum node_type { kDefault, kProcessor, kFactory, kCache, kSource }; - class FactoryCallStats{ - public: - FactoryCallStats(void) { - type = kDefault; - time_waited_on = 0.0; - time_waiting = 0.0; - Nfrom_factory = 0; - Nfrom_source = 0; - Nfrom_cache = 0; - } - node_type type; - double time_waited_on; // time other factories spent waiting on this factory - double time_waiting; // time this factory spent waiting on other factories - unsigned int Nfrom_factory; - unsigned int Nfrom_source; - unsigned int Nfrom_cache; - }; + class CallLink { + public: + std::string caller_name; + std::string caller_tag; + std::string callee_name; + std::string callee_tag; + + bool operator<(const CallLink& link) const { + if (this->caller_name != link.caller_name) + return this->caller_name < link.caller_name; + if (this->callee_name != link.callee_name) + return this->callee_name < link.callee_name; + if (this->caller_tag != link.caller_tag) + return this->caller_tag < link.caller_tag; + return this->callee_tag < link.callee_tag; + } + }; + class CallStats { + public: + CallStats(void) { + from_cache_ms = 0; + from_source_ms = 0; + from_factory_ms = 0; + data_not_available_ms = 0; + Nfrom_cache = 0; + Nfrom_source = 0; + Nfrom_factory = 0; + Ndata_not_available = 0; + } + double from_cache_ms; + double from_source_ms; + double from_factory_ms; + double data_not_available_ms; + unsigned int Nfrom_cache; + unsigned int Nfrom_source; + unsigned int Nfrom_factory; + unsigned int Ndata_not_available; + }; + + class FactoryCallStats { public: + FactoryCallStats(void) { + type = kDefault; + time_waited_on = 0.0; + time_waiting = 0.0; + Nfrom_factory = 0; + Nfrom_source = 0; + Nfrom_cache = 0; + } + node_type type; + double time_waited_on; // time other factories spent waiting on this factory + double time_waiting; // time this factory spent waiting on other factories + unsigned int Nfrom_factory; + unsigned int Nfrom_source; + unsigned int Nfrom_cache; + }; + +public: + JEventProcessorJANATOP() : JEventProcessor() { + SetTypeName("JEventProcessorJANATOP"); + auto app = japp; + }; + + void Init() override {}; + + void BeginRun(const std::shared_ptr& event) override {}; + + void Process(const std::shared_ptr& event) override { + // Get the call stack for ths event and add the results to our stats + auto stack = event->GetJCallGraphRecorder()->GetCallGraph(); + + // Lock mutex in case we are running with multiple threads + std::lock_guard lck(mutex); + + // Loop over the call stack elements and add in the values + for (unsigned int i = 0; i < stack.size(); i++) { + + // Keep track of total time each factory spent waiting and being waited on + std::string nametag1 = MakeNametag(stack[i].caller_name, stack[i].caller_tag); + std::string nametag2 = MakeNametag(stack[i].callee_name, stack[i].callee_tag); + + FactoryCallStats& fcallstats1 = factory_stats[nametag1]; + FactoryCallStats& fcallstats2 = factory_stats[nametag2]; + + auto delta_t_ms = std::chrono::duration_cast(stack[i].end_time - + stack[i].start_time) + .count(); + fcallstats1.time_waiting += delta_t_ms; + fcallstats2.time_waited_on += delta_t_ms; + + // Get pointer to CallStats object representing this calling pair + CallLink link; + link.caller_name = stack[i].caller_name; + link.caller_tag = stack[i].caller_tag; + link.callee_name = stack[i].callee_name; + link.callee_tag = stack[i].callee_tag; + CallStats& stats = + call_links[link]; // get pointer to stats object or create if it doesn't exist + + switch (stack[i].data_source) { + case JCallGraphRecorder::DATA_NOT_AVAILABLE: + stats.Ndata_not_available++; + stats.data_not_available_ms += delta_t_ms; + break; + case JCallGraphRecorder::DATA_FROM_CACHE: + fcallstats2.Nfrom_cache++; + stats.Nfrom_cache++; + stats.from_cache_ms += delta_t_ms; + break; + case JCallGraphRecorder::DATA_FROM_SOURCE: + fcallstats2.Nfrom_source++; + stats.Nfrom_source++; + stats.from_source_ms += delta_t_ms; + break; + case JCallGraphRecorder::DATA_FROM_FACTORY: + fcallstats2.Nfrom_factory++; + stats.Nfrom_factory++; + stats.from_factory_ms += delta_t_ms; + break; + } + } + }; + + void EndRun() override {}; + + void Finish() override { + // In order to get the total time we have to first get a list of + // the event processors (i.e. top-level callers). We can tell + // this just by looking for callers that never show up as callees + std::set callers; + std::set callees; + for (auto iter = call_links.begin(); iter != call_links.end(); iter++) { + const CallLink& link = iter->first; + std::string caller = MakeNametag(link.caller_name, link.caller_tag); + std::string callee = MakeNametag(link.callee_name, link.callee_tag); + callers.insert(caller); + callees.insert(callee); + } - JEventProcessorJANATOP(): JEventProcessor() { - SetTypeName("JEventProcessorJANATOP"); - auto app = japp; + // Loop over list a second time so we can get the total ticks for + // the process in order to add the percentage to the label below + double total_ms = 0.0; + for (auto iter = call_links.begin(); iter != call_links.end(); iter++) { + const CallLink& link = iter->first; + const CallStats& stats = iter->second; + std::string caller = MakeNametag(link.caller_name, link.caller_tag); + std::string callee = MakeNametag(link.callee_name, link.callee_tag); + if (callees.find(caller) == callees.end()) { + total_ms += stats.from_factory_ms + stats.from_source_ms + stats.from_cache_ms + + stats.data_not_available_ms; + } + } + if (total_ms == 0.0) + total_ms = 1.0; + + // Loop over call links + std::cout << "Links:" << std::endl; + std::vector> call_links_vector{ + std::make_move_iterator(std::begin(call_links)), + std::make_move_iterator(std::end(call_links))}; + [[maybe_unused]] auto call_links_compare_time = [](const auto& a, const auto& b) { + return ((a.second.from_factory_ms + a.second.from_source_ms + a.second.from_cache_ms) < + (b.second.from_factory_ms + b.second.from_source_ms + b.second.from_cache_ms)); }; - - void Init() override { }; - - void BeginRun(const std::shared_ptr& event) override { }; - - void Process(const std::shared_ptr& event) override { - // Get the call stack for ths event and add the results to our stats - auto stack = event->GetJCallGraphRecorder()->GetCallGraph(); - - // Lock mutex in case we are running with multiple threads - std::lock_guard lck(mutex); - - // Loop over the call stack elements and add in the values - for (unsigned int i = 0; i < stack.size(); i++) { - - // Keep track of total time each factory spent waiting and being waited on - std::string nametag1 = MakeNametag(stack[i].caller_name, stack[i].caller_tag); - std::string nametag2 = MakeNametag(stack[i].callee_name, stack[i].callee_tag); - - FactoryCallStats &fcallstats1 = factory_stats[nametag1]; - FactoryCallStats &fcallstats2 = factory_stats[nametag2]; - - auto delta_t_ms = std::chrono::duration_cast(stack[i].end_time - stack[i].start_time).count(); - fcallstats1.time_waiting += delta_t_ms; - fcallstats2.time_waited_on += delta_t_ms; - - // Get pointer to CallStats object representing this calling pair - CallLink link; - link.caller_name = stack[i].caller_name; - link.caller_tag = stack[i].caller_tag; - link.callee_name = stack[i].callee_name; - link.callee_tag = stack[i].callee_tag; - CallStats &stats = call_links[link]; // get pointer to stats object or create if it doesn't exist - - switch(stack[i].data_source){ - case JCallGraphRecorder::DATA_NOT_AVAILABLE: - stats.Ndata_not_available++; - stats.data_not_available_ms += delta_t_ms; - break; - case JCallGraphRecorder::DATA_FROM_CACHE: - fcallstats2.Nfrom_cache++; - stats.Nfrom_cache++; - stats.from_cache_ms += delta_t_ms; - break; - case JCallGraphRecorder::DATA_FROM_SOURCE: - fcallstats2.Nfrom_source++; - stats.Nfrom_source++; - stats.from_source_ms += delta_t_ms; - break; - case JCallGraphRecorder::DATA_FROM_FACTORY: - fcallstats2.Nfrom_factory++; - stats.Nfrom_factory++; - stats.from_factory_ms += delta_t_ms; - break; - } - } + [[maybe_unused]] auto call_links_compare_N = [](const auto& a, const auto& b) { + return ((a.second.Nfrom_factory + a.second.Nfrom_source + a.second.Nfrom_cache) < + (b.second.Nfrom_factory + b.second.Nfrom_source + b.second.Nfrom_cache)); }; + std::sort(call_links_vector.begin(), call_links_vector.end(), call_links_compare_time); + for (auto iter = call_links_vector.end() - std::min(call_links_vector.size(), 10ul); + iter != call_links_vector.end(); iter++) { + const CallLink& link = iter->first; + const CallStats& stats = iter->second; + + unsigned int Ntotal = stats.Nfrom_cache + stats.Nfrom_source + stats.Nfrom_factory; + + std::string nametag1 = MakeNametag(link.caller_name, link.caller_tag); + std::string nametag2 = MakeNametag(link.callee_name, link.callee_tag); + + double this_ms = stats.from_factory_ms + stats.from_source_ms + stats.from_cache_ms; + std::string timestr = MakeTimeString(stats.from_factory_ms); + double percent = 100.0 * this_ms / total_ms; + char percentstr[32]; + snprintf(percentstr, 32, "%5.1f%%", percent); + + std::cout << Ntotal << " calls, " << timestr << " (" << percentstr << ") "; + std::cout << nametag1 << " -> " << nametag2; + std::cout << std::endl; + } - void EndRun() override { }; - - void Finish() override { - // In order to get the total time we have to first get a list of - // the event processors (i.e. top-level callers). We can tell - // this just by looking for callers that never show up as callees - std::set callers; - std::set callees; - for (auto iter = call_links.begin(); iter != call_links.end(); iter++) { - const CallLink &link = iter->first; - std::string caller = MakeNametag(link.caller_name, link.caller_tag); - std::string callee = MakeNametag(link.callee_name, link.callee_tag); - callers.insert(caller); - callees.insert(callee); - } - - // Loop over list a second time so we can get the total ticks for - // the process in order to add the percentage to the label below - double total_ms = 0.0; - for (auto iter = call_links.begin(); iter != call_links.end(); iter++) { - const CallLink &link = iter->first; - const CallStats &stats = iter->second; - std::string caller = MakeNametag(link.caller_name, link.caller_tag); - std::string callee = MakeNametag(link.callee_name, link.callee_tag); - if (callees.find(caller) == callees.end()){ - total_ms += stats.from_factory_ms + stats.from_source_ms + stats.from_cache_ms + stats.data_not_available_ms; - } - } - if (total_ms == 0.0) total_ms = 1.0; - - // Loop over call links - std::cout << "Links:" << std::endl; - std::vector> call_links_vector{ - std::make_move_iterator(std::begin(call_links)), - std::make_move_iterator(std::end(call_links)) - }; - [[maybe_unused]] auto call_links_compare_time = [](const auto& a, const auto& b) { - return ((a.second.from_factory_ms + a.second.from_source_ms + a.second.from_cache_ms) - < (b.second.from_factory_ms + b.second.from_source_ms + b.second.from_cache_ms)); - }; - [[maybe_unused]] auto call_links_compare_N = [](const auto& a, const auto& b) { - return ((a.second.Nfrom_factory + a.second.Nfrom_source + a.second.Nfrom_cache) - < (b.second.Nfrom_factory + b.second.Nfrom_source + b.second.Nfrom_cache)); - }; - std::sort(call_links_vector.begin(), call_links_vector.end(), call_links_compare_time); - for (auto iter = call_links_vector.end() - std::min(call_links_vector.size(), 10ul); - iter != call_links_vector.end(); iter++) { - const CallLink &link = iter->first; - const CallStats &stats = iter->second; - - unsigned int Ntotal = stats.Nfrom_cache + stats.Nfrom_source + stats.Nfrom_factory; - - std::string nametag1 = MakeNametag(link.caller_name, link.caller_tag); - std::string nametag2 = MakeNametag(link.callee_name, link.callee_tag); - - double this_ms = stats.from_factory_ms + stats.from_source_ms + stats.from_cache_ms; - std::string timestr = MakeTimeString(stats.from_factory_ms); - double percent = 100.0 * this_ms / total_ms; - char percentstr[32]; - snprintf(percentstr, 32, "%5.1f%%", percent); - - std::cout << Ntotal << " calls, " << timestr << " (" << percentstr << ") "; - std::cout << nametag1 << " -> " << nametag2; - std::cout << std::endl; - } - - // Loop over factories - std::cout << "Factories:" << std::endl; - std::vector> factory_stats_vector{ - std::make_move_iterator(std::begin(factory_stats)), - std::make_move_iterator(std::end(factory_stats)) - }; - auto factory_stats_compare = [](const auto& a, const auto& b) { - return ((a.second.time_waited_on - a.second.time_waiting) - < (b.second.time_waited_on - b.second.time_waiting)); - }; - std::sort(factory_stats_vector.begin(), factory_stats_vector.end(), factory_stats_compare); - for (auto iter = factory_stats_vector.end() - std::min(factory_stats_vector.size(), 10ul); - iter != factory_stats_vector.end(); iter++) { - FactoryCallStats &fcall_stats = iter->second; - std::string nodename = iter->first; - - // Get time spent in this factory proper - double time_spent_in_factory = fcall_stats.time_waited_on - fcall_stats.time_waiting; - std::string timestr = MakeTimeString(time_spent_in_factory); - double percent = 100.0 * time_spent_in_factory / total_ms; - char percentstr[32]; - snprintf(percentstr, 32, "%5.1f%%", percent); - - std::cout << timestr << " (" << percentstr << ") "; - std::cout << nodename; - std::cout << std::endl; - } + // Loop over factories + std::cout << "Factories:" << std::endl; + std::vector> factory_stats_vector{ + std::make_move_iterator(std::begin(factory_stats)), + std::make_move_iterator(std::end(factory_stats))}; + auto factory_stats_compare = [](const auto& a, const auto& b) { + return ((a.second.time_waited_on - a.second.time_waiting) < + (b.second.time_waited_on - b.second.time_waiting)); }; - - private: - - std::mutex mutex; - - std::map call_links; - std::map factory_stats; - - std::string MakeTimeString(double time_in_ms) { - double order = log10(time_in_ms); - std::stringstream ss; - ss << std::fixed << std::setprecision(2); - if (order < 0) { - ss << time_in_ms*1000.0 << " us"; - } else if (order <= 2.0) { - ss << time_in_ms << " ms"; - } else { - ss << time_in_ms / 1000.0 << " s"; - } - return ss.str(); + std::sort(factory_stats_vector.begin(), factory_stats_vector.end(), factory_stats_compare); + for (auto iter = factory_stats_vector.end() - std::min(factory_stats_vector.size(), 10ul); + iter != factory_stats_vector.end(); iter++) { + FactoryCallStats& fcall_stats = iter->second; + std::string nodename = iter->first; + + // Get time spent in this factory proper + double time_spent_in_factory = fcall_stats.time_waited_on - fcall_stats.time_waiting; + std::string timestr = MakeTimeString(time_spent_in_factory); + double percent = 100.0 * time_spent_in_factory / total_ms; + char percentstr[32]; + snprintf(percentstr, 32, "%5.1f%%", percent); + + std::cout << timestr << " (" << percentstr << ") "; + std::cout << nodename; + std::cout << std::endl; } - - std::string MakeNametag(const std::string &name, const std::string &tag) { - std::string nametag = name; - if (tag.size() > 0) nametag += ":" + tag; - return nametag; + }; + +private: + std::mutex mutex; + + std::map call_links; + std::map factory_stats; + + std::string MakeTimeString(double time_in_ms) { + double order = log10(time_in_ms); + std::stringstream ss; + ss << std::fixed << std::setprecision(2); + if (order < 0) { + ss << time_in_ms * 1000.0 << " us"; + } else if (order <= 2.0) { + ss << time_in_ms << " ms"; + } else { + ss << time_in_ms / 1000.0 << " s"; } + return ss.str(); + } + + std::string MakeNametag(const std::string& name, const std::string& tag) { + std::string nametag = name; + if (tag.size() > 0) + nametag += ":" + tag; + return nametag; + } }; diff --git a/src/utilities/janatop/janatop.cc b/src/utilities/janatop/janatop.cc index c2d07ed9be..191af39310 100644 --- a/src/utilities/janatop/janatop.cc +++ b/src/utilities/janatop/janatop.cc @@ -10,9 +10,9 @@ #include "JEventProcessorJANATOP.h" extern "C" { - void InitPlugin(JApplication *app) { - InitJANAPlugin(app); - app->Add(new JEventProcessorJANATOP()); - app->GetJParameterManager()->SetParameter("RECORD_CALL_STACK", true); - } +void InitPlugin(JApplication* app) { + InitJANAPlugin(app); + app->Add(new JEventProcessorJANATOP()); + app->GetJParameterManager()->SetParameter("RECORD_CALL_STACK", true); +} }