CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
MuonTrajectoryCleaner.cc
Go to the documentation of this file.
1 
15 
16 using namespace std;
17 
19 
21  const std::string metname = "Muon|RecoMuon|MuonTrajectoryCleaner";
22 
23  LogTrace(metname) << "Muon Trajectory Cleaner called" << endl;
24 
25  TrajectoryContainer::iterator iter, jter;
26  Trajectory::DataContainer::const_iterator m1, m2;
27 
28  if ( trajC.size() < 1 ) return;
29 
30  LogTrace(metname) << "Number of trajectories in the container: " <<trajC.size()<< endl;
31 
32  int i(0), j(0);
33  int match(0);
34 
35  // Map between chosen seed and ghost seeds (for trigger)
36  map<int, vector<int> > seedmap;
37 
38  // CAVEAT: vector<bool> is not a vector, its elements are not addressable!
39  // This is fine as long as only operator [] is used as in this case.
40  // cf. par 16.3.11
41  vector<bool> mask(trajC.size(),true);
42 
44 
45  for ( iter = trajC.begin(); iter != trajC.end(); iter++ ) {
46  if ( !mask[i] ) { i++; continue; }
47  if ( !(*iter)->isValid() || (*iter)->empty() ) {mask[i] = false; i++; continue; }
48  if(seedmap.count(i)==0) seedmap[i].push_back(i);
49  const Trajectory::DataContainer& meas1 = (*iter)->measurements();
50  j = i+1;
51  bool skipnext=false;
52  for ( jter = iter+1; jter != trajC.end(); jter++ ) {
53  if ( !mask[j] ) { j++; continue; }
54  if(seedmap.count(j)==0) seedmap[j].push_back(j);
55  const Trajectory::DataContainer& meas2 = (*jter)->measurements();
56  match = 0;
57  for( m1 = meas1.begin(); m1 != meas1.end(); m1++ ) {
58  for( m2 = meas2.begin(); m2 != meas2.end(); m2++ ) {
59  if ( ( (*m1).recHit()->globalPosition() - (*m2).recHit()->globalPosition()).mag()< 10e-5 ) match++;
60  } // end for( m2 ... )
61  } // end for( m1 ... )
62 
63 
64  int nTotHits_i = (*iter)->measurements().size();
65  int nTotHits_j = (*jter)->measurements().size();
66 
67  // FIXME Set Boff/on via cfg!
68  double chi2_dof_i = (*iter)->ndof() > 0 ? (*iter)->chiSquared()/(*iter)->ndof() : (*iter)->chiSquared()/1e-10;
69  double chi2_dof_j = (*jter)->ndof() > 0 ? (*jter)->chiSquared()/(*jter)->ndof() : (*jter)->chiSquared()/1e-10;
70 
71  LogTrace(metname) << " MuonTrajectoryCleaner:";
72  LogTrace(metname) << " * trajC " << i
73  << " (pT="<<(*iter)->lastMeasurement().updatedState().globalMomentum().perp()
74  << " GeV) - chi2/nDOF = " << (*iter)->chiSquared() << "/" << (*iter)->ndof() << " = " << chi2_dof_i;
75  LogTrace(metname) << " - valid RH = " << (*iter)->foundHits() << " / total RH = " << nTotHits_i;
76  LogTrace(metname) << " * trajC " << j
77  << " (pT="<<(*jter)->lastMeasurement().updatedState().globalMomentum().perp()
78  << " GeV) - chi2/nDOF = " << (*jter)->chiSquared() << "/" << (*jter)->ndof() << " = " << chi2_dof_j;
79  LogTrace(metname) << " - valid RH = " << (*jter)->foundHits() << " / total RH = " << nTotHits_j;
80  LogTrace(metname) << " *** Shared RecHits: " << match;
81 
82  int hit_diff = (*iter)->foundHits() - (*jter)->foundHits() ;
83  // If there are matches, reject the worst track
84  if ( match > 0 ) {
85  // If the difference in # of rechits is null then compare the chi2/ndf of the two trajectories
86  if ( abs(hit_diff) == 0 ) {
87 
88  double minPt = 3.5;
89  double dPt = 7.; // i.e. considering 10% (conservative!) resolution at minPt it is ~ 10 sigma away from the central value
90 
91  double maxFraction = 0.95;
92 
93  double fraction = (2.*match)/((*iter)->measurements().size()+(*jter)->measurements().size());
94  int belowLimit = 0;
95  int above = 0;
96 
97  if((*jter)->lastMeasurement().updatedState().globalMomentum().perp() <= minPt) ++belowLimit;
98  if((*iter)->lastMeasurement().updatedState().globalMomentum().perp() <= minPt) ++belowLimit;
99 
100  if((*jter)->lastMeasurement().updatedState().globalMomentum().perp() >= dPt) ++above;
101  if((*iter)->lastMeasurement().updatedState().globalMomentum().perp() >= dPt) ++above;
102 
103 
104  if(fraction >= maxFraction && belowLimit == 1 && above == 1){
105  if((*iter)->lastMeasurement().updatedState().globalMomentum().perp() < minPt){
106  mask[i] = false;
107  skipnext=true;
108  seedmap[j].insert(seedmap[j].end(), seedmap[i].begin(), seedmap[i].end());
109  seedmap.erase(i);
110  LogTrace(metname) << "Trajectory # " << i << " (pT="<<(*iter)->lastMeasurement().updatedState().globalMomentum().perp()
111  << " GeV) rejected because it has too low pt";
112  }
113  else {
114  mask[j] = false;
115  seedmap[i].insert(seedmap[i].end(), seedmap[j].begin(), seedmap[j].end());
116  seedmap.erase(j);
117  LogTrace(metname) << "Trajectory # " << j << " (pT="<<(*jter)->lastMeasurement().updatedState().globalMomentum().perp()
118  << " GeV) rejected because it has too low pt";
119  }
120  }
121  else{
122  if (chi2_dof_i > chi2_dof_j) {
123  mask[i] = false;
124  skipnext=true;
125  seedmap[j].insert(seedmap[j].end(), seedmap[i].begin(), seedmap[i].end());
126  seedmap.erase(i);
127  LogTrace(metname) << "Trajectory # " << i << " (pT="<<(*iter)->lastMeasurement().updatedState().globalMomentum().perp() << " GeV) rejected";
128  }
129  else{
130  mask[j] = false;
131  seedmap[i].insert(seedmap[i].end(), seedmap[j].begin(), seedmap[j].end());
132  seedmap.erase(j);
133  LogTrace(metname) << "Trajectory # " << j << " (pT="<<(*jter)->lastMeasurement().updatedState().globalMomentum().perp() << " GeV) rejected";
134  }
135  }
136  }
137  else { // different number of hits
138  if ( hit_diff < 0 ) {
139  mask[i] = false;
140  skipnext=true;
141  seedmap[j].insert(seedmap[j].end(), seedmap[i].begin(), seedmap[i].end());
142  seedmap.erase(i);
143  LogTrace(metname) << "Trajectory # " << i << " (pT="<<(*iter)->lastMeasurement().updatedState().globalMomentum().perp() << " GeV) rejected";
144  }
145  else {
146  mask[j] = false;
147  seedmap[i].insert(seedmap[i].end(), seedmap[j].begin(), seedmap[j].end());
148  seedmap.erase(j);
149  LogTrace(metname) << "Trajectory # " << j << " (pT="<<(*jter)->lastMeasurement().updatedState().globalMomentum().perp() << " GeV) rejected";
150  }
151  }
152  }
153  if(skipnext) break;
154  j++;
155  }
156  i++;
157  if(skipnext) continue;
158  }
159 
160 
161  // Association map between the seed of the chosen trajectory and the seeds of the discarded trajectories
162  if(reportGhosts_) {
163  LogTrace(metname) << " Creating map between chosen seed and ghost seeds." << std::endl;
164 
165  auto_ptr<L2SeedAssoc> seedToSeedsMap(new L2SeedAssoc);
166  if(!seeds->empty()) {
167  edm::Ptr<TrajectorySeed> ptr = seeds->ptrAt(0);
169  event.get(ptr.id(), seedsHandle);
170  seedToSeedsMap.reset(new L2SeedAssoc(seedsHandle, seedsHandle));
171  }
172 
173  int seedcnt(0);
174 
175  for(map<int, vector<int> >::iterator itmap=seedmap.begin(); itmap!=seedmap.end(); ++itmap, ++seedcnt) {
176  edm::RefToBase<TrajectorySeed> tmpSeedRef1 = trajC[(*itmap).first]->seedRef();
178 
179  int tmpsize=(*itmap).second.size();
180  for(int cnt=0; cnt!=tmpsize; ++cnt) {
181  edm::RefToBase<TrajectorySeed> tmpSeedRef2 = trajC[(*itmap).second[cnt]]->seedRef();
183  seedToSeedsMap->insert(tmpL2SeedRef1, tmpL2SeedRef2);
184  }
185  }
186 
187  event.put(seedToSeedsMap, "");
188 
189  } // end if(reportGhosts_)
190 
191  i = 0;
192  for ( iter = trajC.begin(); iter != trajC.end(); iter++ ) {
193  if ( mask[i] ){
194  result.push_back(*iter);
195  LogTrace(metname) << "Keep trajectory with pT = " << (*iter)->lastMeasurement().updatedState().globalMomentum().perp() << " GeV";
196  }
197  else delete *iter;
198  i++;
199  }
200 
201  trajC.clear();
202  trajC = result;
203 }
204 
205 //
206 // clean CandidateContainer
207 //
209  const std::string metname = "Muon|RecoMuon|MuonTrajectoryCleaner";
210 
211  LogTrace(metname) << "Muon Trajectory Cleaner called" << endl;
212 
213  if ( candC.size() < 2 ) return;
214 
215  CandidateContainer::iterator iter, jter;
216  Trajectory::DataContainer::const_iterator m1, m2;
217 
218  const float deltaEta = 0.01;
219  const float deltaPhi = 0.01;
220  const float deltaPt = 1.0;
221 
222  LogTrace(metname) << "Number of muon candidates in the container: " <<candC.size()<< endl;
223 
224  int i(0), j(0);
225  int match(0);
226  //unused bool directionMatch = false;
227 
228  // CAVEAT: vector<bool> is not a vector, its elements are not addressable!
229  // This is fine as long as only operator [] is used as in this case.
230  // cf. par 16.3.11
231  vector<bool> mask(candC.size(),true);
232 
234 
235  for ( iter = candC.begin(); iter != candC.end(); iter++ ) {
236  if ( !mask[i] ) { i++; continue; }
237  const Trajectory::DataContainer& meas1 = (*iter)->trajectory()->measurements();
238  j = i+1;
239  bool skipnext=false;
240 
241  TrajectoryStateOnSurface innerTSOS;
242 
243  if ((*iter)->trajectory()->direction() == alongMomentum) {
244  innerTSOS = (*iter)->trajectory()->firstMeasurement().updatedState();
245  }
246  else if ((*iter)->trajectory()->direction() == oppositeToMomentum) {
247  innerTSOS = (*iter)->trajectory()->lastMeasurement().updatedState();
248  }
249  if ( !(innerTSOS.isValid()) ) continue;
250  float pt1 = innerTSOS.globalMomentum().perp();
251  float eta1 = innerTSOS.globalMomentum().eta();
252  float phi1 = innerTSOS.globalMomentum().phi();
253 
254  for ( jter = iter+1; jter != candC.end(); jter++ ) {
255  if ( !mask[j] ) { j++; continue; }
256  //UNUSED: directionMatch = false;
257  const Trajectory::DataContainer& meas2 = (*jter)->trajectory()->measurements();
258  match = 0;
259  for ( m1 = meas1.begin(); m1 != meas1.end(); m1++ ) {
260  for ( m2 = meas2.begin(); m2 != meas2.end(); m2++ ) {
261  if ( (*m1).recHit()->isValid() && (*m2).recHit()->isValid() )
262  if ( ( (*m1).recHit()->globalPosition() - (*m2).recHit()->globalPosition()).mag()< 10e-5 ) match++;
263  }
264  }
265 
266  LogTrace(metname)
267  << " MuonTrajectoryCleaner: candC " << i << " chi2/nRH = "
268  << (*iter)->trajectory()->chiSquared() << "/" << (*iter)->trajectory()->foundHits() <<
269  " vs trajC " << j << " chi2/nRH = " << (*jter)->trajectory()->chiSquared() <<
270  "/" << (*jter)->trajectory()->foundHits() << " Shared RecHits: " << match;
271 
272  TrajectoryStateOnSurface innerTSOS2;
273  if ((*jter)->trajectory()->direction() == alongMomentum) {
274  innerTSOS2 = (*jter)->trajectory()->firstMeasurement().updatedState();
275  }
276  else if ((*jter)->trajectory()->direction() == oppositeToMomentum) {
277  innerTSOS2 = (*jter)->trajectory()->lastMeasurement().updatedState();
278  }
279  if ( !(innerTSOS2.isValid()) ) continue;
280 
281  float pt2 = innerTSOS2.globalMomentum().perp();
282  float eta2 = innerTSOS2.globalMomentum().eta();
283  float phi2 = innerTSOS2.globalMomentum().phi();
284 
285  float deta(fabs(eta1-eta2));
286  float dphi(fabs(Geom::Phi<float>(phi1)-Geom::Phi<float>(phi2)));
287  float dpt(fabs(pt1-pt2));
288  if ( dpt < deltaPt && deta < deltaEta && dphi < deltaPhi ) {
289  //UNUSED: directionMatch = true;
290  LogTrace(metname)
291  << " MuonTrajectoryCleaner: candC " << i<<" and "<<j<< " direction matched: "
292  <<innerTSOS.globalMomentum()<<" and " <<innerTSOS2.globalMomentum();
293  }
294 
295  // If there are matches, reject the worst track
296  bool hitsMatch = ((match > 0) && ((match/((*iter)->trajectory()->foundHits()) > 0.25) || (match/((*jter)->trajectory()->foundHits()) > 0.25))) ? true : false;
297  bool tracksMatch =
298  ( ( (*iter)->trackerTrack() == (*jter)->trackerTrack() ) &&
299  ( deltaR<double>((*iter)->muonTrack()->eta(),(*iter)->muonTrack()->phi(), (*jter)->muonTrack()->eta(),(*jter)->muonTrack()->phi()) < 0.2) );
300 
301  //if ( ( tracksMatch ) || (hitsMatch > 0) || directionMatch ) {
302  if ( ( tracksMatch ) || (hitsMatch > 0) ) {
303  if ( (*iter)->trajectory()->foundHits() == (*jter)->trajectory()->foundHits() ) {
304  if ( (*iter)->trajectory()->chiSquared() > (*jter)->trajectory()->chiSquared() ) {
305  mask[i] = false;
306  skipnext=true;
307  }
308  else mask[j] = false;
309  }
310  else { // different number of hits
311  if ( (*iter)->trajectory()->foundHits() < (*jter)->trajectory()->foundHits() ) {
312  mask[i] = false;
313  skipnext=true;
314  }
315  else mask[j] = false;
316  }
317  }
318  if(skipnext) break;
319  j++;
320  }
321  i++;
322  if(skipnext) continue;
323  }
324 
325  i = 0;
326  for ( iter = candC.begin(); iter != candC.end(); iter++ ) {
327  if ( mask[i] ) {
328  result.push_back(*iter);
329  } else {
330  delete (*iter)->trajectory();
331  delete (*iter)->trackerTrajectory();
332  delete *iter;
333  }
334  i++;
335  }
336 
337  candC.clear();
338  candC = result;
339 }
340 
int i
Definition: DBlmapReader.cc:9
void clean(TrajectoryContainer &muonTrajectories, edm::Event &evt, const edm::Handle< edm::View< TrajectorySeed > > &seeds)
Clean the trajectories container, erasing the (worst) clone trajectory.
T perp() const
Definition: PV3DBase.h:72
const std::string metname
T mag() const
The vector magnitude. Equivalent to sqrt(vec.mag2())
Geom::Phi< T > phi() const
Definition: PV3DBase.h:69
static const double deltaEta
Definition: CaloConstants.h:8
edm::AssociationMap< edm::OneToMany< L2MuonTrajectorySeedCollection, L2MuonTrajectorySeedCollection > > L2SeedAssoc
tuple result
Definition: mps_fire.py:84
std::vector< TrajectoryMeasurement > DataContainer
Definition: Trajectory.h:44
MuonCandidate::CandidateContainer CandidateContainer
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
int j
Definition: DBlmapReader.cc:9
#define end
Definition: vmac.h:37
How EventSelector::AcceptEvent() decides whether to accept an event for output otherwise it is excluding the probing of A single or multiple positive and the trigger will pass if any such matching triggers are PASS or EXCEPTION[A criterion thatmatches no triggers at all is detected and causes a throw.] A single negative with an expectation of appropriate bit checking in the decision and the trigger will pass if any such matching triggers are FAIL or EXCEPTION A wildcarded negative criterion that matches more than one trigger in the trigger but the state exists so we define the behavior If all triggers are the negative crieriion will lead to accepting the event(this again matches the behavior of"!*"before the partial wildcard feature was incorporated).The per-event"cost"of each negative criterion with multiple relevant triggers is about the same as!*was in the past
#define LogTrace(id)
MuonCandidate::TrajectoryContainer TrajectoryContainer
REF castTo() const
Definition: RefToBase.h:286
ProductID id() const
Accessor for product ID.
Definition: Ptr.h:181
T eta() const
Definition: PV3DBase.h:76
#define begin
Definition: vmac.h:30
GlobalVector globalMomentum() const
std::pair< typename Association::data_type::first_type, double > match(Reference key, Association association, bool bestMatchByMaxValue)
Generic matching function.
Definition: Utils.h:10