CMS 3D CMS Logo

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.empty() ) 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  // FIXME Set Boff/on via cfg!
64  double chi2_dof_i = (*iter)->ndof() > 0 ? (*iter)->chiSquared()/(*iter)->ndof() : (*iter)->chiSquared()/1e-10;
65  double chi2_dof_j = (*jter)->ndof() > 0 ? (*jter)->chiSquared()/(*jter)->ndof() : (*jter)->chiSquared()/1e-10;
66 
67  LogTrace(metname) << " MuonTrajectoryCleaner:";
68  LogTrace(metname) << " * trajC " << i
69  << " (pT="<<(*iter)->lastMeasurement().updatedState().globalMomentum().perp()
70  << " GeV) - chi2/nDOF = " << (*iter)->chiSquared() << "/" << (*iter)->ndof() << " = " << chi2_dof_i;
71  LogTrace(metname) << " - valid RH = " << (*iter)->foundHits() << " / total RH = " << (*iter)->measurements().size();
72  LogTrace(metname) << " * trajC " << j
73  << " (pT="<<(*jter)->lastMeasurement().updatedState().globalMomentum().perp()
74  << " GeV) - chi2/nDOF = " << (*jter)->chiSquared() << "/" << (*jter)->ndof() << " = " << chi2_dof_j;
75  LogTrace(metname) << " - valid RH = " << (*jter)->foundHits() << " / total RH = " << (*jter)->measurements().size();
76  LogTrace(metname) << " *** Shared RecHits: " << match;
77 
78  int hit_diff = (*iter)->foundHits() - (*jter)->foundHits() ;
79  // If there are matches, reject the worst track
80  if ( match > 0 ) {
81  // If the difference in # of rechits is null then compare the chi2/ndf of the two trajectories
82  if ( abs(hit_diff) == 0 ) {
83 
84  double minPt = 3.5;
85  double dPt = 7.; // i.e. considering 10% (conservative!) resolution at minPt it is ~ 10 sigma away from the central value
86 
87  double maxFraction = 0.95;
88 
89  double fraction = (2.*match)/((*iter)->measurements().size()+(*jter)->measurements().size());
90  int belowLimit = 0;
91  int above = 0;
92 
93  if((*jter)->lastMeasurement().updatedState().globalMomentum().perp() <= minPt) ++belowLimit;
94  if((*iter)->lastMeasurement().updatedState().globalMomentum().perp() <= minPt) ++belowLimit;
95 
96  if((*jter)->lastMeasurement().updatedState().globalMomentum().perp() >= dPt) ++above;
97  if((*iter)->lastMeasurement().updatedState().globalMomentum().perp() >= dPt) ++above;
98 
99 
100  if(fraction >= maxFraction && belowLimit == 1 && above == 1){
101  if((*iter)->lastMeasurement().updatedState().globalMomentum().perp() < minPt){
102  mask[i] = false;
103  skipnext=true;
104  seedmap[j].insert(seedmap[j].end(), seedmap[i].begin(), seedmap[i].end());
105  seedmap.erase(i);
106  LogTrace(metname) << "Trajectory # " << i << " (pT="<<(*iter)->lastMeasurement().updatedState().globalMomentum().perp()
107  << " GeV) rejected because it has too low pt";
108  }
109  else {
110  mask[j] = false;
111  seedmap[i].insert(seedmap[i].end(), seedmap[j].begin(), seedmap[j].end());
112  seedmap.erase(j);
113  LogTrace(metname) << "Trajectory # " << j << " (pT="<<(*jter)->lastMeasurement().updatedState().globalMomentum().perp()
114  << " GeV) rejected because it has too low pt";
115  }
116  }
117  else{
118  if (chi2_dof_i > chi2_dof_j) {
119  mask[i] = false;
120  skipnext=true;
121  seedmap[j].insert(seedmap[j].end(), seedmap[i].begin(), seedmap[i].end());
122  seedmap.erase(i);
123  LogTrace(metname) << "Trajectory # " << i << " (pT="<<(*iter)->lastMeasurement().updatedState().globalMomentum().perp() << " GeV) rejected";
124  }
125  else{
126  mask[j] = false;
127  seedmap[i].insert(seedmap[i].end(), seedmap[j].begin(), seedmap[j].end());
128  seedmap.erase(j);
129  LogTrace(metname) << "Trajectory # " << j << " (pT="<<(*jter)->lastMeasurement().updatedState().globalMomentum().perp() << " GeV) rejected";
130  }
131  }
132  }
133  else { // different number of hits
134  if ( hit_diff < 0 ) {
135  mask[i] = false;
136  skipnext=true;
137  seedmap[j].insert(seedmap[j].end(), seedmap[i].begin(), seedmap[i].end());
138  seedmap.erase(i);
139  LogTrace(metname) << "Trajectory # " << i << " (pT="<<(*iter)->lastMeasurement().updatedState().globalMomentum().perp() << " GeV) rejected";
140  }
141  else {
142  mask[j] = false;
143  seedmap[i].insert(seedmap[i].end(), seedmap[j].begin(), seedmap[j].end());
144  seedmap.erase(j);
145  LogTrace(metname) << "Trajectory # " << j << " (pT="<<(*jter)->lastMeasurement().updatedState().globalMomentum().perp() << " GeV) rejected";
146  }
147  }
148  }
149  if(skipnext) break;
150  j++;
151  }
152  i++;
153  if(skipnext) continue;
154  }
155 
156 
157  // Association map between the seed of the chosen trajectory and the seeds of the discarded trajectories
158  if(reportGhosts_) {
159  LogTrace(metname) << " Creating map between chosen seed and ghost seeds." << std::endl;
160 
161  auto seedToSeedsMap = std::make_unique<L2SeedAssoc>();
162  if(!seeds->empty()) {
163  edm::Ptr<TrajectorySeed> ptr = seeds->ptrAt(0);
165  event.get(ptr.id(), seedsHandle);
166  seedToSeedsMap = std::make_unique<L2SeedAssoc>(seedsHandle, seedsHandle);
167  }
168 
169  int seedcnt(0);
170 
171  for(map<int, vector<int> >::iterator itmap=seedmap.begin(); itmap!=seedmap.end(); ++itmap, ++seedcnt) {
172  edm::RefToBase<TrajectorySeed> tmpSeedRef1 = trajC[(*itmap).first]->seedRef();
174 
175  int tmpsize=(*itmap).second.size();
176  for(int cnt=0; cnt!=tmpsize; ++cnt) {
177  edm::RefToBase<TrajectorySeed> tmpSeedRef2 = trajC[(*itmap).second[cnt]]->seedRef();
179  seedToSeedsMap->insert(tmpL2SeedRef1, tmpL2SeedRef2);
180  }
181  }
182 
183  event.put(std::move(seedToSeedsMap), "");
184 
185  } // end if(reportGhosts_)
186 
187  i = 0;
188  for ( iter = trajC.begin(); iter != trajC.end(); iter++ ) {
189  if ( mask[i] ){
190  result.push_back(*iter);
191  LogTrace(metname) << "Keep trajectory with pT = " << (*iter)->lastMeasurement().updatedState().globalMomentum().perp() << " GeV";
192  }
193  else delete *iter;
194  i++;
195  }
196 
197  trajC.clear();
198  trajC = result;
199 }
200 
201 //
202 // clean CandidateContainer
203 //
205  const std::string metname = "Muon|RecoMuon|MuonTrajectoryCleaner";
206 
207  LogTrace(metname) << "Muon Trajectory Cleaner called" << endl;
208 
209  if ( candC.size() < 2 ) return;
210 
211  CandidateContainer::iterator iter, jter;
212  Trajectory::DataContainer::const_iterator m1, m2;
213 
214  const float deltaEta = 0.01;
215  const float deltaPhi = 0.01;
216  const float deltaPt = 1.0;
217 
218  LogTrace(metname) << "Number of muon candidates in the container: " <<candC.size()<< endl;
219 
220  int i(0), j(0);
221  int match(0);
222  //unused bool directionMatch = false;
223 
224  // CAVEAT: vector<bool> is not a vector, its elements are not addressable!
225  // This is fine as long as only operator [] is used as in this case.
226  // cf. par 16.3.11
227  vector<bool> mask(candC.size(),true);
228 
230 
231  for ( iter = candC.begin(); iter != candC.end(); iter++ ) {
232  if ( !mask[i] ) { i++; continue; }
233  const Trajectory::DataContainer& meas1 = (*iter)->trajectory()->measurements();
234  j = i+1;
235  bool skipnext=false;
236 
237  TrajectoryStateOnSurface innerTSOS;
238 
239  if ((*iter)->trajectory()->direction() == alongMomentum) {
240  innerTSOS = (*iter)->trajectory()->firstMeasurement().updatedState();
241  }
242  else if ((*iter)->trajectory()->direction() == oppositeToMomentum) {
243  innerTSOS = (*iter)->trajectory()->lastMeasurement().updatedState();
244  }
245  if ( !(innerTSOS.isValid()) ) continue;
246  float pt1 = innerTSOS.globalMomentum().perp();
247  float eta1 = innerTSOS.globalMomentum().eta();
248  float phi1 = innerTSOS.globalMomentum().phi();
249 
250  for ( jter = iter+1; jter != candC.end(); jter++ ) {
251  if ( !mask[j] ) { j++; continue; }
252  //UNUSED: directionMatch = false;
253  const Trajectory::DataContainer& meas2 = (*jter)->trajectory()->measurements();
254  match = 0;
255  for ( m1 = meas1.begin(); m1 != meas1.end(); m1++ ) {
256  for ( m2 = meas2.begin(); m2 != meas2.end(); m2++ ) {
257  if ( (*m1).recHit()->isValid() && (*m2).recHit()->isValid() )
258  if ( ( (*m1).recHit()->globalPosition() - (*m2).recHit()->globalPosition()).mag()< 10e-5 ) match++;
259  }
260  }
261 
262  LogTrace(metname)
263  << " MuonTrajectoryCleaner: candC " << i << " chi2/nRH = "
264  << (*iter)->trajectory()->chiSquared() << "/" << (*iter)->trajectory()->foundHits() <<
265  " vs trajC " << j << " chi2/nRH = " << (*jter)->trajectory()->chiSquared() <<
266  "/" << (*jter)->trajectory()->foundHits() << " Shared RecHits: " << match;
267 
268  TrajectoryStateOnSurface innerTSOS2;
269  if ((*jter)->trajectory()->direction() == alongMomentum) {
270  innerTSOS2 = (*jter)->trajectory()->firstMeasurement().updatedState();
271  }
272  else if ((*jter)->trajectory()->direction() == oppositeToMomentum) {
273  innerTSOS2 = (*jter)->trajectory()->lastMeasurement().updatedState();
274  }
275  if ( !(innerTSOS2.isValid()) ) continue;
276 
277  float pt2 = innerTSOS2.globalMomentum().perp();
278  float eta2 = innerTSOS2.globalMomentum().eta();
279  float phi2 = innerTSOS2.globalMomentum().phi();
280 
281  float deta(fabs(eta1-eta2));
282  float dphi(fabs(Geom::Phi<float>(phi1)-Geom::Phi<float>(phi2)));
283  float dpt(fabs(pt1-pt2));
284  if ( dpt < deltaPt && deta < deltaEta && dphi < deltaPhi ) {
285  //UNUSED: directionMatch = true;
286  LogTrace(metname)
287  << " MuonTrajectoryCleaner: candC " << i<<" and "<<j<< " direction matched: "
288  <<innerTSOS.globalMomentum()<<" and " <<innerTSOS2.globalMomentum();
289  }
290 
291  // If there are matches, reject the worst track
292  bool hitsMatch = ((match > 0) && ((match/((*iter)->trajectory()->foundHits()) > 0.25) || (match/((*jter)->trajectory()->foundHits()) > 0.25))) ? true : false;
293  bool tracksMatch =
294  ( ( (*iter)->trackerTrack() == (*jter)->trackerTrack() ) &&
295  ( deltaR<double>((*iter)->muonTrack()->eta(),(*iter)->muonTrack()->phi(), (*jter)->muonTrack()->eta(),(*jter)->muonTrack()->phi()) < 0.2) );
296 
297  //if ( ( tracksMatch ) || (hitsMatch > 0) || directionMatch ) {
298  if ( ( tracksMatch ) || (hitsMatch > 0) ) {
299  if ( (*iter)->trajectory()->foundHits() == (*jter)->trajectory()->foundHits() ) {
300  if ( (*iter)->trajectory()->chiSquared() > (*jter)->trajectory()->chiSquared() ) {
301  mask[i] = false;
302  skipnext=true;
303  }
304  else mask[j] = false;
305  }
306  else { // different number of hits
307  if ( (*iter)->trajectory()->foundHits() < (*jter)->trajectory()->foundHits() ) {
308  mask[i] = false;
309  skipnext=true;
310  }
311  else mask[j] = false;
312  }
313  }
314  if(skipnext) break;
315  j++;
316  }
317  i++;
318  if(skipnext) continue;
319  }
320 
321  i = 0;
322  for ( iter = candC.begin(); iter != candC.end(); iter++ ) {
323  if ( mask[i] ) {
324  result.push_back(*iter);
325  } else {
326  delete (*iter)->trajectory();
327  delete (*iter)->trackerTrajectory();
328  delete *iter;
329  }
330  i++;
331  }
332 
333  candC.clear();
334  candC = result;
335 }
336 
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
std::vector< TrajectoryMeasurement > DataContainer
Definition: Trajectory.h:44
MuonCandidate::CandidateContainer CandidateContainer
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
#define end
Definition: vmac.h:39
#define LogTrace(id)
MuonCandidate::TrajectoryContainer TrajectoryContainer
REF castTo() const
Definition: RefToBase.h:286
ProductID id() const
Accessor for product ID.
Definition: Ptr.h:180
T eta() const
Definition: PV3DBase.h:76
#define begin
Definition: vmac.h:32
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
def move(src, dest)
Definition: eostools.py:510
Definition: event.py:1