CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
JetPartonMatching.cc
Go to the documentation of this file.
3 #include <Math/VectorUtil.h>
4 
5 JetPartonMatching::JetPartonMatching(const std::vector<const reco::Candidate*>& p,
6  const std::vector<reco::GenJet>& j,
7  const int algorithm = totalMinDist,
8  const bool useMaxDist = true,
9  const bool useDeltaR = true,
10  const double maxDist = 0.3)
11  : partons(p), algorithm_(algorithm), useMaxDist_(useMaxDist), useDeltaR_(useDeltaR), maxDist_(maxDist) {
12  std::vector<const reco::Candidate*> js;
13  for (unsigned int i = 0; i < j.size(); ++i)
14  js.push_back(&(j[i]));
15  jets = js;
16  calculate();
17 }
18 
19 JetPartonMatching::JetPartonMatching(const std::vector<const reco::Candidate*>& p,
20  const std::vector<reco::CaloJet>& j,
21  const int algorithm = totalMinDist,
22  const bool useMaxDist = true,
23  const bool useDeltaR = true,
24  const double maxDist = 0.3)
25  : partons(p), algorithm_(algorithm), useMaxDist_(useMaxDist), useDeltaR_(useDeltaR), maxDist_(maxDist) {
26  std::vector<const reco::Candidate*> js;
27  for (unsigned int i = 0; i < j.size(); ++i)
28  js.push_back(&(j[i]));
29  jets = js;
30  calculate();
31 }
32 
33 JetPartonMatching::JetPartonMatching(const std::vector<const reco::Candidate*>& p,
34  const std::vector<pat::Jet>& j,
35  const int algorithm = totalMinDist,
36  const bool useMaxDist = true,
37  const bool useDeltaR = true,
38  const double maxDist = 0.3)
39  : partons(p), algorithm_(algorithm), useMaxDist_(useMaxDist), useDeltaR_(useDeltaR), maxDist_(maxDist) {
40  std::vector<const reco::Candidate*> js;
41  for (unsigned int i = 0; i < j.size(); ++i)
42  js.push_back(&(j[i]));
43  jets = js;
44  calculate();
45 }
46 
47 JetPartonMatching::JetPartonMatching(const std::vector<const reco::Candidate*>& p,
48  const std::vector<const reco::Candidate*>& j,
49  const int algorithm = totalMinDist,
50  const bool useMaxDist = true,
51  const bool useDeltaR = true,
52  const double maxDist = 0.3)
53  : partons(p), jets(j), algorithm_(algorithm), useMaxDist_(useMaxDist), useDeltaR_(useDeltaR), maxDist_(maxDist) {
54  calculate();
55 }
56 
58  // use maximal distance between objects
59  // in case of unambiguousOnly algorithmm
61  useMaxDist_ = true;
62 
63  // check if there are empty partons in
64  // the vector, which happpens if the
65  // event is not ttbar or the decay is
66  // not as expected
67  bool emptyParton = false;
68  for (unsigned int ip = 0; ip < partons.size(); ++ip) {
69  if (partons[ip]->pdgId() == 0) {
70  emptyParton = true;
71  break;
72  }
73  }
74 
75  // switch algorithm, default is to match
76  // on the minimal sum of the distance
77  // (if jets or a parton is empty fill match with blanks)
78  if (jets.empty() || emptyParton) {
79  MatchingCollection dummyMatch;
80  for (unsigned int ip = 0; ip < partons.size(); ++ip)
81  dummyMatch.push_back(std::make_pair(ip, -1));
82  matching.push_back(dummyMatch);
83  } else {
84  switch (algorithm_) {
85  case totalMinDist:
87  break;
88 
89  case minSumDist:
91  break;
92 
93  case ptOrderedMinDist:
95  break;
96 
97  case unambiguousOnly:
99  break;
100 
101  default:
103  }
104  }
105 
106  numberOfUnmatchedPartons.clear();
107  sumDeltaE.clear();
108  sumDeltaPt.clear();
109  sumDeltaR.clear();
110  for (unsigned int comb = 0; comb < matching.size(); ++comb) {
112  std::sort(match.begin(), match.end());
113  matching[comb] = match;
114 
115  int nUnmatchedPartons = partons.size();
116  for (unsigned int part = 0; part < partons.size(); ++part)
117  if (getMatchForParton(part, comb) >= 0)
118  --nUnmatchedPartons;
119 
120  double sumDE = -999.;
121  double sumDPt = -999.;
122  double sumDR = -999.;
123  if (nUnmatchedPartons == 0) {
124  sumDE = 0;
125  sumDPt = 0;
126  sumDR = 0;
127  for (unsigned int i = 0; i < match.size(); ++i) {
128  sumDE += fabs(partons[match[i].first]->energy() - jets[match[i].second]->energy());
129  sumDPt += fabs(partons[match[i].first]->pt() - jets[match[i].second]->pt());
130  sumDR += distance(partons[match[i].first]->p4(), jets[match[i].second]->p4());
131  }
132  }
133 
134  numberOfUnmatchedPartons.push_back(nUnmatchedPartons);
135  sumDeltaE.push_back(sumDE);
136  sumDeltaPt.push_back(sumDPt);
137  sumDeltaR.push_back(sumDR);
138  }
139 }
140 
142  // calculate the distance between two lorentz vectors
143  // using DeltaR(eta, phi) or normal space angle(theta, phi)
144  if (useDeltaR_)
145  return ROOT::Math::VectorUtil::DeltaR(v1, v2);
146  return ROOT::Math::VectorUtil::Angle(v1, v2);
147 }
148 
150  // match parton to jet with shortest distance
151  // starting with the shortest distance available
152  // apply some outlier rejection if desired
153 
154  // prepare vector of pairs with distances between
155  // all partons to all jets in the input vectors
156  std::vector<std::pair<double, unsigned int> > distances;
157  for (unsigned int ip = 0; ip < partons.size(); ++ip) {
158  for (unsigned int ij = 0; ij < jets.size(); ++ij) {
159  double dist = distance(jets[ij]->p4(), partons[ip]->p4());
160  distances.push_back(std::pair<double, unsigned int>(dist, ip * jets.size() + ij));
161  }
162  }
163  std::sort(distances.begin(), distances.end());
164 
166 
167  while (match.size() < partons.size()) {
168  unsigned int partonIndex = distances[0].second / jets.size();
169  int jetIndex = distances[0].second - jets.size() * partonIndex;
170 
171  // use primitive outlier rejection if desired
172  if (useMaxDist_ && distances[0].first > maxDist_)
173  jetIndex = -1;
174 
175  // prevent underflow in case of too few jets
176  if (distances.empty())
177  match.push_back(std::make_pair(partonIndex, -1));
178  else
179  match.push_back(std::make_pair(partonIndex, jetIndex));
180 
181  // remove all values for the matched parton
182  // and the matched jet
183  for (unsigned int a = 0; a < distances.size(); ++a) {
184  unsigned int pIndex = distances[a].second / jets.size();
185  int jIndex = distances[a].second - jets.size() * pIndex;
186  if ((pIndex == partonIndex) || (jIndex == jetIndex)) {
187  distances.erase(distances.begin() + a, distances.begin() + a + 1);
188  --a;
189  }
190  }
191  }
192 
193  matching.clear();
194  matching.push_back(match);
195  return;
196 }
197 
198 void JetPartonMatching::minSumDist_recursion(const unsigned int ip,
199  std::vector<unsigned int>& jetIndices,
200  std::vector<bool>& usedJets,
201  std::vector<std::pair<double, MatchingCollection> >& distMatchVec) {
202  // build up jet combinations recursively
203  if (ip < partons.size()) {
204  for (unsigned int ij = 0; ij < jets.size(); ++ij) {
205  if (usedJets[ij])
206  continue;
207  usedJets[ij] = true;
208  jetIndices[ip] = ij;
209  minSumDist_recursion(ip + 1, jetIndices, usedJets, distMatchVec);
210  usedJets[ij] = false;
211  }
212  return;
213  }
214 
215  // calculate sumDist for each completed combination
216  double sumDist = 0;
218  for (unsigned int ip = 0; ip < partons.size(); ++ip) {
219  double dist = distance(partons[ip]->p4(), jets[jetIndices[ip]]->p4());
220  if (useMaxDist_ && dist > maxDist_)
221  return; // outlier rejection
222  sumDist += distance(partons[ip]->p4(), jets[jetIndices[ip]]->p4());
223  match.push_back(std::make_pair(ip, jetIndices[ip]));
224  }
225 
226  distMatchVec.push_back(std::make_pair(sumDist, match));
227  return;
228 }
229 
231  // match partons to jets with minimal sum of
232  // the distances between all partons and jets
233 
234  std::vector<std::pair<double, MatchingCollection> > distMatchVec;
235 
236  std::vector<bool> usedJets;
237  for (unsigned int i = 0; i < jets.size(); ++i) {
238  usedJets.push_back(false);
239  }
240 
241  std::vector<unsigned int> jetIndices;
242  jetIndices.reserve(partons.size());
243 
244  minSumDist_recursion(0, jetIndices, usedJets, distMatchVec);
245 
246  std::sort(distMatchVec.begin(), distMatchVec.end());
247 
248  matching.clear();
249 
250  if (distMatchVec.empty()) {
251  MatchingCollection dummyMatch;
252  for (unsigned int ip = 0; ip < partons.size(); ++ip)
253  dummyMatch.push_back(std::make_pair(ip, -1));
254  matching.push_back(dummyMatch);
255  } else
256  for (unsigned int i = 0; i < distMatchVec.size(); ++i)
257  matching.push_back(distMatchVec[i].second);
258 
259  return;
260 }
261 
263  // match partons to jets with minimal sum of
264  // the distances between all partons and jets
265  // order partons in pt first
266  std::vector<std::pair<double, unsigned int> > ptOrderedPartons;
267 
268  for (unsigned int ip = 0; ip < partons.size(); ++ip)
269  ptOrderedPartons.push_back(std::make_pair(partons[ip]->pt(), ip));
270 
271  std::sort(ptOrderedPartons.begin(), ptOrderedPartons.end());
272  std::reverse(ptOrderedPartons.begin(), ptOrderedPartons.end());
273 
274  std::vector<unsigned int> jetIndices;
275  for (unsigned int ij = 0; ij < jets.size(); ++ij)
276  jetIndices.push_back(ij);
277 
279 
280  for (unsigned int ip = 0; ip < ptOrderedPartons.size(); ++ip) {
281  double minDist = 999.;
282  int ijMin = -1;
283 
284  for (unsigned int ij = 0; ij < jetIndices.size(); ++ij) {
285  double dist = distance(partons[ptOrderedPartons[ip].second]->p4(), jets[jetIndices[ij]]->p4());
286  if (dist < minDist) {
287  if (!useMaxDist_ || dist <= maxDist_) {
288  minDist = dist;
289  ijMin = ij;
290  }
291  }
292  }
293 
294  if (ijMin >= 0) {
295  match.push_back(std::make_pair(ptOrderedPartons[ip].second, jetIndices[ijMin]));
296  jetIndices.erase(jetIndices.begin() + ijMin, jetIndices.begin() + ijMin + 1);
297  } else
298  match.push_back(std::make_pair(ptOrderedPartons[ip].second, -1));
299  }
300 
301  matching.clear();
302  matching.push_back(match);
303  return;
304 }
305 
307  // match partons to jets, only accept event
308  // if there are no ambiguities
309  std::vector<bool> jetMatched;
310  for (unsigned int ij = 0; ij < jets.size(); ++ij)
311  jetMatched.push_back(false);
312 
314 
315  for (unsigned int ip = 0; ip < partons.size(); ++ip) {
316  int iMatch = -1;
317  for (unsigned int ij = 0; ij < jets.size(); ++ij) {
318  double dist = distance(partons[ip]->p4(), jets[ij]->p4());
319  if (dist <= maxDist_) {
320  if (!jetMatched[ij]) { // new match for jet
321  jetMatched[ij] = true;
322  if (iMatch == -1) // new match for parton and jet
323  iMatch = ij;
324  else // parton already matched: ambiguity!
325  iMatch = -2;
326  } else // jet already matched: ambiguity!
327  iMatch = -2;
328  }
329  }
330  match.push_back(std::make_pair(ip, iMatch));
331  }
332 
333  matching.clear();
334  matching.push_back(match);
335  return;
336 }
337 
338 int JetPartonMatching::getMatchForParton(const unsigned int part, const unsigned int comb) {
339  // return index of the matched jet for a given parton
340  // (if arguments for parton index and combinatoric index
341  // are in the valid range)
342  if (comb >= matching.size())
343  return -9;
344  if (part >= matching[comb].size())
345  return -9;
346  return (matching[comb])[part].second;
347 }
348 
349 std::vector<int> JetPartonMatching::getMatchesForPartons(const unsigned int comb) {
350  // return a vector with the indices of the matched jets
351  // (ordered according to the vector of partons)
352  std::vector<int> jetIndices;
353  for (unsigned int part = 0; part < partons.size(); ++part)
354  jetIndices.push_back(getMatchForParton(part, comb));
355  return jetIndices;
356 }
357 
358 double JetPartonMatching::getDistanceForParton(const unsigned int part, const unsigned int comb) {
359  // get the distance between parton and its best matched jet
360  if (getMatchForParton(part, comb) < 0)
361  return -999.;
362  return distance(jets[getMatchForParton(part, comb)]->p4(), partons[part]->p4());
363 }
364 
365 double JetPartonMatching::getSumDistances(const unsigned int comb) {
366  // get sum of distances between partons and matched jets
367  double sumDists = 0.;
368  for (unsigned int part = 0; part < partons.size(); ++part) {
369  double dist = getDistanceForParton(part, comb);
370  if (dist < 0.)
371  return -999.;
372  sumDists += dist;
373  }
374  return sumDists;
375 }
376 
378  //report using MessageLogger
379  edm::LogInfo log("JetPartonMatching");
380  log << "++++++++++++++++++++++++++++++++++++++++++++++ \n";
381  log << " algorithm : ";
382  switch (algorithm_) {
383  case totalMinDist:
384  log << "totalMinDist ";
385  break;
386  case minSumDist:
387  log << "minSumDist ";
388  break;
389  case ptOrderedMinDist:
390  log << "ptOrderedMinDist";
391  break;
392  case unambiguousOnly:
393  log << "unambiguousOnly ";
394  break;
395  default:
396  log << "UNKNOWN ";
397  }
398  log << "\n";
399  log << " useDeltaR : " << std::boolalpha << useDeltaR_;
400  log << "\n";
401  log << " useMaxDist: " << std::boolalpha << useMaxDist_;
402  log << " maxDist: " << maxDist_ << "\n";
403  log << " number of partons / jets: " << partons.size() << " / " << jets.size() << "\n";
404  log << " number of available combinations: " << getNumberOfAvailableCombinations() << "\n";
405  for (unsigned int comb = 0; comb < matching.size(); ++comb) {
406  log << " -------------------------------------------- \n";
407  log << " ind. of matched jets:";
408  for (unsigned int part = 0; part < partons.size(); ++part)
409  log << std::setw(4) << getMatchForParton(part, comb);
410  log << "\n";
411  log << " sumDeltaR : " << getSumDeltaR(comb) << "\n";
412  log << " sumDeltaPt / sumDeltaE: " << getSumDeltaPt(comb) << " / " << getSumDeltaE(comb);
413  log << "\n";
414  }
415  log << "++++++++++++++++++++++++++++++++++++++++++++++";
416 }
std::vector< const reco::Candidate * > partons
static std::vector< std::string > checklist log
std::vector< double > sumDeltaE
unsigned int getNumberOfAvailableCombinations()
U second(std::pair< T, U > const &p)
XYZTLorentzVectorD XYZTLorentzVector
Lorentz vector with cylindrical internal representation using pseudorapidity.
Definition: LorentzVector.h:29
dictionary comb
vector< PseudoJet > jets
std::vector< int > getMatchesForPartons(const unsigned int comb=0)
double getSumDeltaE(const unsigned int comb=0)
std::vector< unsigned int > numberOfUnmatchedPartons
std::vector< std::pair< unsigned int, int > > MatchingCollection
part
Definition: HCALResponse.h:20
void minSumDist_recursion(const unsigned int, std::vector< unsigned int > &, std::vector< bool > &, std::vector< std::pair< double, MatchingCollection > > &)
int getMatchForParton(const unsigned int part, const unsigned int comb=0)
double distance(const math::XYZTLorentzVector &, const math::XYZTLorentzVector &)
std::vector< const reco::Candidate * > jets
std::vector< MatchingCollection > matching
std::vector< double > sumDeltaR
double a
Definition: hdecay.h:119
double getSumDeltaR(const unsigned int comb=0)
std::pair< typename Association::data_type::first_type, double > match(Reference key, Association association, bool bestMatchByMaxValue)
Generic matching function.
Definition: Utils.h:10
std::vector< double > sumDeltaPt
double getSumDistances(const unsigned int comb=0)
tuple size
Write out results.
double getSumDeltaPt(const unsigned int comb=0)
double getDistanceForParton(const unsigned int part, const unsigned int comb=0)