65 {
66
68 if (!states) {
70 return false;
71 }
74 }
75
77
79
80
81 const Trk::FitQuality* fq =
track.fitQuality();
82 if (!fq) return false;
86 ATH_MSG_DEBUG(
" Track discarded: too large chi2 " << reducedChi2);
87 return false;
88 }
89
91 int nrpcs = 0;
92 double aveRpcTime = 0.;
93 double minTime = 1e9;
94 double maxTime = -1e9;
95
96
99 for (; tsit != tsit_end; ++tsit) {
101
102
103 const Trk::MeasurementBase* meas = (*tsit)->measurementOnTrack();
104 if (!meas) continue;
105
106 const RpcClusterOnTrack* rpc = dynamic_cast<const RpcClusterOnTrack*>(meas);
107 if (!rpc) {
108 const CompetingMuonClustersOnTrack* crot = dynamic_cast<const CompetingMuonClustersOnTrack*>(meas);
109 if (crot) { rpc = dynamic_cast<const RpcClusterOnTrack*>(crot->containedROTs().front()); }
110 }
111 if (rpc) {
112 double time = rpc->prepRawData()->time() - rpc->globalPosition().mag() / 300.;
113 ++nrpcs;
115 if (time < minTime) minTime =
time;
116 if (time > maxTime) maxTime =
time;
117 }
118 }
119
120 if (nrpcs != 0) {
121 aveRpcTime /= nrpcs;
122 double timeMinCut = -2.;
123 double timeMaxCut = 20.;
124 ATH_MSG_VERBOSE(
" ave RPC time " << aveRpcTime <<
" min " << minTime <<
" max " << maxTime);
125 if (aveRpcTime < timeMinCut) {
128 return false;
129 }
130 if (aveRpcTime > timeMaxCut) {
133 return false;
134 }
135 if (maxTime > timeMaxCut && minTime < timeMinCut) {
138 return false;
139 }
140 }
141 }
142
143 unsigned int mdtHoles = 0;
144 unsigned int mdtOutliers = 0;
145 unsigned int nholes = 0;
146 std::map<MuonStationIndex::StIndex, StationData> stations;
147
149 Trk::MuonTrackSummary muonSummary;
150 if (summary) {
151 if (
summary->muonTrackSummary())
152 muonSummary = *
summary->muonTrackSummary();
153 else {
155 if (
summary->muonTrackSummary()) muonSummary = *
summary->muonTrackSummary();
156 }
157 } else {
158 Trk::TrackSummary tmpSummary;
161 }
162
163 std::vector<Trk::MuonTrackSummary::ChamberHitSummary>::const_iterator chit = muonSummary.
chamberHitSummary().begin();
164 std::vector<Trk::MuonTrackSummary::ChamberHitSummary>::const_iterator chit_end = muonSummary.
chamberHitSummary().end();
165 for (; chit != chit_end; ++chit) {
166 const Identifier& chId = chit->chamberId();
167
174
175
176 bool useHoles = false;
178 useHoles = true;
179
180 if (isMdt) {
183 stData.netaHits += chit->nhits();
184 if (useHoles) stData.netaHoles += chit->nholes();
185 if (!stData.mdtHasHitsinMl1 && chit->mdtMl1().nhits > 0) stData.mdtHasHitsinMl1 = true;
186 if (!stData.mdtHasHitsinMl2 && chit->mdtMl2().nhits > 0) stData.mdtHasHitsinMl2 = true;
187
188 if (useHoles) {
189 mdtHoles += chit->nholes();
190 nholes += chit->nholes();
191 mdtOutliers += chit->noutliers();
192 }
193
194 stData.isMdt = true;
195
196 } else if (isCsc || issTgc || isMM) {
199 stData.netaHits += chit->etaProjection().nhits;
200 if (useHoles) {
201 stData.netaHoles += chit->etaProjection().nholes;
202 stData.nphiHoles += chit->phiProjection().nholes;
203 nholes += chit->nholes();
204 }
205 stData.nphiHits += chit->phiProjection().nhits;
206 stData.isCsc = isCsc;
207 stData.isNSW = issTgc || isMM;
208
209 } else if (isRpc || isTgc) {
212 stData.netaTrigHits += chit->etaProjection().nhits > 0 ? 1 : 0;
213 stData.nphiTrigHits += chit->phiProjection().nhits > 0 ? 1 : 0;
214 if (useHoles) {
215
217 stData.netaTrigHoles += chit->etaProjection().nholes;
218 nholes += chit->etaProjection().nholes;
219 }
221 stData.nphiTrigHoles += chit->phiProjection().nholes;
222 nholes += chit->phiProjection().nholes;
223 }
224 }
225
226
227 if (!stData.isMdt && !stData.isCsc) stData.isTrigger = true;
228 }
229 }
230
231 unsigned int nGoodStations = 0;
232 unsigned int nstations = 0;
233 unsigned int nTwoMlStations = 0;
234 unsigned int nGoodCscStations = 0;
235 unsigned int nGoodTriggerStations = 0;
236
237 std::map<MuonStationIndex::StIndex, StationData>::iterator sit = stations.begin();
238 std::map<MuonStationIndex::StIndex, StationData>::iterator sit_end = stations.end();
239 for (; sit != sit_end; ++sit) {
241
242 if (stData.nphiTrigHits != 0 && stData.netaTrigHits != 0) { ++nGoodTriggerStations; }
243
244 if (stData.isMdt) {
246 ATH_MSG_VERBOSE(
" Not counting MDT station too few MDT hits: nhits " << stData.netaHits <<
" cut "
248 continue;
249 }
250 ++nstations;
251 double holeHitRatio = (
double)stData.netaHoles / stData.netaHits;
253 ATH_MSG_VERBOSE(
" Not counting MDT station too many holes: nhits " << stData.netaHits <<
" nholes " << stData.netaHoles
254 << " ratio " << holeHitRatio << " cut "
256 continue;
257 }
258 if (stData.mdtHasHitsinBothMl()) ++nTwoMlStations;
259 } else if (stData.isCsc || stData.isNSW) {
260 if (stData.isCsc && stData.nphiHits == 0) {
261 ATH_MSG_VERBOSE(
" Not counting CSC station no phi hits: netaHits " << stData.netaHits <<
" nphiHits "
262 << stData.nphiHits);
263 continue;
264 }
265
269 continue;
270 }
271 ++nstations;
272 ++nGoodCscStations;
273 }
274
275 ++nGoodStations;
276 }
277
278 ATH_MSG_DEBUG(
" good stations " << nGoodStations <<
" MDT stations with two ml " << nTwoMlStations <<
" MDT holes " << mdtHoles
279 << " outliers " << mdtOutliers << " good CSC stations " << nGoodCscStations << " trigger stations "
280 << nGoodTriggerStations);
281
283 ATH_MSG_DEBUG(
" Track discarded: too few stations " << stations.size());
285 return false;
286 }
287
288
289 if (stations.size() == 1) {
290 using namespace MuonStationIndex;
291 if (!stations.count(StIndex::EM)) return false;
292
294
297
298 ATH_MSG_DEBUG(
" Single station track: trigger phi " << stData.nphiTrigHits <<
" eta " << stData.netaTrigHits <<
" cut "
299 << nExpectedTriggerStations << " holes " << stData.netaHoles << " cut "
300 << maxHolesSingle);
301
302 bool ok = true;
303
304 if (nTwoMlStations == 0) ok = false;
305
306
307 if (stData.nphiTrigHits < nExpectedTriggerStations || stData.netaTrigHits < nExpectedTriggerStations) ok = false;
308
309
310 if (stData.netaHoles > maxHolesSingle) ok = false;
311
312 if (!ok) {
313 ATH_MSG_DEBUG(
" Track discarded: failed single track cuts ");
315 }
316 return ok;
317 }
318
319 if (nGoodStations < 2) {
320 ATH_MSG_DEBUG(
" Track discarded: too few good stations " << nGoodStations);
322 return false;
323 }
324
326
327 if (nstations < 3) {
329 ATH_MSG_DEBUG(
" Track discarded: good stations " << nGoodStations <<
" and " << mdtHoles <<
" mdt holes ");
331 return false;
332 }
334 ATH_MSG_DEBUG(
" Track discarded: good stations " << nGoodStations <<
" and " << nholes <<
" holes ");
336 return false;
337 }
338 if (nTwoMlStations == 0 && nGoodCscStations == 0) {
340 << nGoodStations << " but no MDT station with hits in two multilayers nor good CSC station ");
342 return false;
343 }
345 ATH_MSG_DEBUG(
" Track discarded: stations " << nstations <<
" but no trigger hits nor good CSC station ");
347 return false;
348 }
349 } else {
351 ATH_MSG_DEBUG(
" Track discarded: good stations " << nGoodStations <<
" and " << mdtHoles <<
" mdt holes ");
353 return false;
354 }
356 ATH_MSG_DEBUG(
" Track discarded: good stations " << nGoodStations <<
" and " << nholes <<
" holes ");
358 return false;
359 }
360 }
361
363
364 return true;
365 }
#define ATH_MSG_VERBOSE(x)
DataModel_detail::const_iterator< DataVector > const_iterator
int numberDoF() const
returns the number of degrees of freedom of the overall track or vertex fit as integer
double chiSquared() const
returns the of the overall track fit
const std::vector< ChamberHitSummary > & chamberHitSummary() const
access to the vector of chamber hit summaries on the track
@ Measurement
This is a measurement, and will at least contain a Trk::MeasurementBase.
const MuonTrackSummary * muonTrackSummary() const
returns a pointer to the MuonTrackSummary if available
bool hasPositiveDiagElems(const AmgSymMatrix(N) &mat)
Returns true if all diagonal elements of the covariance matrix are finite aka sane in the above defin...
time(flags, cells_name, *args, **kw)
StIndex
enum to classify the different station layers in the muon spectrometer
DataVector< const Trk::TrackStateOnSurface > TrackStates