ATLAS Offline Software
MuonScatteringAngleSignificanceTool.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 
11 #include "TrkTrack/Track.h"
13 
14 namespace Rec {
15 
17  const IInterface* parent) :
18  AthAlgTool(type, name, parent), m_calorimeterVolume(nullptr), m_indetVolume(nullptr), m_inDetOnly(true), m_refitInDetOnly(true) {
19  declareInterface<IMuonScatteringAngleSignificance>(this);
20  declareProperty("InDetOnly", m_inDetOnly);
21  declareProperty("RefitInDetOnly", m_refitInDetOnly);
22  }
23 
24  //<<<<<< PUBLIC MEMBER FUNCTION DEFINITIONS >>>>>>
26  ATH_MSG_INFO("Initializing MuonScatAngleSignificanceTool");
27 
28  // tool needed to refit slimmed tracks
29  if (!m_fitter.empty()) {
30  if (m_fitter.retrieve().isFailure()) {
31  ATH_MSG_FATAL("Failed to retrieve tool " << m_fitter);
32  m_fitter.setTypeAndName(""); // Bang!
33  } else {
34  ATH_MSG_DEBUG("Retrieved tool " << m_fitter);
35  }
36  }
37 
38  // need to know which TrackingVolume we are in: indet/calo/spectrometer
39  if (m_trackingVolumesSvc.retrieve().isFailure()) {
40  ATH_MSG_FATAL("Failed to retrieve Svc " << m_trackingVolumesSvc);
41  return StatusCode::FAILURE;
42  } else {
43  ATH_MSG_DEBUG("Retrieved Svc " << m_trackingVolumesSvc);
46  }
47 
48  return StatusCode::SUCCESS;
49  }
50 
52  if (muon.muonType() == xAOD::Muon::MuonStandAlone) return ScatteringAngleSignificance(0);
53 
54  const Trk::Track* theTrack =
55  muon.trackParticle(xAOD::Muon::CombinedTrackParticle) ? muon.trackParticle(xAOD::Muon::CombinedTrackParticle)->track() : nullptr;
56 
57  if (theTrack == nullptr) {
58  theTrack = muon.trackParticle(xAOD::Muon::InnerDetectorTrackParticle)
59  ? muon.trackParticle(xAOD::Muon::InnerDetectorTrackParticle)->track()
60  : nullptr;
61  }
62 
63  if (theTrack == nullptr) {
64  ATH_MSG_DEBUG("No track, returning empty scatterer-significance object.");
66  } else
67  return scatteringAngleSignificance(*theTrack);
68  }
69 
71  // provide refit for slimmed tracks
72  const Trk::Track* fullTrack = &track;
73  const Trk::Track* refittedTrack = nullptr;
74  // if (track.info().trackProperties(Trk::TrackInfo::SlimmedTrack)) {
75  if (isSlimmed(track)) { // TrackInfo::SlimmedTrack wouldn't detect STACO tracks as (half-)slimmed
76 
77  if (!m_fitter.empty() && track.perigeeParameters() && track.measurementsOnTrack() && track.measurementsOnTrack()->size() > 3) {
78  ATH_MSG_VERBOSE(" perform refit as track has been slimmed");
79  if (m_refitInDetOnly) {
80  std::vector<const Trk::MeasurementBase*> vec;
81  DataVector<const Trk::MeasurementBase>::const_iterator measIter = track.measurementsOnTrack()->begin();
82  for (; measIter != track.measurementsOnTrack()->end(); ++measIter) {
83  const Amg::Vector3D& position = (*measIter)->globalPosition();
84  if (!m_indetVolume->inside(position)) continue;
85  vec.push_back((*measIter));
86  }
87  ATH_MSG_DEBUG("Refitting ID-part of track, meast vector of size " << vec.size());
88  refittedTrack = m_fitter->fit(Gaudi::Hive::currentContext(),
89  vec,
90  *(track.perigeeParameters()),
91  false,
92  Trk::muon).release();
93  } else {
94  refittedTrack = m_fitter->fit(
95  Gaudi::Hive::currentContext(), track, false, Trk::muon).release();
96  }
97  fullTrack = refittedTrack;
98  }
99  ATH_MSG_DEBUG("Detected slimmed track, " << (refittedTrack ? "refit was successful" : "but could not refit it!"));
100 
101  if (!refittedTrack) return ScatteringAngleSignificance(0);
102  }
103 
104  // collect sigma of phi scatterers up to last inDet measurement TSOS or to CaloDeposit TSOS
105  // (according to configuration).
106  // Define scattering in direction of curvature change to be +ve
107  double charge = fullTrack->perigeeParameters()->charge();
108  unsigned measurements = 0;
109  double neighbourRadius = 0.;
110  double neighbourSignificance = 0.;
111  unsigned neighbours = 0;
112  unsigned scatterers = 0;
113  unsigned startMeasurement = 0;
114  std::vector<bool> isMeasurement;
115  std::vector<unsigned> measurementNumber;
116  std::vector<double> radii;
117  std::vector<double> sigmas;
118  double significance = 0.;
119  double totalSigma = 0.;
120  double weightedRadius = 0.;
122  s != fullTrack->trackStateOnSurfaces()->end(); ++s) {
123  // skip leading material
124  if ((**s).measurementOnTrack()) {
125  ++measurements;
126  } else if (!measurements)
127  continue;
128 
129  // select MaterialEffects up to calorimeter energy deposit
130  if (!(**s).materialEffectsOnTrack()) continue;
131  if ((**s).type(Trk::TrackStateOnSurface::CaloDeposit)) break;
132  const Amg::Vector3D& position = (**s).materialEffectsOnTrack()->associatedSurface().globalReferencePoint();
133  if (!m_calorimeterVolume->inside(position)) break;
134 
135  const Trk::MaterialEffectsOnTrack* meot = dynamic_cast<const Trk::MaterialEffectsOnTrack*>((**s).materialEffectsOnTrack());
136  if (!meot) continue;
137 
138  // get scattering angle
139  const Trk::ScatteringAngles* scattering = meot->scatteringAngles();
140  if (!scattering) continue;
141 
142  ++scatterers;
143  double radius = (**s).trackParameters()->position().perp();
144  double sigma = charge * scattering->deltaPhi() / scattering->sigmaDeltaPhi();
145  if ((**s).measurementOnTrack()) {
146  isMeasurement.push_back(true);
147  } else {
148  isMeasurement.push_back(false);
149  }
150  measurementNumber.push_back(measurements);
151 
152  // keep maximum neighbour significance
153  // (summed scattering significance for scatterers spanning neighbouring measurements)
154  ++neighbours;
155  significance += sigma;
156  weightedRadius += sigma * radius;
157  if (neighbours > 1 && measurements > startMeasurement) {
158  double norm = 1. / sqrt(static_cast<double>(neighbours));
159  if (norm * fabs(significance) > fabs(neighbourSignificance)) {
160  if (significance == 0.) {
161  neighbourRadius = radius;
162  } else {
163  neighbourRadius = weightedRadius / significance;
164  }
165  neighbourSignificance = norm * significance;
166  ATH_MSG_VERBOSE(" current maximum for neighbourSignificance " << neighbourSignificance << " from " << neighbours
167  << " scatterers at radius " << neighbourRadius);
168  }
169  ATH_MSG_VERBOSE(" reset neighbour after " << significance << " /sqrt(" << neighbours << ") at radius " << radius);
170  neighbours = 0;
171  significance = 0.;
172  startMeasurement = measurements;
173  weightedRadius = 0.;
174  if (isMeasurement.back()) {
175  ++neighbours;
176  significance += sigma;
177  weightedRadius += sigma * radius;
178  }
179  }
180 
181  radii.push_back(radius);
182  sigmas.push_back(sigma);
183  totalSigma += sigma;
184 
185  ATH_MSG_VERBOSE(scatterers << " " << measurements << " " << isMeasurement.back() << " radius "
186  << (**s).trackParameters()->position().perp() << " deltaPhi " << scattering->deltaPhi()
187  << " significance " << sigma << " integralSignificance " << totalSigma);
188  }
189 
190  // pop_back to last measurement unless configured to use calo
191  delete refittedTrack;
192  if (m_inDetOnly) {
193  while (scatterers && measurementNumber.back() == measurements && !isMeasurement.back()) {
194  --scatterers;
195  totalSigma -= sigmas.back();
196  isMeasurement.pop_back();
197  measurementNumber.pop_back();
198  radii.pop_back();
199  sigmas.pop_back();
200  }
201  }
202 
203  // quit if no scatterers selected
204  if (!scatterers) {
205  ATH_MSG_DEBUG(" no scatterers selected, giving up.");
206  return ScatteringAngleSignificance(0);
207  }
208 
209  // search for discontinuity point (sign change of integral scattering)
210  // maximum value determines curvatureSignificance
211  double curvatureSignificance = totalSigma;
212  double curvatureRadius = *radii.rbegin();
213  unsigned index = scatterers - 1;
214 
215  ATH_MSG_VERBOSE(" scatteringAngleSignificance " << totalSigma << " at radius " << radii[index] << " at scatterer " << scatterers
216  << " sigmas.size() " << sigmas.size());
217 
218  for (std::vector<double>::const_reverse_iterator r = sigmas.rbegin(); r != sigmas.rend(); ++r, --index) {
219  totalSigma -= 2. * (*r);
220  if (index > 1)
221  ATH_MSG_VERBOSE(" scatteringAngleSignificance " << totalSigma << " at radius " << radii[index - 1] << " at scatterer "
222  << index);
223 
224  if (fabs(totalSigma) > fabs(curvatureSignificance) && index > 1) {
225  curvatureSignificance = totalSigma;
226  curvatureRadius = radii[index - 1];
227  }
228  }
229 
230  // normalize final curvature significance
231  curvatureSignificance /= sqrt(static_cast<double>(scatterers));
232 
233  ATH_MSG_DEBUG(" scatteringAngleSignificance" << std::setiosflags(std::ios::fixed) << std::setw(7) << std::setprecision(2)
234  << curvatureSignificance << " at radius " << std::setw(6) << std::setprecision(1)
235  << curvatureRadius << " neighbourSignificance " << std::setw(7) << std::setprecision(2)
236  << neighbourSignificance << " at radius " << std::setw(6) << std::setprecision(1)
237  << neighbourRadius << " from " << scatterers << " scatterers");
238 
239  return ScatteringAngleSignificance(scatterers, curvatureRadius, curvatureSignificance, neighbourRadius, neighbourSignificance);
240  }
241 
243  for (Trk::TrackStates::const_iterator s = track.trackStateOnSurfaces()->begin();
244  s != track.trackStateOnSurfaces()->end(); ++s) {
245  if ((**s).trackParameters()) continue;
246 
247  ATH_MSG_VERBOSE("track is slimmed (found TSOS without trackParameters) ");
248  return true;
249  }
250 
251  ATH_MSG_VERBOSE("track is not slimmed (all TSOS have trackParameters) ");
252 
253  return false;
254  }
255 
256 } // namespace Rec
Rec::MuonScatteringAngleSignificanceTool::MuonScatteringAngleSignificanceTool
MuonScatteringAngleSignificanceTool(const std::string &type, const std::string &name, const IInterface *parent)
Definition: MuonScatteringAngleSignificanceTool.cxx:16
Trk::ScatteringAngles::deltaPhi
double deltaPhi() const
returns the
Definition: ScatteringAngles.h:82
beamspotman.r
def r
Definition: beamspotman.py:676
xAOD::muon
@ muon
Definition: TrackingPrimitives.h:195
Trk::TrackStateOnSurface::CaloDeposit
@ CaloDeposit
This TSOS contains a CaloEnergy object.
Definition: TrackStateOnSurface.h:135
PlotCalibFromCool.norm
norm
Definition: PlotCalibFromCool.py:100
ScatteringAngles.h
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition: AthMsgStreamMacros.h:34
DataModel_detail::const_iterator
Const iterator class for DataVector/DataList.
Definition: DVLIterator.h:82
pdg_comparison.sigma
sigma
Definition: pdg_comparison.py:324
python.SystemOfUnits.s
int s
Definition: SystemOfUnits.py:131
MeasurementBase.h
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
Trk::Track
The ATLAS Track class.
Definition: Tracking/TrkEvent/TrkTrack/TrkTrack/Track.h:73
Trk::Volume::inside
bool inside(const Amg::Vector3D &gp, double tol=0.) const
Inside() method for checks.
Definition: Volume.cxx:90
index
Definition: index.py:1
AthCommonDataStore< AthCommonMsg< AlgTool > >::declareProperty
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T > &t)
Definition: AthCommonDataStore.h:145
Trk::Track::trackStateOnSurfaces
const Trk::TrackStates * trackStateOnSurfaces() const
return a pointer to a const DataVector of const TrackStateOnSurfaces.
Rec::MuonScatteringAngleSignificanceTool::m_indetVolume
const Trk::Volume * m_indetVolume
cache the ID volume pointer
Definition: MuonScatteringAngleSignificanceTool.h:53
Trk::ITrackingVolumesSvc::MuonSpectrometerEntryLayer
@ MuonSpectrometerEntryLayer
Tracking Volume which defines the entrance surfaces of the MS.
Definition: ITrackingVolumesSvc.h:41
Rec::MuonScatteringAngleSignificanceTool::initialize
StatusCode initialize()
Definition: MuonScatteringAngleSignificanceTool.cxx:25
Trk::ScatteringAngles
represents a deflection of the track caused through multiple scattering in material.
Definition: ScatteringAngles.h:26
vec
std::vector< size_t > vec
Definition: CombinationsGeneratorTest.cxx:12
Rec::MuonScatteringAngleSignificanceTool::m_inDetOnly
bool m_inDetOnly
scatterers from ID only (or ID + calo)
Definition: MuonScatteringAngleSignificanceTool.h:56
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
Rec::MuonScatteringAngleSignificanceTool::isSlimmed
bool isSlimmed(const Trk::Track &track) const
does track have TrackParameters at every TSOS ? Method for compatibility with release < 17,...
Definition: MuonScatteringAngleSignificanceTool.cxx:242
xAOD::Muon_v1
Class describing a Muon.
Definition: Muon_v1.h:38
Rec::MuonScatteringAngleSignificanceTool::m_calorimeterVolume
const Trk::Volume * m_calorimeterVolume
cache the calo volume pointer
Definition: MuonScatteringAngleSignificanceTool.h:52
mergePhysValFiles.end
end
Definition: DataQuality/DataQualityUtils/scripts/mergePhysValFiles.py:93
Track.h
Rec::ScatteringAngleSignificance
Definition: ScatteringAngleSignificance.h:22
MaterialEffectsOnTrack.h
Rec::MuonScatteringAngleSignificanceTool::m_fitter
ToolHandle< Trk::ITrackFitter > m_fitter
tool for unslimming via track fit
Definition: MuonScatteringAngleSignificanceTool.h:46
Trk::ParametersT::associatedSurface
virtual const S & associatedSurface() const override final
Access to the Surface method.
CxxUtils::vec
typename vecDetail::vec_typedef< T, N >::type vec
Define a nice alias for the vectorized type.
Definition: vec.h:207
Trk::MaterialEffectsOnTrack
represents the full description of deflection and e-loss of a track in material.
Definition: MaterialEffectsOnTrack.h:40
Rec
Name: MuonSpContainer.h Package : offline/Reconstruction/MuonIdentification/muonEvent.
Definition: FakeTrackBuilder.h:10
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
Rec::MuonScatteringAngleSignificanceTool::m_trackingVolumesSvc
ServiceHandle< Trk::ITrackingVolumesSvc > m_trackingVolumesSvc
Definition: MuonScatteringAngleSignificanceTool.h:48
test_pyathena.parent
parent
Definition: test_pyathena.py:15
Trk::muon
@ muon
Definition: ParticleHypothesis.h:28
DataVector
Derived DataVector<T>.
Definition: DataVector.h:794
Trk::ITrackingVolumesSvc::CalorimeterEntryLayer
@ CalorimeterEntryLayer
Tracking Volume which defines the entrance srufaces of the calorimeter.
Definition: ITrackingVolumesSvc.h:40
Trk::Track::perigeeParameters
const Perigee * perigeeParameters() const
return Perigee.
Definition: Tracking/TrkEvent/TrkTrack/src/Track.cxx:163
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:228
charge
double charge(const T &p)
Definition: AtlasPID.h:756
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
ParticleGun_SamplingFraction.radius
radius
Definition: ParticleGun_SamplingFraction.py:96
DataVector::end
const_iterator end() const noexcept
Return a const_iterator pointing past the end of the collection.
TrackingVolume.h
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
Trk::MaterialEffectsOnTrack::scatteringAngles
const ScatteringAngles * scatteringAngles() const
returns the MCS-angles object.
Rec::MuonScatteringAngleSignificanceTool::m_refitInDetOnly
bool m_refitInDetOnly
steer if to unslim only ID
Definition: MuonScatteringAngleSignificanceTool.h:57
Trk::ScatteringAngles::sigmaDeltaPhi
double sigmaDeltaPhi() const
returns the
Definition: ScatteringAngles.h:94
xAOD::track
@ track
Definition: TrackingPrimitives.h:512
AthAlgTool
Definition: AthAlgTool.h:26
Trk::Volume
Definition: Volume.h:35
MuonScatteringAngleSignificanceTool.h
Rec::MuonScatteringAngleSignificanceTool::scatteringAngleSignificance
ScatteringAngleSignificance scatteringAngleSignificance(const xAOD::Muon &muon) const
Calculate ScatteringAngleSignificance of a muon, stepping down to the relevant track.
Definition: MuonScatteringAngleSignificanceTool.cxx:51
TrackStateOnSurface.h
DataVector::begin
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.