ATLAS Offline Software
MuonDetectorNavTest.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 #include "MuonDetectorNavTest.h"
6 
9 
10 #include "Acts/Definitions/Units.hpp"
11 #include "Acts/Propagator/ActorList.hpp"
12 #include "Acts/Propagator/Propagator.hpp"
13 #include "Acts/Propagator/MaterialInteractor.hpp"
14 #include "Acts/Propagator/EigenStepper.hpp"
15 #include "Acts/Utilities/VectorHelpers.hpp"
16 #include "Acts/Visualization/ObjVisualization3D.hpp"
17 #include "Acts/Visualization/GeometryView3D.hpp"
18 
19 #include "xAODTruth/TruthVertex.h"
20 
21 #include <fstream>
22 
23 using namespace Acts::UnitLiterals;
24 
25 //Struct that is passed as an actor to ACTS that records all state information during propagation
26 //Contains the information at the following link: https://github.com/acts-project/acts/blob/main/Core/include/Acts/Navigation/NavigationState.hpp
27 struct StateRecorder {
28  using result_type = std::vector<Acts::Experimental::DetectorNavigator::State>;
29 
30  template <typename propagator_state_t, typename stepper_t, typename navigator_t>
31  void act(propagator_state_t& state, const stepper_t& /*stepper*/,
32  const navigator_t& /*navigator*/, result_type& result,
33  const Acts::Logger& /*logger*/) const {
34 
35  result.push_back(state.navigation);
36  }
37 
38  template <typename propagator_state_t, typename stepper_t, typename navigator_t>
39  bool checkAbort(propagator_state_t& /*state*/, const stepper_t& /*stepper*/,
40  const navigator_t& /*navigator*/, result_type& /*result*/,
41  const Acts::Logger& /*logger*/) const {
42  return false;
43  }
44 };
45 
46 //Function to write out every step taken during propagation to obj format for visualization
48  std::ofstream os("event_" + std::to_string(eventNumber) + "_Steps.obj");
49  size_t vCounter = 0;
50  //Require at least 3 steps to draw a line
51  if(states.size() > 2){
52  ++vCounter;
53  for(const auto& state : states){
54  os << "v " << state.position.x() << " " << state.position.y() << " " << state.position.z() << '\n';
55  }
56  std::size_t vBreak = vCounter + states.size() - 1;
57  for(; vCounter < vBreak; ++vCounter){
58  os << "l " << vCounter << " " << vCounter + 1 << '\n';
59  }
60  }
61 }
62 
63 namespace ActsTrk {
64  MuonDetectorNavTest::MuonDetectorNavTest(const std::string& name, ISvcLocator* pSvcLocator):
65  AthHistogramAlgorithm(name, pSvcLocator){}
66 
69  const IdentifierHash trfHash = reElement->detectorType() == ActsTrk::DetectorType::Mdt ?
70  reElement->measurementHash(hitId) : reElement->layerHash(hitId);
71  return reElement->localToGlobalTrans(gctx, trfHash);
72  }
73 
75  ATH_CHECK(m_idHelperSvc.retrieve());
79  ATH_CHECK(m_inSimHitKeys.initialize());
80  ATH_CHECK(m_detVolSvc.retrieve());
82  ATH_CHECK(m_tree.init(this));
83  ATH_CHECK(book(TH1D("distanceBetweenHits", "distanceBetweenHits", 250, 0., 500.), "MuonNavigationTestR4", "MuonNavigationTestR4"));
84 
85  ATH_MSG_VERBOSE("Successfully initialized MuonDetectorNavTest");
86  return StatusCode::SUCCESS;
87  }
88 
90  ATH_MSG_VERBOSE("Finalizing MuonDetectorNavTest");
92  hist("distanceBetweenHits")->GetXaxis()->SetTitle("Distance between hits [mm]");
93  return StatusCode::SUCCESS;
94  }
95 
97  ATH_MSG_INFO("Executing MuonDetectorNavTest");
98  const EventContext& ctx{Gaudi::Hive::currentContext()};
102  if (!gctx.isValid() or !truthParticles.isValid() or !magFieldHandle.isValid()) {
103  ATH_MSG_FATAL("Failed to retrieve either the geometry context, truth particles or magnetic field");
104  return StatusCode::FAILURE;
105  }
106  auto simHitCollections = m_inSimHitKeys.makeHandles(ctx);
107  Acts::GeometryContext geoContext = gctx->context();
108  Acts::MagneticFieldContext mfContext = Acts::MagneticFieldContext(*magFieldHandle);
109 
110  std::vector<std::pair<Identifier, Amg::Vector3D>> propagatedHits;
111  std::vector<std::pair<Identifier, Amg::Vector3D>> propagatedHitsGlobal;
112  std::vector<std::pair<Identifier, Amg::Vector3D>> truthHits;
113 
114  for(auto& simHitCollection : simHitCollections){
115  for(const xAOD::MuonSimHit* simHit : *simHitCollection){
116  if(simHit->pdgId() != 13) continue;
117  const Identifier ID = simHit->identify();
118  const Amg::Vector3D localPos = xAOD::toEigen(simHit->localPosition());
119  // const Amg::Vector3D globalDir = toGlobalTrf(*gctx, ID).rotation() * xAOD::toEigen(simHit->localDirection());
120  ATH_MSG_DEBUG("Local direction for hit ID " << m_idHelperSvc->toString(ID) << ": " << Amg::toString(xAOD::toEigen(simHit->localDirection())));
121  truthHits.emplace_back(ID, localPos);
122  }
123  }
124 
125  using Stepper = Acts::EigenStepper<>;
126  using Navigator = Acts::Experimental::DetectorNavigator;
127  using Propagator = Acts::Propagator<Stepper,Navigator>;
128  using ActorList = Acts::ActorList<StateRecorder, Acts::MaterialInteractor, Acts::EndOfWorldReached>;
129  using PropagatorOptions = Propagator::Options<ActorList>;
130 
131  auto bField = std::make_shared<ATLASMagneticFieldWrapper>();
132  auto stepper = Stepper(std::move(bField));
133 
134  PropagatorOptions options(geoContext, mfContext);
135 
136  options.pathLimit = 23_m;
137  options.stepping.maxStepSize = 0.5_m;
138 
139  //Configure the material collector
140  auto& materialInteractor = options.actorList.get<Acts::MaterialInteractor>();
141  materialInteractor.energyLoss = true;
142  materialInteractor.multipleScattering = true;
143  materialInteractor.recordInteractions = true;
144 
145  const Acts::Experimental::Detector* detector = m_detVolSvc->detector().get();
146  for(const auto& truthParticle : *truthParticles){
147  //Require that we only propagate on muons, and of status 1
148  if(truthParticle->status() == 1 and truthParticle->pdgId() == 13){
149  const auto& particle = truthParticle->p4();
150  const auto& prodVertex = (!truthParticle->hasProdVtx()) ? nullptr : truthParticle->prodVtx();
151  double x = prodVertex ? prodVertex->x() : 0.;
152  double y = prodVertex ? prodVertex->y() : 0.;
153  double z = prodVertex ? prodVertex->z() : 0.;
154 
155  Acts::CurvilinearTrackParameters start(
156  Acts::VectorHelpers::makeVector4(Acts::Vector3(x, y, z), 0.),
157  Acts::Vector3(particle.Px(), particle.Py(), particle.Pz()).normalized(),
158  truthParticle->charge() / particle.P(),
159  std::nullopt,
161 
162  Acts::Experimental::DetectorNavigator::Config navCfg;
163  navCfg.detector = detector;
164  navCfg.resolvePassive = true;
165 
166  Acts::Experimental::DetectorNavigator navigator(navCfg, Acts::getDefaultLogger("DetectorNavigator", Acts::Logging::Level::INFO));
167  Acts::Propagator<Stepper, Acts::Experimental::DetectorNavigator> propagator(
168  std::move(stepper), std::move(navigator),
169  Acts::getDefaultLogger("Propagator", Acts::Logging::Level::INFO));
170 
171  auto result = propagator.propagate(start, options).value();
173  const Acts::MaterialInteractor::result_type material = result.get<Acts::MaterialInteractor::result_type>();
174  ATH_MSG_DEBUG("Material interactions: " << material.materialInteractions.size());
175  ATH_MSG_DEBUG("material in x0: " << material.materialInX0);
176  ATH_MSG_DEBUG("material in L0: " << material.materialInL0);
177  std::vector<Acts::MaterialInteraction> interactions = material.materialInteractions;
178  for(const Acts::MaterialInteraction& interaction : interactions){
179  ATH_MSG_DEBUG("Path Correction: " << interaction.pathCorrection);
180  ATH_MSG_DEBUG("Momentum change: " << interaction.deltaP);
181  }
182  // loop through the states drawing each surface or portal
183  Acts::ObjVisualization3D helper{};
184  for (const auto& s : state) {
185  if(s.currentSurface) Acts::GeometryView3D::drawSurface(helper, *s.currentSurface, geoContext);
186  }
187  helper.write("event_" + std::to_string(ctx.evt() + 1) +"_Hits.obj");
188  helper.clear();
189  writeStepsToObj(state, ctx.evt() + 1);
190  ATH_MSG_VERBOSE("Number of propagated steps : " << state.size());
191  for(const auto& state: state){
192  if(state.currentSurface){
193  const SurfaceCache* sCache = dynamic_cast<const SurfaceCache *>(state.currentSurface->associatedDetectorElement());
194  if(!sCache){
195  ATH_MSG_VERBOSE("Surface found but it's a portal, continuing..");
196  continue;
197  }
198  const Identifier ID = sCache->identify();
199  const Amg::Transform3D localTrf = sCache->transform(geoContext).inverse();
200  const Amg::Vector3D localPos{localTrf * state.position};
201  ATH_MSG_DEBUG("Identify hit " << m_idHelperSvc->toString(ID) << " with hit at " << Amg::toString(localPos));
202  propagatedHits.emplace_back(ID, localPos);
203  propagatedHitsGlobal.emplace_back(ID, state.position);
204  }
205  }
206  }
207  }
208  //compare the hits
209  for(const auto& truthHit : truthHits){
210  bool hitFound = false;
211  for(const auto& propagatedHit : propagatedHits){
212  if(truthHit.first == propagatedHit.first){
213  hitFound = true;
214  break;
215  }
216  }
217  if(!hitFound) ATH_MSG_VERBOSE("Truth hit not found, ID: " << m_idHelperSvc->toString(truthHit.first) << " at " << Amg::toString(truthHit.second));
218 
219  }
220  //Check if all propagated hits are found
221  for(const auto& propagatedHit : propagatedHits){
222  bool hitFound = false;
223  for(const auto& truthHit : truthHits){
224  if(truthHit.first == propagatedHit.first){
225  hitFound = true;
226  break;
227  }
228  }
229  if(!hitFound){
230  ATH_MSG_VERBOSE("Propagated hit not found, ID: " << m_idHelperSvc->toString(propagatedHit.first) << " at " << Amg::toString(propagatedHit.second));
231  }
232  }
233 
234  //For one final check, put all hits into the global frame, and find which hits are closest to one another
235  for(const auto& propagatedHit: propagatedHitsGlobal){
236  double minDistance = std::numeric_limits<double>::max();
237  Identifier closestID{};
238  for(const auto& truthHit: truthHits){
239  const double distance = (propagatedHit.second - toGlobalTrf(*gctx, truthHit.first) * truthHit.second).norm();
240  if(distance < minDistance){
241  minDistance = distance;
242  closestID = truthHit.first;
243  }
244  }
245  ATH_MSG_VERBOSE("Closest hit to propagated hit " << m_idHelperSvc->toString(propagatedHit.first) << " is " << m_idHelperSvc->toString(closestID) << " with distance " << minDistance);
246  m_distanceBetweenHits = minDistance;
247  m_propagatedIdentifier = m_idHelperSvc->toString(propagatedHit.first);
248  m_truthIdentifier = m_idHelperSvc->toString(closestID);
249  hist("distanceBetweenHits")->Fill(minDistance);
250  m_tree.fill(ctx);
251  }
252 
253  return StatusCode::SUCCESS;
254  }
255 }
python.PyKernel.retrieve
def retrieve(aClass, aKey=None)
Definition: PyKernel.py:110
StateRecorder::checkAbort
bool checkAbort(propagator_state_t &, const stepper_t &, const navigator_t &, result_type &, const Acts::Logger &) const
Definition: MuonDetectorNavTest.cxx:39
MuonDetectorNavTest.h
xAOD::MuonSimHit_v1
Definition: MuonSimHit_v1.h:18
xAOD::muon
@ muon
Definition: TrackingPrimitives.h:195
PlotCalibFromCool.norm
norm
Definition: PlotCalibFromCool.py:100
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition: AthMsgStreamMacros.h:34
Trk::ParticleSwitcher::particle
constexpr ParticleHypothesis particle[PARTICLEHYPOTHESES]
the array of masses
Definition: ParticleHypothesis.h:76
python.SystemOfUnits.s
int s
Definition: SystemOfUnits.py:131
get_generator_info.result
result
Definition: get_generator_info.py:21
ActsTrk::SurfaceCache::identify
Identifier identify() const override final
Returns the identifier of the Surface.
Definition: SurfaceCache.cxx:31
max
#define max(a, b)
Definition: cfImp.cxx:41
SG::ReadCondHandle
Definition: ReadCondHandle.h:44
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
ID
std::vector< Identifier > ID
Definition: CalibHitIDCheck.h:24
MuonVal::MuonTesterTree::init
StatusCode init(OWNER *instance)
Initialize method.
SurfaceCache.h
ActsTrk::MuonDetectorNavTest::m_tree
MuonVal::MuonTesterTree m_tree
Definition: MuonDetectorNavTest.h:55
AthHistogramming::book
StatusCode book(const TH1 &hist, const std::string &tDir="", const std::string &stream="")
Simplify the booking and registering (into THistSvc) of histograms.
Definition: AthHistogramming.h:303
SG::ReadHandle
Definition: StoreGate/StoreGate/ReadHandle.h:70
ActsTrk::detail::Navigator
Acts::Navigator Navigator
Definition: Tracking/Acts/ActsTrackReconstruction/src/detail/Definitions.h:31
TRTCalib_cfilter.detector
detector
Definition: TRTCalib_cfilter.py:241
mergePhysValFiles.start
start
Definition: DataQuality/DataQualityUtils/scripts/mergePhysValFiles.py:14
ActsTrk::MuonDetectorNavTest::m_truthIdentifier
MuonVal::ScalarBranch< std::string > & m_truthIdentifier
Definition: MuonDetectorNavTest.h:58
MuonGMR4::MuonReadoutElement
The MuonReadoutElement is an abstract class representing the geometry representing the muon detector.
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/MuonReadoutElement.h:38
ActsTrk::SurfaceCache
: Helper class to connect the aligned transformations of each active sensor(layer) with the Acts::Sur...
Definition: Tracking/Acts/ActsGeoUtils/ActsGeoUtils/SurfaceCache.h:23
ActsTrk::IDetectorElementBase::detectorType
virtual DetectorType detectorType() const =0
Returns the detector element type.
StateRecorder::act
void act(propagator_state_t &state, const stepper_t &, const navigator_t &, result_type &result, const Acts::Logger &) const
Definition: MuonDetectorNavTest.cxx:31
MuonGMR4::MuonReadoutElement::layerHash
virtual IdentifierHash layerHash(const Identifier &measId) const =0
ActsTrk::MuonDetectorNavTest::execute
StatusCode execute() override
Definition: MuonDetectorNavTest.cxx:96
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
x
#define x
ReadCondHandle.h
AthCommonDataStore< AthCommonMsg< Algorithm > >::detStore
const ServiceHandle< StoreGateSvc > & detStore() const
The standard StoreGateSvc/DetectorStore Returns (kind of) a pointer to the StoreGateSvc.
Definition: AthCommonDataStore.h:95
runBeamSpotCalibration.helper
helper
Definition: runBeamSpotCalibration.py:112
ActsTrk::MuonDetectorNavTest::m_fieldCacheCondObjInputKey
SG::ReadCondHandleKey< AtlasFieldCacheCondObj > m_fieldCacheCondObjInputKey
Definition: MuonDetectorNavTest.h:43
ActsTrk::MuonDetectorNavTest::m_r4DetMgr
const MuonGMR4::MuonDetectorManager * m_r4DetMgr
Definition: MuonDetectorNavTest.h:49
StateRecorder::result_type
std::vector< Acts::Experimental::DetectorNavigator::State > result_type
Definition: MuonDetectorNavTest.cxx:28
Amg::toString
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Definition: GeoPrimitivesToStringConverter.h:40
ActsTrk::MuonDetectorNavTest::m_geoCtxKey
SG::ReadHandleKey< ActsGeometryContext > m_geoCtxKey
Definition: MuonDetectorNavTest.h:45
z
#define z
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
urldecode::states
states
Definition: urldecode.h:39
ActsTrk::MuonDetectorNavTest::m_truthParticleKey
SG::ReadHandleKey< xAOD::TruthParticleContainer > m_truthParticleKey
Definition: MuonDetectorNavTest.h:47
Amg::Transform3D
Eigen::Affine3d Transform3D
Definition: GeoPrimitives.h:46
jet::CompCategory::Detector
@ Detector
Definition: UncertaintyEnum.h:19
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
python.AtlRunQueryLib.options
options
Definition: AtlRunQueryLib.py:379
ActsTrk::MuonDetectorNavTest::m_idHelperSvc
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
Definition: MuonDetectorNavTest.h:41
xAOD::eventNumber
eventNumber
Definition: EventInfo_v1.cxx:124
SG::VarHandleKey::initialize
StatusCode initialize(bool used=true)
If this object is used as a property, then this should be called during the initialize phase.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:103
AthHistogramAlgorithm
Definition: AthHistogramAlgorithm.h:32
writeStepsToObj
void writeStepsToObj(const StateRecorder::result_type &states, const size_t &eventNumber)
Definition: MuonDetectorNavTest.cxx:47
ActsTrk::MuonDetectorNavTest::initialize
StatusCode initialize() override
Definition: MuonDetectorNavTest.cxx:74
ReadFromCoolCompare.os
os
Definition: ReadFromCoolCompare.py:231
ActsGeometryContext
Include the GeoPrimitives which need to be put first.
Definition: ActsGeometryContext.h:27
ActsTrk::MuonDetectorNavTest::m_inSimHitKeys
SG::ReadHandleKeyArray< xAOD::MuonSimHitContainer > m_inSimHitKeys
Definition: MuonDetectorNavTest.h:51
TruthVertex.h
ActsTrk::MuonDetectorNavTest::finalize
StatusCode finalize() override
Definition: MuonDetectorNavTest.cxx:89
ActsTrk::DetectorType::Mdt
@ Mdt
MuonSpectrometer.
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:221
ActsTrk::to_string
std::string to_string(const DetectorType &type)
Definition: GeometryDefs.h:34
SG::CondHandleKey::initialize
StatusCode initialize(bool used=true)
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
ActsTrk::detail::Stepper
Acts::SympyStepper Stepper
Adapted from Acts Examples/Algorithms/TrackFinding/src/TrackFindingAlgorithmFunction....
Definition: Tracking/Acts/ActsTrackReconstruction/src/detail/Definitions.h:30
ActsTrk::MuonDetectorNavTest::m_propagatedIdentifier
MuonVal::ScalarBranch< std::string > & m_propagatedIdentifier
Definition: MuonDetectorNavTest.h:57
ActsTrk::detail::Propagator
Acts::Propagator< Stepper, Navigator > Propagator
Definition: Tracking/Acts/ActsTrackReconstruction/src/detail/Definitions.h:32
y
#define y
python.Constants.INFO
int INFO
Definition: Control/AthenaCommon/python/Constants.py:16
ActsTrk::MuonDetectorNavTest::m_detVolSvc
ServiceHandle< ActsTrk::IDetectorVolumeSvc > m_detVolSvc
Definition: MuonDetectorNavTest.h:53
MuonGMR4::MuonReadoutElement::measurementHash
virtual IdentifierHash measurementHash(const Identifier &measId) const =0
Constructs the identifier hash from the full measurement Identifier.
MuonVal::MuonTesterTree::fill
bool fill(const EventContext &ctx)
Fills the tree per call.
Definition: MuonTesterTree.cxx:89
MuonGMR4::MuonReadoutElement::localToGlobalTrans
const Amg::Transform3D & localToGlobalTrans(const ActsGeometryContext &ctx) const
Returns the local to global transformation into the ATLAS coordinate system.
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/src/MuonReadoutElement.cxx:81
MuonVal::MuonTesterTree::write
StatusCode write()
Finally write the TTree objects.
Definition: MuonTesterTree.cxx:178
AthHistogramming::hist
TH1 * hist(const std::string &histName, const std::string &tDir="", const std::string &stream="")
Simplify the retrieval of registered histograms of any type.
Definition: AthHistogramming.cxx:198
ActsTrk
The AlignStoreProviderAlg loads the rigid alignment corrections and pipes them through the readout ge...
Definition: MuonDetectorBuilderTool.cxx:49
ActsTrk::SurfaceCache::transform
const Acts::Transform3 & transform(const Acts::GeometryContext &gctx) const override final
Returns the transformation stored in the TransformCache.
Definition: SurfaceCache.cxx:16
ActsTrk::MuonDetectorNavTest::m_distanceBetweenHits
MuonVal::ScalarBranch< float > & m_distanceBetweenHits
Definition: MuonDetectorNavTest.h:56
StateRecorder
Definition: MuonDetectorNavTest.cxx:27
Amg::distance
float distance(const Amg::Vector3D &p1, const Amg::Vector3D &p2)
calculates the distance between two point in 3D space
Definition: GeoPrimitivesHelpers.h:54
ActsTrk::MuonDetectorNavTest::toGlobalTrf
Amg::Transform3D toGlobalTrf(const ActsGeometryContext &gctx, const Identifier &hitId) const
Definition: MuonDetectorNavTest.cxx:67
MuonGMR4::MuonDetectorManager::getReadoutElement
const MuonReadoutElement * getReadoutElement(const Identifier &id) const
Returns a generic Muon readout element.
Identifier
Definition: IdentifierFieldParser.cxx:14