788 {
789
790
791
793
794 state.nscatterers = 0;
795 state.numberOfFlippedMdts = 0;
796 state.numberOfCleanedCompROTs = 0;
797 state.nhits = 0;
798 state.noutliers = 0;
802 state.chambersToBeRemoved.clear();
803 state.chambersToBeRemovedPhi.clear();
804 state.pullSumPerChamber.clear();
805 state.pullSumPerChamberPhi.clear();
806 state.pullSumPerChamberEta.clear();
807 state.hitsPerChamber.clear();
808 state.outBoundsPerChamber.clear();
809 state.measInfo.clear();
810 state.largePullMeasurements.clear();
811 state.chamberLayerStatistics.clear();
812 state.stations.clear();
813 state.phiLayers.clear();
814 state.hasOfBoundsOutliers = false;
815 state.hasVertexConstraint = false;
816 state.hasSmall = false;
817 state.hasLarge = false;
818 state.nIdHits = 0;
819 state.nPseudoMeasurements = 0;
820 state.nPhiConstraints = 0;
821
822 MagField::AtlasFieldCache fieldCache;
823
827 return;
828 }
829 readHandle->getInitializedCache(fieldCache);
830
833
834
836 if (!states) {
838 return;
839 }
840
842
843 state.measInfo.reserve(
states->size());
844
845 std::set<int> rpcLayers;
846 std::set<int> tgcLayers;
847 const Trk::MeasurementBase* mdtmeas = nullptr;
848 double largestmdtpull = -999;
849
850
851 for (const Trk::TrackStateOnSurface* tsit : *states) {
853 ATH_MSG_DEBUG(tsit->dumpType() <<
", parameters " << *tsit->trackParameters());
855 if (!pars) {
856 state.measInfo.emplace_back(tsit);
857 continue;
858 }
859
861 const Trk::MaterialEffectsBase* matEff = tsit->materialEffectsOnTrack();
862 const Trk::MaterialEffectsOnTrack* matTrk = dynamic_cast<const Trk::MaterialEffectsOnTrack*>(matEff);
869 }
871 const Trk::EnergyLoss* eloss = matTrk->
energyLoss();
873 }
874 ++state.nscatterers;
875 state.measInfo.emplace_back(tsit);
876 continue;
877 }
878
879
880 const Trk::MeasurementBase* meas = tsit->measurementOnTrack();
881 if (!meas) {
882 state.measInfo.emplace_back(tsit);
883 continue;
884 }
885
887 bool pseudo = !id.is_valid();
888 if (pseudo) ++state.nPseudoMeasurements;
889
891 ATH_MSG_VERBOSE(
" TSOS is not a muon hit, position: r " <<
pars->position().perp() <<
" z " <<
pars->position().z());
892
893
895 state.measInfo.emplace_back(tsit);
896 continue;
897 }
898
899
900 if (pseudo &&
dynamic_cast<const Trk::PseudoMeasurementOnTrack*
>(meas) &&
pars->associatedSurface().center().perp() < 200.) {
901 state.hasVertexConstraint = true;
902 }
903
905 bool measuresPhi = pseudo ? true :
m_idHelperSvc->measuresPhi(
id);
906
907
911 continue;
912 }
913 bool inBounds = true;
914 double tol1 = 100.;
915 double tol2 = 2 * tol1;
917
918
919 const Trk::StraightLineSurface* slSurf =
dynamic_cast<const Trk::StraightLineSurface*
>(&meas->
associatedSurface());
920
921 const MMClusterOnTrack* mmClusterOnTrack = dynamic_cast<const MMClusterOnTrack*>(meas);
922
923 if (slSurf) {
924
926 } else if (mmClusterOnTrack) {
927
928 inBounds = mmClusterOnTrack->detectorElement()->insideActiveBounds(id, locPos, tol1, tol2);
929 } else {
931 }
932
934
935
938 if (!resPull) {
939 ATH_MSG_DEBUG(
" calculation of residual/pull failed !!!!! ");
940 continue;
941 }
942 int pullSize = resPull->pull().size();
943 double residual = resPull->residual().front();
944 double pull = std::abs(resPull->pull().front());
945
946
947 if (!pseudo && pullSize != 1) {
949 continue;
950 }
951
953 double error =
pull > 0.001 ? std::abs(residual / pull) : 1000.;
956 double rTrackAbs = std::abs(rTrack);
957 double flippedResidual = isMDT ? rDrift + rTrack : 1e10;
958 double flippedPull = isMDT ? std::abs(flippedResidual / error) : 1e10;
959
960 bool isNoise = false;
963 bool flippedIsRecoverable =
965 double innerRadius = 14.6;
966 if (isMDT) {
967 const MdtDriftCircleOnTrack* mdtdc = dynamic_cast<const MdtDriftCircleOnTrack*>(meas);
969 }
970
971 bool isDelta = isOutlier && isMDT && rTrackAbs < innerRadius && rTrackAbs > std::abs(rDrift);
972
973
974 if (isOutlier) {
975 if (isMDT) {
976 if (rTrackAbs > innerRadius) inBounds = false;
977 } else if (pull > 10.) {
978 inBounds = false;
979 }
980 }
981
982 std::unique_ptr<MdtDriftCircleOnTrack> mdtRotFlipped;
983 std::unique_ptr<const CompetingMuonClustersOnTrack> updatedCompRot;
984 bool flipSign = false;
985 if (!pseudo) {
986 const MdtDriftCircleOnTrack* mdtRot = isMDT ? dynamic_cast<const MdtDriftCircleOnTrack*>(meas) : nullptr;
988 isNoise = true;
989 isOutlier = true;
990 isRecoverable = false;
991 flippedIsRecoverable = false;
992 isDelta = false;
993 }
994 if (flippedIsRecoverable) {
997 flipSign = true;
998 }
999 if (!isNoise && flipSign) {
1000 if (mdtRot) {
1001 mdtRotFlipped = std::make_unique<MdtDriftCircleOnTrack>(*mdtRot);
1004 double rDriftFlip = mdtRotFlipped->localParameters()[
Trk::locR];
1005 int signRot = rDrift < 0 ? -1 : 1;
1006 int signRotFlip = rDriftFlip < 0 ? -1 : 1;
1007 if (rDrift != 0. && signRot == signRotFlip) {
1008 ATH_MSG_WARNING(
" failed to flip sign of MDT " << rDrift <<
" flip " << rDriftFlip);
1009 }
1010 } else {
1011 ATH_MSG_WARNING(
" failed to dynamic_cast measurement with MDT Identifier to a MdtDriftCircleOnTrack");
1012 }
1013 } else {
1014
1016 largestmdtpull =
pull;
1017 mdtmeas = meas;
1018 }
1019 }
1020
1021 if (measuresPhi) {
1023 if (isRpc) {
1026 if (stIndex == StIndex::BM &&
m_idHelperSvc->rpcIdHelper().doubletR(
id) == 1)
1028 else if (stIndex == StIndex::BO)
1030 rpcLayers.insert(layer);
1031 }
1032
1034 if (isTgc) {
1037 if (stIndex == StIndex::EM) {
1041 else if (
stName[1] ==
'2')
1043 else if (
stName[1] ==
'3')
1045 else {
1048 }
1049 }
1050 if (layer != -1) tgcLayers.insert(layer);
1051 }
1055 tgcLayers.insert(layer);
1056 ATH_MSG_VERBOSE(
"adding STGC phi hit " << layer <<
" size " << tgcLayers.size());
1057 }
1058 }
1059
1061 const CompetingMuonClustersOnTrack* crot = (measuresPhi && !isMDT &&
m_idHelperSvc->isRpc(
id))
1062 ? dynamic_cast<const CompetingMuonClustersOnTrack*>(meas)
1063 : nullptr;
1064 if (crot) {
1065 ATH_MSG_DEBUG(
" CompetingMuonClustersOnTrack with rots " << crot->numberOfContainedROTs());
1066 double minpos = 0.;
1067 double minres = 0.;
1068 double maxres = 0.;
1069 double absminres = 0.;
1070 double absmaxres = 0.;
1071 for (
unsigned int i = 0;
i < crot->numberOfContainedROTs(); ++
i) {
1072 const MuonClusterOnTrack* cluster = &crot->rioOnTrack(i);
1073 if (!cluster) continue;
1076 if (i == 0) {
1079 minpos = cluster->localParameters()[
Trk::locX];
1080 absminres = absres;
1081 absmaxres = absres;
1082 } else if (absres < absminres) {
1084 absminres = absres;
1085 minpos = cluster->localParameters()[
Trk::locX];
1086 } else if (absres > absmaxres) {
1088 absmaxres = absres;
1089 }
1092 << " residual " << residual);
1093 }
1094 ATH_MSG_DEBUG(
" residuals: min " << minres <<
" max " << maxres <<
" diff " << maxres - minres);
1095 bool splitCompRot = false;
1096 if (std::abs(maxres - minres) > 100 && absmaxres - absminres > 20 && crot->numberOfContainedROTs() < 20) {
1098 splitCompRot = true;
1099 }
1100 if (splitCompRot) {
1101 std::list<const Trk::PrepRawData*> prdList;
1103 for (
unsigned int i = 0;
i < crot->numberOfContainedROTs(); ++
i) {
1104 const MuonClusterOnTrack* cluster = &crot->rioOnTrack(i);
1105 if (!cluster) continue;
1108 if (absres < 40) {
1110 << cluster->localParameters()[
Trk::locX] <<
" pars "
1111 <<
pars->parameters()[
Trk::locX] <<
" residual " << residual);
1113 }
1114 }
1115 if (prdList.empty()) {
1116 ATH_MSG_WARNING(
"No clusters selected during comprot cleaning, keeping old cluster");
1117 } else {
1119 ++state.numberOfCleanedCompROTs;
1120 }
1121 }
1122 }
1123 }
1124 }
1125
1126 state.measInfo.emplace_back(
id, chId,
chIndex, inBounds, residual, pull, tsit, meas, pars, std::move(resPull),
nullptr);
1128 if (flipSign) {
info.flippedMdt = std::move(mdtRotFlipped); }
1129 info.isNoise = isNoise;
1130 if (updatedCompRot) {
1132 info.cleanedCompROT = std::move(updatedCompRot);
1134 std::unique_ptr<Trk::TrackParameters> exPars =
m_extrapolator->extrapolate(ctx,
1135 *pars,
info.cleanedCompROT->associatedSurface(),
1137 if (!exPars) {
1138 ATH_MSG_WARNING(
"Update of comp rot parameters failed, keeping old ones");
1139 info.cleanedCompROT.reset();
1140 } else {
1141 info.pars = exPars.get();
1142 state.parsToBeDeleted.emplace_back(std::move(exPars));
1143 }
1144 }
1145 }
1146
1149
1152 if (isMDT)
1153 ATH_MSG_DEBUG(
" r_drift " << rDrift <<
" r_trk " << rTrack <<
" dr " << std::setw(7)
1156 if (!inBounds)
1158 else {
1160 if (flippedIsRecoverable)
1162 else if (isRecoverable)
1164 else if (isDelta)
1166 }
1167
1168 if (!inBounds) {
1169 state.hasOfBoundsOutliers = true;
1170 ++chamberStatistics.noutBounds;
1171 } else if (flippedIsRecoverable || isRecoverable)
1172 ++chamberStatistics.nrecoverableOutliers;
1173 else if (isDelta)
1174 ++chamberStatistics.ndeltas;
1175 else if (pull < 10)
1176 ++chamberStatistics.noutliers;
1177
1178 if (!pseudo) ++state.noutliers;
1180 continue;
1181 }
1182
1183
1184 ++chamberStatistics.nhits;
1185 if (!pseudo) ++state.nhits;
1186
1187 if (flipSign) ++state.numberOfFlippedMdts;
1188
1189 std::string idString = pseudo ?
" Pseudomeasurement " :
m_idHelperSvc->toString(
id);
1190 std::string boundCheck = inBounds ? "inBounds" : "outBounds";
1192 if (isNoise)
1194 else if (isOutlier)
1196 if (isMDT) {
1197 ATH_MSG_VERBOSE(
" r_drift " << std::setw(8) << rDrift <<
" r_trk " << std::setw(7) << rTrack <<
" dr " << std::setw(7)
1199 if (flipSign)
1201 else if (isDelta)
1203 } else {
1204 const RpcClusterOnTrack* rpc = dynamic_cast<const RpcClusterOnTrack*>(meas);
1205 if (!rpc) {
1206 const CompetingMuonClustersOnTrack* crot = dynamic_cast<const CompetingMuonClustersOnTrack*>(meas);
1207 if (crot) { rpc = dynamic_cast<const RpcClusterOnTrack*>(crot->containedROTs().front()); }
1208 }
1209 if (rpc)
ATH_MSG_DEBUG(
" time " << rpc->prepRawData()->time() - rpc->globalPosition().mag() / 300.);
1210 }
1211
1212 if (pseudo) {
1213
1214 if (!isNoise && isOutlier) { state.largePullPseudoMeasurements.insert(meas); }
1215 continue;
1216
1217 } else {
1218
1220 if (measuresPhi)
1222 else
1224
1225
1226 if (!inBounds) {
1228 if (measuresPhi)
1230 else
1231 ++outHits.neta;
1232 }
1233
1234
1236
1237
1240 pullInfoHits.pullSum +=
pull;
1241 ++pullInfoHits.nhits;
1242 if (pull > pullInfoHits.maxPull) pullInfoHits.maxPull =
pull;
1243
1244 ChamberPullInfo& pullInfoCh = measuresPhi ? state.pullSumPerChamberPhi[
info.chId] : state.pullSumPerChamber[
info.chId];
1246 ++pullInfoCh.nhits;
1247 if (pull > pullInfoCh.maxPull) pullInfoCh.maxPull =
pull;
1248 } else {
1249 ChamberPullInfo& pullInfoTrig = measuresPhi ? state.pullSumPhi : state.pullSumTrigEta;
1250 if (!measuresPhi) state.pullSumPerChamberEta[
info.chId];
1252 ++pullInfoTrig.nhits;
1253 if (pull > pullInfoTrig.maxPull) pullInfoTrig.maxPull =
pull;
1254 }
1255 }
1256 }
1257
1258
1259 if (mdtmeas) state.largePullMeasurements.insert(mdtmeas);
1260
1261
1262 unsigned int nphiLayers = rpcLayers.size() + tgcLayers.size();
1263 if (state.hasVertexConstraint) { nphiLayers += 1; }
1264 if (state.nIdHits > 0) { nphiLayers += 2; }
1265
1266 if ((nphiLayers > 2) && state.numberOfCleanedCompROTs > 0) {
1267 ATH_MSG_DEBUG(
" Sufficient constraints to clean competing ROTs: trigger layers " << nphiLayers);
1268 } else {
1269
1270 state.numberOfCleanedCompROTs = 0;
1271 }
1272
1273
1274 if (!
m_use_slFit && state.slFit && (state.hasVertexConstraint || state.nIdHits > 0) && fieldCache.
solenoidOn()) {
1275 state.slFit = false;
1276 }
1277
1278 if (state.hasVertexConstraint || state.nIdHits) {
1279 if (state.hasVertexConstraint)
ATH_MSG_DEBUG(
" Track has vertex contraint:");
1280 if (state.nIdHits > 0)
ATH_MSG_DEBUG(
" Track has ID Hits: " << state.nIdHits);
1283 else
1287 else
1289 if (state.slFit)
1291 else
1293 }
1294
1295 std::set<Identifier> chambersToBeRemoved, chambersToBeRemovedPhi, goodEtaLayers, goodPhiLayers;
1296
1297
1299
1300
1302
1304
1307 for (; chit != chit_end; ++chit) {
1308 if (!chit->first.is_valid()) continue;
1309
1312 if (isPrec) {
1314 state.stations.insert(stIndex);
1315 }
1316
1318 EtaPhiHits& noutBounds = state.outBoundsPerChamber[chit->first];
1320 << noutBounds.neta << " phi hits " << nhits.nphi << " outBounds " << noutBounds.nphi);
1321 if (nhits.neta != 0 && nhits.neta == noutBounds.neta) {
1323
1324 double fakePull = 1000. * nhits.neta;
1325 if (!chambersToBeRemoved.count(chit->first)) {
1326
1327 state.chambersToBeRemoved.emplace_back(fakePull, chit->first);
1328 chambersToBeRemoved.insert(chit->first);
1329 } else {
1330
1331 PullChIt pIt = state.chambersToBeRemoved.begin();
1332 PullChIt pIt_end = state.chambersToBeRemoved.end();
1333 for (; pIt != pIt_end; ++pIt) {
1334 if (pIt->second == chit->first && pIt->first < fakePull) {
1335 pIt->first = fakePull;
1336 break;
1337 }
1338 }
1339 }
1340 } else {
1341 if (noutBounds.neta != 0)
ATH_MSG_DEBUG(
" --> Some eta hits out of bounds ");
1342
1343 if (isPrec && nhits.neta > 0) {
1345 state.hasSmall = true;
1346 else
1347 state.hasLarge = true;
1348 }
1349 }
1350 if (nhits.nphi != 0 && nhits.nphi == noutBounds.nphi) {
1352
1353 double fakePull = 1000. * nhits.nphi;
1354 if (!chambersToBeRemovedPhi.count(chit->first)) {
1355
1356 state.chambersToBeRemovedPhi.emplace_back(fakePull, chit->first);
1357 chambersToBeRemovedPhi.insert(chit->first);
1358 } else {
1359
1360 PullChIt pIt = state.chambersToBeRemovedPhi.begin();
1361 PullChIt pIt_end = state.chambersToBeRemovedPhi.end();
1362 for (; pIt != pIt_end; ++pIt) {
1363 if (pIt->second == chit->first) {
1364 pIt->first = std::max(pIt->first, fakePull);
1365 break;
1366 }
1367 }
1368 }
1369 } else {
1370 if (noutBounds.nphi != 0)
ATH_MSG_DEBUG(
" --> Some phi hits out of bounds ");
1371 if (nhits.nphi > 0) {
1372 state.phiLayers.insert(
m_idHelperSvc->phiIndex(chit->first));
1373 }
1374 }
1375 }
1376
1377 state.nPhiConstraints = state.phiLayers.size() + state.nPseudoMeasurements;
1378 if (state.hasLarge && state.hasSmall) ++state.nPhiConstraints;
1379 if (state.stations.size() == 1 && nphiLayers > 1) ++state.nPhiConstraints;
1380
1381 double pull_precisionhits = -1.;
1382 if (state.pullSum.nhits != 0) { pull_precisionhits = state.pullSum.pullSum / state.pullSum.nhits; }
1383 double pull_triggerhits = -1.;
1384 if (state.pullSumTrigEta.nhits != 0) { pull_triggerhits = state.pullSumTrigEta.pullSum / state.pullSumTrigEta.nhits; }
1385 double pull_phihits = -1.;
1386 if (state.pullSumPhi.nhits != 0) { pull_phihits = state.pullSumPhi.pullSum / state.pullSumPhi.nhits; }
1388 << pull_precisionhits << " trigger eta " << pull_triggerhits << " phi " << pull_phihits << " measurements "
1389 << state.measInfo.size() << std::endl
1390 << " precision chambers " << state.pullSumPerChamber.size() << " hits with large pull "
1391 << state.largePullMeasurements.size() << " pseudos with large pull " << state.largePullPseudoMeasurements.size()
1392 << " chambers to be removed " << state.chambersToBeRemoved.size() << " phi " << state.chambersToBeRemovedPhi.size()
1393 << " phi lay " << state.phiLayers.size() << " phi constr " << state.nPhiConstraints);
1394
1395 if (state.pullSumPhi.nhits != 0) {
1396 double phiPull = state.pullSumPhi.pullSum / state.pullSumPhi.nhits;
1397 if (state.stations.size() == 1 && phiPull > 5.) {
ATH_MSG_DEBUG(
" Single station track with large phi pulls!! "); }
1398 } else
1400 }
bool solenoidOn() const
status of the magnets
virtual const MuonGM::MdtReadoutElement * detectorElement() const override final
Returns the detector element, assoicated with the PRD of this class.
virtual const MdtPrepData * prepRawData() const override final
Returns the PrepRawData used to create this corrected measurement.
virtual const MuonCluster * prepRawData() const override=0
Returns the Trk::PrepRawData - is a MuonCluster in this scope.
double innerTubeRadius() const
Returns the inner tube radius excluding the aluminium walls.
ToolHandle< Trk::IExtrapolator > m_extrapolator
ServiceHandle< Muon::IMuonEDMHelperSvc > m_edmHelperSvc
bool extractChambersToBeRemoved(CleaningState &state, std::set< Identifier > &chambersToBeRemovedSet, bool usePhi=false) const
helper function to extract chambers that are to be removed
ToolHandle< IMuonCompetingClustersOnTrackCreator > m_compRotCreator
ToolHandle< Muon::IMdtDriftCircleOnTrackCreator > m_mdtRotCreator
ToolHandle< Trk::IResidualPullCalculator > m_pullCalculator
Gaudi::Property< double > m_associationScaleFactor
EtaPhiPerChamberMap::iterator EtaPhiPerChamberIt
SG::ReadCondHandleKey< AtlasFieldCacheCondObj > m_fieldCacheCondObjInputKey
bool isOutsideOnTrackCut(const Identifier &id, double res, double pull, double cutScaleFactor) const
check whether hit is an outlier
Gaudi::Property< double > m_adcCut
Gaudi::Property< bool > m_recoverOutliers
Gaudi::Property< bool > m_use_slFit
double deltaE() const
returns the
double thicknessInX0() const
returns the actually traversed material .
const EnergyLoss * energyLoss() const
returns the energy loss object.
const ScatteringAngles * scatteringAngles() const
returns the MCS-angles object.
const LocalParameters & localParameters() const
Interface method to get the LocalParameters.
virtual const Surface & associatedSurface() const =0
Interface method to get the associated Surface.
const Amg::MatrixX & localCovariance() const
Interface method to get the localError.
@ Biased
RP with track state including the hit.
@ Unbiased
RP with track state that has measurement not included.
double sigmaDeltaPhi() const
returns the
double deltaPhi() const
returns the
double sigmaDeltaTheta() const
returns the
double deltaTheta() const
returns the
virtual const SurfaceBounds & bounds() const override final
This method returns the bounds of the Surface by reference.
virtual bool insideLoc2(const Amg::Vector2D &locpo, double tol2=0.) const =0
Extend the interface to for single inside Loc 1 / Loc2 tests.
virtual bool globalToLocal(const Amg::Vector3D &glob, const Amg::Vector3D &mom, Amg::Vector2D &loc) const =0
Specified by each surface type: GlobalToLocal method without dynamic memory allocation - boolean chec...
virtual bool insideBounds(const Amg::Vector2D &locpos, double tol1=0., double tol2=0.) const =0
virtual methods to be overwritten by the inherited surfaces
@ Perigee
This represents a perigee, and so will contain a Perigee object only.
@ Scatterer
This represents a scattering point on the track, and so will contain TrackParameters and MaterialEffe...
double error(const Amg::MatrixX &mat, int index)
return diagonal error of the matrix caller should ensure the matrix is symmetric and the index is in ...
Eigen::Matrix< double, 2, 1 > Vector2D
ChIndex chIndex(const std::string &index)
convert ChIndex name string to enum
const std::string & stName(StIndex index)
convert StIndex into a string
DriftCircleSide
Enumerates the 'side' of the wire on which the tracks passed (i.e.
@ RIGHT
the drift radius is positive (see Trk::AtaStraightLine)
@ LEFT
the drift radius is negative (see Trk::AtaStraightLine)
DataVector< const Trk::TrackStateOnSurface > TrackStates
ParametersBase< TrackParametersDim, Charged > TrackParameters
MuonStationIndex::ChIndex chIndex
#define CXXUTILS_TRAPPING_FP