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.; }
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; }
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);
207 integratedMomentumKick += momentumKick;
210 if (!isPreciseHit)
continue;
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) {
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;
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) {
455 ATH_MSG_DEBUG(
"track is not projective: sinDeltaPhi " << sc_dPhi.sn);
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) {
466 ATH_MSG_DEBUG(
"track is not projective: 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
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
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
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");
612 if (!perigee->covariance()) {
614 return std::make_unique<Trk::Perigee>(*perigee);
617 if (outerTSOS->
trackParameters() == perigee && perigee->momentum().dot(perigee->position()) <= 0.) {
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);
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(); }
775 if (parametersView->momentum().dot(parametersView->position()) > 0.) {
776 return parametersView->uniqueClone();
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; }
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();
903 parameters.covariance() ? std::optional<AmgSymMatrix(5)>(*
parameters.covariance()) : std::nullopt);