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  {
36  ATH_MSG_DEBUG("Initializing " << name() << " ...");
37 
39  ATH_CHECK(m_tracksKey.initialize());
40 
42  ATH_CHECK(m_ATLASConverterTool.retrieve());
43  ATH_CHECK(m_trkSummaryTool.retrieve());
44 
45  if (not m_RotCreatorTool.empty())
46  {
47  ATH_MSG_DEBUG("RotCreatorTool will be used");
48  ATH_CHECK(m_RotCreatorTool.retrieve());
49  }
50 
51  return StatusCode::SUCCESS;
52  }
53 
54  StatusCode ActsToTrkConvertorAlg::execute(const EventContext &ctx) const
55  {
56  ATH_MSG_DEBUG("Executing " << name() << " ...");
57 
58  // I/O
59  ATH_MSG_DEBUG("Retrieving input track collection '" << m_tracksContainerKey.key() << "' ...");
61  ATH_CHECK(inputTracksHandle.isValid());
62  const ActsTrk::TrackContainer *inputTracks = inputTracksHandle.cptr();
63 
64  std::unique_ptr<::TrackCollection> trackCollection = std::make_unique<::TrackCollection>();
65 
66  Acts::GeometryContext tgContext = m_trackingGeometryTool->getGeometryContext(ctx).context();
67  ATH_CHECK(makeTracks(ctx, tgContext, *inputTracks, *trackCollection));
68 
70  ATH_MSG_DEBUG("Output Tracks Collection `" << m_tracksKey.key() << "` created ...");
71  ATH_CHECK(outputTrackHandle.record(std::move(trackCollection)));
72 
73  return StatusCode::SUCCESS;
74  }
75 
77  const Acts::GeometryContext &tgContext,
78  const ActsTrk::TrackContainer &tracks,
79  ::TrackCollection &tracksContainer) const
80  {
81 
82  for (const typename ActsTrk::TrackContainer::ConstTrackProxy track : tracks)
83  {
84  const auto lastMeasurementIndex = track.tipIndex();
85  auto finalTrajectory = std::make_unique<Trk::TrackStates>();
86  // initialise the number of dead Pixel and Acts strip
87  int numberOfDeadPixel = 0;
88  int numberOfDeadSCT = 0;
89 
90  Acts::ParticleHypothesis hypothesis = track.particleHypothesis();
91 
92  std::vector<std::unique_ptr<const Acts::BoundTrackParameters>> actsSmoothedParam;
93  tracks.trackStateContainer().visitBackwards(
94  lastMeasurementIndex,
95  [this, &tgContext, &track, &finalTrajectory, &actsSmoothedParam, &numberOfDeadPixel, &numberOfDeadSCT](const typename ActsTrk::TrackStateBackend::ConstTrackStateProxy &state) -> void
96  {
97  // First only consider states with an associated detector element
98  if (!state.hasReferenceSurface() || !state.referenceSurface().associatedDetectorElement())
99  {
100  return;
101  }
102 
103  auto flag = state.typeFlags();
104  std::bitset<Trk::TrackStateOnSurface::NumberOfTrackStateOnSurfaceTypes> typePattern;
105  std::unique_ptr<Trk::TrackParameters> parm;
106 
107  // State is a hole (no associated measurement), use predicted parameters
108  if (flag.test(Acts::TrackStateFlag::HoleFlag))
109  {
110  const Acts::BoundTrackParameters actsParam = track.createParametersFromState(state);
111  parm = m_ATLASConverterTool->actsTrackParametersToTrkParameters(actsParam, tgContext);
112  auto boundaryCheck = m_boundaryCheckTool->boundaryCheck(*parm);
113 
114  // Check if this is a hole, a dead sensors or a state outside the sensor boundary
115  if (boundaryCheck == Trk::BoundaryCheckResult::DeadElement)
116  {
117  auto *detElem = actsToDetElem(state.referenceSurface());
118  if (!detElem)
119  {
120  return;
121  }
122  if (detElem->isPixel())
123  {
124  ++numberOfDeadPixel;
125  }
126  else if (detElem->isSCT())
127  {
128  ++numberOfDeadSCT;
129  }
130  // Dead sensors states are not stored
131  return;
132  }
133  else if (boundaryCheck != Trk::BoundaryCheckResult::Candidate)
134  {
135  return;
136  }
137  typePattern.set(Trk::TrackStateOnSurface::Hole);
138  }
139  // The state was tagged as an outlier or (TODO!) was missed in the reverse filtering, use filtered parameters
140  else if (flag.test(Acts::TrackStateFlag::OutlierFlag))
141  {
142  const Acts::BoundTrackParameters actsParam = track.createParametersFromState(state);
143  parm = m_ATLASConverterTool->actsTrackParametersToTrkParameters(actsParam, tgContext);
144  typePattern.set(Trk::TrackStateOnSurface::Outlier);
145  }
146  // The state is a measurement state, use smoothed parameters
147  else
148  {
149  const Acts::BoundTrackParameters actsParam = track.createParametersFromState(state);
150 
151  // is it really necessary to keep our own copy of all the smoothed parameters?
152  actsSmoothedParam.push_back(std::make_unique<const Acts::BoundTrackParameters>(Acts::BoundTrackParameters(actsParam)));
153  parm = m_ATLASConverterTool->actsTrackParametersToTrkParameters(actsParam, tgContext);
154  typePattern.set(Trk::TrackStateOnSurface::Measurement);
155  }
156 
157  std::unique_ptr<Trk::MeasurementBase> measState;
158  if (state.hasUncalibratedSourceLink())
159  {
160  try {
161  auto sl = state.getUncalibratedSourceLink().template get<ATLASUncalibSourceLink>();
162  assert( sl != nullptr);
163  const xAOD::UncalibratedMeasurement &uncalibMeas = getUncalibratedMeasurement(sl);
164  measState = makeRIO_OnTrack(uncalibMeas, *parm);
165  ATH_MSG_DEBUG("Successfully used ATLASUncalibratedSourceLink");
166  } catch ( const std::bad_any_cast& ){
167  ATH_MSG_DEBUG("Not an ATLASUncalibSourceLink, trying ATLASSourceLink");
168  auto sl = state.getUncalibratedSourceLink().template get<ATLASSourceLink>();
169  assert( sl != nullptr );
170  measState.reset(sl->clone());
171  ATH_MSG_DEBUG("Successfully used ATLASSourceLink");
172 
173  }
174  }
175 
176  double nDoF = state.calibratedSize();
177  auto quality = Trk::FitQualityOnSurface(state.chi2(), nDoF);
178  auto perState = new Trk::TrackStateOnSurface(quality,
179  std::move(measState),
180  std::move(parm),
181  nullptr,
182  typePattern);
183 
184  // If a state was succesfully created add it to the trajectory
185  finalTrajectory->insert(finalTrajectory->begin(), perState);
186  });
187 
188  // Convert the perigee state and add it to the trajectory
189  const Acts::BoundTrackParameters actsPer(track.referenceSurface().getSharedPtr(),
190  track.parameters(),
191  track.covariance(),
192  hypothesis);
193 
194  std::unique_ptr<Trk::TrackParameters> per = m_ATLASConverterTool->actsTrackParametersToTrkParameters(actsPer, tgContext);
195  std::bitset<Trk::TrackStateOnSurface::NumberOfTrackStateOnSurfaceTypes> typePattern;
196  typePattern.set(Trk::TrackStateOnSurface::Perigee);
197  auto perState = new Trk::TrackStateOnSurface(nullptr,
198  std::move(per),
199  nullptr,
200  typePattern);
201  finalTrajectory->insert(finalTrajectory->begin(), perState);
202 
203  // Create the track using Athena TrackFitter::KalmanFitter and TrackPatternRecoInfo::SiSPSeededFinder algorithm enums
205  newInfo.setPatternRecognitionInfo(Trk::TrackInfo::TrackPatternRecoInfo::SiSPSeededFinder);
206 
207  auto newtrack = std::make_unique<Trk::Track>(newInfo, std::move(finalTrajectory), nullptr);
208  // TODO: use TrackSummaryTool to create trackSummary?
209  if (!newtrack->trackSummary())
210  {
211  newtrack->setTrackSummary(std::make_unique<Trk::TrackSummary>());
212  newtrack->trackSummary()->update(Trk::numberOfPixelHoles, 0);
213  newtrack->trackSummary()->update(Trk::numberOfSCTHoles, 0);
214  newtrack->trackSummary()->update(Trk::numberOfTRTHoles, 0);
215  newtrack->trackSummary()->update(Trk::numberOfPixelDeadSensors, numberOfDeadPixel);
216  newtrack->trackSummary()->update(Trk::numberOfSCTDeadSensors, numberOfDeadSCT);
217  }
218 
219  m_trkSummaryTool->updateTrackSummary(ctx, *newtrack, true);
220  tracksContainer.push_back(std::move(newtrack));
221  }
222 
223  return StatusCode::SUCCESS;
224  }
225 
226  std::unique_ptr<Trk::MeasurementBase> ActsToTrkConvertorAlg::makeRIO_OnTrack(const xAOD::UncalibratedMeasurement &uncalibMeas,
227  const Trk::TrackParameters &parm) const
228  {
229  const Trk::PrepRawData *rio = nullptr;
230  const xAOD::UncalibMeasType measurementType = uncalibMeas.type();
231 
232  if (measurementType == xAOD::UncalibMeasType::PixelClusterType)
233  {
234  static const SG::AuxElement::ConstAccessor<ElementLink<InDet::PixelClusterCollection>> pixelLinkAcc("pixelClusterLink");
235  auto pixcl = dynamic_cast<const xAOD::PixelCluster *>(&uncalibMeas);
236  if (not pixcl or not pixelLinkAcc.isAvailable(*pixcl))
237  {
238  ATH_MSG_DEBUG("no pixelClusterLink for cluster associated to measurement");
239  return nullptr;
240  }
241 
242  auto pix = *pixelLinkAcc(*pixcl);
243  if (m_RotCreatorTool.empty())
244  {
245  const InDetDD::SiDetectorElement *element = pix->detectorElement();
246  if (!element)
247  {
248  ATH_MSG_WARNING("Cannot access pixel detector element");
249  return nullptr;
250  }
251  ATH_MSG_DEBUG("create InDet::PixelClusterOnTrack without correction");
252  return std::make_unique<InDet::PixelClusterOnTrack>(pix,
253  Trk::LocalParameters(pix->localPosition()),
254  Amg::MatrixX(pix->localCovariance()),
255  element->identifyHash(),
256  pix->globalPosition(),
257  pix->gangedPixel(),
258  false);
259  }
260  rio = pix;
261  }
262  else if (measurementType == xAOD::UncalibMeasType::StripClusterType)
263  {
264  static const SG::AuxElement::ConstAccessor<ElementLink<InDet::SCT_ClusterCollection>> stripLinkAcc("sctClusterLink");
265  auto stripcl = dynamic_cast<const xAOD::StripCluster *>(&uncalibMeas);
266  if (not stripcl or not stripLinkAcc.isAvailable(*stripcl))
267  {
268  ATH_MSG_WARNING("no sctClusterLink for clusters associated to measurement");
269  return nullptr;
270  }
271 
272  auto sct = *stripLinkAcc(*stripcl);
273  if (m_RotCreatorTool.empty())
274  {
275  const InDetDD::SiDetectorElement *element = sct->detectorElement();
276  if (!element)
277  {
278  ATH_MSG_WARNING("Cannot access strip detector element");
279  return nullptr;
280  }
281  ATH_MSG_DEBUG("create InDet::SCT_ClusterOnTrack without correction");
282  return std::make_unique<InDet::SCT_ClusterOnTrack>(sct,
283  Trk::LocalParameters(sct->localPosition()),
284  Amg::MatrixX(sct->localCovariance()),
285  element->identifyHash(),
286  sct->globalPosition(),
287  false);
288  }
289  rio = sct;
290  }
291  else
292  {
293  ATH_MSG_WARNING("xAOD::UncalibratedMeasurement is neither xAOD::PixelCluster nor xAOD::StripCluster");
294  return nullptr;
295  }
296 
297  ATH_MSG_DEBUG("use Trk::RIO_OnTrackCreator::correct to create corrected Trk::RIO_OnTrack");
298  assert(!m_RotCreatorTool.empty());
299  assert(rio != nullptr);
300  return std::unique_ptr<Trk::MeasurementBase>(m_RotCreatorTool->correct(*rio, parm, Gaudi::Hive::currentContext()));
301  }
302 
303 }
Trk::noHypothesis
@ noHypothesis
Definition: ParticleHypothesis.h:40
StripCluster.h
Trk::LocalParameters
Definition: LocalParameters.h:98
SCT_ClusterOnTrack.h
ActsTrk::ActsToTrkConvertorAlg::m_ATLASConverterTool
ToolHandle< ActsTrk::IActsToTrkConverterTool > m_ATLASConverterTool
Definition: ActsToTrkConvertorAlg.h:45
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:30
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:67
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:34
Trk::BoundaryCheckResult::Candidate
@ Candidate
ActsTrk::ActsToTrkConvertorAlg::m_tracksKey
SG::WriteHandleKey<::TrackCollection > m_tracksKey
Definition: ActsToTrkConvertorAlg.h:52
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:50
InDetDD::SolidStateDetectorElementBase::identifyHash
virtual IdentifierHash identifyHash() const override final
identifier hash (inline)
SG::makeHandle
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())
Definition: ReadCondHandle.h:274
Trk::FitQualityOnSurface
Definition: FitQualityOnSurface.h:19
SCT_ClusterCollection.h
xAOD::UncalibratedMeasurement_v1
Definition: UncalibratedMeasurement_v1.h:13
python.TrigInDetConfig.inputTracks
inputTracks
Definition: TrigInDetConfig.py:191
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:54
xAOD::StripCluster_v1
Definition: StripCluster_v1.h:17
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
ActsDetectorElement
Definition: ActsDetectorElement.h:44
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:76
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:48
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:240
InDetDD::SiDetectorElement
Definition: SiDetectorElement.h:109
xAOD::ParticleHypothesis
ParticleHypothesis
Definition: TrackingPrimitives.h:193
ActsToTrkConvertorAlg.h
ActsTrk::ActsToTrkConvertorAlg::m_RotCreatorTool
ToolHandle< Trk::IRIO_OnTrackCreator > m_RotCreatorTool
Definition: ActsToTrkConvertorAlg.h:47
SiDetectorElement.h
SG::WriteHandle
Definition: StoreGate/StoreGate/WriteHandle.h:73
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
ActsTrk::ActsToTrkConvertorAlg::m_trackingGeometryTool
PublicToolHandle< ActsTrk::ITrackingGeometryTool > m_trackingGeometryTool
Definition: ActsToTrkConvertorAlg.h:44
python.TrackLeptonConfig.quality
quality
Definition: TrackLeptonConfig.py:16
xAOD::UncalibMeasType
UncalibMeasType
Define the type of the uncalibrated measurement.
Definition: MeasurementDefs.h:25
if
if(febId1==febId2)
Definition: LArRodBlockPhysicsV0.cxx:567
xAOD::SiSPSeededFinder
@ SiSPSeededFinder
Tracks from SiSPSeedFinder.
Definition: TrackingPrimitives.h:86
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:48
ActsTrk
The AlignStoreProviderAlg loads the rigid alignment corrections and pipes them through the readout ge...
Definition: MSTrackingVolumeBuilder.cxx:24
xAOD::track
@ track
Definition: TrackingPrimitives.h:513
pix
Definition: PixelMapping.cxx:16
PixelClusterOnTrack.h
xAOD::UncalibMeasType::PixelClusterType
@ PixelClusterType