11#include "GaudiKernel/ServiceHandle.h"
38 constexpr double OneOverSqrt2 = M_SQRT1_2;
45 declareInterface<IMuonTrackQuery>(
this);
74 ATH_MSG_ERROR(
"Could not retrieve a valid tracking geometry");
76 return StatusCode::SUCCESS;
88 if (!meot) {
continue; }
101 if (!calorimeterVolume) {
117 if (!tsos->trackParameters())
continue;
119 if (indetVolume->
inside(tsos->trackParameters()->position())) {
120 indetExitParameters = tsos->trackParameters();
124 if (!calorimeterVolume->
inside(tsos->trackParameters()->position()) && caloExitParameters) {
break; }
126 caloExitParameters = tsos->trackParameters();
129 if (!indetExitParameters || !caloExitParameters) {
return 0.; }
131 double energyDeposit = indetExitParameters->
momentum().mag() - caloExitParameters->
momentum().mag();
135 return energyDeposit;
144 if (!calorimeterVolume) {
157 double betweenInDetMeasurements = 0.;
158 double betweenSpectrometerMeasurements = 0.;
160 bool haveInDet =
false;
161 bool haveSpectrometer =
false;
170 bool isPreciseHit = (tsos->measurementOnTrack() &&
dynamic_cast<const Trk::MeasurementBase*
>(tsos->measurementOnTrack()) &&
175 if (!tsos->trackParameters() ||
dynamic_cast<const Trk::Perigee*
>(tsos->trackParameters())) {
continue; }
178 if (isPreciseHit && !calorimeterVolume->
inside(tsos->trackParameters()->position())) {
180 isPreciseHit = (
id.is_valid() && !
m_idHelperSvc->measuresPhi(
id));
183 if (!tsos->materialEffectsOnTrack() && !isPreciseHit) {
continue; }
186 if (!parameters) { parameters = tsos->trackParameters(); }
189 parameters = tsos->trackParameters();
192 if (startMomentum.dot(endDirection) < 0.)
continue;
195 if (tsos->materialEffectsOnTrack()) {
202 endDirection =
Amg::Vector3D(sc_theta.
sn * sc_phi.cs, sc_theta.
sn * sc_phi.sn, sc_theta.
cs);
206 Amg::Vector3D momentumKick = startMomentum.cross(endDirection) / (0.3 * Units::GeV);
207 integratedMomentumKick += momentumKick;
210 if (!isPreciseHit)
continue;
212 if (indetVolume->
inside(parameters->position())) {
214 betweenInDetMeasurements += integratedMomentumKick.mag();
215 integratedMomentumKick = origin;
218 integratedMomentumKick = origin;
221 if (haveSpectrometer) {
222 betweenSpectrometerMeasurements += integratedMomentumKick.mag();
223 integratedMomentumKick = origin;
225 haveSpectrometer =
true;
226 integratedMomentumKick = origin;
232 <<
" field integrals for track at eta, phi " << std::setw(6) << std::setprecision(2)
233 << track.perigeeParameters()->momentum().eta() <<
"," << std::setw(6) << std::setprecision(2)
234 << track.perigeeParameters()->momentum().phi() <<
" : betweenInDetMeasurements " << std::setw(8)
235 << std::setprecision(3) << betweenInDetMeasurements <<
" betweenSpectrometerMeasurements " << std::setw(8)
236 << std::setprecision(3) << betweenSpectrometerMeasurements);
238 return FieldIntegral(betweenInDetMeasurements, betweenSpectrometerMeasurements, 0., 0.);
244 if (!calorimeterVolume) {
256 bool haveCaloDeposit =
false;
257 int numberCaloTSOS = 0;
262 ATH_MSG_VERBOSE(
"haveCaloDeposit, " << numberCaloTSOS <<
" TSOS in calo volume");
263 haveCaloDeposit =
true;
267 if (!s->materialEffectsOnTrack()) {
continue; }
269 Amg::Vector3D position = s->materialEffectsOnTrack()->associatedSurface().globalReferencePoint();
271 if (indetVolume->
inside(position)) {
continue; }
272 if (!calorimeterVolume->
inside(position)) {
break; }
273 if (++numberCaloTSOS > 2 && haveCaloDeposit) {
return true; }
276 ATH_MSG_VERBOSE(
"association false, " << numberCaloTSOS <<
" TSOS in calo volume");
284 if (!calorimeterVolume) {
298 bool spectrometer =
false;
307 if (indetVolume->
inside(tsos->measurementOnTrack()->globalPosition())) {
310 }
else if (!calorimeterVolume->
inside(tsos->measurementOnTrack()->globalPosition())) {
318 for (;
rs != track.trackStateOnSurfaces()->rend(); ++
rs) {
324 if (indetVolume->
inside((**rs).measurementOnTrack()->globalPosition())) {
327 }
else if (!calorimeterVolume->
inside((**rs).measurementOnTrack()->globalPosition())) {
333 return indet && spectrometer;
339 if (!calorimeterVolume) {
353 if (!parameters || !indetVolume->
inside(parameters->position())) {
return false; }
358 bool spectrometer =
false;
367 if (indetVolume->
inside(tsos->measurementOnTrack()->globalPosition())) {
370 }
else if (!calorimeterVolume->
inside(tsos->measurementOnTrack()->globalPosition())) {
378 for (;
rs != track.trackStateOnSurfaces()->rend(); ++
rs) {
384 if (indetVolume->
inside((**rs).measurementOnTrack()->globalPosition())) {
387 }
else if (!calorimeterVolume->
inside((**rs).measurementOnTrack()->globalPosition())) {
393 return !indet && spectrometer;
400 const Trk::Perigee* measuredPerigee = track.perigeeParameters();
402 if (!measuredPerigee)
return false;
404 if (!measuredPerigee->covariance()) {
411 double relativeMomentumCovariance = momentumCovariance * measuredPerigee->
momentum().mag2();
414 if (momentumCovariance < 1.E-19 || relativeMomentumCovariance < 1.E-6)
return true;
417 if (relativeMomentumCovariance > 100.)
return true;
428 startPosition = tsos->measurementOnTrack()->globalPosition();
435 for (;
rs != track.trackStateOnSurfaces()->rend(); ++
rs) {
438 endPosition = (**rs).measurementOnTrack()->globalPosition();
444 double side = endPosition.dot(startPosition);
446 ATH_MSG_DEBUG(
"track is not projective: fails same-side check ");
453 constexpr double PiOver8 =
M_PI / 8.;
454 if (std::abs(sc_dPhi.
sn) > PiOver8) {
460 if (sc_dPhi.
cs < 0.) {
461 double cotTheta = startPosition.z() / startPosition.perp();
462 if (std::abs(startPosition.z()) > std::abs(endPosition.z())) { cotTheta = endPosition.z() / endPosition.perp(); }
465 if (startPosition.z() * endPosition.z() < 0. || std::abs(cotTheta) < 2.0) {
470 ATH_MSG_WARNING(
"forward track changes hemisphere: cotTheta " << cotTheta <<
" cosDeltaPhi " << sc_dPhi.
cs);
478 constexpr double sectorOffset =
M_PI / 16.;
479 bool isOverlap =
true;
487 const Amg::Vector3D& position = tsos->measurementOnTrack()->associatedSurface().globalReferencePoint();
489 cosPhi = position.x() / position.perp();
490 sinPhi = position.y() / position.perp();
492 const Amg::Vector3D& position = tsos->measurementOnTrack()->associatedSurface().globalReferencePoint();
494 double sinDeltaPhi = (position.x() * sinPhi - position.y() * cosPhi) / position.perp();
496 if (std::abs(sinDeltaPhi) > sectorOffset) {
509 for (; s != track.trackStateOnSurfaces()->end(); ++s) {
510 if ((**s).trackParameters())
continue;
512 ATH_MSG_VERBOSE(
"track is slimmed (found TSOS without trackParameters) ");
516 ATH_MSG_VERBOSE(
"track is not slimmed (all TSOS have trackParameters) ");
527 double energyBalance = 0.;
533 if (!tsos->trackParameters())
continue;
535 if (tsos->materialEffectsOnTrack()) {
542 energyBalance = previousParameters->
momentum().mag() - energyLoss->
deltaE() - tsos->trackParameters()->momentum().mag();
544 if (std::abs(energyBalance) < energyLoss->
sigmaDeltaE()) {
546 <<
" momentum balance " << std::setw(6) << std::setprecision(2) << energyBalance / Units::GeV
547 <<
" significance " << std::setw(6) << std::setprecision(1)
548 << energyBalance / energyLoss->
sigmaDeltaE() <<
" p before/after calo" << std::setw(7)
549 << std::setprecision(2) << previousParameters->
momentum().mag() / Units::GeV <<
" /" << std::setw(7)
550 << std::setprecision(2) << tsos->trackParameters()->momentum().mag() / Units::GeV
551 <<
" energy deposit sigma " << energyLoss->
sigmaDeltaE() / Units::GeV <<
" GeV");
554 }
else if (energyBalance < 0.) {
556 <<
" momentum balance " << std::setw(6) << std::setprecision(2) << energyBalance / Units::GeV
557 <<
" significance " << std::setw(6) << std::setprecision(1)
558 << energyBalance / energyLoss->
sigmaDeltaE() <<
" p before/after calo" << std::setw(7)
559 << std::setprecision(2) << previousParameters->
momentum().mag() / Units::GeV <<
" /" << std::setw(7)
560 << std::setprecision(2) << tsos->trackParameters()->momentum().mag() / Units::GeV
561 <<
" energy deposit sigma- " << energyLoss->
sigmaMinusDeltaE() / Units::GeV <<
" GeV");
566 <<
" momentum balance " << std::setw(6) << std::setprecision(2) << energyBalance / Units::GeV
567 <<
" significance " << std::setw(6) << std::setprecision(1)
568 << energyBalance / energyLoss->
sigmaDeltaE() <<
" p before/after calo" << std::setw(7)
569 << std::setprecision(2) << previousParameters->
momentum().mag() / Units::GeV <<
" /" << std::setw(7)
570 << std::setprecision(2) << tsos->trackParameters()->momentum().mag() / Units::GeV
571 <<
" energy deposit sigma+ " << energyLoss->
sigmaPlusDeltaE() / Units::GeV <<
" GeV");
580 previousParameters = tsos->trackParameters();
583 return energyBalance;
587 unsigned numberPseudo = 0;
590 for (; s != track.trackStateOnSurfaces()->end(); ++s) {
596 ATH_MSG_VERBOSE(
" track has " << numberPseudo <<
" PseudoMeasurements");
603 const Trk::Perigee* perigee = track.perigeeParameters();
612 if (!perigee->covariance()) {
614 return std::make_unique<Trk::Perigee>(*perigee);
618 const AmgSymMatrix(5)& perigeeCov = (*perigee->covariance());
621 return std::make_unique<Trk::Perigee>(perigee->
position(), -perigee->
momentum(), -perigee->
charge(), surface, perigeeCov);
624 return std::make_unique<Trk::Perigee>(*perigee);
628 if (!calorimeterVolume) {
641 std::unique_ptr<const Trk::Track> refittedTrack;
650 refittedTrack = std::make_unique<Trk::Track>(track);
654 double charge = refittedTrack->perigeeParameters()->charge();
655 bool haveMeasurement =
false;
656 unsigned scatterers = 0;
657 double totalSigma = 0.;
659 std::vector<bool> isMeasurement;
660 std::vector<double> sigmas;
661 std::vector<double> radii;
665 if (!haveMeasurement) {
666 if (tsos->measurementOnTrack()) { haveMeasurement =
true; }
671 if (!tsos->materialEffectsOnTrack())
continue;
677 if (!calorimeterVolume->
inside(position))
break;
683 if (!scattering)
continue;
687 if (tsos->measurementOnTrack()) {
688 isMeasurement.push_back(
true);
690 isMeasurement.push_back(
false);
693 radii.push_back(tsos->trackParameters()->position().perp());
696 sigmas.push_back(sigma);
698 ATH_MSG_VERBOSE(scatterers <<
" radius " << tsos->trackParameters()->position().perp() <<
" deltaPhi "
699 << scattering->
deltaPhi() <<
" significance " << sigma <<
" totalSignificance " << totalSigma);
707 double curvatureSignificance = totalSigma;
708 double curvatureRadius = 0.;
709 double neighbourSignificance = 0.;
710 double neighbourRadius = 0.;
711 double previousSignificance = 0.;
712 double previousRadius = 0.;
713 unsigned index = scatterers - 1;
715 std::vector<double>::const_reverse_iterator
rs = sigmas.rbegin();
716 for (;
rs != sigmas.rend(); ++
rs, --
index) {
717 totalSigma -= 2. * (*rs);
719 if (std::abs(totalSigma) > std::abs(curvatureSignificance)) {
720 curvatureSignificance = totalSigma;
721 curvatureRadius = radii[
index];
724 if (std::abs(sigmas[
index] + previousSignificance) > std::abs(neighbourSignificance)) {
725 neighbourSignificance = sigmas[
index] + previousSignificance;
727 if (std::abs(neighbourSignificance) > 0.) {
728 neighbourRadius = (sigmas[
index] * radii[
index] + previousSignificance * previousRadius) / neighbourSignificance;
730 neighbourRadius = 0.;
734 previousSignificance = sigmas[
index];
735 previousRadius = radii[
index];
739 curvatureSignificance /= std::sqrt(
static_cast<double>(scatterers));
740 neighbourSignificance *= OneOverSqrt2;
742 ATH_MSG_DEBUG(
" scatteringAngleSignificance " << curvatureSignificance <<
" at radius " << curvatureRadius
743 <<
" neighbourSignificance " << neighbourSignificance <<
" at radius "
744 << neighbourRadius <<
" from " << scatterers <<
" scatterers");
752 if (!calorimeterVolume) {
762 !pThisTrackState->trackParameters() ||
764 calorimeterVolume->
inside(pThisTrackState->trackParameters()->position())) {
768 if (parametersView && pThisTrackState->trackParameters()->
position().mag() > parametersView->
position().mag()) {
break; }
769 parametersView = pThisTrackState->trackParameters();
772 if (!parametersView) { parametersView = track.perigeeParameters(); }
788 if (!calorimeterVolume) {
800 for (; s != track.trackStateOnSurfaces()->end(); ++s) {
803 calorimeterVolume->
inside((**s).trackParameters()->position())) {
808 if (!
id.is_valid() || !
m_idHelperSvc->measuresPhi(
id)) {
continue; }
815 leadingPhiMeasurement = *s;
819 if (!leadingPhiMeasurement)
return 2;
822 for (;
r != track.trackStateOnSurfaces()->rend(); ++
r) {
828 if (calorimeterVolume->
inside((**r).trackParameters()->position())) {
break; }
832 if (!
id.is_valid() || !
m_idHelperSvc->measuresPhi(
id)) {
continue; }
834 if (*
r != leadingPhiMeasurement) { trailingPhiMeasurement = *
r; }
839 if (!trailingPhiMeasurement) {
return 1; }
845 if (separation < 2. * Units::meter) {
return 1; }
851 const EventContext& ctx)
const {
854 if (!calorimeterVolume) {
861 std::unique_ptr<const Trk::TrackParameters> parameters;
864 for (; s != track.trackStateOnSurfaces()->end(); ++s) {
867 calorimeterVolume->
inside((**s).trackParameters()->position())) {
871 if (parameters && (**s).trackParameters()->position().mag() > parameters->position().mag()) {
break; }
873 parameters = (**s).trackParameters()->uniqueClone();
876 if (!parameters)
return nullptr;
879 if (parameters->momentum().dot(parameters->position()) > 0.) {
880 parameters = parameters->uniqueClone();
898 double qOverP = -parameters.parameters()[
Trk::qOverP];
899 const Trk::Surface* surface = &(parameters.associatedSurface());
903 parameters.covariance() ? std::optional<
AmgSymMatrix(5)>(*parameters.covariance()) : std::nullopt);
Scalar phi() const
phi method
Scalar theta() const
theta method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
double charge(const T &p)
#define AmgSymMatrix(dim)
Wrapper to avoid constant divisions when using units.
class extending the basic Trk::EnergyLoss to describe the measured or parameterised muon energy loss ...
DataModel_detail::const_iterator< DataVector > const_iterator
std::reverse_iterator< const_iterator > const_reverse_iterator
Class for competing MuonClusters, it extends the Trk::CompetingRIOsOnTrack base class.
lightweight return data-object for field integral track query
StatusCode initialize() override
std::unique_ptr< const Trk::TrackParameters > triggerStationParameters(const Trk::Track &track, const EventContext &ctx) const override
IMuonTrackQuery interface: trackParameters at innermost trigger chamber TSOS in MS.
SG::ReadCondHandleKey< Trk::TrackingGeometry > m_trackingGeometryReadKey
ToolHandle< Muon::IMdtDriftCircleOnTrackCreator > m_mdtRotCreator
bool isSectorOverlap(const Trk::Track &track) const override
IMuonTrackQuery interface: is there a long/short chamber overlap?
unsigned numberPseudoMeasurements(const Trk::Track &track) const override
IMuonTrackQuery interface: number of PseudoMeasurements on track (counts one for any vertex measureme...
bool isCombined(const Trk::Track &track, const EventContext &ctx) const override
IMuonTrackQuery interface: does track have measurements from indet and spectrometer ?
double caloEnergyDeposit(const Trk::Track &track, const EventContext &ctx) const override
IMuonTrackQuery interface: track energy deposit in calorimeters (as fitted or otherwise applied)
bool isCaloAssociated(const Trk::Track &track, const EventContext &ctx) const override
IMuonTrackQuery interface: does track have at least 3 TSOS's representing calorimeter ?
bool isExtrapolated(const Trk::Track &track, const EventContext &ctx) const override
IMuonTrackQuery interface: does track have perigee inside indet ?
std::unique_ptr< const Trk::Perigee > outgoingPerigee(const Trk::Track &track) const override
IMuonTrackQuery interface: perigee expressed outgoing from IP.
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
ServiceHandle< Muon::IMuonEDMHelperSvc > m_edmHelperSvc
ScatteringAngleSignificance scatteringAngleSignificance(const Trk::Track &track, const EventContext &ctx) const override
IMuonTrackQuery interface: significance of early scattering angle pattern for combined tracks (wider ...
ToolHandle< Trk::ITrackFitter > m_fitter
bool isLineFit(const Trk::Track &track) const override
IMuonTrackQuery interface: does track have fitted curvature ?
bool isSlimmed(const Trk::Track &track) const override
IMuonTrackQuery interface: does track have TrackParameters at every TSOS ?
FieldIntegral fieldIntegral(const Trk::Track &track, const EventContext &ctx) const override
IMuonTrackQuery interface: field integral along track from momentum kick between measurements.
const Trk::TrackingVolume * getVolume(const std::string &&vol_name, const EventContext &ctx) const
const CaloEnergy * caloEnergy(const Trk::Track &track) const override
IMuonTrackQuery interface: caloEnergy from appropriate TSOS.
double momentumBalanceSignificance(const Trk::Track &track, const EventContext &ctx) const override
IMuonTrackQuery interface: significance of momentum balance for combined tracks (biassed residual)
std::unique_ptr< Trk::TrackParameters > spectrometerParameters(const Trk::Track &track, const EventContext &ctx) const override
IMuonTrackQuery interface: trackParameters at innermost measurement TSOS in MS.
MuonTrackQuery(const std::string &type, const std::string &name, const IInterface *parent)
static std::unique_ptr< Trk::TrackParameters > flippedParameters(const Trk::TrackParameters ¶ms)
unsigned spectrometerPhiQuality(const Trk::Track &track, const EventContext &ctx) const override
IMuonTrackQuery interface: assess the number of additional phi measurements needed for MS (or SA) tra...
bool isProjective(const Trk::Track &track) const override
IMuonTrackQuery interface: is track (roughly) projective towards IP?
lightweight return data-object for (mainly indet) scattering angle analysis by track query
This class describes energy loss material effects in the ATLAS tracking EDM.
double sigmaPlusDeltaE() const
returns the positive side
double sigmaMinusDeltaE() const
returns the negative side
double sigmaDeltaE() const
returns the symmatric error
double deltaE() const
returns the
const Surface & associatedSurface() const
returns the surface to which these m.eff. are associated.
represents the full description of deflection and e-loss of a track in material.
const EnergyLoss * energyLoss() const
returns the energy loss object.
const ScatteringAngles * scatteringAngles() const
returns the MCS-angles object.
This class is the pure abstract base class for all fittable tracking measurements.
const Amg::Vector3D & momentum() const
Access method for the momentum.
const Amg::Vector3D & position() const
Access method for the position.
double charge() const
Returns the charge.
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...
virtual const S & associatedSurface() const override final
Access to the Surface method.
Class describing the Line to which the Perigee refers to.
Class to handle pseudo-measurements in fitters and on track objects.
virtual bool type(MeasurementBaseType::Type type) const override final
Extended method checking the type.
represents a deflection of the track caused through multiple scattering in material.
double sigmaDeltaPhi() const
returns the
double deltaPhi() const
returns the
double deltaTheta() const
returns the
Abstract Base Class for tracking surfaces.
virtual ChargedTrackParametersUniquePtr createUniqueTrackParameters(double l1, double l2, double phi, double theat, double qop, std::optional< AmgSymMatrix(5)> cov=std::nullopt) const =0
Use the Surface as a ParametersBase constructor, from local parameters - charged.
virtual const Amg::Vector3D & globalReferencePoint() const
Returns a global reference point on the surface, for PlaneSurface, StraightLineSurface,...
@ StraightTrack
A straight track.
represents the track state (measurement, material, fit parameters and quality) at a surface.
const TrackParameters * trackParameters() const
return ptr to trackparameters const overload
@ Outlier
This TSoS contains an outlier, that is, it contains a MeasurementBase/RIO_OnTrack which was not used ...
@ CaloDeposit
This TSOS contains a CaloEnergy object.
Full Volume description used in Tracking, it inherits from Volume to get the geometrical structure,...
bool inside(const Amg::Vector3D &gp, double tol=0.) const
Inside() method for checks.
Eigen::Matrix< double, 3, 1 > Vector3D
ParametersT< TrackParametersDim, Charged, PerigeeSurface > Perigee
ParametersBase< TrackParametersDim, Charged > TrackParameters
double deltaPhi(double phiA, double phiB)
delta Phi in range [-pi,pi[
Helper to simultaneously calculate sin and cos of the same angle.
Helper to simultaneously calculate sin and cos of the same angle.