diff --git a/Tracking/Acts/ActsConfig/python/ActsAnalysisConfig.py b/Tracking/Acts/ActsConfig/python/ActsAnalysisConfig.py index bf81afdfab92224d1b80d2af506e3a893dee37bc..90aa6e1b3430d962e63bb56c437fd71822bbb8f6 100644 --- a/Tracking/Acts/ActsConfig/python/ActsAnalysisConfig.py +++ b/Tracking/Acts/ActsConfig/python/ActsAnalysisConfig.py @@ -38,7 +38,67 @@ def ActsTrackAnalysisAlgCfg(flags, acc.merge(helper.result()) return acc - + +def ActsTrackParticleAnalysisAlgCfg(flags, + name: str = 'ActsTrackParticleAnalysisAlg', + **kwargs) -> ComponentAccumulator: + acc = ComponentAccumulator() + kwargs.setdefault('MonitorTrackStateCounts',True) + kwargs.setdefault('TrackParticleLocation', 'ActsTrackParticles') + + kwargs.setdefault('MonGroupName', kwargs['TrackParticleLocation']) + + from AthenaMonitoring import AthMonitorCfgHelper + helper = AthMonitorCfgHelper(flags, 'TrackParticleAnalysisAlgCfg') + monitoringAlgorithm = helper.addAlgorithm(CompFactory.ActsTrk.TrackParticleAnalysisAlg, name, **kwargs) + monitoringGroup = helper.addGroup(monitoringAlgorithm, kwargs['MonGroupName'], '/'+name+'/') + + monitoringGroup.defineHistogram('pt', title='TrackParticle pt;pt (MeV);Entries', type='TH1F', path=kwargs['MonGroupName'], + xbins=100, xmin=0, xmax=10e3) + monitoringGroup.defineHistogram('eta', title='TrackParticle eta;eta;Entries', type='TH1F', path=kwargs['MonGroupName'], + xbins=50, xmin=-4, xmax=4) + + # hit counts + monitoringGroup.defineHistogram('pixelHits', title='Number of pixel hits;N;Entries', type='TH1I', path=kwargs['MonGroupName'], + xbins=50, xmin=-1, xmax=49) + monitoringGroup.defineHistogram('innermostHits', title='Number of innermost pixel hits;N;Entries', type='TH1I', path=kwargs['MonGroupName'], + xbins=6, xmin=-1, xmax=5) + monitoringGroup.defineHistogram('nextToInnermostHits', title='Number of next-to-innermost pixel hits;N;Entries', type='TH1I', + path=kwargs['MonGroupName'], xbins=6, xmin=-1, xmax=5) + monitoringGroup.defineHistogram('expectInnermostHit', title='Innermost pixel hit expected;N;Entries', type='TH1I', path=kwargs['MonGroupName'], + xbins=3, xmin=-1, xmax=2) + monitoringGroup.defineHistogram('expectNextToInnermostHit', title='Next-to-innermost pixel hit expected;N;Entries', type='TH1I', + path=kwargs['MonGroupName'],xbins=3, xmin=-1, xmax=2) + + if kwargs['MonitorTrackStateCounts'] : + # have to add artifical dependency, because the ActsTracks are created by + # a special reader algorithm from the various component branches, but the + # element links pointing to the ActsTracks would not add this dependency + # by themselves. + if 'ExtraInputs' not in kwargs : + tracks_name = kwargs['TrackParticleLocation'] + if tracks_name[-len('TrackParticles'):] == 'TrackParticles' : + kwargs.setdefault('ExtraInputs',{('ActsTrk::TrackContainer',tracks_name[:-len('TrackParticles')]+'Tracks')}) + + monitoringGroup.defineHistogram('States', title='Number of states on track;N;Entries', type='TH1I', path=kwargs['MonGroupName'], + xbins=50, xmin=0, xmax=50) + monitoringGroup.defineHistogram('Measurements', title='Number of measurements on track;N;Entries', type='TH1I', path=kwargs['MonGroupName'], + xbins=50, xmin=0, xmax=50) + monitoringGroup.defineHistogram('Parameters', title='Number of parameters on track;N;Entries', type='TH1I', path=kwargs['MonGroupName'], + xbins=50, xmin=0, xmax=50) + monitoringGroup.defineHistogram('Outliers', title='Number of outliers on track;N;Entries', type='TH1I', path=kwargs['MonGroupName'], + xbins=50, xmin=0, xmax=50) + monitoringGroup.defineHistogram('Holes', title='Number of holes on track;N;Entries', type='TH1I', path=kwargs['MonGroupName'], + xbins=50, xmin=0, xmax=50) + monitoringGroup.defineHistogram('SharedHits', title='Number of shared hits on track;N;Entries', type='TH1I', path=kwargs['MonGroupName'], + xbins=50, xmin=0, xmax=50) + monitoringGroup.defineHistogram('MaterialStates', title='Number of material states on track;N;Entries', type='TH1I', path=kwargs['MonGroupName'], + xbins=50, xmin=0, xmax=50) + acc.merge(helper.result()) + + acc.addEventAlgo( CompFactory.ActsTrk.TrackParticleAnalysisAlg(name, **kwargs) ) + return acc + def ActsHgtdClusterAnalysisAlgCfg(flags, name: str = "ActsHgtdClusterAnalysisAlg", **kwargs) -> ComponentAccumulator: diff --git a/Tracking/Acts/ActsConfig/python/ActsPostIncludes.py b/Tracking/Acts/ActsConfig/python/ActsPostIncludes.py index 7fd116b7637358f1410cbec7b3d3cdd2cb2963de..af252cab5230da46d8c3ac770dea5e5097c579c9 100644 --- a/Tracking/Acts/ActsConfig/python/ActsPostIncludes.py +++ b/Tracking/Acts/ActsConfig/python/ActsPostIncludes.py @@ -73,7 +73,15 @@ def PersistifyActsEDMCfg(flags) -> ComponentAccumulator: f"xAOD::TrackSurfaceAuxContainer#{prefix}TrackStateSurfacesAux.", f"xAOD::TrackSurfaceContainer#{prefix}TrackSurfaces", f"xAOD::TrackSurfaceAuxContainer#{prefix}TrackSurfacesAux."] - + + # add track particles created by the Acts TrackToTrackParticleCnvAlg to the AOD + trackCnvPrefixes = ["ActsCombined"] + tracksSuffix = "Tracks" + exclude="." if flags.Acts.EDM.PersistifyTracks else ".-actsTrack" + for prefix in trackCnvPrefixes: + toAOD += [f"xAOD::TrackParticleContainer#{prefix}{tracksSuffix}ParticlesAlt", + f"xAOD::TrackParticleAuxContainer#{prefix}{tracksSuffix}ParticlesAltAux{exclude}"] + # If there is nothing to persistify, returns an empty CA if len(toAOD) == 0: return acc diff --git a/Tracking/Acts/ActsConfig/test/ActsPersistifyEDM.sh b/Tracking/Acts/ActsConfig/test/ActsPersistifyEDM.sh index 33490ece148469781b8dc948f6b50f9bb151bf97..616565011ef05defcddcf5c881c06b6d2f659ffa 100755 --- a/Tracking/Acts/ActsConfig/test/ActsPersistifyEDM.sh +++ b/Tracking/Acts/ActsConfig/test/ActsPersistifyEDM.sh @@ -29,7 +29,9 @@ ActsReadEDM.py \ readClusters=True \ readSpacePoints=True \ readTracks=True \ - tracks="ActsTracks" + tracks="ActsTracks" \ + readTrackParticles=True \ + trackParticles="ActsCombinedTracksParticlesAlt" rc=$? if [ $rc != 0 ]; then diff --git a/Tracking/Acts/ActsEvent/ActsEvent/ActsEventDict.h b/Tracking/Acts/ActsEvent/ActsEvent/ActsEventDict.h index 7e86de6d16fe98d6c3bfc46be643c69afce3a868..83a53ff54c5f5041ff7946110f6ef7aa813da14e 100644 --- a/Tracking/Acts/ActsEvent/ActsEvent/ActsEventDict.h +++ b/Tracking/Acts/ActsEvent/ActsEvent/ActsEventDict.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration */ #ifndef ACTSEVENT_DICT_H @@ -33,5 +33,13 @@ namespace { }; } +#include "ActsEvent/TrackContainer.h" +namespace { + struct GCCXML_DUMMY_ELACTSTRK_TRACKCONTAINER { + ActsTrk::TrackContainer m_dest; + ElementLink<ActsTrk::TrackContainer> m_linkToDest; + std::vector<ElementLink<ActsTrk::TrackContainer> > m_two; + }; +} #endif diff --git a/Tracking/Acts/ActsEvent/ActsEvent/TrackContainer.h b/Tracking/Acts/ActsEvent/ActsEvent/TrackContainer.h index eca05dc3d51a6a51102b477f1ca76121f3b3773b..777ee27b803a37f5765626eda6d203a466af8429 100644 --- a/Tracking/Acts/ActsEvent/ActsEvent/TrackContainer.h +++ b/Tracking/Acts/ActsEvent/ActsEvent/TrackContainer.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration */ #ifndef ACTSTRKEVENT_TRACKCONTAINER_H @@ -23,9 +23,95 @@ struct DataLinkHolder { const T* operator->() const { return m_link.cptr(); } }; -using TrackContainer = - Acts::TrackContainer<ActsTrk::TrackBackend, ActsTrk::TrackStateBackend, - ActsTrk::DataLinkHolder>; +using TrackContainerBase = Acts::TrackContainer<ActsTrk::TrackBackend, ActsTrk::TrackStateBackend, + ActsTrk::DataLinkHolder>; + +class TrackContainer : + public TrackContainerBase +{ +public: + using TrackContainerBase::TrackContainerBase; + using value_type = ConstTrackProxy; + ConstTrackProxy operator[](unsigned int index) const { + return getTrack(index); + } + + // Special indexing policy which will dereference element links + // into an std::optional rather than a pointer or reference to an + // existing element in the destination collection. This is + // needed because the Acts track container does have physical + // representations of tracks, but only creats proxy objects + // for tracks which are created on demand. + class IndexingPolicy + { + public: + /// The type we get when we dereference a link, and derived types. + using ElementType = std::optional<ConstTrackProxy>; + struct ConstTrackProxyPtr { + ConstTrackProxyPtr(const ElementType *src) { + if (src) { + m_proxy = *src; + } + } + ConstTrackProxyPtr(const ConstTrackProxyPtr &) = default; + ConstTrackProxyPtr(ConstTrackProxyPtr &&) = default; + ConstTrackProxyPtr(const ConstTrackProxy &val) :m_proxy(val) {} + ConstTrackProxyPtr(ConstTrackProxy &&val) : m_proxy(std::move(val)) {} + + ConstTrackProxy operator*() const { + return m_proxy.value(); + } + const ConstTrackProxy *operator->() const { + return &m_proxy.value(); + } + bool operator!() const { + return !m_proxy.has_value(); + } + ConstTrackProxyPtr &operator=(const ElementType *src) { + if (src) { + m_proxy = *src; + } + else { + m_proxy.reset(); + } + return *this; + } + + std::optional<ConstTrackProxy> m_proxy; + }; + using ElementConstReference = std::optional<ConstTrackProxy>; + using ElementConstPointer = ConstTrackProxyPtr; + + /// The type of an index, as provided to or returned from a link. + using index_type = TrackContainerBase::IndexType; + + /// The type of an index, as stored internally within a link. + using stored_index_type = index_type; + + static bool isValid (const stored_index_type& index) { + return index != ConstTrackProxy::kInvalid; + } + + static index_type storedToExternal (stored_index_type index) { + return index; + } + static void reset (stored_index_type& index) { + index=ConstTrackProxy::kInvalid; + } + static + ElementType lookup(const stored_index_type& index, const TrackContainerBase& container) { + return container.getTrack(index); + } + + static void + reverseLookup([[maybe_unused]] const TrackContainerBase& container, + ElementConstReference element, + index_type& index) { + index= element.has_value() ? element.value().index() : ConstTrackProxy::kInvalid; + } + }; + +}; struct MutableTrackContainer : public Acts::TrackContainer<ActsTrk::MutableTrackBackend, @@ -40,6 +126,14 @@ struct MutableTrackContainer } // namespace ActsTrk +// register special indexing policy for element links to Acts tracks i.e. +// ElementLink<ActsTrk::TrackContainer> +template <> +struct DefaultIndexingPolicy <ActsTrk::TrackContainer > { + using type = ActsTrk::TrackContainer::IndexingPolicy; +}; + + #include "AthenaKernel/CLASS_DEF.h" CLASS_DEF(ActsTrk::TrackContainer, 1210898253, 1) #endif diff --git a/Tracking/Acts/ActsEvent/ActsEvent/selection.xml b/Tracking/Acts/ActsEvent/ActsEvent/selection.xml index eac0a17091ee32fa5fa1f147061737f87512c2ae..609610e20b6a9014b00665ca99327d36abb1e3cd 100644 --- a/Tracking/Acts/ActsEvent/ActsEvent/selection.xml +++ b/Tracking/Acts/ActsEvent/ActsEvent/selection.xml @@ -1,4 +1,4 @@ -<!-- Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration --> +<!-- Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration --> <lcgdict> <class name="Seed" /> @@ -9,5 +9,17 @@ <class name="BoundTrackParametersContainer" id="07B10B02-CEF7-4FF9-91D5-569F506C46AE" /> + <class name="SG::GenericElementLinkBase<ActsTrk::TrackContainer::IndexingPolicy>" /> + <class name="ElementLink<ActsTrk::TrackContainer>" /> + <read sourceClass="ElementLink<ActsTrk::TrackContainer>" version="[1-]" + targetClass="ElementLink<ActsTrk::TrackContainer>" source="" + target="" > + <![CDATA[ + // Let the object prepare for being used: + if (newObj) newObj->toTransient(); + ]]> + </read> + + <class name="std::vector<ElementLink<ActsTrk::TrackContainer> >" /> </lcgdict> diff --git a/Tracking/Acts/ActsMonitoring/src/TrackParticleAnalysisAlg.cxx b/Tracking/Acts/ActsMonitoring/src/TrackParticleAnalysisAlg.cxx new file mode 100644 index 0000000000000000000000000000000000000000..22d8c1f1c3b136021c7da2a5f2aa912fa01b3800 --- /dev/null +++ b/Tracking/Acts/ActsMonitoring/src/TrackParticleAnalysisAlg.cxx @@ -0,0 +1,130 @@ +/* + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration +*/ + +#include "TrackParticleAnalysisAlg.h" +#include "ActsEvent/TrackContainer.h" +#include "SGTools/CurrentEventStore.h" +#include <iostream> +#include <sstream> +#include <iomanip> + +namespace { + int getSummaryValue(const xAOD::TrackParticle &track_particle, xAOD::SummaryType summary_type) { + uint8_t tmp; + return track_particle.summaryValue(tmp, summary_type) ? static_cast<int>(tmp) : -1; + } +} + + +namespace ActsTrk { + + TrackParticleAnalysisAlg::TrackParticleAnalysisAlg(const std::string& name, ISvcLocator* pSvcLocator) + : AthMonitorAlgorithm(name, pSvcLocator) + {} + + StatusCode TrackParticleAnalysisAlg::initialize() { + ATH_MSG_DEBUG("Initializing " << name() << " ..."); + + ATH_MSG_VERBOSE("Properties:"); + ATH_MSG_VERBOSE(m_tracksKey); + + ATH_CHECK(m_tracksKey.initialize()); + + ATH_MSG_VERBOSE("Monitoring settings ..."); + ATH_MSG_VERBOSE(m_monGroupName); + + return AthMonitorAlgorithm::initialize(); + } + + StatusCode TrackParticleAnalysisAlg::fillHistograms(const EventContext& ctx) const { + ATH_MSG_DEBUG( "Filling Histograms for " << name() << " ... " ); + + // Retrieve the tracks + SG::ReadHandle<xAOD::TrackParticleContainer> trackParticleskHandle = SG::makeHandle(m_tracksKey, ctx); + ATH_CHECK(trackParticleskHandle.isValid()); + const xAOD::TrackParticleContainer *track_particles = trackParticleskHandle.cptr(); + + if (m_monitorTrackStateCounts) { + for (const xAOD::TrackParticle *track_particle : *track_particles) { + monitorTrackStateCounts(*track_particle); + } + } + auto monitor_pt = Monitored::Collection("pt", *track_particles, + [](const xAOD::TrackParticle *tp){return static_cast<double>(tp->pt()); } ); + auto monitor_eta = Monitored::Collection("eta", *track_particles, + [](const xAOD::TrackParticle *tp){return static_cast<double>(tp->eta()); } ); + + auto monitor_pixelHits = Monitored::Collection("pixelHits", *track_particles, + [](const xAOD::TrackParticle *tp){ + return getSummaryValue(*tp,xAOD::numberOfPixelHits); }); + + auto monitor_innermostHits = Monitored::Collection("innermostHits", *track_particles, + [](const xAOD::TrackParticle *tp){ + return getSummaryValue(*tp,xAOD::numberOfInnermostPixelLayerHits); }); + + auto monitor_nextToInnermostHits = Monitored::Collection("nextToInnermostHits", *track_particles, + [](const xAOD::TrackParticle *tp){ + return getSummaryValue(*tp,xAOD::numberOfNextToInnermostPixelLayerHits);}); + + auto monitor_expectInnermost = Monitored::Collection("expectInnermostHit", *track_particles, + [](const xAOD::TrackParticle *tp){ + return getSummaryValue(*tp,xAOD::expectInnermostPixelLayerHit); }); + + auto monitor_expectNextToInnermost = Monitored::Collection("expectNextToInnermostHit", *track_particles, + [](const xAOD::TrackParticle *tp){ + return getSummaryValue(*tp,xAOD::expectNextToInnermostPixelLayerHit); }); + + fill(m_monGroupName.value(),monitor_pt,monitor_eta, monitor_pixelHits, monitor_innermostHits, monitor_nextToInnermostHits, + monitor_expectInnermost, monitor_expectNextToInnermost); + return StatusCode::SUCCESS; + } + + void TrackParticleAnalysisAlg::monitorTrackStateCounts(const xAOD::TrackParticle &track_particle) const { + static const SG::AuxElement::ConstAccessor<ElementLink<ActsTrk::TrackContainer> > actsTrackLink("actsTrack"); + + ElementLink<ActsTrk::TrackContainer> link_to_track = actsTrackLink(track_particle); + // to ensure that the code does not suggest something stupid (i.e. creating an unnecessary copy) + static_assert( std::is_same<ElementLink<ActsTrk::TrackContainer>::ElementConstReference, + std::optional<ActsTrk::TrackContainer::ConstTrackProxy> >::value); + std::optional<ActsTrk::TrackContainer::ConstTrackProxy> optional_track = *link_to_track; + if (optional_track.has_value()) { + ActsTrk::TrackContainer::ConstTrackProxy track = optional_track.value(); + std::array<uint8_t, Acts::NumTrackStateFlags+1> counts{}; + + const ActsTrk::TrackContainer::ConstTrackProxy::IndexType + lastMeasurementIndex = track.tipIndex(); + + track.container().trackStateContainer().visitBackwards( + lastMeasurementIndex, + [&counts + ](const typename ActsTrk::TrackStateBackend::ConstTrackStateProxy &state) -> void + { + Acts::ConstTrackStateType flag = state.typeFlags(); + ++counts[Acts::NumTrackStateFlags]; + for (unsigned int flag_i=0; flag_i<Acts::NumTrackStateFlags; ++flag_i) { + if (flag.test(flag_i)) { + if (flag_i == Acts::TrackStateFlag::HoleFlag) { + if (!state.hasReferenceSurface() || !state.referenceSurface().associatedDetectorElement()) continue; + } + ++counts[flag_i]; + } + } + }); + auto monitor_states = Monitored::Scalar<int>("States",counts[Acts::TrackStateFlag::NumTrackStateFlags]); + auto monitor_measurement = Monitored::Scalar<int>("Measurements",counts[Acts::TrackStateFlag::MeasurementFlag]); + auto monitor_parameter = Monitored::Scalar<int>("Parameters",counts[Acts::TrackStateFlag::ParameterFlag]); + auto monitor_outlier = Monitored::Scalar<int>("Outliers",counts[Acts::TrackStateFlag::OutlierFlag]); + auto monitor_hole = Monitored::Scalar<int>("Holes",counts[Acts::TrackStateFlag::HoleFlag]); + auto monitor_material = Monitored::Scalar<int>("MaterialStates",counts[Acts::TrackStateFlag::MaterialFlag]); + auto monitor_sharedHit = Monitored::Scalar<int>("SharedHits",counts[Acts::TrackStateFlag::SharedHitFlag]); + fill(m_monGroupName.value(), monitor_states, monitor_measurement, monitor_parameter, monitor_outlier, monitor_hole, + monitor_material, monitor_sharedHit); + } + else { + ATH_MSG_WARNING("Invalid track link for particle " << track_particle.index()); + } + } + + +} diff --git a/Tracking/Acts/ActsMonitoring/src/TrackParticleAnalysisAlg.h b/Tracking/Acts/ActsMonitoring/src/TrackParticleAnalysisAlg.h new file mode 100644 index 0000000000000000000000000000000000000000..f7e2c6b448fcfbc9318b7db7e9b8f84dcba836d5 --- /dev/null +++ b/Tracking/Acts/ActsMonitoring/src/TrackParticleAnalysisAlg.h @@ -0,0 +1,37 @@ +/* + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef ACTSTRKANALYSIS_TRACKPARTICLEANALYSISALG_H +#define ACTSTRKANALYSIS_TRACKPARTICLEANALYSISALG_H + +#include "AthenaMonitoring/AthMonitorAlgorithm.h" +#include "xAODTracking/TrackParticleContainer.h" +#include "StoreGate/ReadHandleKey.h" + +namespace ActsTrk { + + class TrackParticleAnalysisAlg final : + public AthMonitorAlgorithm { + public: + TrackParticleAnalysisAlg(const std::string& name, ISvcLocator* pSvcLocator); + virtual ~TrackParticleAnalysisAlg() override = default; + + virtual StatusCode initialize() override; + virtual StatusCode fillHistograms(const EventContext& ctx) const override; + + private: + void monitorTrackStateCounts(const xAOD::TrackParticle &track_particle) const; + + SG::ReadHandleKey<xAOD::TrackParticleContainer> m_tracksKey {this, "TrackParticleLocation", "", + "Input track particle collection"}; + Gaudi::Property< std::string > m_monGroupName + {this, "MonGroupName", "TrackParticleAnalysisAlg"}; + + Gaudi::Property< bool > m_monitorTrackStateCounts + {this, "MonitorTrackStateCounts", true}; + }; + +} + +#endif diff --git a/Tracking/Acts/ActsMonitoring/src/components/ActsMonitoring_entries.cxx b/Tracking/Acts/ActsMonitoring/src/components/ActsMonitoring_entries.cxx index e427cc6d925a07cf94bf6c410cc2cc5cbac3381a..65301e256f785cdb5ed2d673a51310295ff6e267 100644 --- a/Tracking/Acts/ActsMonitoring/src/components/ActsMonitoring_entries.cxx +++ b/Tracking/Acts/ActsMonitoring/src/components/ActsMonitoring_entries.cxx @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration */ // Algs @@ -11,6 +11,7 @@ #include "src/EstimatedTrackParamsAnalysisAlg.h" #include "src/SeedingAlgorithmAnalysisAlg.h" #include "src/TrackAnalysisAlg.h" +#include "src/TrackParticleAnalysisAlg.h" // Tools #include "src/PhysValTool.h" @@ -23,5 +24,6 @@ DECLARE_COMPONENT( ActsTrk::SeedAnalysisAlg ) DECLARE_COMPONENT( ActsTrk::SeedingAlgorithmAnalysisAlg ) DECLARE_COMPONENT( ActsTrk::EstimatedTrackParamsAnalysisAlg ) DECLARE_COMPONENT( ActsTrk::TrackAnalysisAlg ) +DECLARE_COMPONENT( ActsTrk::TrackParticleAnalysisAlg ) // Tools DECLARE_COMPONENT( ActsTrk::PhysValTool ) diff --git a/Tracking/Acts/ActsMonitoring/test/ActsReadEDM.py b/Tracking/Acts/ActsMonitoring/test/ActsReadEDM.py index 4a69de9e65c48dc634caff6059e31c8e807d25a6..0fd14a704345d083cc28f0bc847ed19f76738dee 100755 --- a/Tracking/Acts/ActsMonitoring/test/ActsReadEDM.py +++ b/Tracking/Acts/ActsMonitoring/test/ActsReadEDM.py @@ -3,6 +3,7 @@ # Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration if __name__ == "__main__": + import re from AthenaConfiguration.AllConfigFlags import initConfigFlags flags = initConfigFlags() @@ -20,6 +21,8 @@ if __name__ == "__main__": flags.addFlag("readSpacePoints", False) flags.addFlag("readTracks", False) flags.addFlag("tracks", "") + flags.addFlag("readTrackParticles", False) + flags.addFlag("trackParticles", "ActsCombinedTracksParticlesAlt") flags.fillFromArgs() flags.lock() @@ -58,6 +61,16 @@ if __name__ == "__main__": name=f"{track}AnalysisAlg", OutputLevel=2, TracksLocation=track)) + if flags.readTrackParticles: + from ActsConfig.ActsAnalysisConfig import ActsTrackParticleAnalysisAlgCfg + for tp in flags.trackParticles.split(','): + src_track_name = re.search(r'^(.*)ParticlesAlt.*',tp).group(1) + acc.merge(ActsTrackParticleAnalysisAlgCfg(flags, + name=f"{tp}AnalysisAlg", + OutputLevel=2, + TrackParticleLocation=tp, + ExtraInputs={('ActsTrk::TrackContainer',src_track_name)}, # ensure scheduled after reader + MonGroupName=f"{tp}Analysis")) acc.printConfig() status = acc.run() diff --git a/Tracking/Acts/ActsTrackReconstruction/src/TrackToTrackParticleCnvAlg.cxx b/Tracking/Acts/ActsTrackReconstruction/src/TrackToTrackParticleCnvAlg.cxx index 1ec188aa0c2522b60c758d28507e089d676ad64e..4cbcc2099e1e31888c4867cba08b3d01511935c6 100644 --- a/Tracking/Acts/ActsTrackReconstruction/src/TrackToTrackParticleCnvAlg.cxx +++ b/Tracking/Acts/ActsTrackReconstruction/src/TrackToTrackParticleCnvAlg.cxx @@ -11,6 +11,7 @@ #include "Acts/Propagator/detail/JacobianEngine.hpp" #include "ActsInterop/Logger.h" +#include "AthContainers/Decorator.h" #include "xAODTracking/TrackParticleAuxContainer.h" #include "MagFieldElements/AtlasFieldCache.h" #include "InDetReadoutGeometry/SiDetectorElement.h" @@ -232,6 +233,8 @@ namespace ActsTrk HitSummaryData hitInfo; unsigned int converted_track_states=0; + + static const SG::AuxElement::Decorator<ElementLink<ActsTrk::TrackContainer> > trackLink("actsTrack"); using namespace Acts::UnitLiterals; for (const typename ActsTrk::TrackContainer::ConstTrackProxy &track : *tracksContainer) { @@ -473,7 +476,13 @@ namespace ActsTrk ATH_MSG_ERROR("Invalid size of param element " << param.size() << " != 6" ); } } + track_particle->setTrackParameters(parametersVec); + + // add element to link to the correspond track + trackLink(*track_particle) + = ElementLink<ActsTrk::TrackContainer>( tracksContainer, + track.index() ); } ATH_MSG_DEBUG( "Converted " << tracksContainer->size() << " acts tracks into " << track_particles->size() << " track particles with parameters for " << converted_track_states << " track states.");