ATLAS Offline Software
GsfExtrapolator.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3  */
4 
13 
16 
17 #include "TrkGeometry/Layer.h"
21 
23 
26 
28 #include "TrkSurfaces/Surface.h"
30 
31 #include <utility>
32 
33 #include <boost/container/flat_set.hpp>
34 #include <boost/container/small_vector.hpp>
35 
36 namespace {
37 constexpr bool useBoundaryMaterialUpdate(true);
38 
39 // We have cases where the MultiComponentState is not owned
40 // so we need to set just the cache ptr pointing to that.
41 // In other cases we need to add it to the cache
42 // and make it to point to the last element we push to the m_mcsRecycleBin
43 inline void
44 addMultiComponentToCache(Trk::IMultiStateExtrapolator::Cache& cache,
46  cache.m_mcsRecycleBin.emplace_back(std::move(input));
47  cache.m_stateAtBoundary = &(cache.m_mcsRecycleBin.back());
48 }
49 
50 inline void
51 setRecallInformation(Trk::IMultiStateExtrapolator::Cache& cache,
52  const Trk::Surface& recallSurface,
53  const Trk::Layer& recallLayer,
54  const Trk::TrackingVolume& recallTrackingVolume)
55 {
56  cache.m_recall = true;
57  cache.m_recallSurface = &recallSurface;
58  cache.m_recallLayer = &recallLayer;
59  cache.m_recallTrackingVolume = &recallTrackingVolume;
60 }
61 
62 inline void
63 resetRecallInformation(Trk::IMultiStateExtrapolator::Cache& cache)
64 {
65  cache.m_recall = false;
66  cache.m_recallSurface = nullptr;
67  cache.m_recallLayer = nullptr;
68  cache.m_recallTrackingVolume = nullptr;
69 }
70 
71 inline void
72 emptyRecycleBins(Trk::IMultiStateExtrapolator::Cache& cache)
73 {
74  // Reset the boundary information
75  cache.m_stateAtBoundary = nullptr;
76  cache.m_navigationParameters = nullptr;
77  cache.m_trackingVolume = nullptr;
78  cache.m_mcsRecycleBin.clear();
79 }
80 
81 int
82 radialDirection(const Trk::MultiComponentState& pars, Trk::PropDirection dir)
83 {
84  // safe inbound/outbound estimation
85  double prePositionR = pars.begin()->params->position().perp();
86  return (prePositionR > (pars.begin()->params->position() +
87  static_cast<int>(dir) * 0.5 * prePositionR *
88  pars.begin()->params->momentum().unit())
89  .perp())
90  ? -1
91  : 1;
92 }
97 inline bool
98 radialDirectionCheck(const EventContext& ctx,
99  const Trk::IPropagator& prop,
100  const Trk::MultiComponentState& startParm,
101  const Trk::MultiComponentState& parsOnLayer,
102  const Trk::TrackingVolume& tvol,
103  const Trk::MagneticFieldProperties& fieldProperties,
104  const Trk::PropDirection dir,
106 {
107  const Amg::Vector3D& startPosition = startParm.begin()->params->position();
108  const Amg::Vector3D& onLayerPosition = parsOnLayer.begin()->params->position();
109 
110  // the 3D distance to the layer intersection
111  double distToLayer = (startPosition - onLayerPosition).mag();
112  // get the innermost contained surface for crosscheck
113  const auto& boundarySurfaces = tvol.boundarySurfaces();
114  // only for tubes the crossing makes sense to check for validity
115  if (boundarySurfaces.size() == 4) {
116  // propagate to the inside surface and compare the distance:
117  // it can be either the next layer from the initial point, or the inner tube
118  // boundary surface
119  const Trk::Surface& insideSurface =
120  (boundarySurfaces[Trk::tubeInnerCover])->surfaceRepresentation();
121  auto parsOnInsideSurface =
122  prop.propagateParameters(ctx,
123  *(startParm.begin()->params),
124  insideSurface,
125  dir,
126  true,
127  fieldProperties,
128  particle);
129  double distToInsideSurface =
130  parsOnInsideSurface
131  ? (startPosition - (parsOnInsideSurface->position())).mag()
132  : 10e10;
133  // the intersection with the original layer is valid if it is before the
134  // inside surface
135  return distToLayer < distToInsideSurface;
136  }
137  return true;
138 }
139 
140 } // end of anonymous namespace
141 
142 /*
143  * AlgTool implementations
144  */
146  const std::string& name,
147  const IInterface* parent)
149  , m_fastField(false)
150 {
151  declareInterface<IMultiStateExtrapolator>(this);
152  declareProperty("MagneticFieldProperties", m_fastField);
153 }
154 
156 
159 {
160 
161  ATH_CHECK(m_propagator.retrieve());
162  ATH_CHECK(m_navigator.retrieve());
163  ATH_CHECK(m_materialUpdator.retrieve());
164 
165  m_fieldProperties = m_fastField
168 
169  return StatusCode::SUCCESS;
170 }
171 
172 /************************************************************/
173 /*
174  * Implement the public extrapolate methods
175  */
176 /************************************************************/
177 /*
178  * Extrapolate Interface
179  */
182  const EventContext& ctx,
183  Cache& cache,
184  const Trk::MultiComponentState& multiComponentState,
185  const Trk::Surface& surface,
186  Trk::PropDirection direction,
187  const Trk::BoundaryCheck& boundaryCheck,
188  Trk::ParticleHypothesis particleHypothesis) const
189 {
190  if (multiComponentState.empty()) {
191  return {};
192  }
193  return extrapolateImpl(ctx,
194  cache,
195  multiComponentState,
196  surface,
197  direction,
198  boundaryCheck,
199  particleHypothesis);
200 }
201 
202 /*
203  * Extrapolate Directly method. Does not use a cache
204  */
207  const EventContext& ctx,
208  const Trk::MultiComponentState& multiComponentState,
209  const Trk::Surface& surface,
210  Trk::PropDirection direction,
211  const Trk::BoundaryCheck& boundaryCheck,
212  Trk::ParticleHypothesis particleHypothesis) const
213 {
214  if (multiComponentState.empty()) {
215  return {};
216  }
217 
218  const Trk::TrackingVolume* currentVolume = m_navigator->highestVolume(ctx);
219  if (!currentVolume) {
221  "Current tracking volume could not be determined... returning {}");
222  return {};
223  }
224  return extrapolateDirectlyImpl(ctx,
225  multiComponentState,
226  surface,
227  direction,
228  boundaryCheck,
229  particleHypothesis);
230 }
231 
232 /************************************************************/
233 /*
234  * Now the implementation of all the internal methods
235  * that perform the actual calculations
236  */
237 /************************************************************/
238 
239 /*
240  * This is the actual extrapolation method implementation
241  */
244  const EventContext& ctx,
245  Cache& cache,
246  const Trk::MultiComponentState& multiComponentState,
247  const Trk::Surface& surface,
248  Trk::PropDirection direction,
249  const Trk::BoundaryCheck& boundaryCheck,
250  Trk::ParticleHypothesis particleHypothesis) const
251 {
252 
253  // If the extrapolation is to be without material effects simply revert to the
254  // extrapolateDirectly method
255  if (particleHypothesis == Trk::nonInteracting) {
256  return extrapolateDirectlyImpl(ctx,
257  multiComponentState,
258  surface,
259  direction,
260  boundaryCheck,
261  particleHypothesis);
262  }
263 
264  const Trk::Layer* associatedLayer = nullptr;
265  const Trk::TrackingVolume* startVolume = nullptr;
266  const Trk::TrackingVolume* destinationVolume = nullptr;
267  std::unique_ptr<Trk::TrackParameters> referenceParameters = nullptr;
268 
269  initialiseNavigation(ctx,
270  cache,
271  multiComponentState,
272  surface,
273  associatedLayer,
274  startVolume,
275  destinationVolume,
276  referenceParameters,
277  direction);
278 
279  // Bail to direct extrapolation if the direction cannot be determined
280  if (direction == Trk::anyDirection) {
281  return extrapolateDirectlyImpl(ctx,
282  multiComponentState,
283  surface,
284  direction,
285  boundaryCheck,
286  particleHypothesis);
287  }
288 
289  const Trk::TrackParameters* combinedState =
290  multiComponentState.begin()->params.get();
291 
292  const Trk::MultiComponentState* currentState = &multiComponentState;
293 
294  /* Define the initial distance between destination and current position.
295  Destination should be determined from either
296  - reference parameters (prefered if they exist) or
297  - destination surface
298  */
299 
300  Amg::Vector3D globalSeparation =
301  referenceParameters
302  ? referenceParameters->position() - combinedState->position()
303  : surface.globalReferencePoint() - combinedState->position();
304  double initialDistance = globalSeparation.mag();
305  // Clean up memory from combiner. It is no longer needed
306  combinedState = nullptr;
307 
308  /* There are two parts to the extrapolation:
309  - Extrapolate from start point to volume boundary
310  - Extrapolate from volume boundary to destination surface
311  */
312  /*
313  * Extrapolation to destination volume boundary
314  */
315  bool foundFinalBoundary(true);
316  int fallbackOscillationCounter(0);
317  const Trk::TrackingVolume* currentVolume = startVolume;
318  const Trk::TrackingVolume* previousVolume = nullptr;
319 
320  while (currentVolume && currentVolume != destinationVolume) {
321  // Extrapolate to volume boundary
322  extrapolateToVolumeBoundary(ctx,
323  cache,
324  *currentState,
325  associatedLayer,
326  *currentVolume,
327  direction,
328  particleHypothesis);
329 
330  // New current state is the state extrapolated to the tracking volume
331  // boundary.
332  currentState = cache.m_stateAtBoundary;
333  // The volume that the extrapolation is about to enter into is called the
334  // nextVolume
335  const Trk::TrackingVolume* nextVolume = cache.m_trackingVolume;
336  // Break the loop if the next tracking volume is the same as the current one
337  if (!nextVolume || nextVolume == currentVolume) {
338  foundFinalBoundary = false;
339  break;
340  }
341  // Break the loop if an oscillation is detected
342  if (previousVolume == nextVolume) {
343  ++fallbackOscillationCounter;
344  }
345  if (fallbackOscillationCounter > 10) {
346  foundFinalBoundary = false;
347  break;
348  }
349  // Break the loop if the distance between the surface and the track
350  // parameters has increased
351  combinedState = currentState->begin()->params.get();
352 
353  auto parametersAtDestination =
354  m_propagator->propagateParameters(ctx,
355  *combinedState,
356  surface,
357  direction,
358  false,
359  m_fieldProperties,
360  particleHypothesis);
361  Amg::Vector3D newDestination;
362  if (parametersAtDestination) {
363  newDestination = parametersAtDestination->position();
364  // delete parametersAtDestination;
365  } else {
366  newDestination = surface.center();
367  }
368 
369  double revisedDistance =
370  (cache.m_navigationParameters->position() - newDestination).mag();
371 
372  double distanceChange = std::abs(revisedDistance - initialDistance);
373 
374  if (revisedDistance > initialDistance && distanceChange > 0.01) {
375  foundFinalBoundary = false;
376  break;
377  }
378 
379  combinedState = nullptr;
380  // Initialise the oscillation checker
381  previousVolume = currentVolume;
382  // As the extrapolation is moving into the next volume, the next volume ->
383  // current volume
384  currentVolume = nextVolume;
385  // Associated layer now needs to be reset
386  // if(!entryLayerFound)
387  associatedLayer = nullptr;
388  } // end while loop
389 
390  // catch failures now
391  if (!currentState || (currentVolume != destinationVolume)) {
392  currentState = &multiComponentState;
393  foundFinalBoundary = false;
394  }
395 
396  if (!foundFinalBoundary) {
397  Trk::MultiComponentState bailOutState =
398  m_propagator->multiStatePropagate(ctx,
399  *currentState,
400  surface,
401  m_fieldProperties,
403  boundaryCheck,
404  particleHypothesis);
405 
406  emptyRecycleBins(cache);
407  return bailOutState;
408  }
409 
410  /*
411  * Extrapolation from volume boundary to surface
412  */
413 
414  // extrapolate inside destination volume
415  Trk::MultiComponentState destinationState =
416  extrapolateInsideVolume(ctx,
417  cache,
418  *currentState,
419  surface,
420  associatedLayer,
421  *currentVolume,
422  direction,
423  boundaryCheck,
424  particleHypothesis);
425 
426  // FALLBACK POINT: Crisis if extrapolation fails here... As per extrapolation
427  // to volume boundary, in emergency revert to extrapolateDirectly
428 
429  // or we failed to reach the target
430  if (!destinationState.empty() &&
431  &((*(destinationState.begin())).params->associatedSurface()) != &surface) {
432  destinationState.clear();
433  }
434 
435  if (destinationState.empty()) {
436  destinationState = m_propagator->multiStatePropagate(ctx,
437  *currentState,
438  surface,
439  m_fieldProperties,
441  boundaryCheck,
442  particleHypothesis);
443  }
444  emptyRecycleBins(cache);
445  return destinationState;
446 }
447 
448 /*
449  * Extrapolate Directly method. Does not use a cache
450  */
453  const EventContext& ctx,
454  const Trk::MultiComponentState& multiComponentState,
455  const Trk::Surface& surface,
456  Trk::PropDirection direction,
457  const Trk::BoundaryCheck& boundaryCheck,
458  Trk::ParticleHypothesis particleHypothesis) const
459 {
460  return m_propagator->multiStatePropagate(ctx,
461  multiComponentState,
462  surface,
463  m_fieldProperties,
464  direction,
465  boundaryCheck,
466  particleHypothesis);
467 }
468 
469 /*
470  * Extrapolate to Volume Boundary!
471  */
472 void
474  const EventContext& ctx,
475  Cache& cache,
476  const Trk::MultiComponentState& multiComponentState,
477  const Trk::Layer* layer,
478  const Trk::TrackingVolume& trackingVolume,
479  Trk::PropDirection direction,
480  Trk::ParticleHypothesis particleHypothesis) const
481 {
482 
483  //We 1st point to the input.
484  //As we move on we might change to point to the
485  //last element held by
486  //cache.m_mcsRecycleBin
487  cache.m_stateAtBoundary = &multiComponentState;
488 
489  const Trk::TrackParameters* combinedState =
490  cache.m_stateAtBoundary->begin()->params.get();
491  const Trk::Layer* associatedLayer = layer;
492 
493  if (!associatedLayer) {
494  // Get entry layer but do not use it as it should have already be hit if it
495  // was desired
496  associatedLayer = trackingVolume.associatedLayer(combinedState->position());
497  associatedLayer = associatedLayer
498  ? associatedLayer
499  : trackingVolume.nextLayer(
500  combinedState->position(),
501  direction * combinedState->momentum().unit(),
502  associatedLayer);
503  }
504  // Only loop over layers if they can be found within the tracking volume
505  else if (trackingVolume.confinedLayers() &&
506  associatedLayer->layerMaterialProperties()) {
507  Trk::MultiComponentState updatedState = m_materialUpdator->postUpdate(
509  *(cache.m_stateAtBoundary),
510  *layer,
511  direction,
512  particleHypothesis);
513 
514  if (!updatedState.empty()) {
515  addMultiComponentToCache(cache,std::move(updatedState));
516  }
517  }
518 
519  // If an associated surface can be found, extrapolation within the tracking
520  // volume is mandatory This will take extrapolate to the last layer in the
521  // volume
522  if (associatedLayer) {
523  Trk::MultiComponentState nextState = extrapolateFromLayerToLayer(
524  ctx,
525  cache,
526  *(cache.m_stateAtBoundary),
527  trackingVolume,
528  associatedLayer,
529  nullptr,
530  direction,
531  particleHypothesis);
532  // if we have a next State update the currentState
533  if (!nextState.empty()) {
534  addMultiComponentToCache(cache,std::move(nextState));
535  }
536  }
537 
538  /* =============================================
539  Find the boundary surface using the navigator
540  ============================================= */
541 
542  Trk::NavigationCell nextNavigationCell(nullptr, nullptr);
543 
544  combinedState = cache.m_stateAtBoundary->begin()->params.get();
545 
546  const Trk::TrackingVolume* nextVolume = nullptr;
547  const Trk::TrackParameters* navigationParameters =
549  ? cache.m_navigationParameters.get()
550  : combinedState;
551 
552  nextNavigationCell = m_navigator->nextTrackingVolume(
553  ctx, *m_propagator, *navigationParameters, direction, trackingVolume);
554 
555  nextVolume = nextNavigationCell.nextVolume;
556 
557  std::unique_ptr<Trk::TrackParameters> nextNavigationParameters =
558  std::move(nextNavigationCell.parametersOnBoundary);
559 
560  if (!nextVolume) {
561  // Reset the layer recall
562  resetRecallInformation(cache);
563  }
564 
565  if (useBoundaryMaterialUpdate) {
566  // Check for two things:
567  // 1. If the next volume was found
568  // 2. If there is material associated with the boundary layer.
569  // If so, apply material effects update.
570 
571  // Get layer associated with boundary surface.
572  const Trk::Layer* layerAtBoundary =
573  (nextNavigationCell.parametersOnBoundary)
574  ? (nextNavigationCell.parametersOnBoundary->associatedSurface())
575  .materialLayer()
576  : nullptr;
577  Trk::MultiComponentState matUpdatedState{};
578  if (nextVolume && layerAtBoundary) {
579  if (layerAtBoundary->layerMaterialProperties()) {
580  matUpdatedState = m_materialUpdator->postUpdate(
582  *(cache.m_stateAtBoundary),
583  *layerAtBoundary,
584  direction,
585  particleHypothesis);
586  }
587  }
588 
589  // If state has changed due to boundary material, modify state, parameters
590  // accordingly.
591  if (!matUpdatedState.empty()) {
592  addMultiComponentToCache(cache, std::move(matUpdatedState));
593  nextNavigationParameters =
594  cache.m_stateAtBoundary->begin()->params->uniqueClone();
595  }
596  }
597  // Update the rest of the boundary information in the cache
598  cache.m_navigationParameters = std::move(nextNavigationParameters);
599  cache.m_trackingVolume = nextVolume;
600 }
601 
602 /*
603  * Extrapolate inside volume to destination surface!
604  */
607  const EventContext& ctx,
608  Cache& cache,
609  const Trk::MultiComponentState& multiComponentState,
610  const Trk::Surface& surface,
611  const Trk::Layer* layer,
612  const Trk::TrackingVolume& trackingVolume,
613  Trk::PropDirection direction,
614  const Trk::BoundaryCheck& boundaryCheck,
615  Trk::ParticleHypothesis particleHypothesis) const
616 {
617  //curent state is a plainn ptr to keep track
618  const Trk::MultiComponentState* currentState = &multiComponentState;
619 
620  // Retrieve the destination layer
621  // 1. Association
622  const Trk::Layer* destinationLayer = surface.associatedLayer();
623 
624  // 2. Recall and Global Search
625  if (!destinationLayer) {
626  destinationLayer =
627  (&surface == cache.m_recallSurface)
628  ? cache.m_recallLayer
629  : trackingVolume.associatedLayer(surface.globalReferencePoint());
630  }
631 
632  // Retrieve the current layer
633  // Produce a combined state
634  const Trk::TrackParameters* combinedState =
635  currentState->begin()->params.get();
636 
637  const Trk::Layer* associatedLayer = layer;
638 
639  Trk::MultiComponentState updatedState{};
640  if (!associatedLayer) {
641  // Get entry layer but do not use it as it should have already be hit if it
642  // was desired
643  associatedLayer = trackingVolume.associatedLayer(combinedState->position());
644  associatedLayer =
645  associatedLayer
646  ? associatedLayer
647  : trackingVolume.nextLayer(combinedState->position(),
648  direction * combinedState->momentum().unit(),
649  associatedLayer);
650  }
651 
652  else if (associatedLayer != destinationLayer &&
653  trackingVolume.confinedLayers() &&
654  associatedLayer->layerMaterialProperties()) {
655 
656  updatedState = m_materialUpdator->postUpdate(cache.m_materialEffectsCaches,
657  *currentState,
658  *associatedLayer,
659  direction,
660  particleHypothesis);
661 
662  if (!updatedState.empty()) {
663  // Refresh the current state pointer
664  currentState = &updatedState;
665  }
666  }
667 
668  // Reset combined state target
669  combinedState = nullptr;
670  Trk::MultiComponentState nextState{};
671  if (destinationLayer) {
672  // If there are intermediate layers then additional extrapolations need to
673  // be done
674  if (associatedLayer && associatedLayer != destinationLayer) {
675  nextState = extrapolateFromLayerToLayer(ctx,
676  cache,
677  *currentState,
678  trackingVolume,
679  associatedLayer,
680  destinationLayer,
681  direction,
682  particleHypothesis);
683 
684  // currentState is now the next
685  if (!nextState.empty()) {
686  // Refresh the current state pointer
687  currentState = &nextState;
688  }
689  }
690  // Final extrapolation to destination surface
691  Trk::MultiComponentState returnState =
692  extrapolateToDestinationLayer(ctx,
693  cache,
694  *currentState,
695  surface,
696  *destinationLayer,
697  associatedLayer,
698  direction,
699  boundaryCheck,
700  particleHypothesis);
701  // Set the information for the current layer, surface, tracking volume
702  setRecallInformation(cache, surface, *destinationLayer, trackingVolume);
703  return returnState;
704  }
705 
706  // FALLBACK POINT: If no destination layer is found fall-back and extrapolate
707  // directly
708  Trk::MultiComponentState returnState =
709  m_propagator->multiStatePropagate(ctx,
710  *currentState,
711  surface,
712  m_fieldProperties,
713  direction,
714  boundaryCheck,
715  particleHypothesis);
716 
717  // No destination layer exists so layer recall method cannot be used and
718  // should be reset
719  resetRecallInformation(cache);
720 
721  return returnState;
722 }
723 
724 /*
725  * Extrapolate from Layer to Layer
726  */
729  const EventContext& ctx,
730  Cache& cache,
731  const MultiComponentState& multiComponentState,
732  const TrackingVolume& trackingVolume,
733  const Layer* startLayer,
734  const Layer* destinationLayer,
735  PropDirection direction,
736  ParticleHypothesis particleHypothesis) const
737 {
738 
739  const Trk::Layer* currentLayer = startLayer;
740  Trk::MultiComponentState currentState{};
741 
742  const Trk::TrackParameters* combinedState =
743  multiComponentState.begin()->params.get();
744  Amg::Vector3D currentPosition = combinedState->position();
745  Amg::Vector3D currentDirection = direction * combinedState->momentum().unit();
746 
747  // No need to extrapolate to start layer, find the next one
748  const Trk::Layer* nextLayer =
749  currentLayer->nextLayer(currentPosition, currentDirection);
750 
751  using LayerSet = boost::container::flat_set<
752  const Trk::Layer*,
753  std::less<const Trk::Layer*>,
754  boost::container::small_vector<const Trk::Layer*, 8>>;
755  LayerSet layersHit;
756 
757  layersHit.insert(currentLayer);
758 
759  // Begin while loop over all intermediate layers
760  while (nextLayer && nextLayer != destinationLayer) {
761  layersHit.insert(nextLayer);
762  // Only extrapolate to an intermediate layer if it requires material
763  // update. Otherwise step over it
764  if (nextLayer->layerMaterialProperties()) {
765  currentState = extrapolateToIntermediateLayer(
766  ctx,
767  cache,
768  !currentState.empty() ? currentState : multiComponentState,
769  *nextLayer,
770  trackingVolume,
771  direction,
772  particleHypothesis);
773  }
774 
775  if (!currentState.empty()) {
776  combinedState = currentState.begin()->params.get();
777  currentPosition = combinedState->position();
778  currentDirection = direction * combinedState->momentum().unit();
779  }
780 
781  // Find the next layer
782  currentLayer = nextLayer;
783  nextLayer = currentLayer->nextLayer(currentPosition, currentDirection);
784  if (layersHit.find(nextLayer) != layersHit.end()) {
785  break;
786  }
787  }
788 
789  if (destinationLayer && nextLayer != destinationLayer &&
790  !currentState.empty()) {
791  currentState.clear();
792  }
793 
794  return currentState;
795 }
796 
797 /*
798  * Extrapolate to Intermediate Layer
799  */
802  const EventContext& ctx,
803  Cache& cache,
804  const Trk::MultiComponentState& multiComponentState,
805  const Trk::Layer& layer,
806  const Trk::TrackingVolume& trackingVolume,
807  Trk::PropDirection direction,
808  Trk::ParticleHypothesis particleHypothesis,
809  bool doPerpCheck) const
810 {
811  const Trk::MultiComponentState* initialState = &multiComponentState;
812 
813  // Propagate over all components
814  Trk::MultiComponentState destinationState =
815  m_propagator->multiStatePropagate(ctx,
816  *initialState,
817  layer.surfaceRepresentation(),
818  m_fieldProperties,
819  direction,
820  true,
821  particleHypothesis);
822 
823  if (destinationState.empty()) {
824  return {};
825  }
826 
827  // the layer has been intersected
828  // ------------------------------------------------------------------------
829  // check for radial direction change
830  // ---------------------------------------------------------------------
831  int rDirection = radialDirection(multiComponentState, direction);
832  int newrDirection = radialDirection(destinationState, direction);
833  if (newrDirection != rDirection && doPerpCheck) {
834  // it is unfortunate that the cancelling could invalidate the material
835  // collection
836  // reset the nextParameters if the radial change is not allowed
837  // resetting is ok - since the parameters are in the garbage bin already
838  if (!radialDirectionCheck(ctx,
839  *m_propagator,
840  multiComponentState,
841  destinationState,
842  trackingVolume,
843  m_fieldProperties,
844  direction,
845  particleHypothesis)) {
846  return {};
847  }
848  }
849 
850  /* -------------------------------------
851  Material effects
852  ------------------------------------- */
853 
854  Trk::MultiComponentState updatedState =
855  m_materialUpdator->update(cache.m_materialEffectsCaches,
856  destinationState,
857  layer,
858  direction,
859  particleHypothesis);
860 
861  if (updatedState.empty()) {
862  return destinationState;
863  }
864 
865  return updatedState;
866 }
867 
868 /*
869  Extrapolate to Destination Layer
870 */
873  const EventContext& ctx,
874  Cache& cache,
875  const Trk::MultiComponentState& multiComponentState,
876  const Trk::Surface& surface,
877  const Trk::Layer& layer,
878  const Trk::Layer* startLayer,
879  Trk::PropDirection direction,
880  const Trk::BoundaryCheck& boundaryCheck,
881  Trk::ParticleHypothesis particleHypothesis) const
882 {
883 
884  const Trk::MultiComponentState* initialState = &multiComponentState;
885  const Trk::TrackParameters* combinedState = nullptr;
886 
887  // Propagate over all components
888  Trk::MultiComponentState destinationState =
889  m_propagator->multiStatePropagate(ctx,
890  multiComponentState,
891  surface,
892  m_fieldProperties,
893  direction,
894  boundaryCheck,
895  particleHypothesis);
896 
897  // Require a fall-back if the initial state is close to the destination
898  // surface then a fall-back solution is required
899 
900  if (destinationState.empty()) {
901  combinedState = initialState->begin()->params.get();
902  if (surface.isOnSurface(
903  combinedState->position(), true, 0.5 * layer.thickness())) {
904  destinationState = m_propagator->multiStatePropagate(ctx,
905  *initialState,
906  surface,
907  m_fieldProperties,
909  boundaryCheck,
910  particleHypothesis);
911  }
912  combinedState = nullptr;
913  if (destinationState.empty()) {
914  return {};
915  }
916  }
917 
918  /* ----------------------------------------
919  Material effects
920  ---------------------------------------- */
921 
922  Trk::MultiComponentState updatedState{};
923  if (startLayer != &layer) {
924  updatedState = m_materialUpdator->preUpdate(cache.m_materialEffectsCaches,
925  destinationState,
926  layer,
927  direction,
928  particleHypothesis);
929  }
930 
931  if (updatedState.empty()) {
932  return destinationState;
933  }
934 
935  return updatedState;
936 }
937 
938 /*
939  * Initialise Navigation
940  */
941 void
943  const EventContext& ctx,
944  Cache& cache,
945  const Trk::MultiComponentState& multiComponentState,
946  const Trk::Surface& surface,
947  const Trk::Layer*& currentLayer,
948  const Trk::TrackingVolume*& currentVolume,
949  const Trk::TrackingVolume*& destinationVolume,
950  std::unique_ptr<Trk::TrackParameters>& referenceParameters,
951  Trk::PropDirection direction) const
952 {
953 
954  // Empty the garbage bin
955  emptyRecycleBins(cache);
956  const Trk::TrackParameters* combinedState =
957  multiComponentState.begin()->params.get();
958  /* =============================================
959  Look for current volume
960  ============================================= */
961  // 1. See if the current layer is associated with a tracking volume
962 
963  const Trk::Surface* associatedSurface = &(combinedState->associatedSurface());
964  currentLayer =
965  associatedSurface ? associatedSurface->associatedLayer() : currentLayer;
966  currentVolume =
967  currentLayer ? currentLayer->enclosingTrackingVolume() : currentVolume;
968 
969  // If the association method failed then try the recall method
970 
971  if (!currentVolume && associatedSurface == cache.m_recallSurface) {
972  currentVolume = cache.m_recallTrackingVolume;
973  currentLayer = cache.m_recallLayer;
974  }
975  // Global search method if this fails
976 
977  else if (!currentVolume) {
978  // If the recall method fails then the cashed information needs to be reset
979  resetRecallInformation(cache);
980  currentVolume = m_navigator->volume(ctx, combinedState->position());
981  currentLayer = (currentVolume)
982  ? currentVolume->associatedLayer(combinedState->position())
983  : nullptr;
984  }
985  /* =============================================
986  Determine the resolved direction
987  ============================================= */
988  if (direction == Trk::anyDirection) {
989  referenceParameters =
990  currentVolume
991  ? m_propagator->propagateParameters(
992  ctx, *combinedState, surface, direction, false, m_fieldProperties)
993  : nullptr;
994  // These parameters will need to be deleted later. Add to list of garbage to
995  // be collected
996  if (referenceParameters) {
997  Amg::Vector3D surfaceDirection(referenceParameters->position() -
998  combinedState->position());
999  direction = (surfaceDirection.dot(combinedState->momentum()) > 0.)
1002  }
1003  }
1004 
1005  /* =============================================
1006  Look for destination volume
1007  ============================================= */
1008 
1009  // 1. See if the destination layer is associated with a tracking volume
1010  destinationVolume = surface.associatedLayer()
1012  : nullptr;
1013 
1014  // 2. See if there is a cashed recall surface
1015  if (!destinationVolume && &surface == cache.m_recallSurface) {
1016  destinationVolume = cache.m_recallTrackingVolume;
1017  // If no reference parameters are defined, then determine them
1018  if (!referenceParameters) {
1019  referenceParameters =
1020  currentVolume
1021  ? m_propagator->propagateParameters(
1022  ctx, *combinedState, surface, direction, false, m_fieldProperties)
1023  : nullptr;
1024  }
1025  // 3. Global search
1026  } else {
1027  // If no reference parameters are defined try to determine them
1028  if (!referenceParameters) {
1029  referenceParameters =
1030  currentVolume
1031  ? m_propagator->propagateParameters(
1032  ctx, *combinedState, surface, direction, false, m_fieldProperties)
1033  : nullptr;
1034  }
1035  // Global search of tracking geometry to find the destination volume
1036  destinationVolume = m_navigator->volume(
1037  ctx, referenceParameters ? referenceParameters->position()
1038  : surface.globalReferencePoint());
1039  }
1040 }
1041 
Trk::anyDirection
@ anyDirection
Definition: PropDirection.h:22
make_hlt_rep.pars
pars
Definition: make_hlt_rep.py:90
EnergyLoss.h
ScatteringAngles.h
Trk::ParticleSwitcher::particle
constexpr ParticleHypothesis particle[PARTICLEHYPOTHESES]
the array of masses
Definition: ParticleHypothesis.h:76
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::GsfExtrapolator::extrapolateDirectlyImpl
MultiComponentState extrapolateDirectlyImpl(const EventContext &ctx, const MultiComponentState &, const Surface &, PropDirection direction=anyDirection, const BoundaryCheck &boundaryCheck=true, ParticleHypothesis particleHypothesis=nonInteracting) const
Implementation of extrapolation without material effects.
Definition: GsfExtrapolator.cxx:452
Trk::NavigationCell::nextVolume
const TrackingVolume * nextVolume
Definition: INavigator.h:40
Trk::NavigationCell::parametersOnBoundary
std::unique_ptr< TrackParameters > parametersOnBoundary
Definition: INavigator.h:42
TrackParameters.h
Trk::GsfExtrapolator::extrapolateInsideVolume
MultiComponentState extrapolateInsideVolume(const EventContext &ctx, Cache &cache, const MultiComponentState &, const Surface &, const Layer *, const TrackingVolume &, PropDirection direction, const BoundaryCheck &boundaryCheck, ParticleHypothesis particleHypothesis) const
Definition: GsfExtrapolator.cxx:606
Trk::MagneticFieldProperties
Definition: MagneticFieldProperties.h:31
Surface.h
Trk::IMultiStateExtrapolator::Cache::m_recallSurface
const Surface * m_recallSurface
Layer for recall (not owning)
Definition: IMultiStateExtrapolator.h:60
MaterialProperties.h
Trk::ParametersBase::position
const Amg::Vector3D & position() const
Access method for the position.
Trk::oppositeMomentum
@ oppositeMomentum
Definition: PropDirection.h:21
Trk::ParametersBase::associatedSurface
virtual const Surface & associatedSurface() const override=0
Access to the Surface associated to the Parameters.
AthCommonDataStore< AthCommonMsg< AlgTool > >::declareProperty
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T > &t)
Definition: AthCommonDataStore.h:145
Trk::TrackingVolume::boundarySurfaces
std::vector< SharedObject< BoundarySurface< TrackingVolume > > > & boundarySurfaces()
Method to return the BoundarySurfaces.
Definition: TrackingVolume.cxx:982
Trk::IMultiStateExtrapolator::Cache::m_stateAtBoundary
const MultiComponentState * m_stateAtBoundary
Definition: IMultiStateExtrapolator.h:66
Layer.h
Trk::alongMomentum
@ alongMomentum
Definition: PropDirection.h:20
Trk::Surface::globalReferencePoint
virtual const Amg::Vector3D & globalReferencePoint() const
Returns a global reference point on the surface, for PlaneSurface, StraightLineSurface,...
Trk::Surface::center
const Amg::Vector3D & center() const
Returns the center position of the Surface.
flat_set
boost::container::flat_set< Key > flat_set
Definition: CheckConfig.cxx:11
Trk::GsfExtrapolator::initialiseNavigation
void initialiseNavigation(const EventContext &ctx, Cache &cache, const MultiComponentState &initialState, const Surface &surface, const Layer *&associatedLayer, const TrackingVolume *&currentVolume, const TrackingVolume *&destinationVolume, std::unique_ptr< TrackParameters > &referenceParameters, PropDirection direction) const
Method to initialise navigation parameters including starting state, layer and volume,...
Definition: GsfExtrapolator.cxx:942
Trk::GsfExtrapolator::extrapolateDirectly
virtual MultiComponentState extrapolateDirectly(const EventContext &ctx, const MultiComponentState &, const Surface &, PropDirection direction, const BoundaryCheck &boundaryCheck, ParticleHypothesis particleHypothesis=nonInteracting) const override final
Configured AlgTool extrapolation without material effects method (2)
Definition: GsfExtrapolator.cxx:206
Trk::TrackingVolume::confinedLayers
const LayerArray * confinedLayers() const
Return the subLayer array.
MagneticFieldProperties.h
Trk::FastField
@ FastField
call the fast field access method of the FieldSvc
Definition: MagneticFieldMode.h:20
Trk::ParticleHypothesis
ParticleHypothesis
Definition: ParticleHypothesis.h:25
Trk::PropDirection
PropDirection
Definition: PropDirection.h:19
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::IPropagator
Definition: IPropagator.h:55
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
TRT::Hit::layer
@ layer
Definition: HitInfo.h:79
PlotPulseshapeFromCool.input
input
Definition: PlotPulseshapeFromCool.py:106
Trk::GsfExtrapolator::extrapolate
virtual MultiComponentState extrapolate(const EventContext &ctx, Cache &, const MultiComponentState &, const Surface &, PropDirection direction, const BoundaryCheck &boundaryCheck, ParticleHypothesis particleHypothesis=nonInteracting) const override final
Configured AlgTool extrapolation method (1)
Definition: GsfExtrapolator.cxx:181
test_pyathena.parent
parent
Definition: test_pyathena.py:15
Trk::MultiComponentState
std::vector< ComponentParameters > MultiComponentState
Definition: ComponentParameters.h:27
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::ParametersBase
Definition: ParametersBase.h:55
Trk::IMultiStateExtrapolator::Cache::m_recallTrackingVolume
const TrackingVolume * m_recallTrackingVolume
Definition: IMultiStateExtrapolator.h:64
Trk::IMultiStateExtrapolator::Cache
MultiStateExtrapolator cache class.
Definition: IMultiStateExtrapolator.h:56
Trk::GsfExtrapolator::initialize
virtual StatusCode initialize() override final
AlgTool initialise method.
Definition: GsfExtrapolator.cxx:158
Trk::FullField
@ FullField
Field is set to be realistic, but within a given Volume.
Definition: MagneticFieldMode.h:21
Trk::GsfExtrapolator::~GsfExtrapolator
virtual ~GsfExtrapolator() override final
Destructor.
beamspotman.dir
string dir
Definition: beamspotman.py:623
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::IMultiStateExtrapolator::Cache::m_recallLayer
const Layer * m_recallLayer
Tracking volume for recall (not owning)
Definition: IMultiStateExtrapolator.h:62
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:221
Trk::nonInteracting
@ nonInteracting
Definition: ParticleHypothesis.h:25
Trk::GsfExtrapolator::extrapolateToVolumeBoundary
void extrapolateToVolumeBoundary(const EventContext &ctx, Cache &cache, const MultiComponentState &, const Layer *, const TrackingVolume &, PropDirection direction, ParticleHypothesis particleHypothesis) const
Two primary private extrapolation methods.
Definition: GsfExtrapolator.cxx:473
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
Trk::NavigationCell
useful struct for a single navigation cell
Definition: INavigator.h:38
MaterialUpdateMode.h
Trk::Surface::associatedLayer
const Trk::Layer * associatedLayer() const
return the associated Layer
Trk::ParametersBase::momentum
const Amg::Vector3D & momentum() const
Access method for the momentum.
Trk::GsfExtrapolator::extrapolateToDestinationLayer
MultiComponentState extrapolateToDestinationLayer(const EventContext &ctx, Cache &cache, const MultiComponentState &, const Surface &, const Layer &, const Layer *, PropDirection direction, const BoundaryCheck &boundaryCheck, ParticleHypothesis particleHypothesis) const
Final extrapolation step to a destination layer.
Definition: GsfExtrapolator.cxx:872
TrackingVolume.h
Trk::IMultiStateExtrapolator::Cache::m_recall
bool m_recall
< Flag the recall solution
Definition: IMultiStateExtrapolator.h:58
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
Trk::BoundaryCheck
Definition: BoundaryCheck.h:51
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
Trk::Layer::enclosingTrackingVolume
const TrackingVolume * enclosingTrackingVolume() const
get the confining TrackingVolume
Trk::Layer::layerMaterialProperties
const LayerMaterialProperties * layerMaterialProperties() const
getting the LayerMaterialProperties including full/pre/post update
Trk::IMultiStateExtrapolator::Cache::m_materialEffectsCaches
std::vector< GsfMaterial::Combined > m_materialEffectsCaches
Definition: IMultiStateExtrapolator.h:74
Trk::IMultiStateExtrapolator::Cache::m_trackingVolume
const TrackingVolume * m_trackingVolume
keep track of the MultiComponentStates
Definition: IMultiStateExtrapolator.h:70
GsfConstants.h
Trk::tubeInnerCover
@ tubeInnerCover
Definition: BoundarySurfaceFace.h:39
GsfExtrapolator.h
Trk::IMultiStateExtrapolator::Cache::m_mcsRecycleBin
std::vector< MultiComponentState > m_mcsRecycleBin
Definition: IMultiStateExtrapolator.h:72
AthAlgTool
Definition: AthAlgTool.h:26
IMaterialMixtureConvolution.h
Abstract base class for convolution of material effects.
Trk::IMultiStateExtrapolator::Cache::m_navigationParameters
std::unique_ptr< TrackParameters > m_navigationParameters
Definition: IMultiStateExtrapolator.h:68
Trk::Surface
Definition: Tracking/TrkDetDescr/TrkSurfaces/TrkSurfaces/Surface.h:75
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
mag
Scalar mag() const
mag method
Definition: AmgMatrixBasePlugin.h:26
Trk::GsfExtrapolator::extrapolateToIntermediateLayer
MultiComponentState extrapolateToIntermediateLayer(const EventContext &ctx, Cache &cache, const MultiComponentState &, const Layer &, const TrackingVolume &, PropDirection direction, ParticleHypothesis particleHypothesis, bool perpendicularCheck=true) const
Single extrapolation step to an intermediate layer.
Definition: GsfExtrapolator.cxx:801
Trk::GsfExtrapolator::m_fastField
bool m_fastField
Definition: GsfExtrapolator.h:190
Trk::GsfExtrapolator::extrapolateImpl
MultiComponentState extrapolateImpl(const EventContext &ctx, Cache &cache, const MultiComponentState &, const Surface &, PropDirection direction, const BoundaryCheck &boundaryCheck, ParticleHypothesis particleHypothesis) const
Implementation of main extrapolation method.
Definition: GsfExtrapolator.cxx:243
TrackStateOnSurface.h
Trk::GsfExtrapolator::GsfExtrapolator
GsfExtrapolator(const std::string &, const std::string &, const IInterface *)
Constructor with AlgTool parameters.
Definition: GsfExtrapolator.cxx:145
Trk::Layer
Definition: Layer.h:73
Trk::GsfExtrapolator::extrapolateFromLayerToLayer
MultiComponentState extrapolateFromLayerToLayer(const EventContext &ctx, Cache &cache, const MultiComponentState &, const TrackingVolume &, const Layer *startLayer, const Layer *destinationLayer, PropDirection direction, ParticleHypothesis particleHypothesis) const
Additional private extrapolation methods.
Definition: GsfExtrapolator.cxx:728