ATLAS Offline Software
Extrapolator.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3  */
4 
6 // Extrapolator.cxx, (c) ATLAS Detector software
8 
12 //
14 //
16 #include "TrkTrack/Track.h"
17 //
20 //
22 //
25 //
27 //
32 #include "TrkGeometry/Layer.h"
35 //
38 //
40 #include "TrkSurfaces/DiscBounds.h"
45 //
48 #include "TrkVolumes/Volume.h"
49 //
52 //
53 #include <memory>
54 #include <utility>
55 #include <cstdint>
56 
57 
58 
59 // need specialisation of cloneObj used by ObjContainer to properly clones all
60 
61 template<>
62 inline const Trk::TrackParameters*
63 cloneObj<const Trk::TrackParameters>(const Trk::TrackParameters* p_ptr)
64 {
65  return (p_ptr ? p_ptr->clone() : nullptr);
66 }
67 
68 template<>
70 cloneObj<Trk::TrackParameters>(const Trk::TrackParameters* p_ptr)
71 {
72  return (p_ptr ? p_ptr->clone() : nullptr);
73 }
74 
75 
76 namespace {
77 constexpr double s_distIncreaseTolerance = 100. * Gaudi::Units::millimeter;
78 constexpr unsigned int INVALIDPROPAGATORS = Trk::NumberOfSignatures+3;
79 
83 int
84 radialDirection(const Trk::TrackParameters& pars, Trk::PropDirection dir)
85 {
86  // safe inbound/outbound estimation
87  double prePositionR = pars.position().perp();
88 
89  return (prePositionR > (pars.position() + dir * 0.5 * prePositionR *
90  pars.momentum().normalized())
91  .perp())
92  ? -1
93  : 1;
94 }
95 std::string
96 layerRZoutput(const Trk::Layer& lay)
97 {
98  std::stringstream outStream;
99 
100  outStream << "[r,z] = [ " << lay.surfaceRepresentation().bounds().r() << ", "
101  << lay.surfaceRepresentation().center().z() << " ] - Index ";
102  outStream << lay.layerIndex().value();
103  return outStream.str();
104 }
105 std::string
106 momentumOutput(const Amg::Vector3D& mom)
107 {
108  std::stringstream outStream;
109 
110  outStream << "[eta,phi] = [ " << mom.eta() << ", " << mom.phi() << " ]";
111  return outStream.str();
112 }
113 
114 } // end of anonymous namespace
115 
116 
117 // constructor
118 Trk::Extrapolator::Extrapolator(const std::string& t, const std::string& n, const IInterface* p)
120  , m_subPropagators(Trk::NumberOfSignatures)
121  , m_subupdaters(Trk::NumberOfSignatures)
122  , m_propNames()
123  , m_updatNames()
124  , m_includeMaterialEffects(true)
125  , m_requireMaterialDestinationHit(false)
126  , m_stopWithNavigationBreak(false)
127  , m_stopWithUpdateZero(false)
128  , m_subSurfaceLevel(true)
129  , m_skipInitialLayerUpdate(false)
130  , m_extendedLayerSearch(true)
131  , m_robustSampling(true)
132  , m_referenceMaterial(false)
133  , m_resolveMultilayers(true)
134  , m_cacheLastMatLayer(false)
135  , m_returnPassiveLayers(false)
136  , m_meotpIndex(0)
137  , m_numOfValidPropagators(INVALIDPROPAGATORS)
138  , m_initialLayerAttempts(3)
139  , m_successiveLayerAttempts(1)
140  , m_maxMethodSequence(2000)
141  , m_tolerance(0.002)
142  , m_activeOverlap(false)
143  , m_useMuonMatApprox(false)
144  , m_useDenseVolumeDescription(true)
145  , m_checkForCompundLayers(false)
146  , m_maxNavigSurf{ 1000 }
147  , m_maxNavigVol{ 50 }
148  , m_dumpCache(false)
149  , m_fastField(false)
150  , m_referenceSurface{ nullptr }
151  , m_printRzOutput(true)
152  , m_navigationStatistics(false)
153  , m_navigationBreakDetails(false)
154  , m_materialEffectsOnTrackValidation(false)
155  , m_extrapolateCalls{}
156  , m_extrapolateBlindlyCalls{}
157  , m_extrapolateDirectlyCalls{}
158  , m_extrapolateStepwiseCalls{}
159  , m_startThroughAssociation{}
160  , m_startThroughRecall{}
161  , m_startThroughGlobalSearch{}
162  , m_destinationThroughAssociation{}
163  , m_destinationThroughRecall{}
164  , m_destinationThroughGlobalSearch{}
165  , m_layerSwitched{}
166  , m_navigationBreakLoop{}
167  , m_navigationBreakOscillation{}
168  , m_navigationBreakNoVolume{}
169  , m_navigationBreakDistIncrease{}
170  , m_navigationBreakVolumeSignature{}
171  , m_overlapSurfaceHit{}
172  , m_meotSearchCallsFw{}
173  , m_meotSearchCallsBw{}
174  , m_meotSearchSuccessfulFw{}
175  , m_meotSearchSuccessfulBw{}
176 {
177  declareInterface<IExtrapolator>(this);
178 
179  // extrapolation steering
180  declareProperty("StopWithNavigationBreak", m_stopWithNavigationBreak);
181  declareProperty("StopWithUpdateKill", m_stopWithUpdateZero);
182  declareProperty("SkipInitialPostUpdate", m_skipInitialLayerUpdate);
183  declareProperty("MaximalMethodSequence", m_maxMethodSequence);
184  // propagation steering
185  declareProperty("SubPropagators", m_propNames);
186  // material effects handling
187  declareProperty("ApplyMaterialEffects", m_includeMaterialEffects);
188  declareProperty("RequireMaterialDestinationHit", m_requireMaterialDestinationHit);
189  declareProperty("SubMEUpdators", m_updatNames);
190  declareProperty("CacheLastMaterialLayer", m_cacheLastMatLayer);
191  // muon system specifics
192  declareProperty("UseMuonMatApproximation", m_useMuonMatApprox);
193  declareProperty("UseDenseVolumeDescription", m_useDenseVolumeDescription);
194  declareProperty("CheckForCompoundLayers", m_checkForCompundLayers);
195  declareProperty("ResolveMuonStation", m_resolveActive = false);
196  declareProperty("ResolveMultilayers", m_resolveMultilayers);
197  declareProperty("ConsiderMuonStationOverlaps", m_activeOverlap);
198  declareProperty("RobustSampling", m_robustSampling);
199  // material & navigation related steering
200  declareProperty("MaterialEffectsOnTrackProviderIndex", m_meotpIndex);
201  declareProperty("MaterialEffectsOnTrackValidation", m_materialEffectsOnTrackValidation);
202  declareProperty("ReferenceMaterial", m_referenceMaterial);
203  declareProperty("ExtendedLayerSearch", m_extendedLayerSearch);
204  declareProperty("InitialLayerAttempts", m_initialLayerAttempts);
205  declareProperty("SuccessiveLayerAttempts", m_successiveLayerAttempts);
206  // debug and validation
207  declareProperty("positionOutput", m_printRzOutput);
208  declareProperty("NavigationStatisticsOutput", m_navigationStatistics);
209  declareProperty("DetailedNavigationOutput", m_navigationBreakDetails);
210  declareProperty("Tolerance", m_tolerance);
211  // Magnetic field properties
212  declareProperty("DumpCache", m_dumpCache);
213  declareProperty("MagneticFieldProperties", m_fastField);
214 }
215 
216 // destructor
218 
219 // Athena standard methods
220 // initialize
223 {
224 
225  m_referenceSurface = std::make_unique<Trk::PlaneSurface>(Amg::Transform3D(Trk::s_idTransform), 0., 0.);
226  m_referenceSurface->setOwner(Trk::userOwn); //this is owned by an instance of this class
227 
228  m_fieldProperties = m_fastField ? Trk::MagneticFieldProperties(Trk::FastField)
230 
231  // before we start messing around, how many of these updaters were actually passed in?
232  const auto numberOfSubPropagatorsGiven = m_propNames.size();
233  const auto numberOfSubMatEffUpdatersGiven = m_updatNames.size();
234  //
235  if (m_propagators.empty()) {
236  m_propagators.push_back("Trk::RungeKuttaPropagator/DefaultPropagator");
237  }
238  if (m_updaters.empty()) {
239  m_updaters.push_back("Trk::MaterialEffectsUpdator/DefaultMaterialEffectsUpdator");
240  }
241 
242 
243  if (!m_propagators.empty()) {
244  ATH_CHECK(m_propagators.retrieve());
245  }
246 
247  // from the number of retrieved propagators set the configurationLevel
248  unsigned int validprop = m_propagators.size();
249 
250  if (!validprop) {
251  ATH_MSG_WARNING("None of the defined propagators could be retrieved!");
252  ATH_MSG_WARNING("Extrapolator unconfigured");
253  } else {
254  m_numOfValidPropagators = validprop ;
255  ATH_MSG_VERBOSE("Number of Valid Propagators " << m_numOfValidPropagators);
256  }
257 
258  // Get the Navigation AlgTools
259  ATH_CHECK(m_navigator.retrieve());
260 
261  // Get the Material Updator
262  if (m_includeMaterialEffects && not m_updaters.empty()) {
263  ATH_CHECK(m_updaters.retrieve());
264  for (auto& tool : m_updaters) {
265  // @TODO tools, that are already used, should not be disabled. Those are
266  // currently disabled to silence the warning issued by the tool usage
267  // detection, which is circumvented in case of the m_updaters.
268  tool.disable();
269  }
270  }
271 
272  // from the number of retrieved propagators set the configurationLevel
273  unsigned int validmeuts = m_updaters.size();
274  std::vector<std::string> fullPropagatorNames(m_propagators.size());
275  std::vector<std::string> fullUpdatorNames(m_updaters.size());
276  auto extractNameFromTool = [](const auto& toolHndl) { return toolHndl->name(); };
278  m_propagators.begin(), m_propagators.end(), fullPropagatorNames.begin(), extractNameFromTool);
280  m_updaters.begin(), m_updaters.end(), fullUpdatorNames.begin(), extractNameFromTool);
281 
282  // ------------------------------------
283  // Sanity check 1
284  if (m_propNames.empty() && not m_propagators.empty()) {
286  "Inconsistent setup of Extrapolator, no sub-propagators configured, doing it for you. ");
287  m_propNames.push_back(TrkExTools::getToolSuffix(fullPropagatorNames[0]));
288  if (TrkExTools::numberOfUniqueEntries(m_propNames) !=
289  TrkExTools::numberOfUniqueEntries(fullPropagatorNames)) {
290  ATH_MSG_ERROR("Some configured propagators have same name but different owners");
291  }
292  if (const auto& errMsg = TrkExTools::possibleToolNameError(m_propNames); not errMsg.empty()) {
293  ATH_MSG_ERROR(errMsg);
294  }
295  }
296 
297  if (m_updatNames.empty() && not m_updaters.empty()) {
298  ATH_MSG_DEBUG("Inconsistent setup of Extrapolator, no sub-material updaters configured, doing "
299  "it for you. ");
300  m_updatNames.push_back(TrkExTools::getToolSuffix(fullUpdatorNames[0]));
301  if (TrkExTools::numberOfUniqueEntries(m_updatNames) !=
302  TrkExTools::numberOfUniqueEntries(fullUpdatorNames)) {
303  ATH_MSG_ERROR("Some configured material updaters have same name but different owners");
304  }
305  if (const auto& errMsg = TrkExTools::possibleToolNameError(m_updatNames); not errMsg.empty()) {
306  ATH_MSG_ERROR(errMsg);
307  }
308  }
309 
310  // ------------------------------------
311  // Sanity check 2
312  // fill the number of propagator names and updator names up with first one
313  m_propNames.resize(int(Trk::NumberOfSignatures), m_propNames[0]);
314  m_updatNames.resize(int(Trk::NumberOfSignatures), m_updatNames[0]);
315 
316  if (validprop && validmeuts) {
317  // Per definition: if configured not found, take the lowest one
318  for (unsigned int isign = 0; int(isign) < int(Trk::NumberOfSignatures); ++isign) {
319  unsigned int index = 0;
320  for (unsigned int iProp = 0; iProp < m_propagators.size(); iProp++) {
321  std::string pname = TrkExTools::getToolSuffix(m_propagators[iProp]->name());
322  if (m_propNames[isign] == pname) {
323  index = iProp;
324  }
325  }
327  " subPropagator:" << isign << " pointing to propagator: " << m_propagators[index]->name());
328  m_subPropagators[isign] =
329  (index < validprop) ? &(*m_propagators[index]) : &(*m_propagators[Trk::Global]);
330 
331  index = 0;
332  for (unsigned int iUp = 0; iUp < m_updaters.size(); iUp++) {
333  std::string uname = TrkExTools::getToolSuffix(m_updaters[iUp]->name());
334  if (m_updatNames[isign] == uname) {
335  index = iUp;
336  }
337  }
338  ATH_MSG_DEBUG(" subMEUpdator:" << isign
339  << " pointing to updator: " << m_updaters[index]->name());
340  m_subupdaters[isign] =
341  (index < validmeuts) ? &(*m_updaters[index]) : &(*m_updaters[Trk::Global]);
342  }
343  } else {
345  "Configuration Problem of Extrapolator: "
346  << " -- At least one IPropagator and IMaterialUpdator instance have to be given.! ");
347  }
348  const std::string propStr = std::to_string(numberOfSubPropagatorsGiven) + " propagator" +
349  std::string((numberOfSubPropagatorsGiven == 1) ? "" : "s");
350  const std::string updStr = std::to_string(numberOfSubMatEffUpdatersGiven) + " updater" +
351  std::string((numberOfSubMatEffUpdatersGiven == 1) ? "" : "s");
352  std::string msgString{ "\nThe extrapolator uses six sub-propagators and "
353  "sub-material effects updaters:\n" };
354  msgString += propStr + " and " + updStr + " were given in the configuration,\n";
355  msgString += "the extrapolator sub-tools have been defined as follows: \n";
356  for (int i(0); i != int(Trk::NumberOfSignatures); ++i) {
357  msgString += std::to_string(i) + ") propagator: " + m_subPropagators[i]->name() +
358  ", updater: " + m_subupdaters[i]->name() + "\n";
359  }
360  ATH_MSG_VERBOSE(msgString);
361  ATH_CHECK(m_stepPropagator.retrieve());
362  ATH_MSG_DEBUG("initialize() successful");
363  return StatusCode::SUCCESS;
364 }
365 
366 // finalize
369 {
370  if (m_navigationStatistics) {
371  ATH_MSG_INFO(" Perfomance Statistics : ");
372  ATH_MSG_INFO(" [P] Method Statistics ------- ------------------------------------");
373  ATH_MSG_INFO(" -> Number of extrapolate() calls : " << m_extrapolateCalls);
374  ATH_MSG_INFO(
375  " -> Number of extrapolateBlindly() calls : " << m_extrapolateBlindlyCalls);
376  ATH_MSG_INFO(
377  " -> Number of extrapolateDirectly() calls : " << m_extrapolateDirectlyCalls);
378  ATH_MSG_INFO(
379  " -> Number of extrapolateStepwise() calls : " << m_extrapolateStepwiseCalls);
380  ATH_MSG_INFO(" -> Number of layers switched in layer2layer : " << m_layerSwitched);
381  ATH_MSG_INFO("[P] Navigation Initialization -------------------------------------");
382  ATH_MSG_INFO(
383  " -> Number of start associations : " << m_startThroughAssociation);
384  ATH_MSG_INFO(" -> Number of start recalls : " << m_startThroughRecall);
385  ATH_MSG_INFO(
386  " -> Number of start global searches : " << m_startThroughGlobalSearch);
387  ATH_MSG_INFO(
388  " -> Number of destination associations : " << m_destinationThroughAssociation);
389  ATH_MSG_INFO(
390  " -> Number of destination recalls : " << m_destinationThroughRecall);
391  ATH_MSG_INFO(" -> Number of destination global searches : "
392  << m_destinationThroughGlobalSearch);
393  ATH_MSG_INFO("[P] Navigation Breaks ---------------------------------------------");
394  ATH_MSG_INFO(
395  " -> Number of navigation breaks: loop : " << m_navigationBreakLoop);
396  ATH_MSG_INFO(
397  " -> Number of navigation breaks: oscillation : " << m_navigationBreakOscillation);
398  ATH_MSG_INFO(
399  " -> Number of navigation breaks: no volume found : " << m_navigationBreakNoVolume);
400  ATH_MSG_INFO(
401  " -> Number of navigation breaks: dist. increase : " << m_navigationBreakDistIncrease);
402  ATH_MSG_INFO(" -> Number of navigation breaks: dist. increase : "
403  << m_navigationBreakVolumeSignature);
404  if (m_navigationBreakDetails) {
405  ATH_MSG_DEBUG(" Detailed output for Navigation breaks : ");
406  ATH_MSG_DEBUG(" o " << m_navigationBreakLoop
407  << " loops occured in the following volumes: ");
408  ATH_MSG_DEBUG(" o " << m_navigationBreakOscillation
409  << " oscillations occured in following volumes: ");
410  ATH_MSG_DEBUG(" o " << m_navigationBreakNoVolume
411  << " times no next volume found of volumes: ");
412  ATH_MSG_DEBUG(" o " << m_navigationBreakDistIncrease
413  << " distance increases detected at volumes: ");
414  ATH_MSG_DEBUG(" o " << m_navigationBreakVolumeSignature
415  << " no propagator configured for volumes: ");
416  }
417  // validation of the overlap search
418  ATH_MSG_INFO("[P] Overlaps found ------------------------------------------------");
419  ATH_MSG_INFO(" -> Number of overlap Surface hit : " << m_overlapSurfaceHit);
420  ATH_MSG_INFO(" ------------------------------------------------------------------");
421  // validation of the material collection methods
422  if (m_materialEffectsOnTrackValidation) {
423  ATH_MSG_INFO("[P] MaterialEffectsOnTrack collection -----------------------------");
424  ATH_MSG_INFO(" -> Forward successful/calls (ratio) : "
425  << m_meotSearchSuccessfulFw << "/" << m_meotSearchCallsFw << " ("
426  << double(m_meotSearchSuccessfulFw.value()) / m_meotSearchCallsFw.value()
427  << ")");
428  ATH_MSG_INFO(" -> Backward successful/calls (ratio) : "
429  << m_meotSearchSuccessfulBw << "/" << m_meotSearchCallsBw << " ("
430  << double(m_meotSearchSuccessfulBw.value()) / m_meotSearchCallsBw.value()
431  << ")");
432  ATH_MSG_INFO(" ------------------------------------------------------------------");
433  }
434  }
435 
436  return StatusCode::SUCCESS;
437 }
438 
439 std::unique_ptr<Trk::NeutralParameters>
441  const Surface& sf,
443  const BoundaryCheck& bcheck) const
444 {
445  const IPropagator* currentPropagator =
446  !m_subPropagators.empty() ? m_subPropagators[Trk::Global] : nullptr;
447  if (currentPropagator) {
448  return currentPropagator->propagate(parameters, sf, dir, bcheck);
449  }
451  " [!] No default Propagator is configured ! Please check jobOptions.");
452  return nullptr;
453 }
454 
457  const IPropagator& prop,
458  const Trk::TrackParameters& parm,
459  const Trk::Surface& sf,
461  const Trk::BoundaryCheck& bcheck,
463 
464  Cache cache{};
465  // statistics && sequence output ----------------------------------------
466  ++m_extrapolateStepwiseCalls;
467  ++cache.m_methodSequence;
468  ATH_MSG_DEBUG("F-[" << cache.m_methodSequence << "] extrapolateStepwise(...) ");
469  // initialize the return parameters vector
470  // create a new internal helper vector
472  //The m_parametersOnDetElements point to it
473  cache.m_parametersOnDetElements = &tmp;
474  // Material effect updator cache
475  cache.populateMatEffUpdatorCache(m_subupdaters);
476  //TODO revisit when objcontainer is streamlined
477  auto cloneInput = std::unique_ptr<Trk::TrackParameters>(parm.clone());
478  // run the extrapolation
479  ManagedTrackParmPtr parameterOnSf(extrapolateImpl(
480  ctx, cache, prop, cache.manage(std::move(cloneInput)).index(), sf, dir, bcheck, particle));
481  // assign the return parameter and set cache.m_parametersOnDetElements = 0;
482  if (parameterOnSf) {
483  tmp.emplace_back(parameterOnSf.release());
484  } else {
485  tmp.clear();
486  }
487  //m_parametersOnDetElements point to nullptr
488  cache.m_parametersOnDetElements = nullptr;
489  return Trk::TrackParametersUVector(std::move(tmp));
490 }
491 
492 std::pair<std::unique_ptr<Trk::TrackParameters>, const Trk::Layer*>
494  const EventContext& ctx,
495  const IPropagator& prop,
496  const Trk::TrackParameters& parm,
498  const BoundaryCheck& bcheck,
499  std::vector<const Trk::TrackStateOnSurface*>& material,
501  MaterialUpdateMode matupmode) const
502 {
503  Cache cache{};
504  ++cache.m_methodSequence;
505  ATH_MSG_DEBUG("M-[" << cache.m_methodSequence << "] extrapolateToNextActiveLayerM(...) ");
506  // Material effect updator cache
507  cache.populateMatEffUpdatorCache(m_subupdaters);
508  // initialize the return parameters vector
509  auto cloneInput = std::unique_ptr<Trk::TrackParameters>(parm.clone());
510  ManagedTrackParmPtr currPar(cache.manage(std::move(cloneInput)));
511  //
512  const Trk::TrackingVolume* staticVol = nullptr;
513  const Trk::Surface* destSurface = nullptr;
514  const Trk::Layer* assocLayer = nullptr;
515  // initialize material collection
516  cache.m_matstates = &material;
517 
518  while (currPar) {
519  assocLayer = nullptr;
520  ManagedTrackParmPtr nextPar(extrapolateToNextMaterialLayer(
521  ctx, cache, prop, currPar.index(), destSurface, staticVol, dir, bcheck, particle, matupmode));
522  if (nextPar) {
523  if (cache.m_lastMaterialLayer &&
524  cache.m_lastMaterialLayer->surfaceRepresentation().isOnSurface(
525  nextPar->position(), bcheck, m_tolerance, m_tolerance)) {
526  assocLayer = cache.m_lastMaterialLayer;
527  }
528  if (!assocLayer) {
529  ATH_MSG_ERROR(" [!] No associated layer found - at "
530  << positionOutput(nextPar->position()));
531  }
532  } else {
533  // static volume boundary ?
534  if (cache.m_parametersAtBoundary.nextParameters && cache.m_parametersAtBoundary.nextVolume) {
535  if (cache.m_parametersAtBoundary.nextVolume->geometrySignature() == Trk::MS ||
536  (cache.m_parametersAtBoundary.nextVolume->geometrySignature() == Trk::Calo &&
537  m_useDenseVolumeDescription)) {
538  staticVol = cache.m_parametersAtBoundary.nextVolume;
539  nextPar = cache.m_parametersAtBoundary.nextParameters;
540  ATH_MSG_DEBUG(" [+] Static volume boundary: continue loop over active layers in '"
541  << staticVol->volumeName() << "'.");
542  } else { // MSentrance
543  nextPar = std::move(cache.m_parametersAtBoundary.nextParameters);
544  cache.m_parametersAtBoundary.resetBoundaryInformation();
545  return {nextPar.to_unique(), nullptr};
546  }
547  } else if (cache.m_parametersAtBoundary.nextParameters) { // outer boundary
548  nextPar = std::move(cache.m_parametersAtBoundary.nextParameters);
549  cache.m_parametersAtBoundary.resetBoundaryInformation();
550  return {nextPar.to_unique(), nullptr};
551  }
552  }
553  currPar = std::move(nextPar);
554  if (currPar && assocLayer && assocLayer->layerType() != 0) {
555  break;
556  }
557  }
558  // reset the boundary information
559  cache.m_parametersAtBoundary.resetBoundaryInformation();
560  cache.m_matstates = nullptr;
561  return {currPar.to_unique(), assocLayer};
562 }
563 
566  Cache& cache,
567  const IPropagator& prop,
568  TrackParmPtr parm_ref,
569  const Trk::Surface* destSurf,
570  const Trk::TrackingVolume* vol,
572  const BoundaryCheck& bcheck,
574  MaterialUpdateMode matupmode) const
575 {
576  ++cache.m_methodSequence;
577  ATH_MSG_DEBUG("M-[" << cache.m_methodSequence << "] extrapolateToNextMaterialLayer(...) ");
578 
579  // this is the core of the material loop
580  // extrapolation without target surface returns:
581  // A) trPar at next material layer
582  // B) boundary parameters (static volume boundary)
583  // if target surface:
584  // C) trPar at target surface
585  //
586 
587  // initialize the return parameters vector
588  ManagedTrackParmPtr parm(cache.manage(parm_ref));
589  ManagedTrackParmPtr currPar(parm);
590  const Trk::TrackingVolume* staticVol = nullptr;
591  const Trk::TrackingVolume* currVol = nullptr;
592  const Trk::TrackingVolume* nextVol = nullptr;
593  std::vector<unsigned int> solutions;
594  const Trk::TrackingVolume* assocVol = nullptr;
595  // double tol = 0.001;
596  double path = 0.;
597  bool resolveActive = destSurf == nullptr;
598  if (!resolveActive && m_resolveActive) {
599  resolveActive = m_resolveActive;
600  }
601  if (cache.m_lastMaterialLayer && !cache.m_lastMaterialLayer->isOnLayer(parm->position())) {
602  cache.m_lastMaterialLayer = nullptr;
603  }
604  // set tracking geometry in cache
605  (void) cache.trackingGeometry(*m_navigator, ctx);
606  if (!cache.m_highestVolume) {
608  }
609  // resolve current position
610  Amg::Vector3D gp = parm->position();
611  if (vol && vol->inside(gp, m_tolerance)) {
612  staticVol = vol;
613  } else {
614  staticVol = cache.m_trackingGeometry->lowestStaticTrackingVolume(gp);
615  const Trk::TrackingVolume* nextStatVol = nullptr;
616  if (m_navigator->atVolumeBoundary(currPar.get(), staticVol, dir, nextStatVol, m_tolerance) &&
617  nextStatVol != staticVol) {
618  staticVol = nextStatVol;
619  }
620  }
621 
622  // navigation surfaces
623  if (cache.m_navigSurfs.capacity() > m_maxNavigSurf) {
624  cache.m_navigSurfs.reserve(m_maxNavigSurf);
625  }
626  cache.m_navigSurfs.clear();
627  if (destSurf) {
628  cache.m_navigSurfs.emplace_back(destSurf, false);
629  }
630  // alignable frame volume ?
631  if (staticVol && staticVol->geometrySignature() == Trk::Calo) {
632  if (staticVol->isAlignable()) {
633  const Trk::AlignableTrackingVolume* alignTV =
634  static_cast<const Trk::AlignableTrackingVolume*>(staticVol);
635  cache.m_identifiedParameters.reset();
636  return extrapolateInAlignableTV(
637  ctx, cache, prop, currPar.index(), destSurf, alignTV, dir, particle);
638  }
639  }
640 
641  // update if new static volume
642  if (staticVol && (staticVol != cache.m_currentStatic || resolveActive != m_resolveActive)) {
643  // retrieve boundaries
644  cache.m_currentStatic = staticVol;
645  cache.retrieveBoundaries();
646 
647  cache.m_detachedVols.clear();
648  cache.m_detachedBoundaries.clear();
649  cache.m_denseVols.clear();
650  cache.m_denseBoundaries.clear();
651  cache.m_layers.clear();
652  cache.m_navigLays.clear();
653 
655  staticVol->confinedDetachedVolumes();
656  if (!detVols.empty()) {
658  for (; iTer != detVols.end(); ++iTer) {
659  // active station ?
660  const Trk::Layer* layR = (*iTer)->layerRepresentation();
661  bool active = layR && layR->layerType();
662  const auto detBounds = (*iTer)->trackingVolume()->boundarySurfaces();
663  if (active) {
664  if (resolveActive) {
665  cache.m_detachedVols.emplace_back(*iTer, detBounds.size());
666  for (unsigned int ibb = 0; ibb < detBounds.size(); ibb++) {
667  const Trk::Surface& surf = (detBounds[ibb])->surfaceRepresentation();
668  cache.m_detachedBoundaries.emplace_back(&surf, true);
669  }
670  } else {
671  if (!m_resolveMultilayers || (*iTer)->multilayerRepresentation().empty()) {
672  cache.addOneNavigationLayer((*iTer)->trackingVolume(), layR);
673 
674  } else {
675  const auto& multi = (*iTer)->multilayerRepresentation();
676  for (const auto *i : multi) {
677  cache.addOneNavigationLayer((*iTer)->trackingVolume(), i);
678  }
679  }
680  }
681  } else if (staticVol->geometrySignature() != Trk::MS ||
682  !m_useMuonMatApprox ||
683  (*iTer)->name().compare((*iTer)->name().size() - 4, 4, "PERM") ==
684  0) { // retrieve
685  // inert
686  // detached
687  // objects
688  // only if
689  // needed
690  if ((*iTer)->trackingVolume()->zOverAtimesRho() != 0. &&
691  ((*iTer)->trackingVolume()->confinedDenseVolumes().empty()) &&
692  ((*iTer)->trackingVolume()->confinedArbitraryLayers().empty())) {
693  cache.m_denseVols.emplace_back((*iTer)->trackingVolume(), detBounds.size());
694 
695  for (unsigned int ibb = 0; ibb < detBounds.size(); ibb++) {
696  const Trk::Surface& surf = (detBounds[ibb])->surfaceRepresentation();
697  cache.m_denseBoundaries.emplace_back(&surf, true);
698  }
699  }
701  (*iTer)->trackingVolume()->confinedArbitraryLayers();
702  if (!(*iTer)->trackingVolume()->confinedDenseVolumes().empty() ||
703  (confLays.size() > detBounds.size())) {
704  cache.m_detachedVols.emplace_back(*iTer, detBounds.size());
705  for (unsigned int ibb = 0; ibb < detBounds.size(); ibb++) {
706  const Trk::Surface& surf =
707  (detBounds[ibb])->surfaceRepresentation();
708  cache.m_detachedBoundaries.emplace_back(&surf, true);
709  }
710  } else if (!confLays.empty()) {
711  for (const Trk::Layer* const lIt : confLays) {
712  cache.addOneNavigationLayer((*iTer)->trackingVolume(), (lIt));
713  }
714  }
715  }
716  }
717  }
718  cache.m_denseResolved = std::pair<unsigned int, unsigned int>(cache.m_denseVols.size(),
719  cache.m_denseBoundaries.size());
720  cache.m_layerResolved = cache.m_layers.size();
721  }
722 
723  cache.m_navigSurfs.insert(
724  cache.m_navigSurfs.end(), cache.m_staticBoundaries.begin(), cache.m_staticBoundaries.end());
725 
726  // resolve the use of dense volumes
727  if (staticVol) {
728  cache.m_dense = (staticVol->geometrySignature() == Trk::MS && m_useMuonMatApprox) ||
729  (staticVol->geometrySignature() != Trk::MS && m_useDenseVolumeDescription);
730  }
731  while (currPar && staticVol && staticVol->confinedDetachedVolumes().empty()) {
732  // propagate to closest surface
733  solutions.resize(0);
734  const Trk::TrackingVolume* propagVol = cache.m_dense ? staticVol : cache.m_highestVolume;
735  ATH_MSG_DEBUG(" [+] Starting propagation (static) at " << positionOutput(currPar->position())
736  << " in '" << propagVol->volumeName()
737  << "'");
738  // current static may carry non-trivial material properties, their use is optional;
739  // use highest volume as B field source
740  std::unique_ptr<Trk::TrackParameters> pNextPar = prop.propagate(ctx,*currPar,cache.m_navigSurfs,
741  dir,m_fieldProperties,particle,solutions,path,false,
742  false,propagVol);
743  ManagedTrackParmPtr nextPar(cache.manage(std::move(pNextPar)));
744  if (nextPar) {
745  ATH_MSG_DEBUG(" [+] Position after propagation - at "
746  << positionOutput(nextPar->position()));
747  }
748  if (!nextPar) {
750  return {};
751  }
752  if (nextPar) {
753  // collect material
754  if (propagVol->zOverAtimesRho() != 0. && !cache.m_matstates && cache.m_extrapolationCache) {
755  if (not cache.elossPointerOverwritten()) {
756  if (m_dumpCache) {
757  ATH_MSG_DEBUG(cache.to_string(" extrapolateToNextMaterialLayer"));
758  }
759  double dInX0 = std::abs(path) / propagVol->x0();
760  ATH_MSG_DEBUG(" add x0 " << dInX0);
761  cache.m_extrapolationCache->updateX0(dInX0);
762  Trk::MaterialProperties materialProperties(*propagVol, std::abs(path));
763  double currentqoverp = nextPar->parameters()[Trk::qOverP];
764  EnergyLoss eloss = m_elossupdater->energyLoss(
765  materialProperties, std::abs(1. / currentqoverp), 1., dir, particle);
766  ATH_MSG_DEBUG(" [M] Energy loss: STEP,EnergyLossUpdator:"
767  << nextPar->momentum().mag() - currPar->momentum().mag() << ","
768  << eloss.deltaE());
770  eloss.meanIoni(), eloss.sigmaIoni(), eloss.meanRad(), eloss.sigmaRad());
771  if (m_dumpCache) {
772  ATH_MSG_DEBUG(cache.to_string( " After"));
773  }
774  } else {
775  ATH_MSG_DEBUG(cache.elossPointerErrorMsg(__LINE__));
776  }
777  }
778  if (propagVol->zOverAtimesRho() != 0. && cache.m_matstates) {
779  double dInX0 = std::abs(path) / propagVol->x0();
780  Trk::MaterialProperties materialProperties(*propagVol, std::abs(path));
781  double scatsigma = std::sqrt(m_msupdater->sigmaSquare(
782  materialProperties, 1. / std::abs(nextPar->parameters()[qOverP]), 1., particle));
783  auto newsa = Trk::ScatteringAngles(
784  0, 0, scatsigma / std::sin(nextPar->parameters()[Trk::theta]), scatsigma);
785  // energy loss
786  double currentqoverp = nextPar->parameters()[Trk::qOverP];
787  EnergyLoss eloss = m_elossupdater->energyLoss(
788  materialProperties, std::abs(1. / currentqoverp), 1., dir, particle);
789  // compare energy loss
790  ATH_MSG_DEBUG(" [M] Energy loss: STEP,EnergyLossUpdator:"
791  << nextPar->momentum().mag() - currPar->momentum().mag() << ","
792  << eloss.deltaE());
793  // use curvilinear TPs to simplify retrieval by fitters
794  std::unique_ptr<Trk::TrackParameters> cvlTP(new Trk::CurvilinearParameters(
795  nextPar->position(), nextPar->momentum(), nextPar->charge()));
796  //
797  if (cache.m_extrapolationCache) {
798  if (m_dumpCache) {
799  ATH_MSG_DEBUG(cache.to_string( " mat states extrapolateToNextMaterialLayer"));
800  }
801  cache.m_extrapolationCache->updateX0(dInX0);
803  eloss.meanIoni(), eloss.sigmaIoni(), eloss.meanRad(), eloss.sigmaRad());
804  if (m_dumpCache) {
805  ATH_MSG_DEBUG(cache.to_string( " After"));
806  }
807  }
808  auto mefot = std::make_unique<Trk::MaterialEffectsOnTrack>(
809  dInX0, newsa, std::make_unique<Trk::EnergyLoss>(std::move(eloss)),
810  cvlTP->associatedSurface());
811  cache.m_matstates->push_back(new TrackStateOnSurface(
812  nullptr, std::move(cvlTP), std::move(mefot)));
813  ATH_MSG_DEBUG(" [M] Collecting material from static volume '" << propagVol->volumeName()
814  << "', t/X0 = " << dInX0);
815  }
816  }
817  currPar = std::move(nextPar);
818  unsigned int isurf = destSurf ? 1 : 0;
819  if (destSurf && solutions[0] == 0) {
820  return currPar;
821  }
822  if (destSurf && solutions.size() > 1 && solutions[1] == 0) {
823  return currPar;
824  }
825  if (solutions[0] <= isurf + cache.m_staticBoundaries.size()) { // static volume boundary
826  // use global coordinates to retrieve attached volume (just for static!)
827  const Trk::TrackingVolume* nextVol =
828  cache.m_currentStatic->boundarySurfaces()[solutions[0] - isurf]->attachedVolume(
829  currPar->position(), currPar->momentum(), dir);
830  cache.m_parametersAtBoundary.boundaryInformation(nextVol, currPar, currPar);
831  if (!nextVol) {
832  ATH_MSG_DEBUG(" [!] World boundary at position R,z: " << currPar->position().perp() << ","
833  << currPar->position().z());
834  } else {
835  ATH_MSG_DEBUG("M-S Crossing to static volume '" << nextVol->volumeName() << "'.'");
836  }
837  }
838  return {};
839  }
840 
841  if (!staticVol || (staticVol->confinedDetachedVolumes().empty()) || !currPar) {
842  return {};
843  }
844 
845  // reset remaining counters
846  cache.m_currentDense = cache.m_dense ? cache.m_currentStatic : cache.m_highestVolume;
847  cache.m_navigBoundaries.clear();
848  if (cache.m_denseVols.size() > cache.m_denseResolved.first) {
849  cache.m_denseVols.resize(cache.m_denseResolved.first);
850  }
851  while (cache.m_denseBoundaries.size() > cache.m_denseResolved.second) {
852  cache.m_denseBoundaries.pop_back();
853  }
854  if (cache.m_layers.size() > cache.m_layerResolved) {
855  cache.m_navigLays.resize(cache.m_layerResolved);
856  }
857  while (cache.m_layers.size() > cache.m_layerResolved) {
858  cache.m_layers.pop_back();
859  }
860 
861  // current detached volumes
862  // collect : subvolume boundaries, ordered/unordered layers, confined dense volumes
864  // const Trk::DetachedTrackingVolume* currentActive = 0;
865  if (cache.m_navigVolsInt.capacity() > m_maxNavigVol) {
866  cache.m_navigVolsInt.reserve(m_maxNavigVol);
867  }
868  cache.m_navigVolsInt.clear();
869 
870  gp = currPar->position();
871  std::vector<const Trk::DetachedTrackingVolume*> detVols =
874  for (; dIter != detVols.end(); ++dIter) {
875  const Trk::Layer* layR = (*dIter)->layerRepresentation();
876  bool active = layR && layR->layerType();
877  if (active && !resolveActive) {
878  continue;
879  }
880  if (!active && staticVol->geometrySignature() == Trk::MS && m_useMuonMatApprox &&
881  (*dIter)->name().compare((*dIter)->name().size() - 4, 4, "PERM") != 0) {
882  continue;
883  }
884  const Trk::TrackingVolume* dVol = (*dIter)->trackingVolume();
885  // detached volume exit ?
886  bool dExit =
887  m_navigator->atVolumeBoundary(currPar.get(), dVol, dir, nextVol, m_tolerance) && !nextVol;
888  if (dExit) {
889  continue;
890  }
891  // inert material
892  const auto confinedDense = dVol->confinedDenseVolumes();
893  const auto confinedLays = dVol->confinedArbitraryLayers();
894 
895  if (!active && confinedDense.empty() && confinedLays.empty()) {
896  continue;
897  }
898  const auto bounds = dVol->boundarySurfaces();
899  if (!active && confinedDense.empty() && confinedLays.size() <= bounds.size()) {
900  continue;
901  }
902  if (!confinedDense.empty() || !confinedLays.empty()) {
903  cache.m_navigVolsInt.emplace_back(dVol, bounds.size());
904  for (unsigned int ib = 0; ib < bounds.size(); ib++) {
905  const Trk::Surface& surf = (bounds[ib])->surfaceRepresentation();
906  cache.m_navigBoundaries.emplace_back(&surf, true);
907  }
908  // collect dense volume boundary
909  if (!confinedDense.empty()) {
910  auto vIter = confinedDense.begin();
911  for (; vIter != confinedDense.end(); ++vIter) {
912  const auto bounds = (*vIter)->boundarySurfaces();
913  cache.m_denseVols.emplace_back(*vIter, bounds.size());
914  for (unsigned int ib = 0; ib < bounds.size(); ib++) {
915  const Trk::Surface& surf = (bounds[ib])->surfaceRepresentation();
916  cache.m_denseBoundaries.emplace_back(&surf, true);
917  }
918  }
919  }
920  // collect unordered layers
921  if (!confinedLays.empty()) {
922  for (const auto *confinedLay : confinedLays) {
923  cache.addOneNavigationLayer(dVol, confinedLay);
924  }
925  }
926  } else { // active material
927  const Trk::TrackingVolume* detVol = dVol->associatedSubVolume(gp);
928  if (!detVol && dVol->confinedVolumes()) {
930  for (const auto *subvol : subvols) {
931  if (subvol->inside(gp, m_tolerance)) {
932  detVol = subvol;
933  break;
934  }
935  }
936  }
937 
938  if (!detVol) {
939  detVol = dVol;
940  }
941  bool vExit =
942  m_navigator->atVolumeBoundary(currPar.get(), detVol, dir, nextVol, m_tolerance) &&
943  nextVol != detVol;
944  if (vExit && nextVol && nextVol->inside(gp, m_tolerance)) {
945  detVol = nextVol;
946  vExit = false;
947  }
948  if (!vExit) {
949  const auto bounds = detVol->boundarySurfaces();
950  cache.m_navigVolsInt.emplace_back(detVol, bounds.size());
951  for (unsigned int ib = 0; ib < bounds.size(); ib++) {
952  const Trk::Surface& surf = (bounds[ib])->surfaceRepresentation();
953  cache.m_navigBoundaries.emplace_back(&surf, true);
954  }
955  if (detVol->zOverAtimesRho() != 0.) {
956  cache.m_denseVols.emplace_back(detVol, bounds.size());
957  for (unsigned int ib = 0; ib < bounds.size(); ib++) {
958  const Trk::Surface& surf = (bounds[ib])->surfaceRepresentation();
959  cache.m_denseBoundaries.emplace_back(&surf, true);
960  }
961  }
962  // layers ?
963  if (detVol->confinedLayers()) {
964  const Trk::Layer* lay = detVol->associatedLayer(gp);
965 
966  if (lay) {
967  cache.addOneNavigationLayer(detVol, lay);
968 
969  }
970  const Trk::Layer* nextLayer =
971  detVol->nextLayer(currPar->position(), dir * currPar->momentum().unit(), true);
972  if (nextLayer && nextLayer != lay) {
973  cache.addOneNavigationLayer(detVol, nextLayer);
974  }
975  } else if (!detVol->confinedArbitraryLayers().empty()) {
977  for (const auto *layer : layers) {
978  cache.addOneNavigationLayer(detVol, layer);
979  }
980  }
981  }
982  }
983  }
984  cache.copyToNavigationSurfaces();
985 
986  // current dense
987  cache.m_currentDense = cache.m_highestVolume;
988  if (cache.m_dense && cache.m_denseVols.empty()) {
989  cache.m_currentDense = cache.m_currentStatic;
990  } else {
991  for (unsigned int i = 0; i < cache.m_denseVols.size(); i++) {
992  const Trk::TrackingVolume* dVol = cache.m_denseVols[i].first;
993  if (dVol->inside(currPar->position(), m_tolerance) && dVol->zOverAtimesRho() != 0.) {
994  if (!m_navigator->atVolumeBoundary(currPar.get(), dVol, dir, nextVol, m_tolerance) ||
995  nextVol == dVol) {
996  cache.m_currentDense = dVol;
997  }
998  }
999  }
1000  }
1001 
1002  // ready to propagate
1003  // till: A/ static volume boundary(bcheck=true) , B/ material layer(bcheck=true), C/ destination
1004  // surface(bcheck=false) update of cache.m_navigSurfs required if I/ entry into new navig volume,
1005  // II/ exit from currentActive without overlaps
1006 
1007  nextVol = nullptr;
1008  while (currPar) {
1009  double path = 0.;
1010  std::vector<unsigned int> solutions;
1011  // verify that material input makes sense
1012  Amg::Vector3D tp =
1013  currPar->position() + 2 * m_tolerance * dir * currPar->momentum().normalized();
1014  if (!(cache.m_currentDense->inside(tp, 0.))) {
1015  cache.m_currentDense = cache.m_highestVolume;
1016  if (cache.m_dense && cache.m_denseVols.empty()) {
1017  cache.m_currentDense = cache.m_currentStatic;
1018  } else {
1019  for (unsigned int i = 0; i < cache.m_denseVols.size(); i++) {
1020  const Trk::TrackingVolume* dVol = cache.m_denseVols[i].first;
1021  if (dVol->inside(tp, 0.) && dVol->zOverAtimesRho() != 0.) {
1022  cache.m_currentDense = dVol;
1023  }
1024  }
1025  }
1026  }
1027  // propagate now
1028  ATH_MSG_DEBUG(" [+] Starting propagation at position "
1029  << positionOutput(currPar->position())
1030  << " (current momentum: " << currPar->momentum().mag() << ")");
1031  ATH_MSG_DEBUG(" [+] " << cache.m_navigSurfs.size() << " target surfaces in '"
1032  << cache.m_currentDense->volumeName() << "'.");
1033  ManagedTrackParmPtr nextPar(
1034  cache.manage(prop.propagate(ctx,
1035  *currPar,
1036  cache.m_navigSurfs,
1037  dir,
1038  m_fieldProperties,
1039  particle,
1040  solutions,
1041  path,
1042  false,
1043  false,
1044  cache.m_currentDense)));
1045  if (nextPar) {
1046  ATH_MSG_DEBUG(" [+] Position after propagation - at "
1047  << positionOutput(nextPar->position()));
1048  }
1049  // check missing volume boundary
1050  if (nextPar && !(cache.m_currentDense->inside(nextPar->position(), m_tolerance) ||
1051  m_navigator->atVolumeBoundary(
1052  nextPar.get(), cache.m_currentDense, dir, assocVol, m_tolerance))) {
1053  ATH_MSG_DEBUG(" [!] ERROR: missing volume boundary for volume"
1054  << cache.m_currentDense->volumeName());
1055  if (cache.m_currentDense->zOverAtimesRho() != 0.) {
1056  ATH_MSG_DEBUG(" [!] ERROR: trying to recover: repeat the propagation step in"
1057  << cache.m_highestVolume->volumeName());
1058  cache.m_currentDense = cache.m_highestVolume;
1059  continue;
1060  }
1061  }
1062  if (nextPar) {
1063  ATH_MSG_DEBUG(" [+] Number of intersection solutions: " << solutions.size());
1064  if (cache.m_currentDense->zOverAtimesRho() != 0. && !cache.m_matstates &&
1065  cache.m_extrapolationCache) {
1066  if (not cache.elossPointerOverwritten()) {
1067  if (m_dumpCache) {
1068  ATH_MSG_DEBUG(cache.to_string( " extrapolateToNextMaterialLayer dense "));
1069  }
1070  double dInX0 = std::abs(path) / cache.m_currentDense->x0();
1071  cache.m_extrapolationCache->updateX0(dInX0);
1072  Trk::MaterialProperties materialProperties(*cache.m_currentDense, std::abs(path));
1073  double currentqoverp = nextPar->parameters()[Trk::qOverP];
1074  Trk::EnergyLoss eloss = m_elossupdater->energyLoss(
1075  materialProperties, std::abs(1. / currentqoverp), 1., dir, particle);
1077  eloss.meanIoni(), eloss.sigmaIoni(), eloss.meanRad(), eloss.sigmaRad());
1078  if (m_dumpCache) {
1079  ATH_MSG_DEBUG(cache.to_string(" After"));
1080  }
1081  } else {
1082  ATH_MSG_DEBUG(cache.elossPointerErrorMsg(__LINE__));
1083  }
1084  }
1085  // collect material
1086  if (cache.m_currentDense->zOverAtimesRho() != 0. && cache.m_matstates) {
1087  double dInX0 = std::abs(path) / cache.m_currentDense->x0();
1088  if (path * dir < 0.) {
1089  ATH_MSG_WARNING(" got negative path!! " << path);
1090  }
1091  Trk::MaterialProperties materialProperties(*cache.m_currentDense, std::abs(path));
1092  double scatsigma = std::sqrt(m_msupdater->sigmaSquare(
1093  materialProperties, 1. / std::abs(nextPar->parameters()[qOverP]), 1., particle));
1094  auto newsa = Trk::ScatteringAngles(
1095  0, 0, scatsigma / std::sin(nextPar->parameters()[Trk::theta]), scatsigma);
1096  // energy loss
1097  double currentqoverp = nextPar->parameters()[Trk::qOverP];
1098  EnergyLoss eloss = m_elossupdater->energyLoss(
1099  materialProperties, std::abs(1. / currentqoverp), 1., dir, particle);
1100  // compare energy loss
1101  ATH_MSG_DEBUG(" [M] Energy loss: STEP,EnergyLossUpdator:"
1102  << nextPar->momentum().mag() - currPar->momentum().mag() << ","
1103  << eloss.deltaE());
1104 
1105  // use curvilinear TPs to simplify retrieval by fitters
1106  std::unique_ptr<Trk::TrackParameters> cvlTP(new Trk::CurvilinearParameters(
1107  nextPar->position(), nextPar->momentum(), nextPar->charge()));
1108 
1109  if (cache.m_extrapolationCache) {
1110  if (m_dumpCache) {
1111  ATH_MSG_DEBUG(cache.to_string(" extrapolateToNextMaterialLayer dense"));
1112  }
1113  cache.m_extrapolationCache->updateX0(dInX0);
1114  cache.m_extrapolationCache->updateEloss(eloss.meanIoni(),
1115  eloss.sigmaIoni(),
1116  eloss.meanRad(),
1117  eloss.sigmaRad());
1118  if (m_dumpCache) {
1119  ATH_MSG_DEBUG(cache.to_string(" After"));
1120  }
1121  }
1122  auto mefot = std::make_unique<Trk::MaterialEffectsOnTrack>(
1123  dInX0, newsa, std::make_unique<Trk::EnergyLoss>(std::move(eloss)), cvlTP->associatedSurface());
1124 
1125  cache.m_matstates->push_back(new TrackStateOnSurface(
1126  nullptr, std::move(cvlTP), std::move(mefot)));
1127 
1128  ATH_MSG_DEBUG(" [M] Collecting material from dense volume '"
1129  << cache.m_currentDense->volumeName() << "', t/X0 = " << dInX0);
1130  }
1131  // destination surface
1132  if (destSurf && solutions[0] == 0) {
1133  return nextPar;
1134  }
1135  if (destSurf && solutions.size() > 1 && solutions[1] == 0) {
1136  return nextPar;
1137  }
1138  // destination surface missed ?
1139  if (destSurf) {
1140  double dist = 0.;
1142  nextPar->position(), nextPar->momentum().normalized());
1143  if (distSol.numberOfSolutions() > 0) {
1144  dist = distSol.first();
1145  if (distSol.numberOfSolutions() > 1 && std::abs(dist) < m_tolerance) {
1146  dist = distSol.second();
1147  }
1148  if (distSol.numberOfSolutions() > 1 && dist * dir < 0. && distSol.second() * dir > 0.) {
1149  dist = distSol.second();
1150  }
1151  } else {
1152  dist = distSol.toPointOfClosestApproach();
1153  }
1154  if (dist * dir < 0.) {
1155  ATH_MSG_DEBUG(" [+] Destination surface missed ? " << dist << "," << dir);
1157  return {};
1158  }
1159  ATH_MSG_DEBUG(" [+] New 3D-distance to destinatiion - d3 = " << dist * dir);
1160  }
1161 
1162  int iDest = destSurf ? 1 : 0;
1163  unsigned int iSol = 0;
1164  while (iSol < solutions.size()) {
1165  if (solutions[iSol] < iDest + cache.m_staticBoundaries.size()) {
1166  // material attached ?
1167  const Trk::Layer* mb = cache.m_navigSurfs[solutions[iSol]].first->materialLayer();
1168  if (mb) {
1169  if (mb->layerMaterialProperties() &&
1170  mb->layerMaterialProperties()->fullMaterial(nextPar->position())) {
1171 
1172  const IMaterialEffectsUpdator* currentUpdator =
1173  subMaterialEffectsUpdator(*cache.m_currentStatic);
1174  IMaterialEffectsUpdator::ICache& currentUpdatorCache =
1176 
1177  if (currentUpdator) {
1178  nextPar = cache.manage(
1179  currentUpdator->update(currentUpdatorCache,
1180  nextPar.get(),
1181  *mb,
1182  dir,
1183  particle,
1184  matupmode));
1185  }
1186  if (!nextPar) {
1188  return {};
1189  }
1190 
1191  // collect material
1192  const Trk::MaterialProperties* lmat = mb->fullUpdateMaterialProperties(*nextPar);
1193  double lx0 = lmat->x0();
1194  double layThick = mb->thickness();
1195 
1196  double thick = 0.;
1197  double costr =
1198  std::abs(nextPar->momentum().normalized().dot(mb->surfaceRepresentation().normal()));
1199 
1200  if (mb->surfaceRepresentation().isOnSurface(
1201  mb->surfaceRepresentation().center(), false, 0., 0.)) {
1202  thick = fmin(mb->surfaceRepresentation().bounds().r(),
1203  layThick / std::abs(nextPar->momentum().normalized().dot(
1204  mb->surfaceRepresentation().normal())));
1205  } else {
1206  thick = fmin(2 * mb->thickness(), layThick / (1 - costr));
1207  }
1208 
1209  if (!cache.m_matstates && cache.m_extrapolationCache) {
1210  if (not cache.elossPointerOverwritten()) {
1211  double dInX0 = thick / lx0;
1212  if (m_dumpCache) {
1213  ATH_MSG_DEBUG(cache.to_string(" extrapolateToNextMaterialLayer thin "));
1214  }
1215  cache.m_extrapolationCache->updateX0(dInX0);
1216  double currentqoverp = nextPar->parameters()[Trk::qOverP];
1217  EnergyLoss eloss = m_elossupdater->energyLoss(
1218  *lmat, std::abs(1. / currentqoverp), 1. / costr, dir, particle);
1220  eloss.meanIoni(), eloss.sigmaIoni(), eloss.meanRad(), eloss.sigmaRad());
1221  if (m_dumpCache) {
1222  ATH_MSG_DEBUG(cache.to_string(" After"));
1223  }
1224  } else {
1225  ATH_MSG_DEBUG(cache.elossPointerErrorMsg(__LINE__));
1226  }
1227 
1228  }
1229 
1230  if (cache.m_matstates) {
1231  double dInX0 = thick / lx0;
1232  double scatsigma = std::sqrt(m_msupdater->sigmaSquare(
1233  *lmat, 1. / std::abs(nextPar->parameters()[qOverP]), 1., particle));
1234  auto newsa = Trk::ScatteringAngles(
1235  0, 0, scatsigma / std::sin(nextPar->parameters()[Trk::theta]), scatsigma);
1236  // energy loss
1237  double currentqoverp = nextPar->parameters()[Trk::qOverP];
1238  EnergyLoss eloss = m_elossupdater->energyLoss(
1239  *lmat, std::abs(1. / currentqoverp), 1. / costr, dir, particle);
1240 
1241  // use curvilinear TPs to simplify retrieval by fitters
1242  std::unique_ptr<Trk::TrackParameters> cvlTP(new Trk::CurvilinearParameters(
1243  nextPar->position(), nextPar->momentum(), nextPar->charge()));
1244  if (cache.m_extrapolationCache) {
1245  if (not cache.elossPointerOverwritten()) {
1246  if (m_dumpCache) {
1247  ATH_MSG_DEBUG(cache.to_string(" extrapolateToNextMaterialLayer thin "));
1248  }
1249  cache.m_extrapolationCache->updateX0(dInX0);
1251  eloss.meanIoni(), eloss.sigmaIoni(), eloss.meanRad(), eloss.sigmaRad());
1252  if (m_dumpCache) {
1253  ATH_MSG_DEBUG(cache.to_string(" After"));
1254  }
1255  } else {
1256  ATH_MSG_DEBUG(cache.elossPointerErrorMsg(__LINE__));
1257  }
1258  }
1259  auto mefot =
1260  std::make_unique<Trk::MaterialEffectsOnTrack>(
1261  dInX0, newsa,
1262  std::make_unique<Trk::EnergyLoss>(std::move(eloss)),
1263  cvlTP->associatedSurface());
1264  cache.m_matstates->push_back(new TrackStateOnSurface(
1265  nullptr, std::move(cvlTP), std::move(mefot)));
1266  }
1267  }
1268  } // end material update at massive (static volume) boundary
1269 
1270  // static volume boundary; return to the main loop
1271  unsigned int index = solutions[iSol] - iDest;
1272  // use global coordinates to retrieve attached volume (just for static!)
1273  nextVol = (cache.m_currentStatic->boundarySurfaces())[index]->attachedVolume(
1274  nextPar->position(), nextPar->momentum(), dir);
1275  // double check the next volume
1276  if (nextVol &&
1277  !(nextVol->inside(nextPar->position() + 0.01 * dir * nextPar->momentum().normalized(),
1278  m_tolerance))) {
1279  ATH_MSG_DEBUG(" [!] WARNING: wrongly assigned static volume ?"
1280  << cache.m_currentStatic->volumeName() << "->" << nextVol->volumeName());
1282  nextPar->position() + 0.01 * nextPar->momentum().normalized());
1283  if (nextVol) {
1284  ATH_MSG_DEBUG(" new search yields: " << nextVol->volumeName());
1285  }
1286  }
1287  // end double check - to be removed after validation of the geometry gluing
1288  if (nextVol != cache.m_currentStatic) {
1289  cache.m_parametersAtBoundary.boundaryInformation(nextVol, nextPar, nextPar);
1290  ATH_MSG_DEBUG(" [+] StaticVol boundary reached of '"
1291  << cache.m_currentStatic->volumeName() << "'.");
1292  if (m_navigator->atVolumeBoundary(
1293  nextPar.get(), cache.m_currentStatic, dir, assocVol, m_tolerance) &&
1294  assocVol != cache.m_currentStatic) {
1295  cache.m_currentDense = m_useMuonMatApprox ? nextVol : cache.m_highestVolume;
1296  }
1297  // no next volume found --- end of the world
1298  if (!nextVol) {
1299  ATH_MSG_DEBUG(" [+] Word boundary reached - at "
1300  << positionOutput(nextPar->position()));
1301  }
1302  // next volume found and parameters are at boundary
1303  if (nextVol && nextPar) {
1304  ATH_MSG_DEBUG(" [+] Crossing to next volume '" << nextVol->volumeName() << "'");
1305  ATH_MSG_DEBUG(" [+] Crossing position is - at "
1306  << positionOutput(nextPar->position()));
1307  }
1308  return {};
1309  }
1310  } else if (solutions[iSol] <
1311  iDest + cache.m_staticBoundaries.size() + cache.m_layers.size()) {
1312  // next layer; don't return passive material layers unless required
1313  unsigned int index = solutions[iSol] - iDest - cache.m_staticBoundaries.size();
1314  const Trk::Layer* nextLayer = cache.m_navigLays[index].second;
1315  // material update HERE and NOW (pre/post udpdate ? )
1316  // don't repeat if identical to last update && input parameters on the layer
1317  bool collect = true;
1318  if (nextLayer == cache.m_lastMaterialLayer &&
1320  ATH_MSG_DEBUG(
1321  " [!] This layer is identical to the one with last material update, return layer "
1322  "without repeating the update");
1323  collect = false;
1324  if (!destSurf && (nextLayer->layerType() > 0 || m_returnPassiveLayers)) {
1325  return nextPar;
1326  }
1327  }
1328  double layThick = nextLayer->thickness();
1329  if (collect && layThick > 0.) { // collect material
1330 
1331  // get the right updator
1332  const IMaterialEffectsUpdator* currentUpdator =
1333  subMaterialEffectsUpdator(*cache.m_currentStatic);
1334  IMaterialEffectsUpdator::ICache& currentUpdatorCache =
1336 
1337  if (currentUpdator) {
1338  nextPar = cache.manage(
1339  currentUpdator->update(currentUpdatorCache,
1340  nextPar.get(),
1341  *nextLayer,
1342  dir,
1343  particle,
1344  matupmode));
1345  }
1346  if (!nextPar) {
1348  return {};
1349  }
1350 
1351  // collect material
1352  double lx0 = nextLayer->fullUpdateMaterialProperties(*nextPar)->x0();
1353 
1354  double thick = 0.;
1355  double costr = std::abs(
1356  nextPar->momentum().normalized().dot(nextLayer->surfaceRepresentation().normal()));
1357 
1358  if (nextLayer->surfaceRepresentation().isOnSurface(
1359  nextLayer->surfaceRepresentation().center(), false, 0., 0.)) {
1360  thick = fmin(nextLayer->surfaceRepresentation().bounds().r(),
1361  layThick / std::abs(nextPar->momentum().normalized().dot(
1362  nextLayer->surfaceRepresentation().normal())));
1363  } else {
1364  thick = fmin(2 * nextLayer->thickness(), layThick / (1 - costr));
1365  }
1366 
1367  if (!cache.m_matstates && cache.m_extrapolationCache) {
1368  if (not cache.elossPointerOverwritten()) {
1369  double dInX0 = thick / lx0;
1370  if (m_dumpCache) {
1371  ATH_MSG_DEBUG(cache.to_string(" extrapolateToNextMaterialLayer thin "));
1372  }
1373  cache.m_extrapolationCache->updateX0(dInX0);
1374  Trk::MaterialProperties materialProperties(
1375  *nextLayer->fullUpdateMaterialProperties(*nextPar)); // !<@TODO check
1376  double currentqoverp = nextPar->parameters()[Trk::qOverP];
1377  EnergyLoss eloss = m_elossupdater->energyLoss(
1378  materialProperties, std::abs(1. / currentqoverp), 1. / costr, dir, particle);
1380  eloss.meanIoni(), eloss.sigmaIoni(), eloss.meanRad(), eloss.sigmaRad());
1381  if (m_dumpCache) {
1382  ATH_MSG_DEBUG(cache.to_string( " After"));
1383  }
1384  } else {
1385  ATH_MSG_DEBUG(cache.elossPointerErrorMsg(__LINE__));
1386  }
1387  }
1388 
1389  if (cache.m_matstates) {
1390  double dInX0 = thick / lx0;
1391  Trk::MaterialProperties materialProperties(
1392  *nextLayer->fullUpdateMaterialProperties(*nextPar)); // !<@TODOcheck
1393  double scatsigma = std::sqrt(m_msupdater->sigmaSquare(
1394  materialProperties, 1. / std::abs(nextPar->parameters()[qOverP]), 1., particle));
1395  const double par_theta = std::abs(nextPar->parameters()[Trk::theta]) > FLT_EPSILON
1396  ? nextPar->parameters()[Trk::theta]
1397  : FLT_EPSILON;
1398  Trk::ScatteringAngles newsa(0, 0, scatsigma / std::sin(par_theta), scatsigma);
1399  // energy loss
1400  double currentqoverp = nextPar->parameters()[Trk::qOverP];
1401  EnergyLoss eloss = m_elossupdater->energyLoss(
1402  materialProperties, std::abs(1. / currentqoverp), 1. / costr, dir, particle);
1403 
1404  // use curvilinear TPs to simplify retrieval by fitters
1405  auto cvlTP = std::make_unique<Trk::CurvilinearParameters>(
1406  nextPar->position(), nextPar->momentum(), nextPar->charge());
1407  if (cache.m_extrapolationCache) {
1408  if (not cache.elossPointerOverwritten()) {
1409  if (m_dumpCache) {
1410  ATH_MSG_DEBUG(cache.to_string(" extrapolateToNextMaterialLayer thin "));
1411  }
1412  cache.m_extrapolationCache->updateX0(dInX0);
1414  eloss.meanIoni(), eloss.sigmaIoni(), eloss.meanRad(), eloss.sigmaRad());
1415  if (m_dumpCache) {
1416  ATH_MSG_DEBUG(cache.to_string( " After"));
1417  }
1418  } else {
1419  ATH_MSG_DEBUG(cache.elossPointerErrorMsg(__LINE__));
1420  }
1421  }
1422  auto mefot = std::make_unique<Trk::MaterialEffectsOnTrack>(
1423  dInX0, newsa, std::make_unique<Trk::EnergyLoss>(std::move(eloss)), cvlTP->associatedSurface());
1424  cache.m_matstates->push_back(new TrackStateOnSurface(
1425  nullptr, std::move(cvlTP), std::move(mefot)));
1426  }
1427  //
1428  if (m_cacheLastMatLayer) {
1429  cache.m_lastMaterialLayer = nextLayer;
1430  }
1431  if (!destSurf && (nextLayer->layerType() > 0 || m_returnPassiveLayers)) {
1432  return nextPar;
1433  }
1434  }
1435  if (resolveActive) {
1436  // if ordered layers, retrieve the next layer and replace the current one in the list
1437  if (cache.m_navigLays[index].first &&
1438  cache.m_navigLays[index].first->confinedLayers()) {
1439  const Trk::Layer* newLayer = cache.m_navigLays[index].first->nextLayer(
1440  nextPar->position(), dir * nextPar->momentum().normalized(), true);
1441  if (newLayer) {
1442  cache.m_navigLays[index].second = newLayer;
1443  cache.m_navigSurfs[solutions[iSol]].first = &(newLayer->surfaceRepresentation());
1444  }
1445  }
1446  }
1447  // not necessary: currPar = nextPar; since done outside the loop and currPar not used
1448  // inside the loop
1449  } else if (solutions[iSol] < iDest + cache.m_staticBoundaries.size() +
1450  cache.m_layers.size() + cache.m_denseBoundaries.size()) {
1451  // dense volume boundary
1452  unsigned int index =
1453  solutions[iSol] - iDest - cache.m_staticBoundaries.size() - cache.m_layers.size();
1454  std::vector<std::pair<const Trk::TrackingVolume*, unsigned int>>::iterator dIter =
1455  cache.m_denseVols.begin();
1456  while (dIter != cache.m_denseVols.end() && index >= (*dIter).second) {
1457  index -= (*dIter).second;
1458  ++dIter;
1459  }
1460  if (dIter != cache.m_denseVols.end()) {
1461  currVol = (*dIter).first;
1462  nextVol =
1463  ((*dIter).first->boundarySurfaces())[index]->attachedVolume(*nextPar, dir);
1464  // boundary orientation not reliable
1465  Amg::Vector3D tp =
1466  nextPar->position() + 2 * m_tolerance * dir * nextPar->momentum().normalized();
1467  if (currVol->inside(tp, m_tolerance)) {
1468  cache.m_currentDense = currVol;
1469  } else if (!nextVol || !nextVol->inside(tp, m_tolerance)) { // search for dense volumes
1470  cache.m_currentDense = cache.m_highestVolume;
1471  if (cache.m_dense && cache.m_denseVols.empty()) {
1472  cache.m_currentDense = cache.m_currentStatic;
1473  } else {
1474  for (unsigned int i = 0; i < cache.m_denseVols.size(); i++) {
1475  const Trk::TrackingVolume* dVol = cache.m_denseVols[i].first;
1476  if (dVol->inside(tp, 0.) && dVol->zOverAtimesRho() != 0.) {
1477  cache.m_currentDense = dVol;
1478  ATH_MSG_DEBUG(" [+] Next dense volume found: '"
1479  << cache.m_currentDense->volumeName() << "'.");
1480  break;
1481  }
1482  } // loop over dense volumes
1483  }
1484  } else {
1485  cache.m_currentDense = nextVol;
1486  ATH_MSG_DEBUG(" [+] Next dense volume: '" << cache.m_currentDense->volumeName()
1487  << "'.");
1488  }
1489  }
1490  } else if (solutions[iSol] < iDest + cache.m_staticBoundaries.size() +
1491  cache.m_layers.size() + cache.m_denseBoundaries.size() +
1492  cache.m_navigBoundaries.size()) {
1493  // navig volume boundary
1494  unsigned int index = solutions[iSol] - iDest - cache.m_staticBoundaries.size() -
1495  cache.m_layers.size() - cache.m_denseBoundaries.size();
1496  std::vector<std::pair<const Trk::TrackingVolume*, unsigned int>>::iterator nIter =
1497  cache.m_navigVolsInt.begin();
1498  while (nIter != cache.m_navigVolsInt.end() && index >= (*nIter).second) {
1499  index -= (*nIter).second;
1500  ++nIter;
1501  }
1502  if (nIter != cache.m_navigVolsInt.end()) {
1503  currVol = (*nIter).first;
1504  nextVol =
1505  ((*nIter).first->boundarySurfaces())[index]->attachedVolume(*nextPar, dir);
1506  // boundary orientation not reliable
1507  Amg::Vector3D tp =
1508  nextPar->position() + 2 * m_tolerance * dir * nextPar->momentum().normalized();
1509  if (nextVol && nextVol->inside(tp, 0.)) {
1510  ATH_MSG_DEBUG(" [+] Navigation volume boundary, entering volume '"
1511  << nextVol->volumeName() << "'.");
1512  } else if (currVol->inside(tp, 0.)) {
1513  nextVol = currVol;
1514  ATH_MSG_DEBUG(" [+] Navigation volume boundary, entering volume '"
1515  << nextVol->volumeName() << "'.");
1516  } else {
1517  nextVol = nullptr;
1518  ATH_MSG_DEBUG(" [+] Navigation volume boundary, leaving volume '"
1519  << currVol->volumeName() << "'.");
1520  }
1521  // not necessary: currPar = nextPar; since done outside the loop and currPar not used
1522  // inside the loop return only if detached volume boundaries not collected
1523  if (nextVol) {
1524  return extrapolateToNextMaterialLayer(ctx,
1525  cache,
1526  prop,
1527  nextPar.index(),
1528  destSurf,
1529  cache.m_currentStatic,
1530  dir,
1531  bcheck,
1532  particle,
1533  matupmode);
1534  }
1535  }
1536  } else if (solutions[iSol] < iDest + cache.m_staticBoundaries.size() +
1537  cache.m_layers.size() + cache.m_denseBoundaries.size() +
1538  cache.m_navigBoundaries.size() +
1539  cache.m_detachedBoundaries.size()) {
1540  // detached volume boundary
1541  unsigned int index = solutions[iSol] - iDest - cache.m_staticBoundaries.size() -
1542  cache.m_layers.size() - cache.m_denseBoundaries.size() -
1543  cache.m_navigBoundaries.size();
1544  std::vector<std::pair<const Trk::DetachedTrackingVolume*, unsigned int>>::iterator dIter =
1545  cache.m_detachedVols.begin();
1546  while (dIter != cache.m_detachedVols.end() && index >= (*dIter).second) {
1547  index -= (*dIter).second;
1548  ++dIter;
1549  }
1550  if (dIter != cache.m_detachedVols.end()) {
1551  currVol = (*dIter).first->trackingVolume();
1552  // boundary orientation not reliable
1553  nextVol =
1554  ((*dIter).first->trackingVolume()->boundarySurfaces())[index]->attachedVolume(
1555  *nextPar, dir);
1556  Amg::Vector3D tp =
1557  nextPar->position() + 2 * m_tolerance * dir * nextPar->momentum().normalized();
1558  if (nextVol && nextVol->inside(tp, 0.)) {
1559  ATH_MSG_DEBUG(" [+] Detached volume boundary, entering volume '"
1560  << nextVol->volumeName() << "'.");
1561  } else if (currVol->inside(tp, 0.)) {
1562  nextVol = currVol;
1563  ATH_MSG_DEBUG(" [+] Detached volume boundary, entering volume '"
1564  << nextVol->volumeName() << "'.");
1565  } else {
1566  nextVol = nullptr;
1567  ATH_MSG_DEBUG(" [+] Detached volume boundary, leaving volume '"
1568  << currVol->volumeName() << "'.");
1569  }
1570  // not necessary: currPar = nextPar; since done outside the loop and currPar not used
1571  // inside the loop if ( nextVol || !detachedBoundariesIncluded)
1572  if (nextVol) {
1573  return extrapolateToNextMaterialLayer(ctx,
1574  cache,
1575  prop,
1576  nextPar.index(),
1577  destSurf,
1578  cache.m_currentStatic,
1579  dir,
1580  bcheck,
1581  particle,
1582  matupmode);
1583  }
1584  }
1585  }
1586  iSol++;
1587  }
1588  } else {
1589  ATH_MSG_DEBUG(" [!] Propagation failed, return 0");
1590  cache.m_parametersAtBoundary.boundaryInformation(cache.m_currentStatic, nextPar, nextPar);
1591  return {};
1592  }
1593  currPar = std::move(nextPar);
1594  }
1595 
1596  return {};
1597 }
1598 
1601  Cache& cache,
1602  const IPropagator& prop,
1603  TrackParmPtr parm_ref,
1604  const Trk::Surface* destSurf,
1605  const Trk::AlignableTrackingVolume* vol,
1608 {
1609  ++cache.m_methodSequence;
1610  ATH_MSG_DEBUG("M-[" << cache.m_methodSequence << "] extrapolateInAlignableTV(...) ");
1611 
1612  // material loop in sensitive Calo volumes
1613  // extrapolation without target surface returns:
1614  // A) boundary parameters (static volume boundary)
1615  // if target surface:
1616  // B) trPar at target surface
1617  // material collection done by the propagator ( binned material used )
1618 
1619  // initialize the return parameters vector
1620  ManagedTrackParmPtr parm(cache.manage(parm_ref));
1621  ManagedTrackParmPtr currPar(parm);
1622  const Trk::AlignableTrackingVolume* staticVol = nullptr;
1623  const Trk::TrackingVolume* currVol = nullptr;
1624  const Trk::TrackingVolume* nextVol = nullptr;
1625  std::vector<unsigned int> solutions;
1626  const Trk::TrackingVolume* assocVol = nullptr;
1627  // double tol = 0.001;
1628  // double path = 0.;
1629  // set tracking geometry in cache
1630  (void) cache.trackingGeometry(*m_navigator,ctx);
1631  if (!cache.m_highestVolume) {
1632  cache.m_highestVolume = m_navigator->highestVolume(ctx);
1633  }
1634 
1635  // verify current position
1636  Amg::Vector3D gp = parm->position();
1637  if (vol && vol->inside(gp, m_tolerance)) {
1638  staticVol = vol;
1639  } else {
1640  currVol = cache.m_trackingGeometry->lowestStaticTrackingVolume(gp);
1641  const Trk::TrackingVolume* nextStatVol = nullptr;
1642  if (m_navigator->atVolumeBoundary(currPar.get(), currVol, dir, nextStatVol, m_tolerance) &&
1643  nextStatVol != currVol) {
1644  currVol = nextStatVol;
1645  }
1646  if (currVol && currVol != vol) {
1647  if (currVol->isAlignable()) {
1648  const Trk::AlignableTrackingVolume* aliTG =
1649  static_cast<const Trk::AlignableTrackingVolume*>(currVol);
1650  staticVol = aliTG;
1651  }
1652  }
1653  }
1654 
1655  if (!staticVol) {
1656  ATH_MSG_DEBUG(" [!] failing in retrieval of AlignableTV, return 0");
1657  return {};
1658  }
1659 
1660  // TODO if volume entry go to entry of misaligned volume
1661 
1662  // save volume entry if collection present
1663 
1664  if (cache.m_identifiedParameters) {
1665  const Trk::BinnedMaterial* binMat = staticVol->binnedMaterial();
1666  if (binMat) {
1667  const Trk::IdentifiedMaterial* binIDMat = binMat->material(currPar->position());
1668  if (binIDMat->second > 0) {
1669  ManagedTrackParmPtr identified_parm(
1670  currPar); // first create a copy, to not invalidate currPar on release
1671  cache.m_identifiedParameters->push_back(
1672  std::pair<std::unique_ptr<Trk::TrackParameters>, int>(identified_parm.release(), binIDMat->second));
1673  }
1674  }
1675  }
1676 
1677  // navigation surfaces
1678  if (cache.m_navigSurfs.capacity() > m_maxNavigSurf) {
1679  cache.m_navigSurfs.reserve(m_maxNavigSurf);
1680  }
1681  cache.m_navigSurfs.clear();
1682 
1683  if (destSurf) {
1684  cache.m_navigSurfs.emplace_back(destSurf, false);
1685  }
1686 
1687  // assume new static volume, retrieve boundaries
1688  cache.m_currentStatic = staticVol;
1689  cache.retrieveBoundaries();
1690 
1691  cache.m_navigSurfs.insert(
1692  cache.m_navigSurfs.end(), cache.m_staticBoundaries.begin(), cache.m_staticBoundaries.end());
1693 
1694  // current dense
1695  cache.m_currentDense = staticVol;
1696 
1697  // ready to propagate
1698  // till: A/ static volume boundary(bcheck=true) , B/ destination surface(bcheck=false)
1699 
1700  nextVol = nullptr;
1701  while (currPar) {
1702  double path = 0.;
1703  std::vector<unsigned int> solutions;
1704  // propagate now
1705  ATH_MSG_DEBUG(" [+] Starting propagation at position "
1706  << positionOutput(currPar->position())
1707  << " (current momentum: " << currPar->momentum().mag() << ")");
1708  ATH_MSG_DEBUG(" [+] " << cache.m_navigSurfs.size() << " target surfaces in '"
1709  << cache.m_currentDense->volumeName() << "'.");
1710  // arguments : inputParameters, vector of navigation surfaces, propagation direction, b field
1711  // service, particle
1712  // type, result,
1713  // material collection, intersection collection, path limit, switch for use of path limit,
1714  // switch for curvilinear on return, current TG volume
1715  if (m_dumpCache && cache.m_extrapolationCache) {
1716  ATH_MSG_DEBUG(" prop.propagateM " << cache.m_extrapolationCache);
1717  }
1718  // propagateM takes intersections by non-const reference to a pointer.
1719  // however, it does not modify the pointer, so the parameter
1720  // should really be passed just by pointer.
1721  identifiedParameters_t* intersections = cache.m_identifiedParameters.get();
1722  ManagedTrackParmPtr nextPar(cache.manage(
1723  prop.propagateM(ctx,
1724  *currPar,
1725  cache.m_navigSurfs,
1726  dir,
1727  m_fieldProperties,
1728  particle,
1729  solutions,
1730  cache.m_matstates,
1731  intersections,
1732  path,
1733  false,
1734  false,
1735  cache.m_currentDense,
1736  cache.m_extrapolationCache)));
1737 
1738 
1739  if (nextPar) {
1740  ATH_MSG_DEBUG(" [+] Position after propagation - at "
1741  << positionOutput(nextPar->position()));
1742  ATH_MSG_DEBUG(" [+] Number of intersection solutions: " << solutions.size());
1743  // destination surface
1744  if (destSurf && solutions[0] == 0) {
1745  return nextPar;
1746  }
1747  if (destSurf && solutions.size() > 1 && solutions[1] == 0) {
1748  return nextPar;
1749  }
1750  // destination surface missed ?
1751  if (destSurf) {
1752  double dist = 0.;
1754  nextPar->position(), nextPar->momentum().normalized());
1755  if (distSol.numberOfSolutions() > 0) {
1756  dist = distSol.first();
1757  if (distSol.numberOfSolutions() > 1 && std::abs(dist) < m_tolerance) {
1758  dist = distSol.second();
1759  }
1760  if (distSol.numberOfSolutions() > 1 && dist * dir < 0. && distSol.second() * dir > 0.) {
1761  dist = distSol.second();
1762  }
1763  } else {
1764  dist = distSol.toPointOfClosestApproach();
1765  }
1766  if (dist * dir < 0.) {
1767  ATH_MSG_DEBUG(" [+] Destination surface missed ? " << dist << "," << dir);
1769  return {};
1770  }
1771  ATH_MSG_DEBUG(" [+] New 3D-distance to destinatiion - d3 = " << dist * dir);
1772  }
1773 
1774  int iDest = destSurf ? 1 : 0;
1775  unsigned int iSol = 0;
1776  while (iSol < solutions.size()) {
1777  if (solutions[iSol] < iDest + cache.m_staticBoundaries.size()) {
1778  // TODO if massive boundary coded, add the material effects here
1779  // static volume boundary; return to the main loop : TODO move from misaligned to static
1780  unsigned int index = solutions[iSol] - iDest;
1781  // use global coordinates to retrieve attached volume (just for static!)
1782  nextVol = (cache.m_currentStatic->boundarySurfaces())[index]->attachedVolume(
1783  nextPar->position(), nextPar->momentum(), dir);
1784  // double check the next volume
1785  if (nextVol &&
1786  !(nextVol->inside(nextPar->position() + 0.01 * dir * nextPar->momentum().normalized(),
1787  m_tolerance))) {
1788  ATH_MSG_DEBUG(" [!] WARNING: wrongly assigned static volume ?"
1789  << cache.m_currentStatic->volumeName() << "->" << nextVol->volumeName());
1791  nextPar->position() + 0.01 * nextPar->momentum().normalized());
1792  if (nextVol) {
1793  ATH_MSG_DEBUG(" new search yields: " << nextVol->volumeName());
1794  }
1795  }
1796  // end double check - to be removed after validation of the geometry gluing
1797  // lateral exit from calo sample can be handled here
1798  if (cache.m_identifiedParameters) {
1799  const Trk::BinnedMaterial* binMat = staticVol->binnedMaterial();
1800  if (binMat) {
1801  const Trk::IdentifiedMaterial* binIDMat = binMat->material(nextPar->position());
1802  // save only if entry to the sample present, the exit missing and non-zero step in the
1803  // sample
1804  if (binIDMat && binIDMat->second > 0 && !cache.m_identifiedParameters->empty() &&
1805  cache.m_identifiedParameters->back().second == binIDMat->second) {
1806  double s =
1807  (nextPar->position() - cache.m_identifiedParameters->back().first->position())
1808  .mag();
1809  if (s > 0.001) {
1810  // first create a copy, to not invalidate nextPar on release
1811  ManagedTrackParmPtr identified_parm(nextPar);
1812  cache.m_identifiedParameters->push_back(
1813  std::pair<std::unique_ptr<Trk::TrackParameters>, int>(identified_parm.release(),
1814  -binIDMat->second));
1815  }
1816  }
1817  }
1818  }
1819  // end lateral exit handling
1820  if (nextVol != cache.m_currentStatic) {
1821  cache.m_parametersAtBoundary.boundaryInformation(nextVol, nextPar, nextPar);
1822  ATH_MSG_DEBUG(" [+] StaticVol boundary reached of '"
1823  << cache.m_currentStatic->volumeName() << "'.");
1824  if (m_navigator->atVolumeBoundary(
1825  nextPar.get(), cache.m_currentStatic, dir, assocVol, m_tolerance) &&
1826  assocVol != cache.m_currentStatic) {
1827  cache.m_currentDense = m_useMuonMatApprox ? nextVol : cache.m_highestVolume;
1828  }
1829  // no next volume found --- end of the world
1830  if (!nextVol) {
1831  ATH_MSG_DEBUG(" [+] Word boundary reached - at "
1832  << positionOutput(nextPar->position()));
1833  }
1834  // next volume found and parameters are at boundary
1835  if (nextVol && nextPar) {
1836  ATH_MSG_DEBUG(" [+] Crossing to next volume '" << nextVol->volumeName() << "'");
1837  ATH_MSG_DEBUG(" [+] Crossing position is - at "
1838  << positionOutput(nextPar->position()));
1839  if (!destSurf) {
1840  return nextPar; // return value differs between e->surface (cached boundary values
1841  // used)
1842  }
1843  // implicit : parameters at boundary returned
1844  }
1845  return {};
1846  }
1847  }
1848  iSol++;
1849  }
1850  } else {
1851  ATH_MSG_DEBUG(" [!] Propagation failed, return 0");
1852  cache.m_parametersAtBoundary.boundaryInformation(cache.m_currentStatic, nextPar, nextPar);
1853  return {};
1854  }
1855  currPar = std::move(nextPar);
1856  }
1857 
1858  return {};
1859 }
1860 
1861 std::unique_ptr<Trk::TrackParameters>
1863  const IPropagator& prop,
1864  const Trk::TrackParameters& parm,
1865  const Trk::Surface& sf,
1867  const Trk::BoundaryCheck& bcheck,
1869 {
1870  // statistics && sequence output ----------------------------------------
1871  ++m_extrapolateDirectlyCalls;
1872  return prop.propagate(ctx, parm, sf, dir, bcheck, m_fieldProperties, particle);
1873 }
1874 
1875 std::unique_ptr<Trk::TrackParameters>
1877  const IPropagator& prop,
1878  const TrackParameters& parm,
1879  const TrackingVolume& vol,
1882 {
1883  // @TODO in principle the cache should already be created
1884  // here to correctly set cache.m_methodSequence for sub-sequent calls ...
1885  ATH_MSG_DEBUG("V-[?" /*<< cache.m_methodSequence*/
1886  << "] extrapolateToVolume(...) to volume '" << vol.volumeName() << "'.");
1887  std::unique_ptr<TrackParameters> returnParms = nullptr;
1889  double dist = 0.;
1890 
1891  // retrieve boundary surfaces, order them according to distance estimate
1892  const auto& bounds = vol.boundarySurfaces();
1893  std::vector<std::pair<const Trk::Surface*, double>> surfaces;
1894  surfaces.reserve(bounds.size());
1895  for (unsigned int ib = 0; ib < bounds.size(); ib++) {
1896  const Trk::Surface* nextSurface = &((bounds[ib])->surfaceRepresentation());
1897  if (nextSurface) {
1898  Trk::DistanceSolution distSol = nextSurface->straightLineDistanceEstimate(
1899  parm.position(), propDir * parm.momentum().normalized());
1900  if (distSol.numberOfSolutions() > 0) {
1901  dist = distSol.first();
1902  } else {
1903  dist = distSol.toPointOfClosestApproach();
1904  }
1905  if (!surfaces.empty() && distSol.numberOfSolutions() >= 0 && dist < surfaces.back().second) {
1906  std::vector<std::pair<const Trk::Surface*, double>>::iterator sIter = surfaces.begin();
1907  while (sIter != surfaces.end()) {
1908  if (dist < (*sIter).second) {
1909  break;
1910  }
1911  ++sIter;
1912  }
1913  sIter = surfaces.insert(sIter, (std::pair<const Trk::Surface*, double>(nextSurface, dist)));
1914  } else {
1915  surfaces.emplace_back(nextSurface, dist);
1916  }
1917  }
1918  }
1919 
1920  // solution along path
1921  for (std::pair<const Trk::Surface*, double>& a_surface : surfaces) {
1922  if (a_surface.second > 0) {
1923  Cache cache{};
1924  //TODO revisit when objcontainer is streamlined
1925  auto cloneInput = std::unique_ptr<Trk::TrackParameters>(parm.clone());
1926  // Material effect updator cache
1927  cache.populateMatEffUpdatorCache(m_subupdaters);
1928  returnParms = extrapolateImpl(ctx,
1929  cache,
1930  prop,
1931  cache.manage(std::move(cloneInput)).index(),
1932  *(a_surface.first),
1933  propDir,
1934  true,
1935  particle)
1936  .to_unique();
1937  if (returnParms.get() == &parm) {
1938  throw std::logic_error("Did not create new track parameters.");
1939  }
1940  if (returnParms) {
1941  break;
1942  }
1943  }
1944  }
1945 
1946  if (!returnParms && dir == anyDirection) {
1947  for (std::vector<std::pair<const Trk::Surface*, double>>::reverse_iterator rsIter =
1948  surfaces.rbegin();
1949  rsIter != surfaces.rend();
1950  ++rsIter) {
1951  if ((*rsIter).second < 0) {
1952  Cache cache{};
1953  //TODO revisit when objcontainer is streamlined
1954  auto cloneInput = std::unique_ptr<Trk::TrackParameters>(parm.clone());
1955  // Material effect updator cache
1956  cache.populateMatEffUpdatorCache(m_subupdaters);
1957  returnParms = extrapolateImpl(ctx,
1958  cache,
1959  prop,
1960  cache.manage(std::move(cloneInput)).index(),
1961  *((*rsIter).first),
1963  true,
1964  particle).to_unique();
1965  if (returnParms.get() == &parm) {
1966  throw std::logic_error("Did not create new track parameters.");
1967  }
1968 
1969  if (returnParms) {
1970  break;
1971  }
1972  }
1973  }
1974  }
1975  // cache.m_methodSequence=0; // originially m_methodSequence was reset here but cache not
1976  // available here
1977  return returnParms;
1978 }
1979 
1980 // Interface Extrapolation methods
1981 // ----------------------------------------------------------------/
1982 std::unique_ptr<Trk::TrackParameters>
1983 Trk::Extrapolator::extrapolate(const EventContext& ctx,
1984  const TrackParameters& parm,
1985  const Surface& sf,
1987  const BoundaryCheck& bcheck,
1989  MaterialUpdateMode matupmode,
1990  Trk::ExtrapolationCache* extrapolationCache) const
1991 {
1992  Cache cache{};
1993  // Material effect updator cache
1994  //TODO revisit when objcontainer is streamlined
1995  auto cloneInput = std::unique_ptr<Trk::TrackParameters>(parm.clone());
1996  cache.populateMatEffUpdatorCache(m_subupdaters);
1997  return extrapolateImpl(ctx,
1998  cache,
1999  cache.manage(std::move(cloneInput)).index(),
2000  sf,
2001  dir,
2002  bcheck,
2003  particle,
2004  matupmode,
2005  extrapolationCache).to_unique();
2006 }
2007 
2010  const Trk::TrackParameters& parm,
2011  const Trk::Surface& sf,
2013  const Trk::BoundaryCheck& bcheck,
2015 {
2016 
2017  const IPropagator* currentPropagator =
2018  !m_subPropagators.empty() ? m_subPropagators[Trk::Global] : nullptr;
2019  if (currentPropagator) {
2020  return extrapolateStepwiseImpl(ctx, (*currentPropagator), parm, sf, dir,
2021  bcheck, particle);
2022  }
2023  ATH_MSG_ERROR(
2024  " [!] No default Propagator is configured ! Please check jobOptions.");
2025  return {};
2026 }
2027 
2028 std::unique_ptr<Trk::TrackParameters>
2030  const EventContext& ctx,
2031  const Trk::Track& trk,
2032  const Trk::Surface& sf,
2034  const Trk::BoundaryCheck& bcheck,
2036  MaterialUpdateMode matupmode,
2037  Trk::ExtrapolationCache* extrapolationCache) const
2038 {
2039  const Trk::TrackParameters* closestTrackParameters =
2040  m_navigator->closestParameters(trk, sf);
2041  if (closestTrackParameters) {
2042  return (extrapolate(
2043  ctx, *closestTrackParameters, sf, dir, bcheck, particle, matupmode, extrapolationCache));
2044  }
2045  closestTrackParameters = *(trk.trackParameters()->begin());
2046  if (closestTrackParameters) {
2047  return (extrapolate(
2048  ctx, *closestTrackParameters, sf, dir, bcheck, particle, matupmode, extrapolationCache));
2049  }
2050  return nullptr;
2051 }
2052 
2055  const Trk::TrackParameters& parm,
2057  const Trk::BoundaryCheck& bcheck,
2059  const Trk::Volume* boundaryVol) const
2060 {
2061  // set propagator to the global one
2062  const IPropagator* currentPropagator =
2063  !m_subPropagators.empty() ? m_subPropagators[Trk::Global] : nullptr;
2064 
2065  if (currentPropagator) {
2066  Cache cache{};
2067  // TODO revisit when objcontainer is streamlined
2068  auto cloneInput = std::unique_ptr<Trk::TrackParameters>(parm.clone());
2069  // Material effect updator cache
2070  cache.populateMatEffUpdatorCache(m_subupdaters);
2071  return extrapolateBlindlyImpl(ctx, cache, (*currentPropagator),
2072  cache.manage(std::move(cloneInput)).index(),
2073  dir, bcheck, particle, boundaryVol);
2074  }
2075  ATH_MSG_ERROR(
2076  " [!] No default Propagator is configured ! Please check jobOptions.");
2077  return {};
2078 }
2079 
2080 std::unique_ptr<Trk::TrackParameters>
2082  const Trk::TrackParameters& parm,
2083  const Trk::Surface& sf,
2085  const Trk::BoundaryCheck& bcheck,
2087 {
2088  // set propagator to the global one
2089  const IPropagator* currentPropagator =
2090  !m_subPropagators.empty() ? m_subPropagators[Trk::Global] : nullptr;
2091 
2092  if (!currentPropagator) {
2093  ATH_MSG_ERROR(
2094  " [!] No default Propagator is configured ! Please check jobOptions.");
2095  return nullptr;
2096  }
2097  return extrapolateDirectlyImpl(
2098  ctx, (*currentPropagator), parm, sf, dir, bcheck, particle);
2099 }
2100 
2101 std::pair<std::unique_ptr<Trk::TrackParameters>, const Trk::Layer*>
2103  const EventContext& ctx,
2104  const TrackParameters& parm,
2106  const BoundaryCheck& bcheck,
2107  std::vector<const Trk::TrackStateOnSurface*>& material,
2109  MaterialUpdateMode matupmode) const
2110 {
2111  // set propagator to the MS one - can be reset inside the next methode (once
2112  // volume information is there) set propagator to the MS one - can be reset
2113  // inside the next methode (once volume information is there)
2114  const IPropagator* currentPropagator =
2115  !m_subPropagators.empty() ? m_subPropagators[Trk::MS] : nullptr;
2116  if (currentPropagator) {
2117  return extrapolateToNextActiveLayerMImpl(ctx, (*currentPropagator), parm,
2118  dir, bcheck, material, particle,
2119  matupmode);
2120  }
2121  ATH_MSG_ERROR(
2122  " [!] No default Propagator is configured ! Please check jobOptions.");
2123  return {nullptr, nullptr};
2124 }
2125 
2126 std::unique_ptr<Trk::TrackParameters>
2128  const Trk::TrackParameters& parm,
2129  const Trk::TrackingVolume& vol,
2132 {
2133 
2134  // take the volume signatrue to define the right propagator
2135  const IPropagator* currentPropagator =
2136  !m_subPropagators.empty() ? m_subPropagators[vol.geometrySignature()]
2137  : nullptr;
2138  if (currentPropagator) {
2139  return (extrapolateToVolumeImpl(ctx, *currentPropagator, parm, vol, dir,
2140  particle));
2141  }
2142  ATH_MSG_ERROR(
2143  " [!] No default Propagator is configured ! Please check jobOptions.");
2144  return nullptr;
2145 }
2146 
2147 std::vector<const Trk::TrackStateOnSurface*>*
2148 Trk::Extrapolator::extrapolateM(const EventContext& ctx,
2149  const TrackParameters& parm,
2150  const Surface& sf,
2152  const BoundaryCheck& bcheck,
2154  Trk::ExtrapolationCache* extrapolationCache) const
2155 {
2156 
2157  Cache cache{};
2158  // Material effect updator cache
2159  cache.populateMatEffUpdatorCache(m_subupdaters);
2160  ATH_MSG_DEBUG("C-[" << cache.m_methodSequence << "] extrapolateM()");
2161  // create a new vector for the material to be collected
2162  cache.m_matstates = new std::vector<const Trk::TrackStateOnSurface*>;
2163  if (m_dumpCache && extrapolationCache) {
2164  ATH_MSG_DEBUG(" extrapolateM pointer extrapolationCache " << extrapolationCache << " x0tot "
2165  << extrapolationCache->x0tot());
2166  }
2167 
2168  // collect the material
2169  //TODO revisit when objcontainer is streamlined
2170  auto cloneInput = std::unique_ptr<Trk::TrackParameters>(parm.clone());
2171  ManagedTrackParmPtr parameterAtDestination(extrapolateImpl(ctx,
2172  cache,
2173  cache.manage(std::move(cloneInput)).index(),
2174  sf,
2175  dir,
2176  bcheck,
2177  particle,
2178  Trk::addNoise,
2179  extrapolationCache));
2180  // there are no parameters
2181  if (!parameterAtDestination && m_requireMaterialDestinationHit) {
2182  ATH_MSG_VERBOSE(" [!] Destination surface for extrapolateM has not been hit (required through "
2183  "configuration). Return 0");
2184  // loop over and clean up
2185  std::vector<const Trk::TrackStateOnSurface*>::iterator tsosIter = cache.m_matstates->begin();
2186  std::vector<const Trk::TrackStateOnSurface*>::iterator tsosIterEnd = cache.m_matstates->end();
2187  for (; tsosIter != tsosIterEnd; ++tsosIter) {
2188  delete (*tsosIter);
2189  }
2190  delete cache.m_matstates;
2191  cache.m_matstates = nullptr;
2192  // bail out
2193  return nullptr;
2194  }
2195  if (parameterAtDestination) {
2196  ATH_MSG_VERBOSE(" [+] Adding the destination surface to the TSOS vector in extrapolateM() ");
2197  cache.m_matstates->push_back(
2198  new TrackStateOnSurface(nullptr, parameterAtDestination.to_unique(), nullptr));
2199  } else {
2200  ATH_MSG_VERBOSE(" [-] Destination surface was not hit extrapolateM(), but not required "
2201  "through configuration.");
2202  }
2203  // assign the temporary states
2204  std::vector<const Trk::TrackStateOnSurface*>* tmpMatStates = cache.m_matstates;
2205  cache.m_matstates = nullptr;
2206  // retunr the material states
2207  return tmpMatStates;
2208 }
2209 
2210 /* Private methods
2211  *
2212  * Most accept a Cache struct as an argument.
2213  * This is passed to them from the public/interface methods.
2214  * Then it is also propagated in-between the private methods.
2215  *
2216  * Start with the extrapolate Implementation ones
2217  */
2218 
2220 Trk::Extrapolator::extrapolateImpl(const EventContext& ctx,
2221  Cache& cache,
2222  const IPropagator& prop,
2223  TrackParmPtr parm_ref,
2224  const Trk::Surface& sf,
2226  const Trk::BoundaryCheck& bcheck,
2228  MaterialUpdateMode matupmode) const
2229 {
2230 
2231  // reset the destination surface
2232  cache.m_destinationSurface = nullptr;
2234  ManagedTrackParmPtr parm(cache.manage(parm_ref));
2235  // skip rest of navigation if particle hypothesis is nonInteracting
2236  if (particle == Trk::nonInteracting) {
2237  if (cache.m_methodSequence) {
2238  ++cache.m_methodSequence; // extrapolateDirectly does not have the cache and cannot increment
2239  // m_methodSequence therefore do it here
2240  }
2241  return cache.manage(
2242  extrapolateDirectlyImpl(ctx, prop, *parm, sf, dir, bcheck, particle));
2243  }
2244 
2245  // set the model action of the material effects updaters
2246  for (unsigned int imueot = 0; imueot < m_subupdaters.size(); ++imueot) {
2247  if(m_subupdaters[imueot]){
2248  m_subupdaters[imueot]->modelAction((cache.m_MaterialUpCache[imueot]));
2249  }
2250  }
2251 
2252  // statistics && sequence output ----------------------------------------
2253  ++m_extrapolateCalls;
2254  ++cache.m_methodSequence;
2255  // prepare the values for the startup and call the initialization
2256  // ------------------------------------------
2257  const Trk::TrackingVolume* startVolume = nullptr;
2258  const Trk::TrackingVolume* destVolume = nullptr;
2259  const Trk::Layer* nextLayer = nullptr;
2260  const Trk::TrackingVolume* nextVolume = nullptr;
2261  const Trk::TrackingVolume* lastVolume = nullptr;
2262  ManagedTrackParmPtr refParameters(cache.trackParmContainer());
2263  ManagedTrackParmPtr lastParameters(cache.trackParmContainer());
2264  ManagedTrackParmPtr navParameters(cache.trackParmContainer());
2265  ManagedTrackParmPtr nextParameters(parm);
2266 
2267  // initialize Navigation (calls as well initialize on garbe collection)
2268  // -------------------------------------
2269  Trk::PropDirection navDir = initializeNavigation(ctx,
2270  cache,
2271  prop,
2272  nextParameters.index(),
2273  sf,
2274  dir,
2275  particle,
2276  refParameters,
2277  nextLayer,
2278  nextVolume,
2279  destVolume);
2280  // ----------------------------
2281  // if anyDirection has been chosen as a start directive:
2282  // -> overwrite the dir with the navigation direction
2283  dir = (dir == Trk::anyDirection) ? navDir : dir;
2284  // check for consistency
2285  if (dir == Trk::anyDirection || navDir != dir) {
2286  // navigation could not be resolved
2288  " [!] Navigation direction could not be resolved, switching to extrapolateDirectly()");
2289  // the extrapolate directly call
2290  ++cache.m_methodSequence; // extrapolateDirectly does not have the cache and cannot increment
2291  // m_methodSequence
2292  return cache.manage(
2293  extrapolateDirectlyImpl(ctx, prop, *parm, sf, navDir, bcheck, particle));
2294  }
2295  // ------------------------------
2296  startVolume = nextVolume;
2297  // fallback setup -------------------------------------
2298  bool fallback = false;
2299  // ------- initial distance estimation ---------------
2300  double currentDistance = 0.;
2301  double previousDistance = 0.;
2302  // reference parameters and distance solution: use consistently one of each
2303  if (refParameters) {
2304  ATH_MSG_VERBOSE(" [+] Reference Parameters - at "
2305  << positionOutput(refParameters->position()));
2306  currentDistance = (refParameters->position() - parm->position()).mag();
2307  } else {
2308  // using fast but accureate sl distance from surface
2309  Trk::DistanceSolution distSol =
2310  sf.straightLineDistanceEstimate(parm->position(), dir * parm->momentum().normalized());
2311  if (distSol.numberOfSolutions() > 0) {
2312  currentDistance = distSol.absClosest();
2313  } else {
2314  currentDistance = std::abs(distSol.toPointOfClosestApproach());
2315  }
2316  // VERBOSE output
2317  }
2318  ATH_MSG_VERBOSE(" [+] Initial 3D-distance to destination - d3 = " << currentDistance);
2319  // and for oscillation protection ----------------------------------------------------
2320  const Trk::TrackingVolume* previousVolume = nullptr;
2321  // -----------------------------------------------------------------------------------
2322 
2324  " [" << cache.m_methodSequence << "] extrapolate() "
2325  << ((nextVolume) ? nextVolume->volumeName() : "Unknown (ERROR)")
2326  << " -> "
2327  << (destVolume ? destVolume->volumeName()
2328  : "Unknown (blind extrapolation)"));
2329  ATH_MSG_VERBOSE(" [+] Starting position determined - at "
2330  << positionOutput(parm->position()));
2331  if (nextLayer) {
2332  ATH_MSG_VERBOSE(" [+] Starting layer determined - with " << layerRZoutput(*nextLayer));
2333  }
2334 
2335  // -----------------------------------------------------------------------------------
2336  const IPropagator* currentPropagator = nullptr;
2337  // ----------------- extrapolation from One Volume to the next Volume
2338  // -------------------------------------- the loop continues while:
2339  // - nextVolume extists
2340  // - nextVolume is different from lastVolume (prevent infinite loops)
2341  // - nextVolume is different from destinationVolume (change to extrapolateInsideVolume)
2342  // - nextParameters exist
2343  // - lastVolume is different from previousVolume (prevent oscillation loop,
2344  // one-time-punch-through allowed)
2345  // - the reinforced navigation can find destination parameters
2346  // - the maximum method sequence is not met
2347 
2348  // best starting parameters
2349  bool updateLastValid = true;
2350  // one-time-punch-through allows for volume2 - volume1 - volume2 (cosmics)
2351  bool punchThroughDone = false;
2352 
2353  auto navigationBreakOscillation = m_navigationBreakOscillation.buffer();
2354  auto navigationBreakNoVolume = m_navigationBreakNoVolume.buffer();
2355  auto navigationBreakDistIncrease = m_navigationBreakDistIncrease.buffer();
2356  auto navigationBreakVolumeSignature = m_navigationBreakVolumeSignature.buffer();
2357 
2358  while (nextVolume && nextVolume != destVolume && nextVolume != lastVolume && nextParameters &&
2359  cache.m_methodSequence < m_maxMethodSequence) {
2360  // chose the propagtor type
2361  currentPropagator = subPropagator(*nextVolume);
2362  if (!currentPropagator) {
2363  // [0] Navigation break : configuration problem or consistency problem of TrackingGeometry
2364  // output
2365  ATH_MSG_DEBUG(" [X] Navigation break [X]");
2366  ATH_MSG_DEBUG(" - Reason : No Propagator found for Volume '"
2367  << nextVolume->volumeName() << "'");
2368  // debug statistics
2369  ++m_navigationBreakVolumeSignature;
2370  // trigger the fallback solution
2371  fallback = true;
2372  break;
2373  }
2374 
2375  // check for the distance to destination
2376  // -------------------------------------------------------------
2377  if (updateLastValid) {
2378  cache.m_lastValidParameters = nextParameters;
2379  }
2380  // re-initialize (will only overwrite destVolume)
2381  if (nextVolume->redoNavigation()) {
2382  dir = initializeNavigation(ctx,
2383  cache,
2384  *currentPropagator,
2385  nextParameters.index(),
2386  sf,
2387  dir,
2388  particle,
2389  refParameters,
2390  nextLayer,
2391  nextVolume,
2392  destVolume);
2393  }
2394  // avoid the oszillation
2395  previousVolume = lastVolume;
2396  // for the next step to termine if infinite loop occurs
2397  lastVolume = nextVolume;
2398  // for memory cleanup and backup
2399  ManagedTrackParmPtr lastParameters(nextParameters);
2400 
2401  // MS specific code ------------------
2402  // extrapolation within detached volumes - returns parameters on destination surfaces, or
2403  // boundary solution handles also dense volume description in Calo and beam pipe
2404  if (nextVolume->geometrySignature() > 1) {
2408  // extrapolate to volume boundary to avoid navigation break
2409  ManagedTrackParmPtr nextPar(cache.manage(
2410  currentPropagator->propagate(
2411  ctx,
2414  dir,
2415  bcheck,
2416  // *previousVolume,
2417  m_fieldProperties,
2418  particle,
2419  false,
2420  previousVolume)));
2421  // set boundary and next parameters
2422  cache.m_parametersAtBoundary.boundaryInformation(nextVolume, nextPar, nextPar);
2423  nextParameters = cache.m_parametersAtBoundary.nextParameters;
2424  navParameters = cache.m_parametersAtBoundary.navParameters;
2425  }
2426  // start from the nextParameter (which are at volume boundary)
2427  ManagedTrackParmPtr resultParameters(cache.trackParmContainer());
2428  if (nextParameters) {
2429  if (!m_stepPropagator) {
2430  ATH_MSG_ERROR(
2431  "extrapolation in Calo/MS called without configured STEP propagator, aborting");
2432  return {};
2433  }
2434  resultParameters = extrapolateWithinDetachedVolumes(ctx,
2435  cache,
2436  *m_stepPropagator,
2437  nextParameters.index(),
2438  sf,
2439  *nextVolume,
2440  dir,
2441  bcheck,
2442  particle,
2443  matupmode);
2444  }
2445  if (resultParameters) {
2446  // destination reached : indicated through result parameters
2447  // set the model action of the material effects updaters
2448  for (unsigned int imueot = 0; imueot < m_subupdaters.size(); ++imueot) {
2449  if(m_subupdaters[imueot]){
2450  m_subupdaters[imueot]->modelAction((cache.m_MaterialUpCache[imueot]));
2451  }
2452  }
2453  // return the parameters at destination
2454  ATH_MSG_DEBUG(" [+] Destination surface successfully hit.");
2455  // return the result (succesful)
2456  return resultParameters;
2457  } if (!cache.m_parametersAtBoundary.nextParameters ||
2459  ATH_MSG_DEBUG(" [-] Destination surface could not be hit.");
2460  return resultParameters;
2461  }
2462  } else {
2463  // -------------------------------------------------------------------------
2464  // standard loop over volumes (but last one)
2465  // extrapolate to volume boundary - void method as 'cache.m_parametersAtBoundary' hold the
2466  // information
2467  extrapolateToVolumeBoundary(ctx,
2468  cache,
2469  *currentPropagator,
2470  nextParameters.index(),
2471  nextLayer,
2472  *nextVolume,
2473  dir,
2474  bcheck,
2475  particle,
2476  matupmode);
2477  }
2478  // go on with the next volume / get next Volume and Boundary from the private member
2479  nextVolume = cache.m_parametersAtBoundary.nextVolume;
2480  nextParameters = cache.m_parametersAtBoundary.nextParameters;
2481  navParameters = cache.m_parametersAtBoundary.navParameters;
2482  // new distance estimation ( after step to next volume ) -------------------------
2483  previousDistance = currentDistance;
2484  // make it either from the navParmaters (if the exist) or the nextParameters
2485  {
2486  const Trk::TrackParameters* distParameters =
2489  : nextParameters.get();
2490 
2491  if (distParameters) {
2492  // use consistently either the:
2493  // (A) reference parameters or the
2494  if (refParameters) {
2495  currentDistance = (refParameters->position() - distParameters->position()).mag();
2496  } else {
2497  // (B) distance solution to surface
2498  Trk::DistanceSolution newDistSol = sf.straightLineDistanceEstimate(
2499  distParameters->position(), dir * distParameters->momentum().normalized());
2500  currentDistance = newDistSol.numberOfSolutions() > 0
2501  ? newDistSol.absClosest()
2502  : std::abs(newDistSol.toPointOfClosestApproach());
2503  }
2504  }
2505  }
2506  ATH_MSG_VERBOSE(" [+] New 3D-distance to destination - d3 = "
2507  << currentDistance << " (from "
2509  ? "boundary parameters"
2510  : "last parameters within volume ")
2511  << ")");
2512 
2513  // --------------------------------------------------------------------------------
2514  // (1) NAVIGATION BREAK : next Volume is identical to last volume -- LOOP
2515  if (nextVolume == lastVolume && nextVolume) {
2516  // ST false when crossing beam pipe : additional check on step distance
2517  if (nextParameters && lastParameters &&
2518  (nextParameters->position() - lastParameters->position())
2519  .dot(lastParameters->momentum().normalized()) *
2520  dir >
2521  0.001) {
2522  } else {
2523  // output
2524  ATH_MSG_DEBUG(" [X] Navigation break [X]");
2525  if (nextParameters && lastParameters) {
2526  ATH_MSG_DEBUG(
2527  "last step:" << (nextParameters->position() - lastParameters->position()).mag());
2528  }
2529  ATH_MSG_DEBUG("- Reason : Loop detected in TrackingVolume '"
2530  << nextVolume->volumeName() << "'");
2531  // statistics
2532  ++m_navigationBreakLoop;
2533  // fallback flag
2534  fallback = true;
2535  // break it
2536  break;
2537  }
2538  }
2539  // (2) NAVIGATION BREAK : Oscillation
2540  else if (nextVolume == previousVolume && nextVolume) {
2541  // one time the loop oscillation has been allowed already
2542  if (punchThroughDone) {
2543  // output
2544  ATH_MSG_DEBUG(" [X] Navigation break [X]");
2545  ATH_MSG_DEBUG("- Reason : Oscillation detected in TrackingVolume '"
2546  << nextVolume->volumeName() << "'");
2547  // statistics
2548  ++navigationBreakOscillation;
2549  // fallback flag
2550  fallback = true;
2551  // break it
2552  break;
2553  }
2554  // set the punch-through to true
2555  punchThroughDone = true;
2556  ATH_MSG_DEBUG(" [!] One time punch-through a volume done.");
2557 
2558  }
2559  // ------------------- the output interpretationn of the extrapolateToVolumeBoundary
2560  // (3) NAVIGATION BREAK : no nextVolume found - but not in extrapolateBlindly() mode
2561  else if (!nextVolume && !cache.m_parametersOnDetElements && lastVolume &&
2562  !m_stopWithUpdateZero) {
2563  // output
2564  ATH_MSG_VERBOSE(" [X] Navigation break [X]");
2565  ATH_MSG_VERBOSE("- Reason : No next volume found of TrackingVolume '"
2566  << lastVolume->volumeName() << "'");
2567  // statistics
2568  ++navigationBreakNoVolume;
2569  // record the "no next" volume -- increase the counter for the (last) volume
2570  // fallback flag
2571  fallback = true;
2572  // break it
2573  break;
2574  }
2575  // ------------------- the output interpretationn of the extrapolateToVolumeBoundary
2576  // (4) NAVIGATION BREAK : // nextParameters found but distance to surface increases
2577  else if (nextParameters && !cache.m_parametersOnDetElements && navParameters && nextVolume &&
2578  currentDistance > s_distIncreaseTolerance + previousDistance) {
2579  // output
2580  ATH_MSG_DEBUG(" [X] Navigation break [X]");
2581  ATH_MSG_DEBUG(" - Reason : Distance increase [ "
2582  << previousDistance << " to " << currentDistance << "] in TrackingVolume '"
2583  << nextVolume->volumeName() << "'");
2584  // statistics
2585  ++navigationBreakDistIncrease;
2586  // record the "dist increase" volume -- increase the counter for the volume
2587  // fallback flag
2588  fallback = true;
2589  break;
2590  }
2591  // ------------------- the output interpretationn of the extrapolateToVolumeBoundary
2592  // (+) update killed track
2593  else if ((!nextParameters && m_stopWithUpdateZero) || !nextVolume) {
2594  ATH_MSG_DEBUG(" [+] Navigation stop : either the update killed the "
2595  "track, or end of detector/boundary volume reached");
2596  return {};
2597  }
2598  // ------------------- the output interpretationn of the extrapolateToVolumeBoundary
2599  // (+) end of extrapolate blindly(volume*)
2600  else if (cache.m_boundaryVolume && navParameters &&
2601  !(cache.m_boundaryVolume->inside(navParameters->position()))) {
2602  ATH_MSG_DEBUG(
2603  " [+] Navigation stop : next navigation step would lead outside given boundary volume");
2604  return {};
2605  }
2606  // ------------------- the output interpretationn of the extrapolateToVolumeBoundary
2607  // (5) NAVIGATION BREAK : // nextParameters found but distance to surface increases
2608  else if (nextVolume) {
2609  ATH_MSG_DEBUG(" [+] next Tracking Volume = " << nextVolume->volumeName());
2610  }
2611  // set validity of last parameters to cache ------------------------------------------
2612  updateLastValid = !nextParameters || cache.m_parametersOnDetElements || !navParameters ||
2613  !nextVolume || currentDistance <= previousDistance;
2614  // reset
2615  if (!nextParameters) {
2616  nextParameters = std::move(lastParameters);
2617  }
2618  // one volume step invalidates the nextLayer information
2619  nextLayer = nullptr;
2620  }
2621 
2622  // ------------------- fallback was triggered in volume to volume loop
2623  // --------------------------------------
2624  if (fallback) {
2625  // continue with the output
2626  ATH_MSG_DEBUG(" - Consequence : " << (m_stopWithNavigationBreak
2627  ? "return 0 (configured) "
2628  : "switch to extrapolateDirectly() "));
2629  // stop with navigaiton break or zero update
2630  if (m_stopWithNavigationBreak || m_stopWithUpdateZero) {
2631  return {};
2632  }
2633  if (cache.m_lastValidParameters && lastVolume) {
2634  currentPropagator = subPropagator(*lastVolume);
2635  }
2636  if (!currentPropagator) {
2637  return {};
2638  }
2639  // create the result now
2640  ManagedTrackParmPtr resultParameters(cache.manage(
2641  currentPropagator->propagate(ctx,
2642  *cache.m_lastValidParameters,
2643  sf,
2645  bcheck,
2646  m_fieldProperties,
2647  particle,
2648  false,
2649  lastVolume)));
2650  // desperate try
2651  if (!resultParameters) {
2652  resultParameters = cache.manage(
2653  currentPropagator->propagate(ctx,
2654  *parm,
2655  sf,
2656  dir,
2657  bcheck,
2658  m_fieldProperties,
2659  particle,
2660  false,
2661  startVolume));
2662  }
2663  return resultParameters;
2664  }
2665 
2666  // ----------------- this is the exit of the extrapolateBlindly() call
2667  // --------------------------------------
2668  if ((&sf) == (m_referenceSurface.get())) {
2669  return {};
2670  }
2671 
2672  // ---------------- extrapolation inside the Volume -----------------------------------
2673  // ManagedTrackParmPtr finalNextParameters(cache.trackParmContainer(),nextParameters);
2674  ManagedTrackParmPtr finalNextParameters = nextParameters;
2675  ATH_MSG_DEBUG("create finalNextParameters " << *finalNextParameters.get());
2676  ManagedTrackParmPtr resultParameters(cache.trackParmContainer());
2677  if (nextVolume) {
2678  // chose the propagator fromt he geometry signature
2679  currentPropagator = subPropagator(*nextVolume);
2680  // extrapolate inside the volume
2681  if (currentPropagator) {
2682  resultParameters = extrapolateInsideVolume(ctx,
2683  cache,
2684  *currentPropagator,
2685  nextParameters.index(),
2686  sf,
2687  nextLayer,
2688  *nextVolume,
2689  dir,
2690  bcheck,
2691  particle,
2692  matupmode);
2693  }
2694  }
2695  // -------------------------------------------------------------------------------------
2696  // the final - desperate backup --- just try to hit the surface
2697  if (!resultParameters && !m_stopWithNavigationBreak && !m_stopWithUpdateZero) {
2698  if (finalNextParameters)
2699  ATH_MSG_DEBUG("propagate using parameters " << *finalNextParameters.get());
2700  else {
2701  ATH_MSG_DEBUG("no finalNextParameters, bailing out of extrapolateDirectly");
2702  return {};
2703  }
2704  ATH_MSG_DEBUG(" [-] Fallback to extrapolateDirectly triggered ! ");
2705  resultParameters =
2706  cache.manage(prop.propagate(ctx,
2707  *finalNextParameters,
2708  sf,
2709  dir,
2710  bcheck,
2711  // *startVolume,
2712  m_fieldProperties,
2713  particle,
2714  false,
2715  startVolume));
2716  }
2717  // return whatever you have
2718  return resultParameters;
2719 }
2720 
2722 Trk::Extrapolator::extrapolateImpl(const EventContext& ctx,
2723  Cache& cache,
2724  const IPropagator& prop,
2725  TrackParmPtr parm,
2726  const std::vector<MaterialEffectsOnTrack>& sfMeff,
2727  const TrackingVolume& tvol,
2730  MaterialUpdateMode matupmode) const
2731 {
2732  // statistics && sequence output ----------------------------------------
2733  if (cache.m_methodSequence) {
2734  ++cache.m_methodSequence;
2735  }
2736  ATH_MSG_DEBUG("D-[" << cache.m_methodSequence
2737  << "] extrapolate with given MaterialEffectsOnTrack in Volume '"
2738  << tvol.volumeName() << "'.");
2739 
2740  ManagedTrackParmPtr currPar(cache.manage(parm));
2741 
2742  // loop over the provided material effects on track
2743  for (const MaterialEffectsOnTrack& a_sfMeff : sfMeff) {
2744  // first propagate to the given surface
2745  // nextParameters = prop.propagate(*nextParameters, sfMeffI->associatedSurface(),dir,true,tvol,
2746  // particle);
2747  ManagedTrackParmPtr nextPar(
2748  cache.manage(prop.propagate(ctx,
2749  *currPar,
2750  a_sfMeff.associatedSurface(),
2751  dir,
2752  true,
2753  m_fieldProperties,
2754  particle,
2755  false,
2756  &tvol)));
2757  // user might have not calculated well which surfaces are intersected ... break if break
2758  if (!nextPar) {
2759  return (currPar.index() != parm)
2760  ? currPar
2761  : ManagedTrackParmPtr(); // only return track parameters if at
2762  // least one iteration was successful
2763  }
2764  currPar = std::move(nextPar);
2765  // then update
2766 
2767  const IMaterialEffectsUpdator* currentUpdator = subMaterialEffectsUpdator(tvol);
2768  IMaterialEffectsUpdator::ICache& currentUpdatorCache =
2769  cache.subMaterialEffectsUpdatorCache(tvol);
2770 
2771  ManagedTrackParmPtr upNext;
2772  if (currentUpdator) {
2773  upNext = cache.manage(currentUpdator->update(
2774  currentUpdatorCache, currPar.get(), a_sfMeff, particle, matupmode));
2775  }
2776  if (!upNext) {
2777  // update killed the track or config problem. Return
2778  ATH_MSG_VERBOSE(" [+] Update killed track.");
2779  break;
2780  }
2781  currPar = std::move(upNext);
2782  }
2783  return currPar;
2784 }
2785 
2787 Trk::Extrapolator::extrapolateImpl(const EventContext& ctx,
2788  Cache& cache,
2789  TrackParmPtr parm,
2790  const Surface& sf,
2792  const BoundaryCheck& bcheck,
2794  MaterialUpdateMode matupmode,
2795  Trk::ExtrapolationCache* extrapolationCache) const
2796 {
2797  cache.m_extrapolationCache = extrapolationCache;
2798  cache.m_cacheEloss = extrapolationCache ? extrapolationCache->eloss() : nullptr;
2799 
2800  if (extrapolationCache && m_dumpCache) {
2801  ATH_MSG_DEBUG(" In extrapolate cache pointer input: " << extrapolationCache
2802  << " cache.m_extrapolationCache "
2803  << cache.m_extrapolationCache);
2804  if (cache.m_extrapolationCache) {
2805  ATH_MSG_DEBUG(cache.to_string(" In extrapolate "));
2806  }
2807  }
2808 
2809  // chose the propagator fromt he geometry signature -- start with default
2810  const IPropagator* currentPropagator =
2811  !m_subPropagators.empty() ? m_subPropagators[Trk::Global] : nullptr;
2812  if (currentPropagator) {
2813  return extrapolateImpl(ctx, cache, (*currentPropagator), parm, sf, dir,
2814  bcheck, particle, matupmode);
2815  }
2816  ATH_MSG_ERROR(
2817  " [!] No default Propagator is configured ! Please check jobOptions.");
2818  return {};
2819 }
2820 
2823  Cache& cache,
2824  const IPropagator& prop,
2825  TrackParmPtr parm,
2827  const Trk::BoundaryCheck& bcheck,
2829  const Trk::Volume* boundaryVol) const
2830 {
2831  // statistics && sequence output ----------------------------------------
2832  ++m_extrapolateBlindlyCalls;
2833  ++cache.m_methodSequence;
2834  ATH_MSG_DEBUG("F-[" << cache.m_methodSequence << "] extrapolateBlindly() ");
2835  // assign the boundaryVolume
2836  cache.m_boundaryVolume = boundaryVol;
2837  // initialize the return parameters vector
2838  // create a new internal helper vector
2840  //The m_parametersOnDetElements point to it
2841  cache.m_parametersOnDetElements = &tmp;
2842  // run the extrapolation
2843  {
2844  ManagedTrackParmPtr parameterOnSf(
2845  extrapolateImpl(ctx, cache, prop, parm, *m_referenceSurface, dir, bcheck, particle));
2846  }
2847  // reset the .m_parametersOnDetElements to point to nullptr
2848  cache.m_parametersOnDetElements = nullptr;
2849  // reset the boundary Volume
2850  cache.m_boundaryVolume = nullptr;
2851  // return what you have
2852  return Trk::TrackParametersUVector(std::move(tmp));
2853 }
2854 
2855 // ----------------------- The private Volume extrapolation methods --------------------------
2858  Cache& cache,
2859  const IPropagator& prop,
2860  TrackParmPtr parm,
2861  const Surface& sf,
2862  const Layer* assLayer,
2863  const TrackingVolume& tvol,
2865  const BoundaryCheck& bcheck,
2867  MaterialUpdateMode matupmode) const
2868 {
2869  // ---> C) detached volumes exist
2870  if (!tvol.confinedDetachedVolumes().empty()) {
2871  return extrapolateWithinDetachedVolumes(
2872  ctx, cache, prop, parm, sf, tvol, dir, bcheck, particle, matupmode);
2873  }
2874  // ---> A) static layers exist
2875  return insideVolumeStaticLayers(
2876  ctx, cache, false, prop, parm, assLayer, tvol, dir, bcheck, particle, matupmode);
2877 }
2878 
2881  Cache& cache,
2882  const IPropagator& prop,
2883  TrackParmPtr parm,
2884  const Surface& sf,
2885  const TrackingVolume& tvol,
2887  const BoundaryCheck& bcheck,
2889  MaterialUpdateMode matupmode) const
2890 {
2891  // method sequence output ---------------------------------
2892  ++cache.m_methodSequence;
2893  ATH_MSG_DEBUG("M-[" << cache.m_methodSequence << "] extrapolateWithinDetachedVolumes() inside '"
2894  << tvol.volumeName() << "' to destination surface. ");
2895 
2896  double dist = 0.;
2897  // double tol = 0.001;
2898 
2899  // initialization
2900  ManagedTrackParmPtr nextParameters(cache.manage(parm));
2901  const Trk::TrackingVolume* currVol = &tvol;
2902  // ============================================================
2903 
2904  // set tracking geometry in cache
2905  (void) cache.trackingGeometry(*m_navigator,ctx);
2906  // arbitrary surface or destination layer ?
2907  // bool loopOverLayers = false;
2908  const Trk::Layer* destinationLayer =
2909  cache.m_trackingGeometry->associatedLayer(sf.center());
2910  // if ( destinationLayer ) loopOverLayers = true;
2911 
2912  // initial distance to surface
2913  Trk::DistanceSolution distSol = sf.straightLineDistanceEstimate(
2914  nextParameters->position(), dir * nextParameters->momentum().normalized());
2915  if (distSol.numberOfSolutions() > 0) {
2916  dist = distSol.first();
2917  } else {
2918  dist = distSol.toPointOfClosestApproach();
2919  }
2920 
2921  if (destinationLayer && destinationLayer->isOnLayer(nextParameters->position())) {
2922  ATH_MSG_DEBUG(" [-] Already at destination layer, distance:" << dist);
2923  ManagedTrackParmPtr fwd(
2924  cache.manage(prop.propagate(ctx,
2925  *nextParameters,
2926  sf,
2927  dir,
2928  bcheck,
2929  m_fieldProperties,
2930  particle,
2931  false,
2932  currVol)));
2933 
2934  if (fwd) {
2935  return fwd;
2936  }
2937  Trk::PropDirection oppDir =
2939  return cache.manage(prop.propagate(ctx,
2940  *nextParameters,
2941  sf,
2942  oppDir,
2943  bcheck,
2944  m_fieldProperties,
2945  particle,
2946  false,
2947  currVol));
2948  }
2949 
2950  if (std::abs(dist) < m_tolerance) {
2951  ATH_MSG_DEBUG(" [-] Already at the destination surface.");
2952 
2953  if (dist >= 0.) {
2954  return cache.manage(prop.propagate(ctx,
2955  *nextParameters,
2956  sf,
2957  dir,
2958  bcheck,
2959  m_fieldProperties,
2960  particle,
2961  false,
2962  currVol));
2963  }
2964  Trk::PropDirection oppDir =
2966  return cache.manage(prop.propagate(ctx,
2967  *nextParameters,
2968  sf,
2969  oppDir,
2970  bcheck,
2971  m_fieldProperties,
2972  particle,
2973  false,
2974  currVol));
2975  }
2976  if (dist < 0.) {
2977  ATH_MSG_DEBUG(" [!] Initial 3D-distance to the surface negative ("
2978  << dist << ") -> skip extrapolation.");
2980  return {};
2981  }
2982 
2983  ATH_MSG_DEBUG(" [+] Initial 3D-distance to destination - d3 = " << dist);
2984 
2985  // loop over material layers till
2986  // a/ destination layer found (accept solutions outside surface boundary)
2987  // b/ boundary reached
2988  // c/ negative distance to destination surface( propagate directly to the surface )
2989 
2990  // ---------------------------- main loop over next material layers
2991  ManagedTrackParmPtr last_boundary_parameters; // used only to check whether parametersAtBoundary
2992 
2993  while (nextParameters) {
2994  const Trk::BoundaryCheck& bchk = false;
2995  ManagedTrackParmPtr onNextLayer(extrapolateToNextMaterialLayer(
2996  ctx, cache, prop, nextParameters.index(), &sf, currVol, dir, bchk, particle, matupmode));
2997  if (onNextLayer) { // solution with the destination surface ?
2998  // isOnSurface dummy for Perigee, use straightline distance estimate instead
2999  // if ( sf.isOnSurface(onNextLayer->position(),bchk,m_tolerance,m_tolerance) ) {
3000  Trk::DistanceSolution distSol = sf.straightLineDistanceEstimate(
3001  onNextLayer->position(), dir * onNextLayer->momentum().normalized());
3002  double currentDistance = (distSol.numberOfSolutions() > 0)
3003  ? distSol.absClosest()
3004  : std::abs(distSol.toPointOfClosestApproach());
3005  if (currentDistance <= m_tolerance &&
3006  sf.isOnSurface(onNextLayer->position(), bchk, m_tolerance, m_tolerance)) {
3008  if (!bcheck || sf.isOnSurface(onNextLayer->position(), bcheck, m_tolerance, m_tolerance)) {
3009  if (sf.type() != onNextLayer->associatedSurface().type()) {
3010  ATH_MSG_DEBUG("mismatch in destination surface type:"
3011  << static_cast<int>(sf.type())
3012  << "," << static_cast<int>(onNextLayer->associatedSurface().type())
3013  << ":distance to the destination surface:" << currentDistance);
3014  ManagedTrackParmPtr cParms(
3015  cache.manage(prop.propagate(ctx,
3016  *onNextLayer,
3017  sf,
3018  dir,
3019  bchk,
3020  m_fieldProperties,
3021  particle)));
3022  return cParms;
3023  }
3024  return onNextLayer;
3025  }
3026  return {};
3027 
3028  }
3029  } else {
3030  // world boundary ?
3032  nextParameters = std::move(onNextLayer);
3033  break;
3034  }
3036  return {};
3037  }
3038 
3039  // static volume boundary: check distance to destination
3040  Trk::DistanceSolution distSol = sf.straightLineDistanceEstimate(
3042  dir * cache.m_parametersAtBoundary.nextParameters->momentum().normalized());
3043  if (distSol.numberOfSolutions() > 0) {
3044  dist = distSol.first();
3045  } else {
3046  dist = distSol.toPointOfClosestApproach();
3047  }
3048  if (dist < 0.) {
3050  return {};
3051  } if (cache.m_parametersAtBoundary.nextVolume &&
3054  m_useDenseVolumeDescription))) {
3055  // @TODO compare and store position rather than comparing pointers
3057  if (last_boundary_parameters &&
3058  last_boundary_parameters.get() == cache.m_parametersAtBoundary.nextParameters.get()) {
3060  " [!] Already tried parameters at boundary -> exit: pos="
3061  << positionOutput(cache.m_parametersAtBoundary.nextParameters->position())
3062  << " momentum="
3063  << momentumOutput(cache.m_parametersAtBoundary.nextParameters->momentum()));
3065  return {};
3066  }
3067  onNextLayer = cache.m_parametersAtBoundary.nextParameters;
3068  last_boundary_parameters = cache.m_parametersAtBoundary.nextParameters;
3069  ATH_MSG_DEBUG(" [+] Try parameters at boundary: pos="
3070  << positionOutput(cache.m_parametersAtBoundary.nextParameters->position())
3071  << " momentum="
3072  << momentumOutput(cache.m_parametersAtBoundary.nextParameters->momentum()));
3073  }
3074  currVol = cache.m_parametersAtBoundary.nextVolume;
3075  }
3076  }
3077  nextParameters = std::move(onNextLayer);
3078  } // end loop over material layers
3079 
3080  // boundary reached , return to the main loop
3081  ATH_MSG_DEBUG(" [+] extrapolateWithinDetachedVolumes(...) reached static boundary, return to "
3082  "the main loop.");
3083  return nextParameters;
3084 }
3085 
3086 void
3088  Cache& cache,
3089  const IPropagator& prop,
3090  TrackParmPtr parm,
3091  const Layer* assLayer,
3092  const TrackingVolume& tvol,
3094  const BoundaryCheck& bcheck,
3096  MaterialUpdateMode matupmode) const
3097 {
3098  // ---> C) detached volumes exist
3099  if (!tvol.confinedDetachedVolumes().empty()) {
3101  " [!] toVolumeBoundaryDetachedVolumes(...) with confined detached volumes? This should "
3102  "not happen ! volume name and signature: "
3103  << tvol.volumeName() << ":" << tvol.geometrySignature());
3104  }
3105  // ---> A) static layers exist
3106  ManagedTrackParmPtr inside_volume_static_layer(insideVolumeStaticLayers(
3107  ctx, cache, true, prop, parm, assLayer, tvol, dir, bcheck, particle, matupmode));
3108  if (inside_volume_static_layer && cache.m_parametersAtBoundary.navParameters) {
3109  ATH_MSG_VERBOSE(" [+] Boundary intersection - at "
3110  << positionOutput(cache.m_parametersAtBoundary.navParameters->position()));
3111  }
3112 }
3113 
3116  Cache& cache,
3117  bool toBoundary,
3118  const IPropagator& prop,
3119  TrackParmPtr parm_ref,
3120  const Trk::Layer* assLayer,
3121  const TrackingVolume& tvol,
3123  const BoundaryCheck& bcheck,
3125  MaterialUpdateMode matupmode) const
3126 {
3127  // method sequence output ---------------------------------
3128  ++cache.m_methodSequence;
3129  // the next volume as given from the navigator
3130  const Trk::TrackingVolume* nextVolume = nullptr;
3131  // initialization
3132  // nextParameters : parameters to be used for the extrapolation stream
3133  ManagedTrackParmPtr parm(cache.manage(parm_ref));
3134  ManagedTrackParmPtr nextParameters(parm);
3135  // navParameters : parameters to be used for the navigation stream (if possible, start from
3136  // boundary parameters)
3139  : nextParameters);
3140 
3141  // adjust the radial scaling for the layer search, this is for inwards vs. outwards moving
3142  double rPos = parm->position().perp();
3143  double rComponent = parm->momentum().normalized().perp();
3144  // numerical stability
3145  rComponent = rComponent < 10e-5 ? 10e-5 : rComponent;
3146  // a special case for closed cylinders, check if rScalor is not below numerical tolerance
3147  double rScalor = (toBoundary && tvol.boundarySurfaces().size() == 3) ? 2. * rPos / rComponent
3148  : 0.5 * rPos / rComponent;
3149  rScalor = rScalor * rScalor < 10e-10 ? 0.1 : rScalor;
3150 
3151  // output and fast exit if the volume does not have confined layers
3152  if (toBoundary) {
3153  ATH_MSG_VERBOSE("S-[" << cache.m_methodSequence
3154  << "] insideVolumeStaticLayers(...) to volume boundary of '"
3155  << tvol.volumeName() << "'");
3156  } else { // to destination surface
3157  ATH_MSG_VERBOSE("S-[" << cache.m_methodSequence
3158  << "] insideVolumeStaticLayers(...) to destination surface in '"
3159  << tvol.volumeName() << "'");
3160  // no layer case - just do the extrapolation to the destination surface
3161  if (!tvol.confinedLayers()) {
3163  " [+] Volume does not contain layers, just propagate to destination surface.");
3164  // the final extrapolation to the destinationLayer
3165  nextParameters =
3166  cache.manage(prop.propagate(ctx,
3167  *parm,
3168  *cache.m_destinationSurface,
3169  dir,
3170  bcheck,
3171  m_fieldProperties,
3172  particle));
3173  if (!nextParameters) {
3174  nextParameters = cache.manage(
3175  prop.propagate(ctx,
3176  *parm,
3177  *cache.m_destinationSurface,
3179  bcheck,
3180  m_fieldProperties,
3181  particle));
3182  }
3183  return nextParameters;
3184  }
3185  }
3186 
3187  // print out the perpendicular direction best guess parameters
3189  " [+] Perpendicular direction of the track : " << radialDirection(*navParameters, dir));
3190  // check whether to do a postupdate with the assoicated Layer
3191  const Trk::Layer* associatedLayer = assLayer;
3192  // chache the assLayer given, because this may be needed for the destination layer
3193  const Trk::Layer* assLayerReference = assLayer;
3194 
3195  // the exit face of the last volume
3197 
3198  // ============================ RESOLVE DESTINATION / STARTPOINT ============================
3199  // (1) ASSOCIATION
3200  const Trk::Layer* destinationLayer = nullptr;
3201  // will be only executed if directive is not to go to the boundary
3202  if (!toBoundary) {
3203  destinationLayer = cache.m_destinationSurface->associatedLayer();
3204  if (!destinationLayer) { // (2) RECALL (very unlikely) // (3) GLOBAL SEARCH
3205  destinationLayer =
3206  (cache.m_recallSurface == cache.m_destinationSurface &&
3208  ? cache.m_recallLayer
3210  }
3211  if (destinationLayer) {
3212  ATH_MSG_VERBOSE(" [+] Destination layer found - with "
3213  << layerRZoutput(*destinationLayer));
3214  }
3215  } // destination layer only gather if extrapolation does not go to boundary
3216 
3217  // The update on the starting layer if necessary ----------------------------------
3218  // - only done in static volume setup
3219  // - only done if required
3220  // - only done if the parameter is on the layer
3221  // - only if no volume skip has been done
3222  // - only if associated layer is not destination layer (and both exist)
3223  if (!m_skipInitialLayerUpdate && associatedLayer && associatedLayer != destinationLayer &&
3224  associatedLayer->layerMaterialProperties() && tvol.confinedLayers()) {
3226  " [+] In starting volume: check for eventual necessary postUpdate and overlapSearch.");
3227 
3228  // check if the parameter is on the layer
3229  const Trk::Layer* parsLayer = nextParameters->associatedSurface().associatedLayer();
3230  if ((parsLayer && parsLayer == associatedLayer) ||
3231  associatedLayer->surfaceRepresentation().isOnSurface(parm->position(),
3232  false,
3233  0.5 * associatedLayer->thickness(),
3234  0.5 * associatedLayer->thickness())) {
3235  // call the overlap search for the starting layer if asked for
3236  if (cache.m_parametersOnDetElements && associatedLayer->surfaceArray() && m_subSurfaceLevel) {
3237  ATH_MSG_VERBOSE(" [o] Calling overlapSearch() on start layer.");
3238  overlapSearch(ctx,
3239  cache,
3240  prop,
3241  parm.index(),
3242  nextParameters.index(),
3243  *associatedLayer,
3244  tvol,
3245  dir,
3246  bcheck,
3247  particle,
3248  true);
3249  }
3250 
3251  // the post-update is valid
3252  ATH_MSG_VERBOSE(" [+] Calling postUpdate on inital track parameters.");
3253  // do the post-update according to the associated Layer - parameters are
3254  // either (&parm) or newly created ones chose current updator
3255 
3256  const IMaterialEffectsUpdator* currentUpdator = subMaterialEffectsUpdator(tvol);
3257  IMaterialEffectsUpdator::ICache& currentUpdatorCache =
3258  cache.subMaterialEffectsUpdatorCache(tvol);
3259 
3260  if (currentUpdator) {
3261  nextParameters = cache.manage(
3262  currentUpdator->postUpdate(currentUpdatorCache,
3263  *nextParameters,
3264  *associatedLayer,
3265  dir,
3266  particle,
3267  matupmode));
3268  }
3269  // collect the material : either for extrapolateM or for the valdiation
3270  if (nextParameters && (cache.m_matstates || m_materialEffectsOnTrackValidation)) {
3271  addMaterialEffectsOnTrack(
3272  ctx, cache, prop, nextParameters.index(), *associatedLayer, tvol, dir, particle);
3273  }
3274  if (nextParameters && nextParameters.get() != parm.get()) {
3275  } else if (!m_stopWithUpdateZero) { // re-assign the start parameters
3276  // @TODO condition correct ?
3277  nextParameters = parm;
3278  } else {
3279  ATH_MSG_VERBOSE(" [-] Initial postUpdate killed track.");
3281  cache.resetRecallInformation();
3282  return {};
3283  }
3284  }
3285  } else {
3286  assLayer = nullptr; // reset the provided Layer in case no postUpdate happened: search a new one
3287  // for layer2layer start
3288  }
3289  // ============================ RESOLVE STARTPOINT =============================
3290  // only if you do not have an input associated Layer
3291  // - this means that a volume step has been done
3292 
3293  if (!associatedLayer) {
3294  ATH_MSG_VERBOSE(" [+] Volume switch has happened, searching for entry layers.");
3295  // reset the exitFace
3296  exitFace = cache.m_parametersAtBoundary.exitFace;
3297  // Step [1] Check for entry layers --------------------------
3298  associatedLayer = tvol.associatedLayer(navParameters->position());
3299  if (associatedLayer && associatedLayer->layerMaterialProperties()) {
3300  // --------------------------------------------------------
3301  ATH_MSG_VERBOSE(" [+] Entry layer to volume found with "
3302  << layerRZoutput(*associatedLayer));
3303  // try to go to the entry Layer first - do not delete the parameters (garbage collection done
3304  // by method)
3305  // - set entry flag
3306  auto [new_track_parm, killed] = extrapolateToIntermediateLayer(
3307  ctx, cache, prop, parm.index(), *associatedLayer, tvol, dir, bcheck, particle, matupmode);
3308  nextParameters = std::move(new_track_parm);
3309  // -------------------------------------------------------
3310  if (m_stopWithUpdateZero && killed) {
3311  ATH_MSG_VERBOSE(" [+] Update may have killed track - return.");
3312  // set the new boundary information
3314  cache.resetRecallInformation();
3315  return {};
3316  } if (cache.m_boundaryVolume && nextParameters &&
3317  !cache.m_boundaryVolume->inside(nextParameters->position())) {
3318  ATH_MSG_VERBOSE(" [+] Parameter outside the given boundary/world stopping loop.");
3319  // set the new boundary information
3321  cache.resetRecallInformation();
3322  return {};
3323  }
3324  // --------------------------------------------------------
3325  if (nextParameters) {
3326  ATH_MSG_VERBOSE(" [+] Entry layer successfully hit - at "
3327  << positionOutput(nextParameters->position()));
3328  }
3329  // --------------------------------------------------------
3330  // check whether it worked or not
3331  if (!nextParameters) {
3332  nextParameters = parm;
3333  }
3334  }
3335  }
3336 
3337  // Step [2] Associate the starting point to the layer ------------------------------------------
3338  // if an action has been taken, the nextParameters are not identical with the provided parameters
3339  // anymore
3340  if (nextParameters.get() != parm.get()) {
3341  navParameters = nextParameters;
3342  }
3343  // only associate the layer if the destination layer is not the assigned reference
3344  if (destinationLayer != assLayerReference || toBoundary) {
3345  // get the starting layer for the layer - layer loop
3346  associatedLayer = assLayer ? assLayer : tvol.associatedLayer(navParameters->position());
3347  // ignore closest material layer if it is equal to the initially given layer (has been handled
3348  // by the post update )
3349  associatedLayer =
3350  (associatedLayer && associatedLayer == assLayerReference)
3351  ? associatedLayer->nextLayer(navParameters->position(),
3352  dir * rScalor * navParameters->momentum().normalized())
3353  : associatedLayer;
3354  }
3355 
3356  if (associatedLayer) {
3357  ATH_MSG_VERBOSE(" [+] Associated layer at start with " << layerRZoutput(*associatedLayer));
3358  }
3359 
3360  // the layer to layer step and the final destination layer step can be done
3361  if (destinationLayer || toBoundary) {
3362  // the layer to layer step only makes sense here
3363  if (associatedLayer && associatedLayer != destinationLayer) {
3364  // screen output
3365  ATH_MSG_VERBOSE(" [+] First layer for layer2layer with "
3366  << layerRZoutput(*associatedLayer));
3367 
3368  // now do the loop from the associatedLayer to one before the destinationLayer
3369  ManagedTrackParmPtr updateNext(extrapolateFromLayerToLayer(ctx,
3370  cache,
3371  prop,
3372  nextParameters.index(),
3373  tvol,
3374  associatedLayer,
3375  destinationLayer,
3376  navParameters.index(),
3377  dir,
3378  bcheck,
3379  particle,
3380  matupmode));
3381  // kill the track when the update ----------------------
3382  if (m_stopWithUpdateZero && !updateNext) {
3383  ATH_MSG_VERBOSE(" [+] Update may have killed track - return.");
3384  // set the new boundary information
3386  cache.resetRecallInformation();
3387  return {};
3388  } if (cache.m_boundaryVolume && updateNext &&
3389  !cache.m_boundaryVolume->inside(updateNext->position())) {
3390  ATH_MSG_VERBOSE(" [+] Parameter outside the given boundary/world stopping loop.");
3391  // set the new boundary information
3393  cache.resetRecallInformation();
3394  return {};
3395  }
3396  // the fallback if only one step was done - solve cleaner
3397  if (updateNext) {
3398  nextParameters = std::move(updateNext);
3399  }
3400  }
3401  // Case Ia: To Destination after LayerToLayer sequence
3402  if (!toBoundary) {
3403  // the final extrapolation to the destinationLayer
3404  nextParameters = extrapolateToDestinationLayer(ctx,
3405  cache,
3406  prop,
3407  nextParameters.index(),
3408  *cache.m_destinationSurface,
3409  *destinationLayer,
3410  tvol,
3411  assLayerReference,
3412  dir,
3413  bcheck,
3414  particle,
3415  matupmode);
3416 
3417  // set the recallInformation <- everything went fine
3418  cache.setRecallInformation( *cache.m_destinationSurface, *destinationLayer, tvol);
3419  // done
3420  return nextParameters;
3421  }
3422  // -----------------------------------------------------------------------------------
3423  // Case Ib: To Destination directly since no destination layer has been found
3424  } else if (!toBoundary) {
3425  nextParameters =
3426  cache.manage(prop.propagate(ctx,
3427  *nextParameters,
3428  *cache.m_destinationSurface,
3429  dir,
3430  bcheck,
3431  m_fieldProperties,
3432  particle));
3433  // job done: cleanup and go home
3434  // reset the recallInformation
3435  cache.resetRecallInformation();
3436  // return the directly extrapolated ones
3437  return nextParameters;
3438  }
3439 
3440  // the reset to the initial in case the extrapolationFromLayerToLayer
3441  if (!nextParameters) {
3442  nextParameters = parm;
3443  }
3444 
3445  // start the search with the simplest possible propagator
3446  unsigned int navprop = 0;
3447 
3448  ManagedTrackParmPtr bParameters(cache.manage());
3449 
3450  if (m_numOfValidPropagators != INVALIDPROPAGATORS) {
3451  // loop over propagators to do the search
3452  while (navprop < m_numOfValidPropagators) {
3453  const IPropagator* navPropagator = &(*m_propagators[navprop]);
3454 
3455  // we veto the navigaiton parameters for calo-volumes with calo dynamic
3456  bool vetoNavParameters = false; //
3457  // the next Parameters are usually better, because they're closer to the
3458  // boundary
3459  // --- in the initial volume (assLayerReference!=0), the parm are good if
3460  // no action taken
3461  if (nextParameters.get() != parm.get() || assLayerReference) {
3462  navParameters = nextParameters;
3463  } else {
3464  navParameters = (cache.m_parametersAtBoundary.navParameters && !vetoNavParameters)
3466  : nextParameters;
3467  }
3468 
3469  ATH_MSG_VERBOSE(" [+] Starting next boundary search from "
3470  << positionOutput(navParameters->position()));
3471  ATH_MSG_VERBOSE(" [+] Starting next boundary search with "
3472  << momentumOutput(navParameters->momentum()));
3473 
3474  // get the new navigaiton cell from the Navigator
3475  Trk::NavigationCell nextNavCell =
3476  m_navigator->nextTrackingVolume(ctx, *navPropagator, *navParameters, dir, tvol);
3477  nextVolume = nextNavCell.nextVolume;
3478 
3479  navParameters = cache.manage(
3480  std::move(nextNavCell.parametersOnBoundary));
3481 
3482  bParameters = navParameters;
3483  // set the new exit Cell
3484  exitFace = nextNavCell.exitFace;
3485  navprop++;
3486  if (nextVolume) {
3487  break;
3488  }
3489  }
3490  } else {
3491  Trk::NavigationCell nextNavCell =
3492  m_navigator->nextTrackingVolume(ctx, prop, *navParameters, dir, tvol);
3493 
3494  nextVolume = nextNavCell.nextVolume;
3495 
3496  navParameters =
3497  cache.manage(std::move(nextNavCell.parametersOnBoundary));
3498  bParameters = navParameters;
3499  // set the new exit Cell
3500  exitFace = nextNavCell.exitFace;
3501  }
3502 
3503  if (!nextVolume && !cache.m_parametersOnDetElements) {
3504  ATH_MSG_DEBUG(" [-] Cannot find nextVolume of TrackingVolume: " << tvol.volumeName());
3505  if (navParameters) {
3506  ATH_MSG_VERBOSE(" Starting Parameters : " << navParameters.get());
3507  } else {
3508  ATH_MSG_VERBOSE(" Starting Parameters not defined.");
3509  }
3510  // reset the recall information as it is invalid
3511  cache.resetRecallInformation();
3512  }
3513 
3514  if (bParameters && bParameters->associatedSurface().materialLayer()) {
3515  ATH_MSG_VERBOSE(" [+] parameters on BoundarySurface with material.");
3516  if (m_includeMaterialEffects) {
3517 
3518  const IMaterialEffectsUpdator* currentUpdator = m_subupdaters[tvol.geometrySignature()];
3519  IMaterialEffectsUpdator::ICache& currentUpdatorCache =
3520  cache.subMaterialEffectsUpdatorCache(tvol);
3521 
3522  if (currentUpdator) {
3523  bParameters = cache.manage(currentUpdator->update(
3524  currentUpdatorCache,
3525  bParameters.get(),
3526  *(bParameters->associatedSurface().materialLayer()),
3527  dir,
3528  particle,
3529  matupmode));
3530  }
3531  // collect the material
3532  if (bParameters && (cache.m_matstates || m_materialEffectsOnTrackValidation)) {
3533  addMaterialEffectsOnTrack(ctx,
3534  cache,
3535  prop,
3536  bParameters.index(),
3537  *(bParameters->associatedSurface().materialLayer()),
3538  tvol,
3539  dir,
3540  particle);
3541  }
3542 
3543  // the bParameters need to be put into the gargabe bin if they differ from the navParmaeters
3544  navParameters = std::move(bParameters);
3545  }
3546  }
3547 
3548  // set the new boundary information
3550  nextVolume, nextParameters, navParameters, exitFace);
3551 
3552  // return the navParameters
3553  return navParameters;
3554 }
3555 
3556 // ----------------------- The private Layer extrapolation methods --------------------------
3557 
3560  Cache& cache,
3561  const IPropagator& prop,
3562  TrackParmPtr parm,
3563  const TrackingVolume& tvol,
3564  const Layer* startLayer,
3565  const Layer* destinationLayer,
3566  TrackParmPtr navParm,
3568  const BoundaryCheck& bcheck,
3570  MaterialUpdateMode matupmode) const
3571 {
3572  // method sequence output ---------------------------------
3573  ++cache.m_methodSequence;
3574  ATH_MSG_DEBUG("S-[" << cache.m_methodSequence << "] extrapolateFromLayerToLayer(...) in '"
3575  << tvol.volumeName() << "'. ");
3576 
3577  // initialize the loop
3578  const Trk::Layer* nextLayer = startLayer;
3579  // avoiding straight loops and oszillations
3580  const Trk::Layer* lastLayer = nullptr;
3581  const Trk::Layer* previousLayer = nullptr;
3582  // pars & fallback
3583  ManagedTrackParmPtr currPar(cache.manage(parm));
3584  ManagedTrackParmPtr navParameters(cache.manage(navParm));
3585  // avoid initial perpendicular check if:
3586  // - navParameters and currPar have different perpendicular direction (resolved in navigaiton)
3587  bool perpCheck = radialDirection(*currPar, dir) * radialDirection(*navParameters, dir) > 0;
3588 
3589  // break conditions: --------- handeled by layerAttempts
3590  unsigned int failedAttempts = 0;
3591 
3592  // get the max attempts from the volume : only for Fatras - for reco take the maximum number
3594  unsigned int layersInVolume =
3595  tvol.confinedLayers() ? tvol.confinedLayers()->arrayObjects().size() : 0;
3596  unsigned int maxAttempts = (!cache.m_parametersOnDetElements && !m_extendedLayerSearch)
3597  ? tvol.layerAttempts(lastExitFace)
3598  : int(layersInVolume * 0.5);
3599 
3600  // set the maximal attempts to at least m_initialLayerAttempts
3601  maxAttempts = (maxAttempts < m_initialLayerAttempts) ? m_initialLayerAttempts : maxAttempts;
3602 
3603  ATH_MSG_VERBOSE(" [+] Maximum number of failed layer attempts: " << maxAttempts);
3604 
3605  // conditions for the loop are :
3606  // - nextLayer exists
3607  // - nextLayer is not the previous one, Exception : inbound cosmics
3608  // - nextLayer is not the last layer, Exception: formerly inbound cosmics
3609  // - nextLayer is not the destination layer
3610  // - the number of attempts does not exceed a set maximum
3611 
3612  while (nextLayer && nextLayer != previousLayer && nextLayer != lastLayer &&
3613  nextLayer != destinationLayer && failedAttempts < maxAttempts) {
3614  // screen output
3615  ATH_MSG_VERBOSE(" [+] Found next "
3616  << ((nextLayer->layerMaterialProperties() ? "material layer - with "
3617  : "navigation layer with "))
3618  << layerRZoutput(*nextLayer));
3619 
3620  // skip the navigation layers
3621  if (nextLayer->layerMaterialProperties() ||
3622  (cache.m_parametersOnDetElements && nextLayer->surfaceArray())) {
3623  // the next step - do not delete the parameters (garbage collection done by method)
3624  auto [new_track_parm, killed] = extrapolateToIntermediateLayer(ctx,
3625  cache,
3626  prop,
3627  currPar.index(),
3628  *nextLayer,
3629  tvol,
3630  dir,
3631  bcheck,
3632  particle,
3633  matupmode,
3634  perpCheck);
3635  ManagedTrackParmPtr nextPar(std::move(new_track_parm));
3636  // previous and last layer setting for loop and oscillation protection
3637  previousLayer = lastLayer;
3638  lastLayer = nextLayer;
3639  // the breaking condition ------------------------------------
3640  // check killed first because if killed is true nexPar will be invalid.
3641  if (killed) {
3642  ATH_MSG_VERBOSE(" [+] Material update killed the track parameters - return 0");
3643  // kill the track - Fatras case
3644  return {};
3645  } if (!nextPar) {
3646  ++failedAttempts;
3647  ++m_layerSwitched; // record for statistics output
3648  // reset until break condition is fullfilled
3649  } else if (cache.m_boundaryVolume && !cache.m_boundaryVolume->inside(nextPar->position())) {
3650  ATH_MSG_VERBOSE(" [+] Parameter outside the given boundary/world stopping loop.");
3651  // set the new boundary information
3652  return nextPar;
3653  } else { // reset the failed attempts
3654  ATH_MSG_VERBOSE(" [+] Intersection successful: allowing for " << maxAttempts
3655  << " more failed attempt.");
3656  failedAttempts = 0;
3657  // but a hit sets the max attempts to m_successiveLayerAttempts => navigation machine
3658  // started ! maxAttempts = m_successiveLayerAttempts; new navParameters are currPar
3659  navParameters = nextPar;
3660  currPar = std::move(nextPar);
3661  // enforce the perpendicular check
3662  perpCheck = true;
3663  }
3664  }
3665 
3666  // cache of radiatl direction and next layer request
3667  nextLayer =
3668  nextLayer->nextLayer(navParameters->position(), dir * navParameters->momentum().normalized());
3669 
3670  // screen output
3671  if (!nextLayer) {
3672  ATH_MSG_VERBOSE(" [+] No next Layer provided by the previous layer -> stop of layer2layer");
3673  }
3674  }
3675  if (failedAttempts >= maxAttempts) {
3676  ATH_MSG_VERBOSE(" [-] Maximum number of Attempts triggered in '" << tvol.volumeName() << "'.");
3677  }
3678 
3679  // return the result
3680  return currPar;
3681 }
3682 
3685  Cache& cache,
3686  const IPropagator& prop,
3687  TrackParmPtr parm_ref,
3688  const Surface& sf,
3689  const Layer& lay,
3690  const TrackingVolume& tvol,
3691  const Layer* startLayer,
3693  const BoundaryCheck& bcheck,
3695  MaterialUpdateMode matupmode) const
3696 {
3697  // method sequence output ---------------------------------
3698  ++cache.m_methodSequence;
3699  ATH_MSG_DEBUG("S-[" << cache.m_methodSequence << "] extrapolateToDestinationLayer(...) in '"
3700  << tvol.volumeName() << "'.");
3701  // start is destination layer -> on layer navigation, take care
3702  bool startIsDestLayer = startLayer == (&lay);
3703 
3704  // get the Parameters on the destination surface
3705  ManagedTrackParmPtr parm(cache.manage(parm_ref));
3706  ManagedTrackParmPtr destParameters(cache.manage(prop.propagate(
3707  ctx, *parm, sf, dir, bcheck, MagneticFieldProperties(), particle)));
3708 
3709  // fallback to anyDirection
3710  if (!destParameters) {
3711  destParameters =
3712  cache.manage(prop.propagate(ctx, *parm, sf, Trk::anyDirection, bcheck,
3713  m_fieldProperties, particle));
3714  }
3715 
3716  // return the pre-updated ones
3717  const IMaterialEffectsUpdator* currentUpdator = subMaterialEffectsUpdator(tvol);
3718  IMaterialEffectsUpdator::ICache& currentUpdatorCache =
3719  cache.subMaterialEffectsUpdatorCache(tvol);
3720 
3721  ManagedTrackParmPtr preUpdatedParameters(cache.manage());
3722  if (currentUpdator && destParameters && !startIsDestLayer) {
3723  preUpdatedParameters = cache.manage(
3724  currentUpdator->preUpdate(currentUpdatorCache,
3725  destParameters.get(),
3726  lay,
3727  dir,
3728  particle,
3729  matupmode));
3730  } else {
3731  preUpdatedParameters = destParameters;
3732  }
3733 
3734  // collect the material : either for extrapolateM or for the valdiation
3735  if ((cache.m_matstates || m_materialEffectsOnTrackValidation) && preUpdatedParameters &&
3736  currentUpdator && !startIsDestLayer &&
3737  lay.preUpdateMaterialFactor(*destParameters, dir) >= 0.01) {
3738  addMaterialEffectsOnTrack(
3739  ctx, cache, prop, preUpdatedParameters.index(), lay, tvol, dir, particle);
3740  }
3741 
3742  // call the overlap search on the destination parameters - we are at the surface already
3743  if (cache.m_parametersOnDetElements && preUpdatedParameters && lay.surfaceArray() &&
3744  m_subSurfaceLevel) {
3745  ATH_MSG_VERBOSE(" [o] Calling overlapSearch() on destination layer.");
3746  // start is destination layer
3747  overlapSearch(ctx,
3748  cache,
3749  prop,
3750  parm.index(),
3751  preUpdatedParameters.index(),
3752  lay,
3753  tvol,
3754  dir,
3755  bcheck,
3756  particle,
3757  startIsDestLayer);
3758  }
3759 
3760  if (preUpdatedParameters) {
3761  ATH_MSG_VERBOSE(" [+] Destination surface successfully hit.");
3762  }
3763 
3764  // return the pre-updated parameters (can be 0 though)
3765  return preUpdatedParameters;
3766 }
3767 
3768 std::pair<Trk::ManagedTrackParmPtr, bool>
3770  Cache& cache,
3771  const IPropagator& prop,
3772  TrackParmPtr parm_ref,
3773  const Layer& lay,
3774  const TrackingVolume& tvol,
3776  const BoundaryCheck& bcheck,
3778  MaterialUpdateMode matupmode,
3779  bool doPerpCheck) const
3780 {
3781  // method sequence output ---------------------------------
3782  ++cache.m_methodSequence;
3783  ATH_MSG_DEBUG("S-[" << cache.m_methodSequence << "] to extrapolateToIntermediateLayer(...) layer "
3784  << lay.layerIndex() << " in '" << tvol.volumeName() << "'.");
3785 
3786  // chose the current updator
3787  const IMaterialEffectsUpdator* currentUpdator = subMaterialEffectsUpdator(tvol);
3788  IMaterialEffectsUpdator::ICache& currentUpdatorCache =
3789  cache.subMaterialEffectsUpdatorCache(tvol);
3790  // then go onto the Layer
3791  ManagedTrackParmPtr parm(cache.manage(parm_ref));
3792  ManagedTrackParmPtr parsOnLayer(cache.trackParmContainer());
3793 
3794  if (m_checkForCompundLayers) {
3795  const Trk::CompoundLayer* cl = dynamic_cast<const Trk::CompoundLayer*>(&lay);
3796  if (cl) {
3797  // try each surface in turn
3798  const std::vector<const Surface*> cs = cl->constituentSurfaces();
3799  for (const auto *c : cs) {
3800  parsOnLayer = cache.manage(prop.propagate(
3801  ctx, *parm, *c, dir, true, m_fieldProperties, particle));
3802  if (parsOnLayer) {
3803  break;
3804  }
3805  }
3806  } else {
3807  parsOnLayer = cache.manage(
3808  prop.propagate(
3809  ctx, *parm, lay.surfaceRepresentation(), dir, true, m_fieldProperties, particle));
3810  }
3811  } else {
3812  parsOnLayer = cache.manage(
3813  prop.propagate(
3814  ctx, *parm, lay.surfaceRepresentation(), dir, true, m_fieldProperties, particle));
3815  }
3816 
3817  // return if there is nothing to do
3818  if (!parsOnLayer) {
3819  return std::make_pair(ManagedTrackParmPtr(), false);
3820  }
3821  // the layer has been intersected -----------------------------------------------------
3822  // check for radial direction change ----------------------------------------------
3823  int rDirection = radialDirection(*parm, dir);
3824  int newrDirection = radialDirection(*parsOnLayer, dir);
3825  if (newrDirection != rDirection && doPerpCheck) {
3826  // it is unfortunate that the cancelling could invalidate the material collection
3827  ATH_MSG_DEBUG(" [!] Perpendicular direction of track has changed -- checking");
3828  // reset the nextParameters if the radial change is not allowed
3829  // resetting is ok - since the parameters are in the garbage bin already
3830  if (!radialDirectionCheck(ctx, prop, *parm, *parsOnLayer, tvol, dir, particle)) {
3831  ATH_MSG_DEBUG(" [+] Perpendicular direction check cancelled this layer intersection.");
3832  return std::make_pair(ManagedTrackParmPtr(), false);
3833  }
3834  }
3835  // ----------------------------------------------------------------------------------
3836  ATH_MSG_VERBOSE(" [+] Layer intersection successful at "
3837  << positionOutput(parsOnLayer->position()));
3838  ATH_MSG_VERBOSE(" [+] Layer intersection successful with "
3839  << momentumOutput(parsOnLayer->momentum()));
3840 
3841  // Fatras mode -----------------------------------------------------------------------
3842  if (cache.m_parametersOnDetElements && lay.surfaceArray() && m_subSurfaceLevel) {
3843  // ceck the parameters size before the search
3844  size_t sizeBeforeSearch = cache.m_parametersOnDetElements->size();
3845  // perform the overlap Search on this layer
3846  ATH_MSG_VERBOSE(" [o] Calling overlapSearch() on intermediate layer.");
3847  overlapSearch(
3848  ctx, cache, prop, parm.index(), parsOnLayer.index(), lay, tvol, dir, bcheck, particle);
3849  size_t sizeAfterSearch = cache.m_parametersOnDetElements->size();
3850  // the Fatras mode was successful -> postUpdate and garbage collection
3851  int lastElement = (int)cache.m_parametersOnDetElements->size() - 1;
3852  // we have created hits in the vector
3853  if (lastElement >= 0 && sizeBeforeSearch < sizeAfterSearch) {
3854  // get the last element
3855  // it's ok to reassign parOnLayer as the pointer to the first one is in the garbage bin
3856  // already get the latest Fatras hit to start from this one
3857  if (!(*cache.m_parametersOnDetElements)[lastElement]) {
3858  throw std::logic_error("Invalid track parameters on det elements (lastElement)");
3859  }
3860  //TODO revisit when objcontainer is streamlined
3861  auto cloneInput =
3862  std::unique_ptr<Trk::TrackParameters>(((*cache.m_parametersOnDetElements)[lastElement])->clone());
3863  parsOnLayer = ((*cache.m_parametersOnDetElements)[lastElement]
3864  ? cache.manage(std::move(cloneInput))
3865  : cache.manage());
3866  ATH_MSG_DEBUG(" [+] Detector element & overlapSearch successful,"
3867  << " call update on last parameter on this layer.");
3868  }
3869  } // -------------------------- Fatras mode off -----------------------------------
3870 
3871  // return the full-updated ones - may create a new object
3872  if (lay.layerMaterialProperties() && currentUpdator) {
3873  parsOnLayer = cache.manage(
3874  currentUpdator->update(
3875  currentUpdatorCache, parsOnLayer.get(), lay, dir, particle, matupmode));
3876  }
3877  // there are layers that have a surfaceArray but no material properties
3878  if (parsOnLayer && lay.layerMaterialProperties() &&
3879  (cache.m_matstates || m_materialEffectsOnTrackValidation)) {
3880  addMaterialEffectsOnTrack(ctx, cache, prop, parsOnLayer.index(), lay, tvol, dir, particle);
3881  }
3882  // kill the track if the update killed the track
3883  // ------------------------------------------------
3884  if (!parsOnLayer && m_stopWithUpdateZero) {
3885  return std::make_pair(ManagedTrackParmPtr(),
3886  true); // the indicator to kill the loopfrom material update
3887  }
3888  // ------------ the return of the parsOnLayer --- they're in the garbage bin already
3889  return std::make_pair(parsOnLayer, false);
3890 }
3891 
3892 void
3893 Trk::Extrapolator::overlapSearch(const EventContext& ctx,
3894  Cache& cache,
3895  const IPropagator& prop,
3896  TrackParmPtr parm_ref,
3897  TrackParmPtr parsOnLayer_ref,
3898  const Layer& lay,
3899  const TrackingVolume& /*tvol*/,
3901  const BoundaryCheck& bcheck, // bcheck
3903  bool startingLayer) const
3904 {
3905  // indicate destination layer
3906  ManagedTrackParmPtr parm(cache.manage(parm_ref));
3907  ManagedTrackParmPtr parsOnLayer(cache.manage(parsOnLayer_ref));
3908  bool isDestinationLayer = (&parsOnLayer->associatedSurface() == cache.m_destinationSurface);
3909  // start and end surface for on-layer navigation
3910  // -> take the start surface if ther parameter surface is owned by detector element
3911  const Trk::Surface* startSurface =
3912  ((parm->associatedSurface()).associatedDetectorElement() && startingLayer)
3913  ? &(parm->associatedSurface())
3914  : nullptr;
3915  const Trk::Surface* endSurface = isDestinationLayer ? cache.m_destinationSurface : nullptr;
3916  // - the best detSurface to start from is the one associated to the detector element
3917  const Trk::Surface* detSurface = (parsOnLayer->associatedSurface()).associatedDetectorElement()
3918  ? &parsOnLayer->associatedSurface()
3919  : nullptr;
3920 
3921  ATH_MSG_VERBOSE(" [o] OverlapSearch called " << (startSurface ? "with " : "w/o ") << "start, "
3922  << (endSurface ? "with " : "w/o ")
3923  << "end surface.");
3924 
3925  if (!detSurface) {
3926  // of parsOnLayer are different from parm, then local position is safe, because the
3927  // extrapolation
3928  // to the detector surface has been done !
3929  detSurface = isDestinationLayer ? lay.subSurface(parsOnLayer->localPosition())
3930  : lay.subSurface(parsOnLayer->position());
3931  if (detSurface) {
3932  ATH_MSG_VERBOSE(" [o] Detector surface found through subSurface() call");
3933  } else {
3934  ATH_MSG_VERBOSE(" [o] No Detector surface found on this layer.");
3935  }
3936  } else {
3937  ATH_MSG_VERBOSE(" [o] Detector surface found through parameter on layer association");
3938  }
3939 
3940  // indicate the start layer
3941  bool isStartLayer = (detSurface && detSurface == startSurface);
3942 
3943  // the temporary vector (might have to be ordered)
3944  TrackParametersUVector detParametersOnLayer;
3945  bool reorderDetParametersOnLayer = false;
3946  // the first test for the detector surface to be hit (false test)
3947  // - only do this if the parameters aren't on the surface
3948  // (i.e. search on the start layer or end layer)
3949  ManagedTrackParmPtr detParameters;
3950  if (isDestinationLayer) {
3951  detParameters = parsOnLayer;
3952  } else if (isStartLayer) {
3953  detParameters = parm;
3954  } else if (detSurface) {
3955  detParameters = cache.manage(
3956  prop.propagate(ctx, *parm, *detSurface, dir, false, m_fieldProperties, particle));
3957  }
3958 
3959  // set the surface hit to true, it is anyway overruled
3960  bool surfaceHit = true;
3961  // circumvents pointer management
3962  // to allow using detParameters after detParameters.release()
3963  ManagedTrackParmPtr track_parm_for_overlap(detParameters);
3964  if (detParameters && !isStartLayer && !isDestinationLayer) {
3965  ATH_MSG_VERBOSE(" [o] First intersection with Detector surface: " << *detParameters);
3966  // for the later use in the overlapSearch
3967  surfaceHit = detParameters && detSurface ? detSurface->isOnSurface(detParameters->position())
3968  : 0; // ,bcheck) -creates problems on start layer;
3969  // check also for start/endSurface on this level
3970  surfaceHit =
3971  (surfaceHit && startSurface)
3972  ? ((detParameters->position() - parm->position()).dot(dir * parm->momentum().normalized()) >
3973  0)
3974  : surfaceHit;
3975  surfaceHit = (surfaceHit && endSurface)
3976  ? ((detParameters->position() - parsOnLayer->position())
3977  .dot(dir * parsOnLayer->momentum().normalized()) < 0)
3978  : surfaceHit;
3979  // surface is hit within bounds (or at least with given boundary check directive) -> it counts
3980  // surface hit also survived start/endsurface search
3981  //
3982  // Convention for Fatras: always apply the full update on the last parameters
3983  // of the gathered vector (no pre/post schema)
3984  // don't record a hit on the destination surface
3985  if (surfaceHit && detSurface != startSurface && detSurface != cache.m_destinationSurface) {
3986  ATH_MSG_VERBOSE(" [H] Hit with detector surface recorded ! ");
3987  // push into the temporary vector
3988  detParametersOnLayer.emplace_back(detParameters.release());
3989  } else if (detParameters) {
3990  // no hit -> fill into the garbage bin
3992  " [-] Detector surface hit cancelled through bounds check or start/end surface check.");
3993  }
3994  }
3995 
3996  // search for the overlap -------------------------------------------------
3997  if (track_parm_for_overlap) {
3998  // retrive compatible subsurfaces
3999  std::vector<Trk::SurfaceIntersection> cSurfaces;
4000  size_t ncSurfaces =
4001  lay.compatibleSurfaces(cSurfaces, *track_parm_for_overlap, Trk::anyDirection, bcheck, false);
4002 
4003  // import from StaticEngine.icc
4004  if (ncSurfaces) {
4005  ATH_MSG_VERBOSE("found " << ncSurfaces << " candidate sensitive surfaces to test.");
4006  // now loop over the surfaces:
4007  // the surfaces will be sorted @TODO integrate pathLength propagation into this
4008 
4009  auto overlapSurfaceHit = m_overlapSurfaceHit.buffer();
4010  for (auto& csf : cSurfaces) {
4011  // propagate to the compatible surface, return types are (pathLimit
4012  // failure is excluded by Trk::anyDirection for the moment):
4013  ManagedTrackParmPtr overlapParameters(cache.manage(
4014  prop.propagate(
4015  ctx, *parm, *(csf.object), Trk::anyDirection, true, m_fieldProperties, particle)));
4016 
4017  if (overlapParameters) {
4018  ATH_MSG_VERBOSE(" [+] Overlap surface was hit, checking start/end surface condition.");
4019  // check on start / end surface for on-layer navigaiton action
4020 
4021  surfaceHit = (startSurface) ? ((overlapParameters->position() - parm->position())
4022  .dot(dir * parm->momentum().normalized()) > 0)
4023  : true;
4024 
4025  surfaceHit = (surfaceHit && endSurface)
4026  ? ((overlapParameters->position() - parsOnLayer->position())
4027  .dot(dir * parsOnLayer->momentum().normalized()) < 0)
4028  : surfaceHit;
4029 
4030  if (surfaceHit) {
4031  ATH_MSG_VERBOSE(" [H] Hit with detector surface recorded !");
4032  // count the overlap Surfaces hit
4033  ++overlapSurfaceHit;
4034  // distinguish whether sorting is needed or not
4035  reorderDetParametersOnLayer = true;
4036  // push back into the temporary vector
4037  detParametersOnLayer.emplace_back(overlapParameters.release());
4038  } else { // the parameters have been cancelled by start/end surface
4039  // no hit -> fill into the garbage bin
4041  " [-] Detector surface hit cancelled through start/end surface check.");
4042  }
4043  }
4044  } // loop over test surfaces done
4045  } // there are compatible surfaces
4046  } // ----------------------------------------------------------------------
4047 
4048  // reorder the track parameters if neccessary, the overlap descriptor did not provide the ordered
4049  // surfaces
4050  if (reorderDetParametersOnLayer) {
4051  // sort to reference of incoming parameters
4052  Trk::TrkParametersComparisonFunction parameterSorter(parm->position());
4053  sort(detParametersOnLayer.begin(), detParametersOnLayer.end(), parameterSorter);
4054  }
4055  assert(cache.m_parametersOnDetElements);
4056  if (cache.m_parametersOnDetElements->empty()) {
4057  *(cache.m_parametersOnDetElements) = std::move(detParametersOnLayer);
4058  } else {
4059  std::move(detParametersOnLayer.begin(), detParametersOnLayer.end(),
4060  std::back_inserter(*(cache.m_parametersOnDetElements)));
4061  }
4062 }
4063 
4064 // ----------------------- The Initialization --------------------------
4067  Cache& cache,
4068  const IPropagator& prop,
4069  TrackParmPtr parm_ref,
4070  const Surface& sf,
4073  ManagedTrackParmPtr& refParameters,
4074  const Layer*& associatedLayer,
4075  const TrackingVolume*& associatedVolume,
4076  const TrackingVolume*& destVolume) const
4077 {
4078  (void) cache.trackingGeometry(*m_navigator, ctx);
4079  ManagedTrackParmPtr parm(cache.manage(parm_ref));
4080  // @TODO parm shared ?
4081  // output for initializeNavigation should be an eye-catcher
4082  if (!cache.m_destinationSurface) {
4083  ATH_MSG_DEBUG(" [I] initializeNaviagtion() -------------------------- ");
4084  cache.m_methodSequence = 0;
4085  } else {
4086  ATH_MSG_DEBUG(" [I] (re)initializeNaviagtion() ---------------------- ");
4087  }
4088 
4089  Trk::PropDirection navigationDirection = dir;
4090  // only for the initial and not for the redoNavigation - give back the navigation direction
4091  if (!cache.m_destinationSurface) {
4093  " [I] Starting with Start Layer/Volume search: ------------------------------");
4094  ATH_MSG_VERBOSE(" [I] Destination surface : " << sf);
4095  // reset the boundary information
4097  // and set the destination surface
4098  cache.m_destinationSurface = (&sf);
4099  // prepare for screen output
4100  const char* startSearchType = "association";
4101 
4102  // ---------------------------------- ASSOCIATED VOLUME ----------------------------------
4103  // 1 - TRY the association method
4104  const Trk::Surface* associatedSurface = &parm->associatedSurface();
4105  associatedLayer = (associatedSurface) ? associatedSurface->associatedLayer() : associatedLayer;
4106  associatedVolume =
4107  associatedLayer ? associatedLayer->enclosingTrackingVolume() : associatedVolume;
4108  // 2 - TRY the recall method -> only if association method didn't work
4109  // only if associated detector element exists to protect against dynamic surfaces
4110  if (!associatedVolume && associatedSurface && associatedSurface == cache.m_recallSurface &&
4111  associatedSurface->associatedDetectorElement()) {
4112  // statistics output
4113  ++m_startThroughRecall;
4114  associatedVolume = cache.m_recallTrackingVolume;
4115  associatedLayer = cache.m_recallLayer;
4116  // change the association type
4117  startSearchType = "recall";
4118  } else if (!associatedVolume) {
4119  // 3 - GLOBAL SEARCH METHOD
4120  ++m_startThroughGlobalSearch;
4121  // non-perigee surface
4122  cache.resetRecallInformation();
4123  associatedVolume = cache.volume(ctx,parm->position());
4124 
4125  associatedLayer =
4126  (associatedVolume) ? associatedVolume->associatedLayer(parm->position()) : nullptr;
4127 
4128  // change the association type
4129  startSearchType = "global search";
4130 
4131  // ---------------------------------- ASSOCIATED STATIC VOLUME
4132  // -------------------------------------- this is not necessary for ( association & recall )
4133  const Trk::TrackingVolume* lowestStaticVol =
4135 
4136  if (lowestStaticVol && lowestStaticVol != associatedVolume) {
4137  associatedVolume = lowestStaticVol;
4138  }
4139  // ---------------------------------------------------------------------------
4140  } else {
4141  ++m_startThroughAssociation;
4142  }
4143 
4144  // verify if not exit point from associated volume
4145  if (associatedVolume && navigationDirection != Trk::anyDirection) {
4146  const Trk::TrackingVolume* nextAssVol = nullptr;
4147  if (m_navigator->atVolumeBoundary(
4148  parm.get(), associatedVolume, dir, nextAssVol, m_tolerance) &&
4149  nextAssVol != associatedVolume) {
4150  if (nextAssVol) {
4151  associatedVolume = nextAssVol;
4152  } else {
4153  ATH_MSG_WARNING(" [X] Navigation break occurs in volume "
4154  << associatedVolume->volumeName() << " no action taken");
4155  }
4156  }
4157  }
4158  // ---------------- anyDirection given : navigation direction has to be estimated ---------
4159  if (navigationDirection == Trk::anyDirection) {
4161  " [I] 'AnyDirection' has been chosen: approaching direction must be determined.");
4162 
4163  // refParameters = prop.propagateParameters(parm,sf,dir,false,*associatedVolume);
4164  refParameters = cache.manage(
4165  prop.propagateParameters(
4166  ctx, *parm, sf, dir, false, m_fieldProperties, particle, false, associatedVolume));
4167  // chose on projective method
4168  if (refParameters) {
4169  // check the direction on basis of a vector projection
4170  Amg::Vector3D surfaceDir(refParameters->position() - parm->position());
4171  if (surfaceDir.dot(parm->momentum()) > 0.) {
4172  navigationDirection = Trk::alongMomentum;
4173  } else {
4174  navigationDirection = Trk::oppositeMomentum;
4175  }
4176 
4177  // really verbose statement, but needed for debugging
4178  ATH_MSG_VERBOSE(" [+] Approaching direction determined as: "
4179  << ((navigationDirection < 0) ? "oppositeMomentum." : "alongMomentum"));
4180  } else {
4182  " [+] Approaching direction could not be determined, they remain: anyDirection.");
4183  }
4184  }
4185  ATH_MSG_VERBOSE(" [I] Starting Information gathered through : " << startSearchType << ".");
4186  }
4187  // -----------------------------------------------------------------
4188 
4189  // ---------------------------------- DESTINATION VOLUME ----------------------------------
4190  // only do it if sf is not the reference Surface
4191  ATH_MSG_VERBOSE(" [I] Starting with destination Volume search: -----------------------------");
4192 
4193  if ((&sf) != (m_referenceSurface.get())) {
4194  // (1) - TRY the association method
4195  destVolume = (sf.associatedLayer()) ? sf.associatedLayer()->enclosingTrackingVolume() : nullptr;
4196  // for the summary output
4197  std::string destinationSearchType = "association";
4198  if (destVolume) {
4199  ++m_destinationThroughAssociation;
4200  }
4201  // (2) - RECALL
4202  // only if associated detector element exists to protect against dynamic surfaces
4203  if (!destVolume && ((&sf) == cache.m_recallSurface) && sf.associatedDetectorElement()) {
4204  destVolume = cache.m_recallTrackingVolume;
4205  destinationSearchType = "recall";
4206  // the recal case ----------
4207  ++m_destinationThroughRecall;
4208  } else if (!destVolume) {
4209  // (3) GLOBAL SEARCH
4210  destinationSearchType = "global search";
4211  ++m_destinationThroughGlobalSearch;
4212  // if the propagation has not been done already (for direction estimation)
4213  // do the global search always with a reference propagation
4214  if (!refParameters && associatedVolume) {
4215  refParameters = cache.manage(
4216  prop.propagateParameters(
4217  ctx, *parm, sf, dir, false, m_fieldProperties, particle, false, associatedVolume));
4218  }
4219  // get the destination Volume
4220  if (refParameters) {
4221  destVolume = cache.volume(ctx,refParameters->position());
4222  }
4223  // ------ the last chance : associate to the globalReferencePoint
4224  // std::cout << "destVolume: " << destVolume << " ref par: " << refParameters << "
4225  // associatedVolume: "
4226  // << associatedVolume << std::endl;
4227  if (!destVolume) {
4228  destVolume = cache.volume(ctx,sf.globalReferencePoint());
4229  }
4230  }
4231  ATH_MSG_VERBOSE(" [I] Destination Information gathered through : " << destinationSearchType
4232  << ".");
4233  }
4234  // screen output summary -----------------------------------------------------------
4235  if (msgLvl(MSG::VERBOSE)) {
4236  ATH_MSG_VERBOSE(" [+] Association Volume search ...... "
4237  << (associatedVolume ? "ok." : "failed."));
4238  ATH_MSG_VERBOSE(" [+] Association Layer search ...... "
4239  << (associatedLayer ? "ok." : "failed."));
4240  ATH_MSG_VERBOSE(" [+] Destinaiton Volume search ...... " << (destVolume ? "ok." : "failed."));
4241  // give a line of output when start volume is destination volume
4242  if (destVolume == associatedVolume) {
4243  ATH_MSG_VERBOSE(" [+] Start volume is destination volume.");
4244  }
4245  std::string navDirString =
4246  ((navigationDirection < 0) ? "oppositeMomentum"
4247  : (navigationDirection > 0) ? "alongMomentum" : "undefined");
4248  ATH_MSG_VERBOSE(" [+] NavigationDirection is : " << navDirString);
4249  ATH_MSG_VERBOSE(" [I] initializeNaviagtion() end ---------------------- ");
4250  }
4251 
4252  // ----------------------------------------------------------------------------
4253  return navigationDirection;
4254 }
4255 
4256 bool
4258  const IPropagator& prop,
4259  const TrackParameters& startParm,
4260  const TrackParameters& parsOnLayer,
4261  const TrackingVolume& tvol,
4264 {
4265 
4266  const Amg::Vector3D& startPosition = startParm.position();
4267  const Amg::Vector3D& onLayerPosition = parsOnLayer.position();
4268 
4269  // the 3D distance to the layer intersection
4270  double distToLayer = (startPosition - onLayerPosition).mag();
4271  // get the innermost contained surface for crosscheck
4272  const auto& boundarySurfaces = tvol.boundarySurfaces();
4273 
4274  // only for tubes the crossing makes sense to check for validity
4275  if (boundarySurfaces.size() == 4) {
4276  // it can be either the next layer from the initial point, or the inner tube boundary surface
4277  const Trk::Surface& insideSurface =
4278  (boundarySurfaces[Trk::tubeInnerCover])->surfaceRepresentation();
4279  // const Trk::TrackParameters* parsOnInsideSurface =
4280  std::unique_ptr<const Trk::TrackParameters> parsOnInsideSurface(prop.propagateParameters(
4281  ctx, startParm, insideSurface, dir, true, m_fieldProperties, particle));
4282 
4283  double distToInsideSurface =
4284  parsOnInsideSurface ? (startPosition - (parsOnInsideSurface->position())).mag() : 10e10;
4285 
4286  ATH_MSG_VERBOSE(" [+] Radial direction check start - at " << positionOutput(startPosition));
4287  ATH_MSG_VERBOSE(" [+] Radial direction check layer - at " << positionOutput(onLayerPosition));
4288  if (parsOnInsideSurface) {
4289  ATH_MSG_VERBOSE(" [+] Radial direction check inner - at "
4290  << positionOutput(parsOnInsideSurface->position()));
4291  }
4292 
4293  // memory cleanup (no garbage bin, this is faster)
4294  ATH_MSG_VERBOSE(" [+] Check radial direction: distance layer / boundary = "
4295  << distToLayer << " / " << distToInsideSurface);
4296  // the intersection with the original layer is valid if it is before the inside surface
4297  return distToLayer < distToInsideSurface;
4298  }
4299  return true;
4300 }
4301 
4302 std::string
4304 {
4305  std::stringstream outStream;
4306 
4307  if (m_printRzOutput) {
4308  outStream << "[r,phi,z] = [ " << pos.perp() << ", " << pos.phi() << ", " << pos.z() << " ]";
4309  } else {
4310  outStream << "[xyz] = [ " << pos.x() << ", " << pos.y() << ", " << pos.z() << " ]";
4311  }
4312  return outStream.str();
4313 }
4314 
4315 void
4317  Cache& cache,
4318  const Trk::IPropagator& prop,
4319  TrackParmPtr parm_ref,
4320  const Trk::Layer& lay,
4321  const Trk::TrackingVolume& /*tvol*/,
4322  Trk::PropDirection propDir,
4324 {
4325 
4326  ManagedTrackParmPtr parms(cache.manage(parm_ref));
4327  ATH_MSG_VERBOSE(" [+] addMaterialEffectsOnTrack() - at " << positionOutput(parms->position()));
4328  // statistics counter Fw/Bw
4329  if (propDir == Trk::alongMomentum) {
4330  ++m_meotSearchCallsFw;
4331  } else {
4332  ++m_meotSearchCallsBw;
4333  }
4334  // preparation for the material effects on track
4335  const Trk::MaterialProperties* materialProperties = nullptr;
4336  double pathCorrection = 0.;
4337  ManagedTrackParmPtr parsOnLayer;
4338  // make sure the parameters are on surface
4339  if (parms->associatedSurface() != lay.surfaceRepresentation()) {
4340  if (m_checkForCompundLayers) {
4341  const Trk::CompoundLayer* cl = dynamic_cast<const Trk::CompoundLayer*>(&lay);
4342  if (cl) {
4343  // try each surface in turn
4344  const std::vector<const Surface*> cs = cl->constituentSurfaces();
4345  for (const auto *c : cs) {
4346  parsOnLayer = cache.manage(
4347  prop.propagateParameters(
4348  ctx, *parms, *c, Trk::anyDirection, false, m_fieldProperties));
4349  if (parsOnLayer) {
4350  break;
4351  }
4352  }
4353  } else {
4354  parsOnLayer = cache.manage(
4355  prop.propagateParameters(
4356  ctx, *parms, lay.surfaceRepresentation(), Trk::anyDirection, false, m_fieldProperties));
4357  }
4358  } else {
4359  parsOnLayer = cache.manage(
4360  prop.propagateParameters(
4361  ctx, *parms, lay.surfaceRepresentation(), Trk::anyDirection, false, m_fieldProperties));
4362  }
4363  } else {
4364  parsOnLayer = parms;
4365  }
4366  // should not really happen
4367  if (!parsOnLayer) {
4368  return;
4369  }
4370  // reference material section:
4371  pathCorrection = pathCorrection > 0. ? pathCorrection
4373  parsOnLayer->position(), parsOnLayer->momentum());
4374 
4375  // material properties are not given by the reference material, get them from the layer
4376  if (!materialProperties) {
4377  materialProperties = lay.fullUpdateMaterialProperties(*parsOnLayer);
4378  }
4379 
4380  if (!materialProperties) {
4381  ATH_MSG_DEBUG(" [!] No MaterialProperties on Layer after intersection.");
4382  return;
4383  }
4384  // statistics
4385  if (propDir == Trk::alongMomentum) {
4386  ++m_meotSearchSuccessfulFw;
4387  } else {
4388  ++m_meotSearchSuccessfulBw;
4389  }
4390  // pure validation mode
4391  if (!cache.m_matstates) {
4392  if (cache.m_extrapolationCache) {
4393  double tInX0 = pathCorrection * materialProperties->thicknessInX0();
4394  if (m_dumpCache) {
4395  ATH_MSG_DEBUG(cache.to_string(" addMaterialEffectsOnTrack"));
4396  }
4397  cache.m_extrapolationCache->updateX0(tInX0);
4398  double currentQoP = parsOnLayer->parameters()[Trk::qOverP];
4399  Trk::EnergyLoss energyLoss(m_elossupdater->energyLoss(
4400  *materialProperties, std::abs(1. / currentQoP), pathCorrection, propDir, particle));
4401  cache.m_extrapolationCache->updateEloss(energyLoss.meanIoni(),
4402  energyLoss.sigmaIoni(),
4403  energyLoss.meanRad(),
4404  energyLoss.sigmaRad());
4405  if (m_dumpCache) {
4406  ATH_MSG_DEBUG(cache.to_string(" After"));
4407  }
4408  }
4409  ATH_MSG_VERBOSE(" [V] Validation mode: MaterialProperties found on this layer.");
4410  } else { // collection mode
4411  // material properties from the layer
4412  double tInX0 = pathCorrection * materialProperties->thicknessInX0();
4413  // get the q/p for the energyLoss object
4414  double currentQoP = parsOnLayer->parameters()[Trk::qOverP];
4415  auto energyLoss = m_elossupdater->energyLoss(
4416  *materialProperties, std::abs(1. / currentQoP), pathCorrection, propDir,
4417  particle);
4418  // get the scattering angle
4419  double sigmaMS = std::sqrt(m_msupdater->sigmaSquare(
4420  *materialProperties, std::abs(1. / currentQoP), pathCorrection, particle));
4421  auto scatAngles =
4422  ScatteringAngles(0, 0, sigmaMS / std::sin(parsOnLayer->parameters()[Trk::theta]), sigmaMS);
4423 
4424  // update cache
4425  if (cache.m_extrapolationCache) {
4426  if (energyLoss.meanIoni() == 0. && tInX0 > 0.) {
4427  ATH_MSG_WARNING(" Extrapolator: the ExtrapolationCache cannot work "
4428  "because the ElossUpdator is wrongly configured: "
4429  "switch joboption DetailedEloss on ");
4430  }
4431  if (m_dumpCache) {
4432  ATH_MSG_DEBUG(cache.to_string(" addMaterialEffectsOnTrack"));
4433  }
4434  cache.m_extrapolationCache->updateX0(tInX0);
4435  cache.m_extrapolationCache->updateEloss(energyLoss.meanIoni(),
4436  energyLoss.sigmaIoni(),
4437  energyLoss.meanRad(),
4438  energyLoss.sigmaRad());
4439  if (m_dumpCache) {
4440  ATH_MSG_DEBUG(cache.to_string(" After"));
4441  }
4442  }
4443  auto meot = std::make_unique<Trk::MaterialEffectsOnTrack>(
4444  tInX0, scatAngles, std::make_unique<Trk::EnergyLoss>(std::move(energyLoss)),
4446  // push it to the material states
4447  cache.m_matstates->push_back(
4448  new TrackStateOnSurface(nullptr, parsOnLayer.to_unique(), std::move(meot)));
4449 
4450  }
4451 }
4452 
4453 
4454 
4455 
4456 std::unique_ptr<std::vector<std::pair<std::unique_ptr<Trk::TrackParameters>, int>>>
4458  const EventContext& ctx,
4459  const Trk::TrackParameters& parm,
4462  std::vector<const Trk::TrackStateOnSurface*>*& material,
4463  int destination) const
4464 {
4465 
4466  // extrapolation method intended for collection of intersections with active layers/volumes
4467  // extrapolation stops at indicated geoID subdetector exit
4468  Cache cache{};
4469  ++cache.m_methodSequence;
4470  ATH_MSG_DEBUG("M-[" << cache.m_methodSequence << "] extrapolate(through active volumes), from "
4471  << parm.position());
4472  // reset the path
4473  cache.m_path = 0.;
4474  // initialize parameters vector
4475  cache.m_identifiedParameters = std::make_unique<identifiedParameters_t>();
4476  // initialize material collection
4477  cache.m_matstates = material;
4478  // dummy input
4479  cache.m_currentStatic = nullptr;
4480  const Trk::TrackingVolume* boundaryVol = nullptr;
4481  // cleanup
4482  cache.m_parametersAtBoundary.resetBoundaryInformation();
4483  // Material effect updator cache
4484  cache.populateMatEffUpdatorCache(m_subupdaters);
4485  // extrapolate to subdetector boundary
4486  //TODO revisit when objcontainer is streamlined
4487  auto cloneInput = std::unique_ptr<Trk::TrackParameters>(parm.clone());
4488  ManagedTrackParmPtr subDetBounds(extrapolateToVolumeWithPathLimit(
4489  ctx, cache, cache.manage(std::move(cloneInput)).index(), -1., dir, particle, boundaryVol));
4490 
4491  while (subDetBounds) {
4492  ATH_MSG_DEBUG(" Identified subdetector boundary crossing saved "
4493  << positionOutput(subDetBounds->position()));
4494  ManagedTrackParmPtr nextPar(subDetBounds);
4495  cache.m_identifiedParameters->push_back(std::pair<std::unique_ptr<Trk::TrackParameters>, int>(
4496  subDetBounds.release(),
4497  cache.m_currentStatic ? cache.m_currentStatic->geometrySignature() : 0));
4498  if (cache.m_currentStatic && cache.m_currentStatic->geometrySignature() == destination) {
4499  break;
4500  }
4501 
4502  if (!cache.m_parametersAtBoundary.nextVolume) {
4503  break; // world boundary
4504  }
4505  subDetBounds = extrapolateToVolumeWithPathLimit(
4506  ctx, cache, nextPar.index(), -1., dir, particle, boundaryVol);
4507  }
4508  if (cache.m_identifiedParameters->empty()) {
4509  return nullptr;
4510  }
4511  return std::move(cache.m_identifiedParameters);
4512 }
4513 
4516  Cache& cache,
4517  TrackParmPtr parm_ref,
4518  double pathLim,
4521  const Trk::TrackingVolume* destVol,
4522  MaterialUpdateMode matupmod) const
4523 {
4524 
4525  // returns:
4526  // A) curvilinear track parameters if path limit reached
4527  // B) boundary parameters (at destination volume boundary)
4528  // initialize the return parameters vector
4529  ManagedTrackParmPtr parm(cache.manage(parm_ref));
4530  ManagedTrackParmPtr currPar(parm);
4531  const Trk::TrackingVolume* currVol = nullptr;
4532  const Trk::TrackingVolume* nextVol = nullptr;
4533  std::vector<unsigned int> solutions;
4534  const Trk::TrackingVolume* assocVol = nullptr;
4535  unsigned int iDest = 0;
4536 
4537  // set tracking geometry in cache
4538  (void) cache.trackingGeometry(*m_navigator, ctx);
4539 
4540  // destination volume boundary ?
4541  if (destVol && m_navigator->atVolumeBoundary(currPar.get(), destVol, dir, nextVol, m_tolerance) &&
4542  nextVol != destVol) {
4543  pathLim = cache.m_path;
4544  return currPar;
4545  }
4546 
4547  bool resolveActive = true;
4548  if (cache.m_lastMaterialLayer && !cache.m_lastMaterialLayer->isOnLayer(parm->position())) {
4549  cache.m_lastMaterialLayer = nullptr;
4550  }
4551  if (!cache.m_highestVolume) {
4553  }
4554 
4555  // navigation surfaces
4556  if (cache.m_navigSurfs.capacity() > m_maxNavigSurf) {
4557  cache.m_navigSurfs.reserve(m_maxNavigSurf);
4558  }
4559  cache.m_navigSurfs.clear();
4560 
4561  // target volume may not be part of tracking geometry
4562  if (destVol) {
4563  const Trk::TrackingVolume* tgVol =
4564  cache.m_trackingGeometry->trackingVolume(destVol->volumeName());
4565  if (!tgVol || tgVol != destVol) {
4566  const auto& bounds = destVol->boundarySurfaces();
4567  for (unsigned int ib = 0; ib < bounds.size(); ib++) {
4568  const Trk::Surface& surf = (bounds[ib])->surfaceRepresentation();
4569  cache.m_navigSurfs.emplace_back(&surf, true);
4570  }
4571  iDest = bounds.size();
4572  }
4573  }
4574 
4575  // resolve current position
4576  bool updateStatic = false;
4577  Amg::Vector3D gp = parm->position();
4578  if (!cache.m_currentStatic || !cache.m_currentStatic->inside(gp, m_tolerance)) {
4580  updateStatic = true;
4581  }
4582 
4583  // the navigation sequence may have been evaluated already - check the cache
4584 
4585  bool navigDone = false;
4587  if ((cache.m_parametersAtBoundary.nextParameters->position() - currPar->position()).mag() <
4588  0.001 &&
4589  cache.m_parametersAtBoundary.nextParameters->momentum().dot(currPar->momentum()) > 0.001) {
4590  nextVol = cache.m_parametersAtBoundary.nextVolume;
4591  navigDone = true;
4592  if (nextVol != cache.m_currentStatic) {
4593  cache.m_currentStatic = nextVol;
4594  updateStatic = true;
4595  }
4596  }
4597  }
4598 
4599  if (!navigDone &&
4600  m_navigator->atVolumeBoundary(
4601  currPar.get(), cache.m_currentStatic, dir, nextVol, m_tolerance) &&
4602  nextVol != cache.m_currentStatic) {
4603  // no next volume found --- end of the world
4604  if (!nextVol) {
4605  ATH_MSG_DEBUG(" [+] Word boundary reached - at "
4606  << positionOutput(currPar->position()));
4607  if (!destVol) {
4608  pathLim = cache.m_path;
4609  }
4610  // return currPar->clone();
4611  return currPar;
4612  }
4613  cache.m_currentStatic = nextVol;
4614  updateStatic = true;
4615  }
4616 
4617  // alignable volume ?
4618  if (cache.m_currentStatic && cache.m_currentStatic->geometrySignature() == Trk::Calo) {
4619  if (cache.m_currentStatic->isAlignable()) {
4620  const Trk::AlignableTrackingVolume* alignTV =
4621  static_cast<const Trk::AlignableTrackingVolume*>(cache.m_currentStatic);
4622  ManagedTrackParmPtr nextPar(extrapolateInAlignableTV(
4623  ctx, cache, *m_stepPropagator, currPar.index(), nullptr, alignTV, dir, particle));
4624  if (nextPar) {
4625  return extrapolateToVolumeWithPathLimit(
4626  ctx, cache, nextPar.index(), pathLim, dir, particle, destVol, matupmod);
4627  }
4628  return {};
4629 
4630  }
4631  }
4632 
4633  // update if new static volume
4634  if (updateStatic) { // retrieve boundaries
4635  cache.retrieveBoundaries();
4636  //
4637  cache.m_detachedVols.clear();
4638  cache.m_detachedBoundaries.clear();
4639  cache.m_denseVols.clear();
4640  cache.m_denseBoundaries.clear();
4641  cache.m_layers.clear();
4642  cache.m_navigLays.clear();
4643 
4644  // detached volume boundaries
4647  if (!detVols.empty()) {
4649  for (; iTer != detVols.end(); ++iTer) {
4650  // active station ?
4651  const Trk::Layer* layR = (*iTer)->layerRepresentation();
4652  bool active = layR && layR->layerType();
4653  const auto& detBounds = (*iTer)->trackingVolume()->boundarySurfaces();
4654  if (active) {
4655  cache.m_detachedVols.emplace_back(*iTer, detBounds.size());
4656  for (unsigned int ibb = 0; ibb < detBounds.size(); ibb++) {
4657  const Trk::Surface& surf = (detBounds[ibb])->surfaceRepresentation();
4658  cache.m_detachedBoundaries.emplace_back(&surf, true);
4659  }
4660  } else if (cache.m_currentStatic->geometrySignature() != Trk::MS ||
4661  !m_useMuonMatApprox ||
4662  (*iTer)->name().compare((*iTer)->name().size() - 4, 4, "PERM") ==
4663  0) {
4664  // retrieve inert detached
4665  // objects only if needed
4666  if ((*iTer)->trackingVolume()->zOverAtimesRho() != 0. &&
4667  ((*iTer)->trackingVolume()->confinedDenseVolumes().empty()) &&
4668  ((*iTer)->trackingVolume()->confinedArbitraryLayers().empty())) {
4669  cache.m_denseVols.emplace_back((*iTer)->trackingVolume(), detBounds.size());
4670  for (unsigned int ibb = 0; ibb < detBounds.size(); ibb++) {
4671  const Trk::Surface& surf = (detBounds[ibb])->surfaceRepresentation();
4672  cache.m_denseBoundaries.emplace_back(&surf, true);
4673  }
4674  }
4676  (*iTer)->trackingVolume()->confinedArbitraryLayers();
4677  if (!(*iTer)->trackingVolume()->confinedDenseVolumes().empty() ||
4678  (confLays.size() > detBounds.size())) {
4679  cache.m_detachedVols.emplace_back(*iTer, detBounds.size());
4680  for (unsigned int ibb = 0; ibb < detBounds.size(); ibb++) {
4681  const Trk::Surface& surf = (detBounds[ibb])->surfaceRepresentation();
4682  cache.m_detachedBoundaries.emplace_back(&surf, true);
4683  }
4684  } else if (!confLays.empty()) {
4685  for (const Trk::Layer* const lIt : confLays) {
4686  cache.addOneNavigationLayer((*iTer)->trackingVolume(), lIt);
4687  }
4688  }
4689  }
4690  }
4691  }
4692  cache.m_denseResolved = std::pair<unsigned int, unsigned int>(cache.m_denseVols.size(),
4693  cache.m_denseBoundaries.size());
4694  cache.m_layerResolved = cache.m_layers.size();
4695  }
4696 
4697  cache.m_navigSurfs.insert(
4698  cache.m_navigSurfs.end(), cache.m_staticBoundaries.begin(), cache.m_staticBoundaries.end());
4699 
4700  // resolve the use of dense volumes
4701  cache.m_dense =
4702  (cache.m_currentStatic->geometrySignature() == Trk::MS && m_useMuonMatApprox) ||
4703  (cache.m_currentStatic->geometrySignature() != Trk::MS && m_useDenseVolumeDescription);
4704 
4705  // reset remaining counters
4706  cache.m_currentDense = cache.m_dense ? cache.m_currentStatic : cache.m_highestVolume;
4707  cache.m_navigBoundaries.clear();
4708  if (cache.m_denseVols.size() > cache.m_denseResolved.first) {
4709  cache.m_denseVols.resize(cache.m_denseResolved.first);
4710  }
4711  while (cache.m_denseBoundaries.size() > cache.m_denseResolved.second) {
4712  cache.m_denseBoundaries.pop_back();
4713  }
4714 
4715  if (cache.m_layers.size() > cache.m_layerResolved) {
4716  cache.m_navigLays.resize(cache.m_layerResolved);
4717  }
4718  while (cache.m_layers.size() > cache.m_layerResolved) {
4719  cache.m_layers.pop_back();
4720  }
4721 
4722  // current detached volumes
4723  // collect : subvolume boundaries, ordered/unordered layers, confined dense volumes
4725  // const Trk::DetachedTrackingVolume* currentActive = 0;
4726  std::vector<std::pair<const Trk::TrackingVolume*, unsigned int>> navigVols;
4727 
4728  gp = currPar->position();
4729  std::vector<const Trk::DetachedTrackingVolume*> detVols =
4732  for (; dIter != detVols.end(); ++dIter) {
4733  const Trk::Layer* layR = (*dIter)->layerRepresentation();
4734  bool active = layR && layR->layerType();
4735  if (active && !resolveActive) {
4736  continue;
4737  }
4738  if (!active && cache.m_currentStatic->geometrySignature() == Trk::MS && m_useMuonMatApprox &&
4739  (*dIter)->name().compare((*dIter)->name().size() - 4, 4, "PERM") != 0) {
4740  continue;
4741  }
4742  const Trk::TrackingVolume* dVol = (*dIter)->trackingVolume();
4743  // detached volume exit ?
4744  bool dExit =
4745  m_navigator->atVolumeBoundary(currPar.get(), dVol, dir, nextVol, m_tolerance) && !nextVol;
4746  if (dExit) {
4747  continue;
4748  }
4749  // inert material
4750  const auto confinedDense = dVol->confinedDenseVolumes();
4751  const auto confinedLays = dVol->confinedArbitraryLayers();
4752 
4753  if (!active && confinedDense.empty() && confinedLays.empty()) {
4754  continue;
4755  }
4756  const auto& bounds = dVol->boundarySurfaces();
4757  if (!active && confinedDense.empty() && confinedLays.size() <= bounds.size()) {
4758  continue;
4759  }
4760  if (!confinedDense.empty() || !confinedLays.empty()) {
4761  navigVols.emplace_back(dVol, bounds.size());
4762  for (unsigned int ib = 0; ib < bounds.size(); ib++) {
4763  const Trk::Surface& surf = (bounds[ib])->surfaceRepresentation();
4764  cache.m_navigBoundaries.emplace_back(&surf, true);
4765  }
4766  // collect dense volume boundary
4767  if (!confinedDense.empty()) {
4768  auto vIter = confinedDense.begin();
4769  for (; vIter != confinedDense.end(); ++vIter) {
4770  const auto& bounds = (*vIter)->boundarySurfaces();
4771  cache.m_denseVols.emplace_back(*vIter, bounds.size());
4772  for (unsigned int ib = 0; ib < bounds.size(); ib++) {
4773  const Trk::Surface& surf = (bounds[ib])->surfaceRepresentation();
4774  cache.m_denseBoundaries.emplace_back(&surf, true);
4775  }
4776  }
4777  }
4778  // collect unordered layers
4779  if (!confinedLays.empty()) {
4780  for (const auto *confinedLay : confinedLays) {
4781  cache.addOneNavigationLayer(dVol, confinedLay);
4782  }
4783  }
4784  } else { // active material
4785  const Trk::TrackingVolume* detVol = dVol->associatedSubVolume(gp);
4786  if (!detVol && dVol->confinedVolumes()) {
4788  for (const auto *subvol : subvols) {
4789  if (subvol->inside(gp, m_tolerance)) {
4790  detVol = subvol;
4791  break;
4792  }
4793  }
4794  }
4795 
4796  if (!detVol) {
4797  detVol = dVol;
4798  }
4799  bool vExit =
4800  m_navigator->atVolumeBoundary(currPar.get(), detVol, dir, nextVol, m_tolerance) &&
4801  nextVol != detVol;
4802  if (vExit && nextVol && nextVol->inside(gp, m_tolerance)) {
4803  detVol = nextVol;
4804  vExit = false;
4805  }
4806  if (!vExit) {
4807  const auto& bounds = detVol->boundarySurfaces();
4808  navigVols.emplace_back(detVol, bounds.size());
4809  for (unsigned int ib = 0; ib < bounds.size(); ib++) {
4810  const Trk::Surface& surf = (bounds[ib])->surfaceRepresentation();
4811  cache.m_navigBoundaries.emplace_back(&surf, true);
4812  }
4813  if (detVol->zOverAtimesRho() != 0.) {
4814  cache.m_denseVols.emplace_back(detVol, bounds.size());
4815  for (unsigned int ib = 0; ib < bounds.size(); ib++) {
4816  const Trk::Surface& surf = (bounds[ib])->surfaceRepresentation();
4817  cache.m_denseBoundaries.emplace_back(&surf, true);
4818  }
4819  }
4820  // layers ?
4821  if (detVol->confinedLayers()) {
4822  if (cache.m_robustSampling) {
4824  for (const auto *cLay : cLays) {
4825  if (cLay->layerType() > 0 || cLay->layerMaterialProperties()) {
4826  cache.addOneNavigationLayer(cLay);
4827  }
4828  }
4829  } else {
4830  const Trk::Layer* lay = detVol->associatedLayer(gp);
4831  if (lay) {
4832  cache.addOneNavigationLayer(detVol, lay);
4833  }
4834  const Trk::Layer* nextLayer =
4835  detVol->nextLayer(currPar->position(), dir * currPar->momentum().normalized(), true);
4836  if (nextLayer && nextLayer != lay) {
4837  cache.addOneNavigationLayer(detVol, nextLayer);
4838  }
4839  }
4840  } else if (!detVol->confinedArbitraryLayers().empty()) {
4841  for (const auto & pThisLayer: detVol->confinedArbitraryLayers()) {
4842  cache.addOneNavigationLayer(detVol, pThisLayer);
4843  }
4844  }
4845  }
4846  }
4847  }
4848 
4849  // confined layers
4850  if (cache.m_currentStatic->confinedLayers() && updateStatic) {
4851  // if ( cache.m_currentStatic->confinedLayers() ) {
4852  if (cache.m_robustSampling) {
4855  for (const auto *cLay : cLays) {
4856  if (cLay->layerType() > 0 || cLay->layerMaterialProperties()) {
4857  cache.addOneNavigationLayer(cLay);
4858  }
4859  }
4860  } else {
4861  // * this does not work - debug !
4862  const Trk::Layer* lay = cache.m_currentStatic->associatedLayer(gp);
4863  if (lay) {
4864  static constexpr bool boundsCheck{false};
4865  cache.addOneNavigationLayer(lay, boundsCheck);
4866  const Trk::Layer* nextLayer =
4867  lay->nextLayer(currPar->position(), dir * currPar->momentum().normalized());
4868  if (nextLayer && nextLayer != lay) {
4869  cache.addOneNavigationLayer(nextLayer, boundsCheck);
4870  }
4871  const Trk::Layer* backLayer =
4872  lay->nextLayer(currPar->position(), -dir * currPar->momentum().normalized());
4873  if (backLayer && backLayer != lay) {
4874  cache.addOneNavigationLayer(backLayer, boundsCheck);
4875  }
4876  }
4877  }
4878  }
4879  cache.copyToNavigationSurfaces();
4880 
4881  // current dense
4882  cache.m_currentDense = cache.m_highestVolume;
4883  if (cache.m_dense && cache.m_denseVols.empty()) {
4884  cache.m_currentDense = cache.m_currentStatic;
4885  } else {
4886  for (unsigned int i = 0; i < cache.m_denseVols.size(); i++) {
4887  const Trk::TrackingVolume* dVol = cache.m_denseVols[i].first;
4888  if (dVol->inside(currPar->position(), m_tolerance) && dVol->zOverAtimesRho() != 0.) {
4889  if (!m_navigator->atVolumeBoundary(currPar.get(), dVol, dir, nextVol, m_tolerance) ||
4890  nextVol == dVol) {
4891  cache.m_currentDense = dVol;
4892  }
4893  }
4894  }
4895  }
4896 
4897  // ready to propagate
4898  // till: A/ static volume boundary(bcheck=true) , B/ material
4899  // layer(bcheck=true), C/ destination surface(bcheck=false) update of
4900  // cache.m_navigSurfs required if I/ entry into new navig volume, II/ exit
4901  // from currentActive without overlaps
4902  nextVol = nullptr;
4903  while (currPar) {
4904  double path = 0.;
4905  if (pathLim > 0.) {
4906  path = pathLim;
4907  }
4908  std::vector<unsigned int> solutions;
4909  ATH_MSG_DEBUG(" [+] Starting propagation at position "
4910  << positionOutput(currPar->position())
4911  << " (current momentum: " << currPar->momentum().mag() << ")");
4912  ATH_MSG_DEBUG(" [+] " << cache.m_navigSurfs.size() << " target surfaces in '"
4913  << cache.m_currentDense->volumeName()
4914  << "'."); // verify that material input makes sense
4915  ATH_MSG_DEBUG(" [+] "
4916  << " with path limit" << pathLim
4917  << ","); // verify that material input makes sense
4918  ATH_MSG_DEBUG(" [+] "
4919  << " in the direction" << dir << "."); // verify that material input makes sense
4920  if (!(cache.m_currentDense->inside(currPar->position(), m_tolerance) ||
4921  m_navigator->atVolumeBoundary(
4922  currPar.get(), cache.m_currentDense, dir, assocVol, m_tolerance))) {
4923  cache.m_currentDense = cache.m_highestVolume;
4924  }
4925  ManagedTrackParmPtr nextPar(cache.manage(
4926  m_stepPropagator->propagate(ctx,
4927  *currPar,
4928  cache.m_navigSurfs,
4929  dir,
4930  m_fieldProperties,
4931  particle,
4932  solutions,
4933  path,
4934  true,
4935  false,
4936  cache.m_currentDense)));
4937  if (nextPar) {
4938  ATH_MSG_DEBUG(" [+] Position after propagation - at "
4939  << positionOutput(nextPar->position()));
4940  ATH_MSG_DEBUG(" [+] Momentum after propagation - " << nextPar->momentum());
4941  }
4942 
4943  if (pathLim > 0. && cache.m_path + path >= pathLim) {
4944  cache.m_path += path;
4945  return nextPar;
4946  }
4947  // check missing volume boundary
4948  if (nextPar && !(cache.m_currentDense->inside(nextPar->position(), m_tolerance) ||
4949  m_navigator->atVolumeBoundary(
4950  nextPar.get(), cache.m_currentDense, dir, assocVol, m_tolerance))) {
4951  ATH_MSG_DEBUG(" [!] ERROR: missing volume boundary for volume"
4952  << cache.m_currentDense->volumeName());
4953  if (cache.m_currentDense->zOverAtimesRho() != 0.) {
4954  ATH_MSG_DEBUG(" [!] ERROR: trying to recover: repeat the propagation step in"
4955  << cache.m_highestVolume->volumeName());
4956  cache.m_currentDense = cache.m_highestVolume;
4957  continue;
4958  }
4959  }
4960  if (!nextPar) {
4961  ATH_MSG_DEBUG(" [!] Propagation failed, return 0");
4962  cache.m_parametersAtBoundary.boundaryInformation(cache.m_currentStatic, nextPar, nextPar);
4963  // @TODO reset m_parametersAtBoundary ?
4964  return {};
4965  }
4966  cache.m_path += path;
4967  if (pathLim > 0.) {
4968  pathLim -= path;
4969  }
4970  ATH_MSG_DEBUG(" [+] Number of intersection solutions: " << solutions.size());
4971  // collect material
4972  if (cache.m_currentDense->zOverAtimesRho() != 0. && !cache.m_matstates &&
4973  cache.m_extrapolationCache) {
4974  double dInX0 = std::abs(path) / cache.m_currentDense->x0();
4975  double currentqoverp = nextPar->parameters()[Trk::qOverP];
4976  MaterialProperties materialProperties(*cache.m_currentDense, std::abs(path));
4977  EnergyLoss eloss = (m_elossupdater->energyLoss(
4978  materialProperties, std::abs(1. / currentqoverp), 1., dir, particle));
4979  if (m_dumpCache) {
4980  ATH_MSG_DEBUG(cache.to_string( " extrapolateToVolumeWithPathLimit"));
4981  }
4982  cache.m_extrapolationCache->updateX0(dInX0);
4984  eloss.meanIoni(), eloss.sigmaIoni(), eloss.meanRad(), eloss.sigmaRad());
4985  if (m_dumpCache) {
4986  ATH_MSG_DEBUG(cache.to_string(" After"));
4987  }
4988  }
4989  if (cache.m_currentDense->zOverAtimesRho() != 0. && cache.m_matstates) {
4990  double dInX0 = std::abs(path) / cache.m_currentDense->x0();
4991  MaterialProperties materialProperties(*cache.m_currentDense, std::abs(path));
4992  double scatsigma = std::sqrt(m_msupdater->sigmaSquare(
4993  materialProperties, 1. / std::abs(nextPar->parameters()[qOverP]), 1., particle));
4994  auto newsa = Trk::ScatteringAngles(
4995  0, 0, scatsigma / std::sin(nextPar->parameters()[Trk::theta]), scatsigma);
4996  // energy loss
4997  double currentqoverp = nextPar->parameters()[Trk::qOverP];
4998  EnergyLoss eloss = m_elossupdater->energyLoss(
4999  materialProperties, std::abs(1. / currentqoverp), 1., dir, particle);
5000  // compare energy loss
5001  ATH_MSG_DEBUG(" [M] Energy loss: STEP , EnergyLossUpdator:"
5002  << nextPar->momentum().mag() - currPar->momentum().mag() << ","
5003  << eloss.deltaE());
5004 
5005  if (cache.m_extrapolationCache) {
5006  if (m_dumpCache) {
5007  ATH_MSG_DEBUG(cache.to_string(" extrapolateToVolumeWithPathLimit"));
5008  }
5009  cache.m_extrapolationCache->updateX0(dInX0);
5011  eloss.meanIoni(), eloss.sigmaIoni(), eloss.meanRad(), eloss.sigmaRad());
5012  if (m_dumpCache) {
5013  ATH_MSG_DEBUG(cache.to_string( " After"));
5014  }
5015  }
5016  auto mefot = std::make_unique<Trk::MaterialEffectsOnTrack>(
5017  dInX0, newsa, std::make_unique<Trk::EnergyLoss>(std::move(eloss)),
5018  *((nextPar->associatedSurface()).baseSurface()));
5019 
5020  cache.m_matstates->push_back(
5021  new TrackStateOnSurface(nullptr, ManagedTrackParmPtr(nextPar).to_unique(), std::move(mefot)));
5022 
5023  ATH_MSG_DEBUG(" [M] Collecting material from dense volume '"
5024  << cache.m_currentDense->volumeName() << "', t/X0 = " << dInX0);
5025  }
5026 
5027  // int iDest = 0;
5028  unsigned int iSol = 0;
5029  while (iSol < solutions.size()) {
5030  if (solutions[iSol] < iDest) {
5031  return nextPar;
5032  } if (solutions[iSol] < iDest + cache.m_staticBoundaries.size()) {
5033  // material attached ?
5034  const Trk::Layer* mb = cache.m_navigSurfs[solutions[iSol]].first->materialLayer();
5035  if (mb) {
5036  if (mb->layerMaterialProperties() &&
5037  mb->layerMaterialProperties()->fullMaterial(nextPar->position())) {
5038  double pIn = nextPar->momentum().mag();
5039  const IMaterialEffectsUpdator* currentUpdator =
5040  subMaterialEffectsUpdator(*cache.m_currentStatic);
5041  IMaterialEffectsUpdator::ICache& currentUpdatorCache =
5043  if (currentUpdator) {
5044  nextPar = cache.manage(
5045  currentUpdator->update(
5046  currentUpdatorCache, nextPar.get(), *mb, dir, particle, matupmod));
5047  }
5048  if (!nextPar) {
5049  ATH_MSG_VERBOSE(" [+] Update may have killed track - return.");
5051  return {};
5052  } // the MEOT will be saved at the end
5053  ATH_MSG_VERBOSE(" Update energy loss:" << nextPar->momentum().mag() - pIn
5054  << "at position:" << nextPar->position());
5055  if (cache.m_matstates) {
5056  addMaterialEffectsOnTrack(ctx,
5057  cache,
5058  *m_stepPropagator,
5059  nextPar.index(),
5060  *mb,
5061  *cache.m_currentStatic,
5062  dir,
5063  particle);
5064  }
5065 
5066  }
5067  }
5068 
5069  // static volume boundary; return to the main loop
5070  unsigned int index = solutions[iSol] - iDest;
5071  // use global coordinates to retrieve attached volume (just for static!)
5072  nextVol = (cache.m_currentStatic->boundarySurfaces())[index]->attachedVolume(
5073  nextPar->position(), nextPar->momentum(), dir);
5074  if (nextVol != cache.m_currentStatic) {
5075  cache.m_parametersAtBoundary.boundaryInformation(nextVol, nextPar, nextPar);
5076  ATH_MSG_DEBUG(" [+] StaticVol boundary reached of '"
5077  << cache.m_currentStatic->volumeName()
5078  << "', geoID: " << cache.m_currentStatic->geometrySignature());
5079 
5080  if (m_navigator->atVolumeBoundary(
5081  nextPar.get(), cache.m_currentStatic, dir, assocVol, m_tolerance) &&
5082  assocVol != cache.m_currentStatic) {
5083  cache.m_currentDense = cache.m_dense ? nextVol : cache.m_highestVolume;
5084  }
5085  // no next volume found --- end of the world
5086  if (!nextVol) {
5087  ATH_MSG_DEBUG(" [+] World boundary reached - at "
5088  << positionOutput(nextPar->position()));
5089  if (!destVol) {
5090  pathLim = cache.m_path;
5091  return nextPar;
5092  }
5093  }
5094  // next volume found and parameters are at boundary
5095  if (nextVol /*&& nextPar nextPar is dereferenced after*/) {
5096  ATH_MSG_DEBUG(" [+] Crossing to next volume '"
5097  << nextVol->volumeName()
5098  << "', next geoID: " << nextVol->geometrySignature());
5099  ATH_MSG_DEBUG(" [+] Crossing position is - at "
5100  << positionOutput(nextPar->position()));
5101  if (!destVol &&
5102  cache.m_currentStatic->geometrySignature() != nextVol->geometrySignature()) {
5103  pathLim = cache.m_path;
5104  return nextPar;
5105  }
5106  }
5107  return extrapolateToVolumeWithPathLimit(
5108  ctx, cache, nextPar.index(), pathLim, dir, particle, destVol, matupmod);
5109  }
5110  } else if (solutions[iSol] <
5111  iDest + cache.m_staticBoundaries.size() + cache.m_layers.size()) {
5112  // next layer; don't return passive material layers unless required
5113  unsigned int index = solutions[iSol] - iDest - cache.m_staticBoundaries.size();
5114  const Trk::Layer* nextLayer = cache.m_navigLays[index].second;
5115  // material update ?
5116  // bool matUp = nextLayer->layerMaterialProperties() && m_includeMaterialEffects &&
5117  // nextLayer->isOnLayer(nextPar->position());
5118  bool matUp = nextLayer->fullUpdateMaterialProperties(*nextPar) &&
5119  m_includeMaterialEffects && nextLayer->isOnLayer(nextPar->position());
5120  // identical to last material layer ?
5121  if (matUp && nextLayer == cache.m_lastMaterialLayer &&
5123  matUp = false;
5124  }
5125 
5126  // material update: pre-update
5127  const IMaterialEffectsUpdator* currentUpdator =
5128  subMaterialEffectsUpdator(*cache.m_currentStatic);
5129  IMaterialEffectsUpdator::ICache& currentUpdatorCache =
5131 
5132  if (matUp && nextLayer->surfaceArray()) {
5133  double pIn = nextPar->momentum().mag();
5134  if (currentUpdator) {
5135  nextPar = cache.manage(
5136  currentUpdator->preUpdate(
5137  currentUpdatorCache, nextPar.get(), *nextLayer, dir, particle, matupmod));
5138  }
5139  if (!nextPar) {
5140  ATH_MSG_VERBOSE(" [+] Update may have killed track - return.");
5142  return {};
5143  } // the MEOT will be saved at the end
5144  ATH_MSG_VERBOSE(" Pre-update energy loss:"
5145  << nextPar->momentum().mag() - pIn << "at position:"
5146  << nextPar->position() << ", current momentum:" << nextPar->momentum());
5147 
5148  }
5149  // active surface intersections ( Fatras hits ...)
5151  if (nextLayer->surfaceArray()) {
5152  ATH_MSG_VERBOSE(" [o] Calling overlapSearch() on layer.");
5153  overlapSearch(ctx,
5154  cache,
5155  *m_subPropagators[0],
5156  currPar.index(),
5157  nextPar.index(),
5158  *nextLayer,
5159  *cache.m_currentStatic,
5160  dir,
5161  true,
5162  particle);
5163  } else if (nextLayer->layerType() > 0 && nextLayer->isOnLayer(nextPar->position())) {
5164  ATH_MSG_VERBOSE(" [o] Collecting intersection with active layer.");
5165  cache.m_parametersOnDetElements->emplace_back(nextPar->uniqueClone());
5166  }
5167  } // -------------------------- Fatras mode off -----------------------------------
5168 
5169  if (matUp) {
5170  if (nextLayer->surfaceArray()) {
5171  // verify there is material for postUpdate
5172  double postFactor = nextLayer->postUpdateMaterialFactor(*nextPar, dir);
5173  if (postFactor > 0.1) {
5174  double pIn = nextPar->momentum().mag();
5175  if (currentUpdator) {
5176  nextPar = cache.manage(
5177  currentUpdator->postUpdate(currentUpdatorCache,
5178  *nextPar,
5179  *nextLayer,
5180  dir,
5181  particle,
5182  matupmod));
5183  }
5184  if (!nextPar) {
5185  ATH_MSG_VERBOSE("postUpdate failed for input parameters:"
5186  << nextPar->position() << "," << nextPar->momentum());
5187  ATH_MSG_VERBOSE(" [+] Update may have killed track - return.");
5189  return {};
5190  } // the MEOT will be saved at the end
5191  ATH_MSG_VERBOSE(" Post-update energy loss:" << nextPar->momentum().mag() - pIn
5192  << "at position:"
5193  << nextPar->position());
5194 
5195  }
5196  } else {
5197  double pIn = nextPar->momentum().mag();
5198  if (currentUpdator) {
5199  nextPar = cache.manage(
5200  currentUpdator->update(currentUpdatorCache,
5201  nextPar.get(),
5202  *nextLayer,
5203  dir,
5204  particle,
5205  matupmod));
5206  }
5207  if (!nextPar) {
5208  ATH_MSG_VERBOSE(" [+] Update may have killed track - return.");
5210  return {};
5211  } // the MEOT will be saved at the end
5212  ATH_MSG_VERBOSE(" Update energy loss:" << nextPar->momentum().mag() - pIn
5213  << "at position:" << nextPar->position());
5214 
5215  }
5216  if (cache.m_matstates) {
5217  addMaterialEffectsOnTrack(ctx,
5218  cache,
5219  *m_stepPropagator,
5220  nextPar.index(),
5221  *nextLayer,
5222  *cache.m_currentStatic,
5223  dir,
5224  particle);
5225  }
5226  if (m_cacheLastMatLayer) {
5227  cache.m_lastMaterialLayer = nextLayer;
5228  }
5229  }
5230 
5231  if (!cache.m_robustSampling) {
5232  if (cache.m_navigLays[index].first && cache.m_navigLays[index].first->confinedLayers()) {
5233  const Trk::Layer* newLayer =
5234  nextLayer->nextLayer(nextPar->position(), dir * nextPar->momentum().normalized());
5235  if (newLayer && newLayer != nextLayer) {
5236  bool found = false;
5237  int replace = -1;
5238  for (unsigned int i = 0; i < cache.m_navigLays.size(); i++) {
5239  if (cache.m_navigLays[i].second == newLayer) {
5240  found = true;
5241  break;
5242  }
5243  if (cache.m_navigLays[i].second != nextLayer) {
5244  replace = i;
5245  }
5246  }
5247  if (!found) {
5248  if (replace > -1) {
5249  cache.m_navigLays[replace].second = newLayer;
5250  cache.m_navigSurfs[solutions[iSol] + replace - index].first =
5251  &(newLayer->surfaceRepresentation());
5252  } else {
5253  // can't insert a surface in middle
5254  return extrapolateToVolumeWithPathLimit(
5255  ctx, cache, nextPar.index(), pathLim, dir, particle, destVol, matupmod);
5256  }
5257  }
5258  }
5259  }
5260  }
5261  currPar = nextPar;
5262  } else if (solutions[iSol] < iDest + cache.m_staticBoundaries.size() + cache.m_layers.size() +
5263  cache.m_denseBoundaries.size()) {
5264  // dense volume boundary
5265  unsigned int index =
5266  solutions[iSol] - iDest - cache.m_staticBoundaries.size() - cache.m_layers.size();
5267  std::vector<std::pair<const Trk::TrackingVolume*, unsigned int>>::iterator dIter =
5268  cache.m_denseVols.begin();
5269  while (dIter != cache.m_denseVols.end() && index >= (*dIter).second) {
5270  index -= (*dIter).second;
5271  ++dIter;
5272  }
5273  if (dIter != cache.m_denseVols.end()) {
5274  currVol = (*dIter).first;
5275  nextVol =
5276  ((*dIter).first->boundarySurfaces())[index]->attachedVolume(*nextPar, dir);
5277  // the boundary orientation is not reliable
5278  Amg::Vector3D tp =
5279  nextPar->position() + 2 * m_tolerance * dir * nextPar->momentum().normalized();
5280  if (currVol->inside(tp, 0.)) {
5281  cache.m_currentDense = currVol;
5282  } else if (!nextVol || !nextVol->inside(tp, 0.)) { // search for dense volumes
5283  cache.m_currentDense = cache.m_highestVolume;
5284  if (cache.m_dense && cache.m_denseVols.empty()) {
5285  cache.m_currentDense = cache.m_currentStatic;
5286  } else {
5287  for (unsigned int i = 0; i < cache.m_denseVols.size(); i++) {
5288  const Trk::TrackingVolume* dVol = cache.m_denseVols[i].first;
5289  if (dVol->inside(tp, 0.) && dVol->zOverAtimesRho() != 0.) {
5290  cache.m_currentDense = dVol;
5291  ATH_MSG_DEBUG(" [+] Next dense volume found: '"
5292  << cache.m_currentDense->volumeName() << "'.");
5293  break;
5294  }
5295  } // loop over dense volumes
5296  }
5297  } else {
5298  cache.m_currentDense = nextVol;
5299  ATH_MSG_DEBUG(" [+] Next dense volume: '" << cache.m_currentDense->volumeName()
5300  << "'.");
5301  }
5302  }
5303  } else if (solutions[iSol] < iDest + cache.m_staticBoundaries.size() + cache.m_layers.size() +
5304  cache.m_denseBoundaries.size() +
5305  cache.m_navigBoundaries.size()) {
5306  // navig volume boundary
5307  unsigned int index = solutions[iSol] - iDest - cache.m_staticBoundaries.size() -
5308  cache.m_layers.size() - cache.m_denseBoundaries.size();
5309  std::vector<std::pair<const Trk::TrackingVolume*, unsigned int>>::iterator nIter =
5310  navigVols.begin();
5311  while (nIter != navigVols.end() && index >= (*nIter).second) {
5312  index -= (*nIter).second;
5313  ++nIter;
5314  }
5315  if (nIter != navigVols.end()) {
5316  currVol = (*nIter).first;
5317  nextVol =
5318  ((*nIter).first->boundarySurfaces())[index]->attachedVolume(*nextPar, dir);
5319  // the boundary orientation is not reliable
5320  Amg::Vector3D tp =
5321  nextPar->position() + 2 * m_tolerance * dir * nextPar->momentum().normalized();
5322  if (nextVol && nextVol->inside(tp, 0.)) {
5323  ATH_MSG_DEBUG(" [+] Navigation volume boundary, entering volume '"
5324  << nextVol->volumeName() << "'.");
5325  } else if (currVol->inside(tp, 0.)) {
5326  nextVol = currVol;
5327  ATH_MSG_DEBUG(" [+] Navigation volume boundary, entering volume '"
5328  << nextVol->volumeName() << "'.");
5329  } else {
5330  nextVol = nullptr;
5331  ATH_MSG_DEBUG(" [+] Navigation volume boundary, leaving volume '"
5332  << currVol->volumeName() << "'.");
5333  }
5334  // return only if detached volume boundaries not collected
5335  // if ( nextVol || !detachedBoundariesIncluded )
5336  if (nextVol) {
5337  return extrapolateToVolumeWithPathLimit(
5338  ctx, cache, nextPar.index(), pathLim, dir, particle, destVol, matupmod);
5339  }
5340  currPar = nextPar;
5341  }
5342  } else if (solutions[iSol] < iDest + cache.m_staticBoundaries.size() + cache.m_layers.size() +
5343  cache.m_denseBoundaries.size() +
5344  cache.m_navigBoundaries.size() +
5345  cache.m_detachedBoundaries.size()) {
5346  // detached volume boundary
5347  unsigned int index = solutions[iSol] - iDest - cache.m_staticBoundaries.size() -
5348  cache.m_layers.size() - cache.m_denseBoundaries.size() -
5349  cache.m_navigBoundaries.size();
5350  std::vector<std::pair<const Trk::DetachedTrackingVolume*, unsigned int>>::iterator dIter =
5351  cache.m_detachedVols.begin();
5352  while (dIter != cache.m_detachedVols.end() && index >= (*dIter).second) {
5353  index -= (*dIter).second;
5354  ++dIter;
5355  }
5356  if (dIter != cache.m_detachedVols.end()) {
5357  currVol = (*dIter).first->trackingVolume();
5358  nextVol =
5359  ((*dIter).first->trackingVolume()->boundarySurfaces())[index]->attachedVolume(
5360  *nextPar, dir);
5361  // the boundary orientation is not reliable
5362  Amg::Vector3D tp =
5363  nextPar->position() + 2 * m_tolerance * dir * nextPar->momentum().normalized();
5364  if (nextVol && nextVol->inside(tp, 0.)) {
5365  ATH_MSG_DEBUG(" [+] Detached volume boundary, entering volume '"
5366  << nextVol->volumeName() << "'.");
5367  } else if (currVol->inside(tp, 0.)) {
5368  nextVol = currVol;
5369  ATH_MSG_DEBUG(" [+] Detached volume boundary, entering volume '"
5370  << nextVol->volumeName() << "'.");
5371  } else {
5372  nextVol = nullptr;
5373  ATH_MSG_DEBUG(" [+] Detached volume boundary, leaving volume '"
5374  << currVol->volumeName() << "'.");
5375  }
5376  // if ( nextVol || !detachedBoundariesIncluded)
5377  if (nextVol) {
5378  return extrapolateToVolumeWithPathLimit(
5379  ctx, cache, nextPar.index(), pathLim, dir, particle, destVol, matupmod);
5380  }
5381  currPar = nextPar; // cannot move both currPar and nextPar are used and may be different.
5382  }
5383  }
5384  iSol++;
5385  }
5386  currPar = std::move(nextPar);
5387  }
5388 
5389  return {};
5390 }
Trk::ExtrapolationCache::updateX0
void updateX0(double x0)
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
Trk::Extrapolator::initializeNavigation
PropDirection initializeNavigation(const EventContext &ctx, Cache &cache, const Trk::IPropagator &prop, TrackParmPtr startPars, const Trk::Surface &destSurface, Trk::PropDirection dir, ParticleHypothesis particle, ManagedTrackParmPtr &referenceParameters, const Trk::Layer *&associatedLayer, const Trk::TrackingVolume *&associatedVolume, const Trk::TrackingVolume *&destinationVolume) const
Private method for Initial Extrapolation setup -> overwrites the given pointers for the start and des...
Definition: Extrapolator.cxx:4066
Trk::IPropagator::propagateM
virtual std::unique_ptr< TrackParameters > propagateM(const EventContext &ctx, const TrackParameters &parm, std::vector< DestSurf > &sfs, PropDirection dir, const MagneticFieldProperties &mprop, ParticleHypothesis particle, std::vector< unsigned int > &solutions, std::vector< const Trk::TrackStateOnSurface * > *&matstates, std::vector< std::pair< std::unique_ptr< Trk::TrackParameters >, int >> *intersections, double &path, bool usePathLim=false, bool returnCurv=false, const TrackingVolume *tVol=nullptr, Trk::ExtrapolationCache *cache=nullptr) const =0
Propagation interface: The propagation method with internal material collection.
Trk::anyDirection
@ anyDirection
Definition: PropDirection.h:22
Trk::Cache::m_detachedBoundaries
std::vector< DestSurf > m_detachedBoundaries
Definition: LocalExtrapolatorCache.h:81
make_hlt_rep.pars
pars
Definition: make_hlt_rep.py:90
replace
std::string replace(std::string s, const std::string &s2, const std::string &s3)
Definition: hcg.cxx:307
Trk::Cache::m_lastValidParameters
ManagedTrackParmPtr m_lastValidParameters
return helper for parameters and boundary
Definition: LocalExtrapolatorCache.h:37
Trk::CompoundLayer
A class to represent complex geometries requiring a description using multiple surfaces.
Definition: CompoundLayer.h:60
Trk::Layer::isOnLayer
virtual bool isOnLayer(const Amg::Vector3D &gp, const BoundaryCheck &bcheck=BoundaryCheck(true)) const
isOnLayer() method, using isOnSurface() with Layer specific tolerance
Definition: Layer.cxx:149
Trk::Cache::m_denseVols
std::vector< std::pair< const Trk::TrackingVolume *, unsigned int > > m_denseVols
Definition: LocalExtrapolatorCache.h:87
EnergyLoss.h
Trk::Layer::postUpdateMaterialFactor
virtual double postUpdateMaterialFactor(const TrackParameters &, PropDirection) const
getting the MaterialProperties back - for pre-update
Definition: Layer.h:151
Trk::Surface::pathCorrection
virtual double pathCorrection(const Amg::Vector3D &pos, const Amg::Vector3D &mom) const
the pathCorrection for derived classes with thickness - it reflects if the direction projection is po...
ObjPtr::release
T_Obj * release()
Release the object this pointer points to from the container.
Definition: ObjContainer.h:610
Trk::Cache::m_detachedVols
std::vector< std::pair< const Trk::DetachedTrackingVolume *, unsigned int > > m_detachedVols
Definition: LocalExtrapolatorCache.h:86
ScatteringAngles.h
TrkExTools::getToolSuffix
std::string getToolSuffix(const std::string &fullToolName)
Return the name suffix, e.g. return 'myNiceTool' from 'ToolSvc.myNiceTool'.
Definition: TrkExToolsStringUtility.cxx:14
Trk::IMaterialEffectsUpdator::ICache
Cache class to allow passing information to/between calls.
Definition: IMaterialEffectsUpdator.h:63
Trk::TrackParametersUVector
std::vector< std::unique_ptr< Trk::TrackParameters > > TrackParametersUVector
Definition: Extrapolator.h:59
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition: AthMsgStreamMacros.h:34
Trk::Extrapolator::finalize
virtual StatusCode finalize() override
AlgTool finalize method.
Definition: Extrapolator.cxx:368
Trk::Layer::fullUpdateMaterialProperties
const MaterialProperties * fullUpdateMaterialProperties(const TrackParameters &par) const
getting the MaterialProperties back - for full update
Definition: Layer.cxx:183
Trk::ParticleSwitcher::particle
constexpr ParticleHypothesis particle[PARTICLEHYPOTHESES]
the array of masses
Definition: ParticleHypothesis.h:76
python.SystemOfUnits.s
int s
Definition: SystemOfUnits.py:131
Trk::TrackingVolume::nextLayer
const Layer * nextLayer(const Amg::Vector3D &gp, const Amg::Vector3D &mom, bool asres=true, bool skipNavLayer=false) const
Return the next Layer if existing, NULL if no next layer corresponds.
Definition: TrackingVolume.cxx:605
Trk::Surface::associatedDetectorElement
const TrkDetElementBase * associatedDetectorElement() const
return associated Detector Element
TrkExTools::numberOfUniqueEntries
unsigned int numberOfUniqueEntries(const std::vector< std::string > &nameVector)
Give the number of unique entries in a vector.
Definition: TrkExToolsStringUtility.cxx:45
python.PerfMonSerializer.p
def p
Definition: PerfMonSerializer.py:743
Trk::NavigationCell::nextVolume
const TrackingVolume * nextVolume
Definition: INavigator.h:40
athena.path
path
python interpreter configuration --------------------------------------—
Definition: athena.py:126
StraightLineSurface.h
Trk::NavigationCell::parametersOnBoundary
std::unique_ptr< TrackParameters > parametersOnBoundary
Definition: INavigator.h:42
DiscBounds.h
TrackParameters.h
Trk::Extrapolator::extrapolateImpl
ManagedTrackParmPtr extrapolateImpl(const EventContext &ctx, Cache &cache, const IPropagator &prop, TrackParmPtr parm, const Surface &sf, PropDirection dir=anyDirection, const BoundaryCheck &bcheck=true, ParticleHypothesis particle=pion, MaterialUpdateMode matupmode=addNoise) const
Actual heavy lifting implementation for extrapolate.
Definition: Extrapolator.cxx:2220
GeometrySignature.h
Trk::DistanceSolution::toPointOfClosestApproach
double toPointOfClosestApproach() const
Distance to point of closest approach along direction.
Trk::MagneticFieldProperties
Definition: MagneticFieldProperties.h:31
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
PerigeeSurface.h
Trk::ParametersNextVolume::boundaryInformation
void boundaryInformation(const TrackingVolume *tvol, ManagedTrackParmPtr nextPars, ManagedTrackParmPtr navPars, BoundarySurfaceFace face=undefinedFace)
reset the boundary information by invalidating it
Definition: ParametersNextVolume.h:31
Trk::ParametersBase::charge
double charge() const
Returns the charge.
Trk::Track
The ATLAS Track class.
Definition: Tracking/TrkEvent/TrkTrack/TrkTrack/Track.h:73
CaloCellPos2Ntuple.int
int
Definition: CaloCellPos2Ntuple.py:24
Trk::DistanceSolution
Definition: DistanceSolution.h:25
Trk::Volume::inside
bool inside(const Amg::Vector3D &gp, double tol=0.) const
Inside() method for checks.
Definition: Volume.cxx:90
Trk::Extrapolator::extrapolateToVolumeBoundary
void extrapolateToVolumeBoundary(const EventContext &ctx, Cache &cache, const IPropagator &prop, TrackParmPtr parm, const Layer *associatedLayer, const TrackingVolume &tvol, PropDirection dir=anyDirection, const BoundaryCheck &bcheck=true, ParticleHypothesis particle=pion, MaterialUpdateMode matupmode=addNoise) const
Private method for extrapolation in intermediate volume to boundary surface.
Definition: Extrapolator.cxx:3087
Trk::ParametersBase::position
const Amg::Vector3D & position() const
Access method for the position.
Trk::oppositeMomentum
@ oppositeMomentum
Definition: PropDirection.h:21
Trk::TrackingVolume::geometrySignature
GeometrySignature geometrySignature() const
return the Signature
Trk::DistanceSolution::numberOfSolutions
int numberOfSolutions() const
Number of intersection solutions.
index
Definition: index.py:1
Trk::ParametersBase::associatedSurface
virtual const Surface & associatedSurface() const override=0
Access to the Surface associated to the Parameters.
Trk::Surface::straightLineDistanceEstimate
virtual DistanceSolution straightLineDistanceEstimate(const Amg::Vector3D &pos, const Amg::Vector3D &dir) const =0
fast straight line distance evaluation to Surface
Trk::ParametersBase::uniqueClone
std::unique_ptr< ParametersBase< DIM, T > > uniqueClone() const
clone method for polymorphic deep copy returning unique_ptr; it is not overriden, but uses the existi...
Definition: ParametersBase.h:97
IEnergyLossUpdator.h
Trk::Cache::m_MaterialUpCache
std::vector< Trk::IMaterialEffectsUpdator::ICache > m_MaterialUpCache
internal switch for resolved configuration
Definition: LocalExtrapolatorCache.h:41
Trk::TrackingVolume::boundarySurfaces
std::vector< SharedObject< BoundarySurface< TrackingVolume > > > & boundarySurfaces()
Method to return the BoundarySurfaces.
Definition: TrackingVolume.cxx:982
Trk::Cache
Definition: LocalExtrapolatorCache.h:27
Trk::Cache::m_extrapolationCache
Trk::ExtrapolationCache * m_extrapolationCache
cache pointer for Eloss
Definition: LocalExtrapolatorCache.h:67
Trk::Cache::m_navigBoundaries
std::vector< DestSurf > m_navigBoundaries
Definition: LocalExtrapolatorCache.h:83
Trk::Cache::m_recallTrackingVolume
const TrackingVolume * m_recallTrackingVolume
Definition: LocalExtrapolatorCache.h:57
Trk::Cache::trackingGeometry
const Trk::TrackingGeometry * trackingGeometry(const Trk::INavigator &navigator, const EventContext &ctx)
Definition: LocalExtrapolatorCache.h:110
Trk::Cache::m_layers
std::vector< DestSurf > m_layers
Definition: LocalExtrapolatorCache.h:84
CompoundLayer.h
Trk::MaterialProperties::thicknessInX0
float thicknessInX0() const
Return the radiationlength fraction.
Trk::BinnedMaterial
Definition: BinnedMaterial.h:38
Trk::Cache::populateMatEffUpdatorCache
void populateMatEffUpdatorCache(const std::vector< const IMaterialEffectsUpdator * > &updaters)
Definition: LocalExtrapolatorCache.cxx:43
Trk::TrackingVolume::associatedSubVolume
const TrackingVolume * associatedSubVolume(const Amg::Vector3D &gp) const
Return the associated sub Volume, returns THIS if no subVolume exists.
Definition: TrackingVolume.cxx:710
Trk::Cache::m_parametersOnDetElements
TrackParametersUVector * m_parametersOnDetElements
cache layer with last material update
Definition: LocalExtrapolatorCache.h:63
module_driven_slicing.layers
layers
Definition: module_driven_slicing.py:114
Trk::Material::zOverAtimesRho
float zOverAtimesRho() const
access to members
Definition: Material.h:225
Trk::Cache::m_navigLays
std::vector< std::pair< const Trk::TrackingVolume *, const Trk::Layer * > > m_navigLays
Definition: LocalExtrapolatorCache.h:88
Trk::Cache::setRecallInformation
void setRecallInformation(const Surface &, const Layer &, const TrackingVolume &)
Private method for setting recall Information.
Definition: LocalExtrapolatorCache.cxx:52
Trk::Cache::retrieveBoundaries
void retrieveBoundaries()
Retrieve boundaries.
Definition: LocalExtrapolatorCache.cxx:100
Trk::Cache::resetRecallInformation
void resetRecallInformation()
Definition: LocalExtrapolatorCache.cxx:60
PlotCalibFromCool.ib
ib
Definition: PlotCalibFromCool.py:419
ParticleTest.tp
tp
Definition: ParticleTest.py:25
Trk::TrackingVolume::confinedDetachedVolumes
ArraySpan< DetachedTrackingVolume const *const > confinedDetachedVolumes() const
Return detached subVolumes - not the ownership.
Trk::Cache::m_path
double m_path
Definition: LocalExtrapolatorCache.h:76
Trk::ScatteringAngles
represents a deflection of the track caused through multiple scattering in material.
Definition: ScatteringAngles.h:26
Trk::Extrapolator::extrapolateDirectlyImpl
std::unique_ptr< TrackParameters > extrapolateDirectlyImpl(const EventContext &ctx, const IPropagator &prop, const TrackParameters &parm, const Surface &sf, PropDirection dir=anyDirection, const BoundaryCheck &bcheck=true, ParticleHypothesis particle=pion) const
Actual heavy lifting implementation for extrapolateDirectly.
Definition: Extrapolator.cxx:1862
Layer.h
Trk::MaterialUpdateMode
MaterialUpdateMode
This is a steering enum to force the material update it can be: (1) addNoise (-1) removeNoise Second ...
Definition: MaterialUpdateMode.h:18
Trk::alongMomentum
@ alongMomentum
Definition: PropDirection.h:20
Trk::MaterialProperties::x0
float x0() const
Return the radiation length.
Trk::EnergyLoss::sigmaRad
double sigmaRad() const
Trk::ParametersNextVolume::resetBoundaryInformation
void resetBoundaryInformation()
Definition: ParametersNextVolume.h:41
Trk::Surface::globalReferencePoint
virtual const Amg::Vector3D & globalReferencePoint() const
Returns a global reference point on the surface, for PlaneSurface, StraightLineSurface,...
read_hist_ntuple.t
t
Definition: read_hist_ntuple.py:5
Trk::DistanceSolution::first
double first() const
Distance to first intersection solution along direction.
PlotCalibFromCool.multi
multi
Definition: PlotCalibFromCool.py:99
Trk::Extrapolator::~Extrapolator
~Extrapolator()
Destructor.
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
Trk::Cache::m_robustSampling
bool m_robustSampling
Definition: LocalExtrapolatorCache.h:46
Trk::EnergyLoss::meanIoni
double meanIoni() const
Trk::Surface::center
const Amg::Vector3D & center() const
Returns the center position of the Surface.
Trk::Calo
@ Calo
Definition: GeometrySignature.h:28
Trk::TrackingVolume::layerAttempts
unsigned int layerAttempts(BoundarySurfaceFace exitFace) const
Layer attempts - as provided by the LayerAttemptCreator.
Trk::ParametersNextVolume::nextVolume
const TrackingVolume * nextVolume
Definition: ParametersNextVolume.h:18
Trk::Layer::compatibleSurfaces
size_t compatibleSurfaces(std::vector< SurfaceIntersection > &cSurfaces, const TrackParameters &pars, PropDirection pdir, const BoundaryCheck &bcheck, bool materialSurfacesOnly=true, const Surface *startSurface=nullptr, const Surface *endSurface=nullptr, const ICompatibilityEstimator *ice=nullptr) const
get compatible surfaces starting from charged parameters
Trk::AlignableTrackingVolume::binnedMaterial
const BinnedMaterial * binnedMaterial() const
access to binned material
Definition: AlignableTrackingVolume.h:74
TrkExTools::possibleToolNameError
std::string possibleToolNameError(const std::vector< std::string > &toolNameVector)
Give an error message if tool names are invalid; empty string if good.
Definition: TrkExToolsStringUtility.cxx:34
Trk::NumberOfSignatures
@ NumberOfSignatures
Definition: GeometrySignature.h:32
Trk::BoundarySurfaceFace
BoundarySurfaceFace
Definition: BoundarySurfaceFace.h:31
Trk::Layer::layerType
int layerType() const
get the Layer coding
Trk::Extrapolator::extrapolateToVolume
virtual std::unique_ptr< TrackParameters > extrapolateToVolume(const EventContext &ctx, const TrackParameters &parm, const Trk::TrackingVolume &vol, PropDirection dir=anyDirection, ParticleHypothesis particle=pion) const override final
Extrapolation to volume :
Definition: Extrapolator.cxx:2127
Trk::Cache::addOneNavigationLayer
void addOneNavigationLayer(const Trk::TrackingVolume *pDetVol, const Trk::Layer *pLayer, bool boundaryCheck=true)
Add one layer and navigLayer.
Definition: LocalExtrapolatorCache.cxx:110
Trk::Extrapolator::extrapolateToVolumeImpl
std::unique_ptr< TrackParameters > extrapolateToVolumeImpl(const EventContext &ctx, const IPropagator &prop, const TrackParameters &parm, const Trk::TrackingVolume &vol, PropDirection dir=anyDirection, ParticleHypothesis particle=pion) const
Actual heavy lifting implementation for extrapolateToVolume.
Definition: Extrapolator.cxx:1876
Trk::Layer::preUpdateMaterialFactor
virtual double preUpdateMaterialFactor(const TrackParameters &, PropDirection) const
getting the MaterialProperties back - for pre-update
Definition: Layer.h:145
ExtrapolationCache.h
Trk::Surface::baseSurface
virtual const Trk::Surface * baseSurface() const
return the base surface (simplified for persistification)
Track.h
Trk::MS
@ MS
Definition: GeometrySignature.h:29
Trk::TrackingVolume::confinedLayers
const LayerArray * confinedLayers() const
Return the subLayer array.
Trk::Layer::surfaceArray
const SurfaceArray * surfaceArray() const
Return the entire SurfaceArray, returns nullptr if no SurfaceArray.
Trk::FastField
@ FastField
call the fast field access method of the FieldSvc
Definition: MagneticFieldMode.h:20
Trk::Extrapolator::extrapolateDirectly
virtual std::unique_ptr< TrackParameters > extrapolateDirectly(const EventContext &ctx, const TrackParameters &parm, const Surface &sf, PropDirection dir=anyDirection, const BoundaryCheck &bcheck=true, ParticleHypothesis particle=pion) const override final
Extrapolate directly: Forwards directly the call to the configured "Global" propagator.
Definition: Extrapolator.cxx:2081
Trk::ParticleHypothesis
ParticleHypothesis
Definition: ParticleHypothesis.h:25
GeoPrimitives.h
SurfaceBounds.h
Trk::MaterialEffectsOnTrack
represents the full description of deflection and e-loss of a track in material.
Definition: MaterialEffectsOnTrack.h:40
Trk::Layer::subSurface
const Surface * subSurface(const Amg::Vector3D &gp) const
If no subSurface array is defined or no subSurface can be found to the given Amg::Vector3D,...
Definition: Layer.cxx:121
Volume.h
Trk::Cache::m_boundaryVolume
const Volume * m_boundaryVolume
Destination Surface for recall.
Definition: LocalExtrapolatorCache.h:51
Trk::PropDirection
PropDirection
Definition: PropDirection.h:19
Trk::Cache::subMaterialEffectsUpdatorCache
IMaterialEffectsUpdator::ICache & subMaterialEffectsUpdatorCache(const TrackingVolume &tvol)
Get the IMaterialEffectsUpdator::ICache for the MaterialEffectsUpdator.
Definition: LocalExtrapolatorCache.cxx:33
Trk::TrackingGeometry::highestTrackingVolume
const TrackingVolume * highestTrackingVolume() const
return the world
Trk::Surface::isOnSurface
virtual bool isOnSurface(const Amg::Vector3D &glopo, const BoundaryCheck &bchk=true, double tol1=0., double tol2=0.) const
This method returns true if the GlobalPosition is on the Surface for both, within or without check of...
Definition: Surface.cxx:123
Trk::Material::x0
float x0() const
Definition: Material.h:226
ParticleGun_EoverP_Config.mom
mom
Definition: ParticleGun_EoverP_Config.py:63
python.SystemOfUnits.millimeter
int millimeter
Definition: SystemOfUnits.py:53
Trk::Extrapolator::addMaterialEffectsOnTrack
void addMaterialEffectsOnTrack(const EventContext &ctx, Cache &cache, const Trk::IPropagator &prop, TrackParmPtr parm, const Trk::Layer &lay, const Trk::TrackingVolume &vol, Trk::PropDirection propDir, Trk::ParticleHypothesis) const
helper method for MaterialEffectsOnTrack to be added
Definition: Extrapolator.cxx:4316
ObjContainer.h
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
Trk::Layer::surfaceRepresentation
virtual const Surface & surfaceRepresentation() const =0
Transforms the layer into a Surface representation for extrapolation.
Trk::Extrapolator::extrapolateStepwiseImpl
TrackParametersUVector extrapolateStepwiseImpl(const EventContext &ctx, const IPropagator &prop, const TrackParameters &parm, const Surface &sf, PropDirection dir=anyDirection, const BoundaryCheck &bcheck=true, ParticleHypothesis particle=pion) const
Definition: Extrapolator.cxx:456
Trk::Cache::m_layerResolved
unsigned int m_layerResolved
Definition: LocalExtrapolatorCache.h:47
Trk::active
@ active
Definition: Layer.h:48
AthCheckedComponent
Mixin class to perform additional checks on a component.
Definition: AthCheckedComponent.h:25
Trk::Extrapolator::extrapolateFromLayerToLayer
ManagedTrackParmPtr extrapolateFromLayerToLayer(const EventContext &ctx, Cache &cache, const IPropagator &prop, TrackParmPtr parm, const TrackingVolume &tvol, const Layer *nextLayer, const Layer *destinationLayer, TrackParmPtr navParameters, PropDirection dir=anyDirection, const BoundaryCheck &bcheck=true, ParticleHypothesis particle=pion, MaterialUpdateMode matupmode=addNoise) const
Private method to step from one to the last layer and stop at last layer (before 0) or before destina...
Definition: Extrapolator.cxx:3559
lumiFormat.i
int i
Definition: lumiFormat.py:92
Trk::ArraySpan
std::span< T > ArraySpan
Definition: DetachedTrackingVolume.h:34
Trk::Cache::m_matstates
std::vector< const Trk::TrackStateOnSurface * > * m_matstates
Definition: LocalExtrapolatorCache.h:71
beamspotman.n
n
Definition: beamspotman.py:731
Trk::TrackingVolume::confinedArbitraryLayers
ArraySpan< Layer const *const > confinedArbitraryLayers() const
Return the confined subLayer array.
Trk::theta
@ theta
Definition: ParamDefs.h:72
Trk::IPropagator
Definition: IPropagator.h:55
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
TrkExToolsStringUtility.h
namespaced string utilities for TrkExTools
Trk::Cache::m_denseResolved
std::pair< unsigned int, unsigned int > m_denseResolved
Definition: LocalExtrapolatorCache.h:78
Trk::TrackingVolume::confinedDenseVolumes
ArraySpan< TrackingVolume const *const > confinedDenseVolumes() const
Return unordered subVolumes - not the ownership.
TRT::Hit::layer
@ layer
Definition: HitInfo.h:79
Trk::DistanceSolution::second
double second() const
Distance to second intersection solution along direction (for a cylinder surface)
Trk::Cache::m_dense
bool m_dense
Flag the recall solution.
Definition: LocalExtrapolatorCache.h:43
Trk::Extrapolator::radialDirectionCheck
bool radialDirectionCheck(const EventContext &ctx, const IPropagator &prop, const TrackParameters &startParm, const TrackParameters &parsOnLayer, const TrackingVolume &tvol, PropDirection dir=anyDirection, ParticleHypothesis particle=pion) const
Check for punchThrough in case of radial (perpendicular) direction change, returns true if the radial...
Definition: Extrapolator.cxx:4257
Trk::TrackingGeometry::lowestStaticTrackingVolume
const TrackingVolume * lowestStaticTrackingVolume(const Amg::Vector3D &gp) const
return the lowest static tracking Volume
Definition: TrackingGeometry.cxx:77
Trk::Extrapolator::extrapolateToDestinationLayer
ManagedTrackParmPtr extrapolateToDestinationLayer(const EventContext &ctx, Cache &cache, const IPropagator &prop, TrackParmPtr parm, const Surface &sf, const Layer &lay, const TrackingVolume &tvol, const Layer *startLayer, PropDirection dir=anyDirection, const BoundaryCheck &bcheck=true, ParticleHypothesis particle=pion, MaterialUpdateMode matupmode=addNoise) const
Private to extrapolate to the destination layer + surface.
Definition: Extrapolator.cxx:3684
Amg::Transform3D
Eigen::Affine3d Transform3D
Definition: GeoPrimitives.h:46
Trk::Extrapolator::identifiedParameters_t
std::vector< std::pair< std::unique_ptr< Trk::TrackParameters >, int > > identifiedParameters_t
Definition: Extrapolator.h:254
Amg::transform
Amg::Vector3D transform(Amg::Vector3D &v, Amg::Transform3D &tr)
Transform a point from a Trasformation3D.
Definition: GeoPrimitivesHelpers.h:156
Trk::Extrapolator::extrapolateInAlignableTV
ManagedTrackParmPtr extrapolateInAlignableTV(const EventContext &ctx, Cache &cache, const IPropagator &prop, TrackParmPtr parm, const Trk::Surface *destSurf, const Trk::AlignableTrackingVolume *vol, PropDirection dir, ParticleHypothesis particle=pion) const
Definition: Extrapolator.cxx:1600
CylinderSurface.h
Trk::Cache::m_navigSurfs
std::vector< std::pair< const Trk::Surface *, Trk::BoundaryCheck > > m_navigSurfs
Definition: LocalExtrapolatorCache.h:89
Trk::EnergyLoss::deltaE
double deltaE() const
returns the
Trk::ParametersNextVolume::navParameters
ManagedTrackParmPtr navParameters
Definition: ParametersNextVolume.h:20
Trk::Cache::m_highestVolume
const Trk::TrackingVolume * m_highestVolume
Pointer (not owning) pointing.
Definition: LocalExtrapolatorCache.h:60
Trk::NavigationCell::exitFace
BoundarySurfaceFace exitFace
Definition: INavigator.h:43
Trk::Surface::normal
virtual const Amg::Vector3D & normal() const
Returns the normal vector of the Surface (i.e.
Trk::Layer::nextLayer
const Layer * nextLayer(const Amg::Vector3D &gp, const Amg::Vector3D &udir) const
getting the next/previous Layer if registered - unit for direction vector required
Definition: Layer.cxx:175
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
Trk::Cache::m_staticBoundaries
std::vector< DestSurf > m_staticBoundaries
Definition: LocalExtrapolatorCache.h:80
CylinderLayer.h
Trk::Cache::m_denseBoundaries
std::vector< DestSurf > m_denseBoundaries
Definition: LocalExtrapolatorCache.h:82
Trk::Surface::materialLayer
const Trk::Layer * materialLayer() const
return the material Layer
Trk::ParametersBase
Definition: ParametersBase.h:55
Trk::Extrapolator::extrapolateWithinDetachedVolumes
ManagedTrackParmPtr extrapolateWithinDetachedVolumes(const EventContext &ctx, Cache &cache, const IPropagator &prop, TrackParmPtr parm, const Surface &sf, const TrackingVolume &tvol, PropDirection dir=anyDirection, const BoundaryCheck &bcheck=true, ParticleHypothesis particle=pion, MaterialUpdateMode matupmode=addNoise) const
C) call from extrapolateInsideVolume.
Definition: Extrapolator.cxx:2880
Trk::Cache::m_recallSurface
const Surface * m_recallSurface
Destination Layer for recall.
Definition: LocalExtrapolatorCache.h:53
Trk::CurvilinearParametersT
Definition: CurvilinearParametersT.h:48
Trk::Cache::m_currentDense
const Trk::TrackingVolume * m_currentDense
Definition: LocalExtrapolatorCache.h:59
Trk::Cache::m_trackingGeometry
const Trk::TrackingGeometry * m_trackingGeometry
Definition: LocalExtrapolatorCache.h:75
DeMoUpdate.tmp
string tmp
Definition: DeMoUpdate.py:1167
Trk::neutron
@ neutron
Definition: ParticleHypothesis.h:33
Trk::Extrapolator::positionOutput
std::string positionOutput(const Amg::Vector3D &pos) const
For the output - global position.
Definition: Extrapolator.cxx:4303
SharedObject.h
Trk::EnergyLoss::meanRad
double meanRad() const
dot.dot
def dot(G, fn, nodesToHighlight=[])
Definition: dot.py:5
Trk::LayerIndex::value
int value() const
layerIndex expressed in an integer
Definition: LayerIndex.h:71
Trk::FullField
@ FullField
Field is set to be realistic, but within a given Volume.
Definition: MagneticFieldMode.h:21
Trk::Cache::m_recallLayer
const Layer * m_recallLayer
Destination TrackingVolume for recall.
Definition: LocalExtrapolatorCache.h:55
DetachedTrackingVolume.h
beamspotman.dir
string dir
Definition: beamspotman.py:623
Trk::Extrapolator::extrapolateStepwise
virtual TrackParametersUVector extrapolateStepwise(const EventContext &ctx, const TrackParameters &parm, const Surface &sf, PropDirection dir=anyDirection, const BoundaryCheck &bcheck=true, ParticleHypothesis particle=pion) const override final
Extrapolation method where a step-wise navigation to the destination surface is performed.
Definition: Extrapolator.cxx:2009
Trk::IPropagator::propagateParameters
virtual std::unique_ptr< TrackParameters > propagateParameters(const EventContext &ctx, const TrackParameters &parm, const Surface &sf, PropDirection dir, const BoundaryCheck &bcheck, const MagneticFieldProperties &mprop, ParticleHypothesis particle=pion, bool returnCurv=false, const TrackingVolume *tVol=nullptr) const =0
Main propagation method for parameters only.
Trk::Global
@ Global
Definition: GeometrySignature.h:25
Trk::ParametersCommon::localPosition
Amg::Vector2D localPosition() const
Access method for the local coordinates, local parameter definitions differ for each surface type.
Trk::Track::trackParameters
const DataVector< const TrackParameters > * trackParameters() const
Return a pointer to a vector of TrackParameters.
Definition: Tracking/TrkEvent/TrkTrack/src/Track.cxx:97
Trk::Cache::elossPointerErrorMsg
std::string elossPointerErrorMsg(int lineNumber=0) const
String error message if the cache has a problem.
Definition: LocalExtrapolatorCache.cxx:91
EventPrimitives.h
Trk::Cache::m_destinationSurface
const Surface * m_destinationSurface
the boundary volume check
Definition: LocalExtrapolatorCache.h:49
Trk
Ensure that the ATLAS eigen extensions are properly loaded.
Definition: FakeTrackBuilder.h:9
Trk::TrackingVolume::volumeName
const std::string & volumeName() const
Returns the VolumeName - for debug reason, might be depreciated later.
ObjPtr< Trk::TrackParameters >
IMultipleScatteringUpdator.h
Trk::TrackStateOnSurface
represents the track state (measurement, material, fit parameters and quality) at a surface.
Definition: TrackStateOnSurface.h:71
Trk::Extrapolator::collectIntersections
virtual std::unique_ptr< std::vector< std::pair< std::unique_ptr< Trk::TrackParameters >, int > > > collectIntersections(const EventContext &ctx, const Trk::TrackParameters &parm, Trk::PropDirection dir, Trk::ParticleHypothesis particle, std::vector< const Trk::TrackStateOnSurface * > *&material, int destination=3) const override final
Extrapolation method collecting intersections with subdetector boundaries and active volumes/layers.
Definition: Extrapolator.cxx:4457
Trk::Surface::bounds
virtual const SurfaceBounds & bounds() const =0
Surface Bounds method.
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:195
ActsTrk::to_string
std::string to_string(const DetectorType &type)
Definition: GeometryDefs.h:34
Trk::Extrapolator::extrapolate
virtual std::unique_ptr< NeutralParameters > extrapolate(const NeutralParameters &parameters, const Surface &sf, PropDirection dir=anyDirection, const BoundaryCheck &bcheck=true) const override final
Main extrapolation Interface starting from neutral parameters and aiming at surface.
Definition: Extrapolator.cxx:440
Trk::IMaterialEffectsUpdator::update
virtual std::unique_ptr< TrackParameters > update(ICache &icache, const TrackParameters *param, const Layer &sf, PropDirection dir=alongMomentum, ParticleHypothesis particle=pion, MaterialUpdateMode matupmode=addNoise) const =0
Updator interface (full update for a layer): The parameters are given as a pointer owned by the calle...
Trk::nonInteracting
@ nonInteracting
Definition: ParticleHypothesis.h:25
Trk::EnergyLoss
This class describes energy loss material effects in the ATLAS tracking EDM.
Definition: EnergyLoss.h:34
Trk::BinnedArray::arrayObjects
virtual BinnedArraySpan< T *const > arrayObjects()=0
Return all objects of the Array non-const we can still modify the T.
BoundarySurfaceFace.h
AtlCoolConsole.tool
tool
Definition: AtlCoolConsole.py:453
Trk::DistanceSolution::absClosest
double absClosest() const
Absolute Distance to closest solution.
Trk::Extrapolator::extrapolateM
virtual std::vector< const TrackStateOnSurface * > * extrapolateM(const EventContext &ctx, const TrackParameters &parameters, const Surface &sf, PropDirection dir, const BoundaryCheck &bcheck, ParticleHypothesis particle=pion, Trk::ExtrapolationCache *cache=nullptr) const override final
Extrapolate to a destination surface, while collecting all the material layers in between.
Definition: Extrapolator.cxx:2148
Trk::Layer::thickness
double thickness() const
Return the Thickness of the Layer.
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
Trk::ExtrapolationCache::updateEloss
void updateEloss(double ioni, double sigi, double rad, double sigr)
Trk::IMaterialEffectsUpdator::preUpdate
virtual std::unique_ptr< TrackParameters > preUpdate(ICache &icache, const TrackParameters *param, const Layer &sf, PropDirection dir=alongMomentum, ParticleHypothesis particle=pion, MaterialUpdateMode matupmode=addNoise) const =0
Updator interface (pre-update for a layer): The parameters are given as a pointer owned by the caller...
python.LumiBlobConversion.pos
pos
Definition: LumiBlobConversion.py:18
BoundarySurface.h
Trk::NavigationCell
useful struct for a single navigation cell
Definition: INavigator.h:38
Trk::Extrapolator::initialize
virtual StatusCode initialize() override
AlgTool initailize method.
Definition: Extrapolator.cxx:222
Trk::ParametersNextVolume::nextParameters
ManagedTrackParmPtr nextParameters
Definition: ParametersNextVolume.h:19
Trk::Surface::associatedLayer
const Trk::Layer * associatedLayer() const
return the associated Layer
Trk::Extrapolator::extrapolateToVolumeWithPathLimit
ManagedTrackParmPtr extrapolateToVolumeWithPathLimit(const EventContext &ctx, Cache &cache, TrackParmPtr parm, double pathLim, Trk::PropDirection dir, Trk::ParticleHypothesis particle, const Trk::TrackingVolume *destVol, MaterialUpdateMode matupmod=addNoise) const
Definition: Extrapolator.cxx:4515
Trk::ParametersBase::momentum
const Amg::Vector3D & momentum() const
Access method for the momentum.
Trk::IMaterialEffectsUpdator::postUpdate
virtual std::unique_ptr< TrackParameters > postUpdate(ICache &icache, const TrackParameters &param, const Layer &sf, PropDirection dir=alongMomentum, ParticleHypothesis particle=pion, MaterialUpdateMode matupmode=addNoise) const =0
Updator interface (pre-update for a layer): The parameters are given as a pointer owned by the caller...
DeMoScan.index
string index
Definition: DeMoScan.py:362
Trk::TrackingVolume::redoNavigation
bool redoNavigation() const
Boolean, if true navigation needs to be redone when hitting this volume.
Trk::MaterialProperties
Definition: MaterialProperties.h:40
DiTauMassTools::MaxHistStrategyV2::e
e
Definition: PhysicsAnalysis/TauID/DiTauMassTools/DiTauMassTools/HelperFunctions.h:26
ObjRef
Helper class to refer to objects in the container ObjContainer.
Definition: ObjContainer.h:61
CondAlgsOpts.found
int found
Definition: CondAlgsOpts.py:101
Trk::Cache::m_methodSequence
unsigned int m_methodSequence
Definition: LocalExtrapolatorCache.h:48
Trk::ExtrapolationCache::x0tot
double x0tot() const
Trk::Extrapolator::insideVolumeStaticLayers
ManagedTrackParmPtr insideVolumeStaticLayers(const EventContext &ctx, Cache &cache, bool toBoundary, const IPropagator &prop, TrackParmPtr parm, const Layer *associatedLayer, const TrackingVolume &tvol, PropDirection dir=anyDirection, const BoundaryCheck &bcheck=true, ParticleHypothesis particle=pion, MaterialUpdateMode matupmode=addNoise) const
A) call from extrapolateInsideVolume or toBoundary, if it is to boundary, the return parameters are t...
Definition: Extrapolator.cxx:3115
Trk::IPropagator::propagate
virtual std::unique_ptr< NeutralParameters > propagate(const NeutralParameters &parameters, const Surface &sf, PropDirection dir, const BoundaryCheck &bcheck, bool returnCurv=false) const =0
Main propagation method for NeutralParameters.
mapkey::sf
@ sf
Definition: TElectronEfficiencyCorrectionTool.cxx:38
ObjPtr::get
T_Obj * get()
Get a pointer to a valid manged object.
Definition: ObjContainer.h:588
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
Trk::TrackingGeometry::lowestDetachedTrackingVolumes
std::vector< const Trk::DetachedTrackingVolume * > lowestDetachedTrackingVolumes(const Amg::Vector3D &gp) const
return the vector of lowest detached tracking Volume(->overlaps)
Definition: TrackingGeometry.cxx:65
TRT_PAI_physicsConstants::mb
const double mb
1mb to cm2
Definition: TRT_PAI_physicsConstants.h:15
Trk::TrackingVolume::nextVolume
const TrackingVolume * nextVolume(const Amg::Vector3D &gp, const Amg::Vector3D &dir, PropDirection pDir=alongMomentum) const
Return the next volume along the navigation stream.
Definition: TrackingVolume.cxx:760
Trk::userOwn
@ userOwn
Definition: Tracking/TrkDetDescr/TrkSurfaces/TrkSurfaces/Surface.h:57
Trk::BoundaryCheck
Definition: BoundaryCheck.h:51
Trk::BinnedMaterial::material
const IdentifiedMaterial * material(const Amg::Vector3D &position) const
access to material/id per bin
Definition: BinnedMaterial.cxx:65
Trk::addNoise
@ addNoise
Definition: MaterialUpdateMode.h:19
PlaneSurface.h
Trk::ManagedTrackParmPtr
ObjPtr< Trk::TrackParameters > ManagedTrackParmPtr
Definition: Extrapolator.h:66
Trk::TrackingVolume::confinedVolumes
const TrackingVolumeArray * confinedVolumes() const
Return the subLayer array.
Trk::Extrapolator::overlapSearch
void overlapSearch(const EventContext &ctx, Cache &cache, const IPropagator &prop, TrackParmPtr parm, TrackParmPtr parsOnLayer, const Layer &lay, const TrackingVolume &tvol, PropDirection dir=anyDirection, const BoundaryCheck &bcheck=true, ParticleHypothesis particle=pion, bool startingLayer=false) const
Private to search for overlap surfaces.
Definition: Extrapolator.cxx:3893
ObjPtr::to_unique
std::unique_ptr< T_Obj > to_unique()
Release the object this pointer points to from the container.
Definition: ObjContainer.h:622
Trk::qOverP
@ qOverP
perigee
Definition: ParamDefs.h:73
Trk::Cache::elossPointerOverwritten
bool elossPointerOverwritten() const
Check cache integrity.
Definition: LocalExtrapolatorCache.cxx:86
Trk::Layer::enclosingTrackingVolume
const TrackingVolume * enclosingTrackingVolume() const
get the confining TrackingVolume
Trk::SurfaceType::Cylinder
@ Cylinder
Trk::Extrapolator::Extrapolator
Extrapolator(const std::string &, const std::string &, const IInterface *)
Constructor.
Definition: Extrapolator.cxx:118
Trk::Layer::layerMaterialProperties
const LayerMaterialProperties * layerMaterialProperties() const
getting the LayerMaterialProperties including full/pre/post update
Trk::TrackingGeometry::trackingVolume
const TrackingVolume * trackingVolume(const std::string &name) const
return the tracking Volume by name, 0 if it doesn't exist
Trk::IMaterialEffectsUpdator
Definition: IMaterialEffectsUpdator.h:45
Trig::FeatureAccessImpl::collect
void collect(const HLT::TriggerElement *te, std::vector< Trig::Feature< T > > &data, const std::string &label, unsigned int condition, const std::string &teName, const HLT::TrigNavStructure *navstructure)
actual feature acceess implementation It has (thanks to the ClassTraits) functionality to flatten con...
Definition: FeatureCollectAthena.h:299
Trk::TrackingVolume::isAlignable
virtual bool isAlignable() const
physics_parameters.parameters
parameters
Definition: physics_parameters.py:144
declareProperty
#define declareProperty(n, p, h)
Definition: BaseFakeBkgTool.cxx:15
Trk::Cache::to_string
std::string to_string(const std::string &txt) const
String representation of cache.
Definition: LocalExtrapolatorCache.cxx:68
MuonHough::extrapolate
float extrapolate(const MuonLayerHough::Maximum &ref, const MuonLayerHough::Maximum &ex, bool doparabolic=false)
Definition: MuonLayerHough.cxx:519
Trk::Cache::copyToNavigationSurfaces
void copyToNavigationSurfaces()
Insert navigation surfaces from layers, dense boundaries, navig boundaries and detached boundaries.
Definition: LocalExtrapolatorCache.cxx:122
TrackingGeometry.h
Trk::Extrapolator::extrapolateToIntermediateLayer
std::pair< ManagedTrackParmPtr, bool > extrapolateToIntermediateLayer(const EventContext &ctx, Cache &cache, const IPropagator &prop, TrackParmPtr parm, const Layer &lay, const TrackingVolume &tvol, PropDirection dir=anyDirection, const BoundaryCheck &bcheck=true, ParticleHypothesis particle=pion, MaterialUpdateMode matupmode=addNoise, bool perpendicularCheck=true) const
Private to extrapolate to the destination layer + surface, special treatment for exit layer.
Definition: Extrapolator.cxx:3769
Trk::undefinedFace
@ undefinedFace
Definition: BoundarySurfaceFace.h:59
Trk::Extrapolator::extrapolateToNextMaterialLayer
ManagedTrackParmPtr extrapolateToNextMaterialLayer(const EventContext &ctx, Cache &cache, const IPropagator &prop, TrackParmPtr parm, const Trk::Surface *destSurf, const Trk::TrackingVolume *vol, PropDirection dir, const BoundaryCheck &bcheck, ParticleHypothesis particle=pion, MaterialUpdateMode matupmode=addNoise) const
Definition: Extrapolator.cxx:565
SubtractedCylinderLayer.h
Trk::tubeInnerCover
@ tubeInnerCover
Definition: BoundarySurfaceFace.h:39
python.Constants.VERBOSE
int VERBOSE
Definition: Control/AthenaCommon/python/Constants.py:14
Trk::ComparisonFunction< TrackParameters >
drawFromPickle.sin
sin
Definition: drawFromPickle.py:36
Trk::Extrapolator::extrapolateBlindlyImpl
Trk::TrackParametersUVector extrapolateBlindlyImpl(const EventContext &ctx, Cache &cache, const IPropagator &prop, TrackParmPtr parm, PropDirection dir=anyDirection, const BoundaryCheck &bcheck=true, ParticleHypothesis particle=pion, const Volume *boundaryVol=nullptr) const
Actual heavy lifting implementation for extrapolateBlindly.
Definition: Extrapolator.cxx:2822
AthAlgTool
Definition: AthAlgTool.h:26
Trk::Cache::m_navigVolsInt
std::vector< std::pair< const Trk::TrackingVolume *, unsigned int > > m_navigVolsInt
Definition: LocalExtrapolatorCache.h:91
Trk::Cache::manage
ManagedTrackParmPtr manage(std::unique_ptr< Trk::TrackParameters > &&parm)
Definition: LocalExtrapolatorCache.h:100
Trk::TrackingGeometry::associatedLayer
const Layer * associatedLayer(const Amg::Vector3D &gp) const
Forward the associated Layer information.
Trk::Extrapolator::extrapolateInsideVolume
ManagedTrackParmPtr extrapolateInsideVolume(const EventContext &ctx, Cache &cache, const IPropagator &prop, TrackParmPtr parm, const Surface &sf, const Layer *associatedLayer, const TrackingVolume &tvol, PropDirection dir=anyDirection, const BoundaryCheck &bcheck=true, ParticleHypothesis particle=pion, MaterialUpdateMode matupmode=addNoise) const
Private method for extrapolation in final volume to destination surface.
Definition: Extrapolator.cxx:2857
Trk::Cache::volume
const Trk::TrackingVolume * volume(const EventContext &, const Amg::Vector3D &gp) const
Definition: LocalExtrapolatorCache.h:118
Trk::Surface
Definition: Tracking/TrkDetDescr/TrkSurfaces/TrkSurfaces/Surface.h:75
Trk::Extrapolator::extrapolateTrack
virtual std::unique_ptr< TrackParameters > extrapolateTrack(const EventContext &ctx, const Track &trk, const Surface &sf, PropDirection dir=anyDirection, const BoundaryCheck &bcheck=true, ParticleHypothesis particle=pion, MaterialUpdateMode matupmode=addNoise, Trk::ExtrapolationCache *cache=nullptr) const override final
Main extrapolation interface starting from a Trk::Track and aiming at Surface.
Definition: Extrapolator.cxx:2029
Trk::Volume
Definition: Volume.h:35
Trk::Cache::trackParmContainer
TrackParmContainer & trackParmContainer()
Definition: LocalExtrapolatorCache.h:98
Trk::Extrapolator::extrapolateToNextActiveLayerM
virtual std::pair< std::unique_ptr< TrackParameters >, const Layer * > extrapolateToNextActiveLayerM(const EventContext &ctx, const TrackParameters &parm, PropDirection dir, const BoundaryCheck &bcheck, std::vector< const Trk::TrackStateOnSurface * > &material, ParticleHypothesis particle=pion, MaterialUpdateMode matupmode=addNoise) const override final
Extrapolation to the next active layer with material collection.
Definition: Extrapolator.cxx:2102
Trk::IdentifiedMaterial
std::pair< const Material *, int > IdentifiedMaterial
Definition: BinnedMaterial.h:28
Trk::TrackingVolume
Definition: TrackingVolume.h:121
Trk::TrackingVolume::associatedLayer
const Layer * associatedLayer(const Amg::Vector3D &gp) const
Return the associated Layer.
Definition: TrackingVolume.cxx:569
AlignableTrackingVolume.h
python.compressB64.c
def c
Definition: compressB64.py:93
dq_make_web_display.cl
cl
print [x.__class__ for x in toList(dqregion.getSubRegions()) ]
Definition: dq_make_web_display.py:26
Trk::Extrapolator::extrapolateToNextActiveLayerMImpl
std::pair< std::unique_ptr< TrackParameters >, const Layer * > extrapolateToNextActiveLayerMImpl(const EventContext &ctx, const IPropagator &prop, const TrackParameters &parm, PropDirection dir, const BoundaryCheck &bcheck, std::vector< const Trk::TrackStateOnSurface * > &material, ParticleHypothesis particle=pion, MaterialUpdateMode matupmode=addNoise) const
Actual heavy lifting implementation for extrapolateToNextActiveLayerM.
Definition: Extrapolator.cxx:493
Trk::ExtrapolationCache
Definition: ExtrapolationCache.h:26
Trk::BinnedArraySpan
std::span< T > BinnedArraySpan
Definition: BinnedArray.h:34
Trk::Cache::m_cacheEloss
const Trk::EnergyLoss * m_cacheEloss
cache of TrackStateOnSurfaces
Definition: LocalExtrapolatorCache.h:69
Trk::Surface::type
constexpr virtual SurfaceType type() const =0
Returns the Surface type to avoid dynamic casts.
Trk::Cache::m_lastMaterialLayer
const Layer * m_lastMaterialLayer
cache for collecting the total X0 ans Eloss
Definition: LocalExtrapolatorCache.h:65
mag
Scalar mag() const
mag method
Definition: AmgMatrixBasePlugin.h:25
Trk::Cache::m_currentStatic
const Trk::TrackingVolume * m_currentStatic
Definition: LocalExtrapolatorCache.h:58
Trk::Extrapolator::extrapolateBlindly
virtual TrackParametersUVector extrapolateBlindly(const EventContext &ctx, const TrackParameters &parm, PropDirection dir=anyDirection, const BoundaryCheck &bcheck=true, ParticleHypothesis particle=pion, const Volume *boundaryVol=nullptr) const override final
extrapolateBlindly like step-wise extrapolation, but without a destination surface.
Definition: Extrapolator.cxx:2054
TrackStateOnSurface.h
Trk::Cache::m_parametersAtBoundary
ParametersNextVolume m_parametersAtBoundary
Caches per MaterialUpdator.
Definition: LocalExtrapolatorCache.h:39
Extrapolator.h
Trk::Cache::m_identifiedParameters
std::unique_ptr< identifiedParameters_t > m_identifiedParameters
Definition: LocalExtrapolatorCache.h:73
ObjPtr::index
ObjRef index() const
Get a light-weight reference to the object pointed to by this pointer The returned light-weight refer...
Definition: ObjContainer.h:629
Trk::ParametersBase::clone
virtual ParametersBase< DIM, T > * clone() const override=0
clone method for polymorphic deep copy
Trk::ExtrapolationCache::eloss
const EnergyLoss * eloss() const
Trk::ParametersNextVolume::exitFace
BoundarySurfaceFace exitFace
Definition: ParametersNextVolume.h:21
Trk::EnergyLoss::sigmaIoni
double sigmaIoni() const
Trk::Layer
Definition: Layer.h:73
Trk::AlignableTrackingVolume
Definition: AlignableTrackingVolume.h:36
Trk::Layer::layerIndex
const LayerIndex & layerIndex() const
get the layerIndex
TrkParametersComparisonFunction.h
Trk::SurfaceBounds::r
virtual double r() const =0
Interface method for the maximal extension or the radius.