ATLAS Offline Software
ActsToTrkConvertorAlg.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
6 
8 #include "Acts/Surfaces/Surface.hpp"
9 #include "Acts/Surfaces/PerigeeSurface.hpp"
19 
20 // get Athena SiDetectorElement from Acts surface
21 static const InDetDD::SiDetectorElement *actsToDetElem(const Acts::Surface &surface)
22 {
23  const auto *actsElement = dynamic_cast<const ActsDetectorElement *>(surface.associatedDetectorElement());
24  if (!actsElement)
25  {
26  return nullptr;
27  }
28  return dynamic_cast<const InDetDD::SiDetectorElement *>(actsElement->upstreamDetectorElement());
29 }
30 
31 namespace ActsTrk
32 {
33 
35  ISvcLocator *pSvcLocator)
36  : AthReentrantAlgorithm(name, pSvcLocator)
37  {
38  }
39 
41  {
42  ATH_MSG_DEBUG("Initializing " << name() << " ...");
43 
45  ATH_CHECK(m_tracksKey.initialize());
46 
48  ATH_CHECK(m_ATLASConverterTool.retrieve());
49  ATH_CHECK(m_trkSummaryTool.retrieve());
50 
51  if (not m_RotCreatorTool.empty())
52  {
53  ATH_MSG_DEBUG("RotCreatorTool will be used");
54  ATH_CHECK(m_RotCreatorTool.retrieve());
55  }
56 
57  return StatusCode::SUCCESS;
58  }
59 
60  StatusCode ActsToTrkConvertorAlg::execute(const EventContext &ctx) const
61  {
62  ATH_MSG_DEBUG("Executing " << name() << " ...");
63 
64  // I/O
65  ATH_MSG_DEBUG("Retrieving input track collection '" << m_tracksContainerKey.key() << "' ...");
67  ATH_CHECK(inputTracksHandle.isValid());
68  const ActsTrk::TrackContainer *inputTracks = inputTracksHandle.cptr();
69 
70  std::unique_ptr<::TrackCollection> trackCollection = std::make_unique<::TrackCollection>();
71 
72  Acts::GeometryContext tgContext = m_trackingGeometryTool->getGeometryContext(ctx).context();
73  ATH_CHECK(makeTracks(ctx, tgContext, *inputTracks, *trackCollection));
74 
76  ATH_MSG_DEBUG("Output Tracks Collection `" << m_tracksKey.key() << "` created ...");
77  ATH_CHECK(outputTrackHandle.record(std::move(trackCollection)));
78 
79  return StatusCode::SUCCESS;
80  }
81 
83  const Acts::GeometryContext &tgContext,
84  const ActsTrk::TrackContainer &tracks,
85  ::TrackCollection &tracksContainer) const
86  {
87 
88  for (const typename ActsTrk::TrackContainer::ConstTrackProxy track : tracks)
89  {
90  const auto lastMeasurementIndex = track.tipIndex();
91  auto finalTrajectory = std::make_unique<Trk::TrackStates>();
92  // initialise the number of dead Pixel and Acts strip
93  int numberOfDeadPixel = 0;
94  int numberOfDeadSCT = 0;
95 
96  Acts::ParticleHypothesis hypothesis = track.particleHypothesis();
97 
98  std::vector<std::unique_ptr<const Acts::BoundTrackParameters>> actsSmoothedParam;
99  tracks.trackStateContainer().visitBackwards(
100  lastMeasurementIndex,
101  [this, &tgContext, &track, &finalTrajectory, &actsSmoothedParam, &numberOfDeadPixel, &numberOfDeadSCT](const typename ActsTrk::TrackStateBackend::ConstTrackStateProxy &state) -> void
102  {
103  // First only consider states with an associated detector element
104  if (!state.hasReferenceSurface() || !state.referenceSurface().associatedDetectorElement())
105  {
106  return;
107  }
108 
109  auto flag = state.typeFlags();
110  std::bitset<Trk::TrackStateOnSurface::NumberOfTrackStateOnSurfaceTypes> typePattern;
111  std::unique_ptr<Trk::TrackParameters> parm;
112 
113  // State is a hole (no associated measurement), use predicted parameters
114  if (flag.test(Acts::TrackStateFlag::HoleFlag))
115  {
116  const Acts::BoundTrackParameters actsParam = track.createParametersFromState(state);
117  parm = m_ATLASConverterTool->actsTrackParametersToTrkParameters(actsParam, tgContext);
118  auto boundaryCheck = m_boundaryCheckTool->boundaryCheck(*parm);
119 
120  // Check if this is a hole, a dead sensors or a state outside the sensor boundary
121  if (boundaryCheck == Trk::BoundaryCheckResult::DeadElement)
122  {
123  auto *detElem = actsToDetElem(state.referenceSurface());
124  if (!detElem)
125  {
126  return;
127  }
128  if (detElem->isPixel())
129  {
130  ++numberOfDeadPixel;
131  }
132  else if (detElem->isSCT())
133  {
134  ++numberOfDeadSCT;
135  }
136  // Dead sensors states are not stored
137  return;
138  }
139  else if (boundaryCheck != Trk::BoundaryCheckResult::Candidate)
140  {
141  return;
142  }
143  typePattern.set(Trk::TrackStateOnSurface::Hole);
144  }
145  // The state was tagged as an outlier or (TODO!) was missed in the reverse filtering, use filtered parameters
146  else if (flag.test(Acts::TrackStateFlag::OutlierFlag))
147  {
148  const Acts::BoundTrackParameters actsParam = track.createParametersFromState(state);
149  parm = m_ATLASConverterTool->actsTrackParametersToTrkParameters(actsParam, tgContext);
150  typePattern.set(Trk::TrackStateOnSurface::Outlier);
151  }
152  // The state is a measurement state, use smoothed parameters
153  else
154  {
155  const Acts::BoundTrackParameters actsParam = track.createParametersFromState(state);
156 
157  // is it really necessary to keep our own copy of all the smoothed parameters?
158  actsSmoothedParam.push_back(std::make_unique<const Acts::BoundTrackParameters>(Acts::BoundTrackParameters(actsParam)));
159  parm = m_ATLASConverterTool->actsTrackParametersToTrkParameters(actsParam, tgContext);
160  typePattern.set(Trk::TrackStateOnSurface::Measurement);
161  }
162 
163  std::unique_ptr<Trk::MeasurementBase> measState;
164  if (state.hasUncalibratedSourceLink())
165  {
166  try {
167  auto sl = state.getUncalibratedSourceLink().template get<ATLASUncalibSourceLink>();
168  assert( sl != nullptr);
169  const xAOD::UncalibratedMeasurement &uncalibMeas = getUncalibratedMeasurement(sl);
170  measState = makeRIO_OnTrack(uncalibMeas, *parm);
171  ATH_MSG_DEBUG("Successfully used ATLASUncalibratedSourceLink");
172  } catch ( const std::bad_any_cast& ){
173  ATH_MSG_DEBUG("Not an ATLASUncalibSourceLink, trying ATLASSourceLink");
174  auto sl = state.getUncalibratedSourceLink().template get<ATLASSourceLink>();
175  assert( sl != nullptr );
176  measState.reset(sl->clone());
177  ATH_MSG_DEBUG("Successfully used ATLASSourceLink");
178 
179  }
180  }
181 
182  double nDoF = state.calibratedSize();
183  auto quality = Trk::FitQualityOnSurface(state.chi2(), nDoF);
184  auto perState = new Trk::TrackStateOnSurface(quality,
185  std::move(measState),
186  std::move(parm),
187  nullptr,
188  typePattern);
189 
190  // If a state was succesfully created add it to the trajectory
191  finalTrajectory->insert(finalTrajectory->begin(), perState);
192  });
193 
194  // Convert the perigee state and add it to the trajectory
195  const Acts::BoundTrackParameters actsPer(track.referenceSurface().getSharedPtr(),
196  track.parameters(),
197  track.covariance(),
198  hypothesis);
199 
200  std::unique_ptr<Trk::TrackParameters> per = m_ATLASConverterTool->actsTrackParametersToTrkParameters(actsPer, tgContext);
201  std::bitset<Trk::TrackStateOnSurface::NumberOfTrackStateOnSurfaceTypes> typePattern;
202  typePattern.set(Trk::TrackStateOnSurface::Perigee);
203  auto perState = new Trk::TrackStateOnSurface(nullptr,
204  std::move(per),
205  nullptr,
206  typePattern);
207  finalTrajectory->insert(finalTrajectory->begin(), perState);
208 
209  // Create the track using Athena TrackFitter::KalmanFitter and TrackPatternRecoInfo::SiSPSeededFinder algorithm enums
211  newInfo.setPatternRecognitionInfo(Trk::TrackInfo::TrackPatternRecoInfo::SiSPSeededFinder);
212 
213  auto newtrack = std::make_unique<Trk::Track>(newInfo, std::move(finalTrajectory), nullptr);
214  // TODO: use TrackSummaryTool to create trackSummary?
215  if (!newtrack->trackSummary())
216  {
217  newtrack->setTrackSummary(std::make_unique<Trk::TrackSummary>());
218  newtrack->trackSummary()->update(Trk::numberOfPixelHoles, 0);
219  newtrack->trackSummary()->update(Trk::numberOfSCTHoles, 0);
220  newtrack->trackSummary()->update(Trk::numberOfTRTHoles, 0);
221  newtrack->trackSummary()->update(Trk::numberOfPixelDeadSensors, numberOfDeadPixel);
222  newtrack->trackSummary()->update(Trk::numberOfSCTDeadSensors, numberOfDeadSCT);
223  }
224 
225  m_trkSummaryTool->updateTrackSummary(ctx, *newtrack, true);
226  tracksContainer.push_back(std::move(newtrack));
227  }
228 
229  return StatusCode::SUCCESS;
230  }
231 
232  std::unique_ptr<Trk::MeasurementBase> ActsToTrkConvertorAlg::makeRIO_OnTrack(const xAOD::UncalibratedMeasurement &uncalibMeas,
233  const Trk::TrackParameters &parm) const
234  {
235  const Trk::PrepRawData *rio = nullptr;
236  const xAOD::UncalibMeasType measurementType = uncalibMeas.type();
237 
238  if (measurementType == xAOD::UncalibMeasType::PixelClusterType)
239  {
240  static const SG::AuxElement::ConstAccessor<ElementLink<InDet::PixelClusterCollection>> pixelLinkAcc("pixelClusterLink");
241  auto pixcl = dynamic_cast<const xAOD::PixelCluster *>(&uncalibMeas);
242  if (not pixcl or not pixelLinkAcc.isAvailable(*pixcl))
243  {
244  ATH_MSG_DEBUG("no pixelClusterLink for cluster associated to measurement");
245  return nullptr;
246  }
247 
248  auto pix = *pixelLinkAcc(*pixcl);
249  if (m_RotCreatorTool.empty())
250  {
251  const InDetDD::SiDetectorElement *element = pix->detectorElement();
252  if (!element)
253  {
254  ATH_MSG_WARNING("Cannot access pixel detector element");
255  return nullptr;
256  }
257  ATH_MSG_DEBUG("create InDet::PixelClusterOnTrack without correction");
258  return std::make_unique<InDet::PixelClusterOnTrack>(pix,
259  Trk::LocalParameters(pix->localPosition()),
260  Amg::MatrixX(pix->localCovariance()),
261  element->identifyHash(),
262  pix->globalPosition(),
263  pix->gangedPixel(),
264  false);
265  }
266  rio = pix;
267  }
268  else if (measurementType == xAOD::UncalibMeasType::StripClusterType)
269  {
270  static const SG::AuxElement::ConstAccessor<ElementLink<InDet::SCT_ClusterCollection>> stripLinkAcc("sctClusterLink");
271  auto stripcl = dynamic_cast<const xAOD::StripCluster *>(&uncalibMeas);
272  if (not stripcl or not stripLinkAcc.isAvailable(*stripcl))
273  {
274  ATH_MSG_WARNING("no sctClusterLink for clusters associated to measurement");
275  return nullptr;
276  }
277 
278  auto sct = *stripLinkAcc(*stripcl);
279  if (m_RotCreatorTool.empty())
280  {
281  const InDetDD::SiDetectorElement *element = sct->detectorElement();
282  if (!element)
283  {
284  ATH_MSG_WARNING("Cannot access strip detector element");
285  return nullptr;
286  }
287  ATH_MSG_DEBUG("create InDet::SCT_ClusterOnTrack without correction");
288  return std::make_unique<InDet::SCT_ClusterOnTrack>(sct,
289  Trk::LocalParameters(sct->localPosition()),
290  Amg::MatrixX(sct->localCovariance()),
291  element->identifyHash(),
292  sct->globalPosition(),
293  false);
294  }
295  rio = sct;
296  }
297  else
298  {
299  ATH_MSG_WARNING("xAOD::UncalibratedMeasurement is neither xAOD::PixelCluster nor xAOD::StripCluster");
300  return nullptr;
301  }
302 
303  ATH_MSG_DEBUG("use Trk::RIO_OnTrackCreator::correct to create corrected Trk::RIO_OnTrack");
304  assert(!m_RotCreatorTool.empty());
305  assert(rio != nullptr);
306  return std::unique_ptr<Trk::MeasurementBase>(m_RotCreatorTool->correct(*rio, parm, Gaudi::Hive::currentContext()));
307  }
308 
309 }
Trk::noHypothesis
@ noHypothesis
Definition: ParticleHypothesis.h:37
StripCluster.h
Trk::LocalParameters
Definition: LocalParameters.h:98
SCT_ClusterOnTrack.h
ActsTrk::ActsToTrkConvertorAlg::m_ATLASConverterTool
ToolHandle< ActsTrk::IActsToTrkConverterTool > m_ATLASConverterTool
Definition: ActsToTrkConvertorAlg.h:47
Trk::TrackInfo
Contains information about the 'fitter' of this track.
Definition: Tracking/TrkEvent/TrkTrack/TrkTrack/TrackInfo.h:32
Trk::TrackStateOnSurface::Perigee
@ Perigee
This represents a perigee, and so will contain a Perigee object only.
Definition: TrackStateOnSurface.h:117
ActsTrk::TrackContainer
Definition: TrackContainer.h:31
Amg::MatrixX
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic > MatrixX
Dynamic Matrix - dynamic allocation.
Definition: EventPrimitives.h:27
SG::ReadHandle::cptr
const_pointer_type cptr()
Dereference the pointer.
TrackParameters.h
SG::ReadHandle
Definition: StoreGate/StoreGate/ReadHandle.h:70
xAOD::UncalibMeasType::StripClusterType
@ StripClusterType
Trk::numberOfSCTDeadSensors
@ numberOfSCTDeadSensors
number of TRT hits
Definition: Tracking/TrkEvent/TrkTrackSummary/TrkTrackSummary/TrackSummary.h:76
ActsTrk::ActsToTrkConvertorAlg::initialize
virtual StatusCode initialize() override
Definition: ActsToTrkConvertorAlg.cxx:40
Trk::BoundaryCheckResult::Candidate
@ Candidate
ActsTrk::ActsToTrkConvertorAlg::m_tracksKey
SG::WriteHandleKey<::TrackCollection > m_tracksKey
Definition: ActsToTrkConvertorAlg.h:54
ActsTrk::ActsToTrkConvertorAlg::ActsToTrkConvertorAlg
ActsToTrkConvertorAlg(const std::string &name, ISvcLocator *pSvcLocator)
Definition: ActsToTrkConvertorAlg.cxx:34
SG::ConstAccessor
Helper class to provide constant type-safe access to aux data.
Definition: ConstAccessor.h:55
SG::VarHandleKey::key
const std::string & key() const
Return the StoreGate ID for the referenced object.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:141
Trk::numberOfSCTHoles
@ numberOfSCTHoles
number of Holes in both sides of a SCT module
Definition: Tracking/TrkEvent/TrkTrackSummary/TrkTrackSummary/TrackSummary.h:73
Trk::numberOfTRTHoles
@ numberOfTRTHoles
number of TRT hits which pass the high threshold (only xenon counted) total number of TRT hits which ...
Definition: Tracking/TrkEvent/TrkTrackSummary/TrkTrackSummary/TrackSummary.h:83
ActsTrk::ActsToTrkConvertorAlg::m_tracksContainerKey
SG::ReadHandleKey< ActsTrk::TrackContainer > m_tracksContainerKey
Definition: ActsToTrkConvertorAlg.h:52
InDetDD::SolidStateDetectorElementBase::identifyHash
virtual IdentifierHash identifyHash() const override final
identifier hash (inline)
AthReentrantAlgorithm
An algorithm that can be simultaneously executed in multiple threads.
Definition: AthReentrantAlgorithm.h:83
SG::makeHandle
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())
Definition: ReadCondHandle.h:270
Trk::FitQualityOnSurface
Definition: FitQualityOnSurface.h:19
SCT_ClusterCollection.h
xAOD::UncalibratedMeasurement_v1
Definition: UncalibratedMeasurement_v1.h:13
python.TrigInDetConfig.inputTracks
inputTracks
Definition: TrigInDetConfig.py:183
xAOD::UncalibratedMeasurement_v1::type
virtual xAOD::UncalibMeasType type() const =0
Returns the type of the measurement type as a simple enumeration.
Trk::TrackStateOnSurface::Hole
@ Hole
A hole on the track - this is defined in the following way.
Definition: TrackStateOnSurface.h:128
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
Trk::numberOfPixelDeadSensors
@ numberOfPixelDeadSensors
number of pixel hits with broad errors (width/sqrt(12))
Definition: Tracking/TrkEvent/TrkTrackSummary/TrkTrackSummary/TrackSummary.h:65
master.flag
bool flag
Definition: master.py:29
PixelCluster.h
ActsTrk::ActsToTrkConvertorAlg::execute
virtual StatusCode execute(const EventContext &ctx) const override
Definition: ActsToTrkConvertorAlg.cxx:60
xAOD::StripCluster_v1
Definition: StripCluster_v1.h:17
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
ActsDetectorElement
Definition: ActsDetectorElement.h:42
Trk::ParametersBase
Definition: ParametersBase.h:55
SG::VarHandleKey::initialize
StatusCode initialize(bool used=true)
If this object is used as a property, then this should be called during the initialize phase.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:103
ActsDetectorElement.h
PixelClusterCollection.h
DataVector< Trk::Track >
ActsTrk::ActsToTrkConvertorAlg::makeTracks
StatusCode makeTracks(const EventContext &ctx, const Acts::GeometryContext &tgContext, const ActsTrk::TrackContainer &tracks, ::TrackCollection &tracksContainer) const
Definition: ActsToTrkConvertorAlg.cxx:82
SG::ReadHandle::isValid
virtual bool isValid() override final
Can the handle be successfully dereferenced?
Trk::numberOfPixelHoles
@ numberOfPixelHoles
number of pixels which have a ganged ambiguity.
Definition: Tracking/TrkEvent/TrkTrackSummary/TrkTrackSummary/TrackSummary.h:59
Trk::PrepRawData
Definition: PrepRawData.h:62
xAOD::KalmanFitter
@ KalmanFitter
tracks produced by the Kalman Fitter
Definition: TrackingPrimitives.h:47
Trk::TrackStateOnSurface
represents the track state (measurement, material, fit parameters and quality) at a surface.
Definition: TrackStateOnSurface.h:71
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:221
InDetDD::SiDetectorElement
Definition: SiDetectorElement.h:109
xAOD::ParticleHypothesis
ParticleHypothesis
Definition: TrackingPrimitives.h:192
ActsToTrkConvertorAlg.h
ActsTrk::ActsToTrkConvertorAlg::m_RotCreatorTool
ToolHandle< Trk::IRIO_OnTrackCreator > m_RotCreatorTool
Definition: ActsToTrkConvertorAlg.h:49
SiDetectorElement.h
SG::WriteHandle
Definition: StoreGate/StoreGate/WriteHandle.h:76
xAOD::PixelCluster_v1
Definition: PixelCluster_v1.h:17
SG::WriteHandle::record
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
xAOD::UncalibMeasType
UncalibMeasType
Define the type of the uncalibrated measurement.
Definition: MeasurementDefs.h:24
if
if(febId1==febId2)
Definition: LArRodBlockPhysicsV0.cxx:567
xAOD::SiSPSeededFinder
@ SiSPSeededFinder
Tracks from SiSPSeedFinder.
Definition: TrackingPrimitives.h:85
SG::ConstAccessor::isAvailable
bool isAvailable(const ELT &e) const
Test to see if this variable exists in the store.
ActsTrk::ActsToTrkConvertorAlg::m_trkSummaryTool
ToolHandle< Trk::IExtendedTrackSummaryTool > m_trkSummaryTool
Definition: ActsToTrkConvertorAlg.h:50
ActsTrk
The AlignStoreProviderAlg loads the rigid alignment corrections and pipes them through the readout ge...
Definition: MuonDetectorBuilderTool.cxx:49
xAOD::track
@ track
Definition: TrackingPrimitives.h:512
pix
Definition: PixelMapping.cxx:16
PixelClusterOnTrack.h
ActsTrk::ActsToTrkConvertorAlg::m_trackingGeometryTool
ToolHandle< IActsTrackingGeometryTool > m_trackingGeometryTool
Definition: ActsToTrkConvertorAlg.h:46
xAOD::UncalibMeasType::PixelClusterType
@ PixelClusterType