00001 #include "TopQuarkAnalysis/TopTools/interface/JetPartonMatching.h"
00002 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00003 #include <Math/VectorUtil.h>
00004
00005 JetPartonMatching::JetPartonMatching(const std::vector<const reco::Candidate*>& p, const std::vector<reco::GenJet>& j,
00006 const int algorithm = totalMinDist, const bool useMaxDist = true,
00007 const bool useDeltaR = true, const double maxDist = 0.3)
00008 : partons(p), algorithm_(algorithm), useMaxDist_(useMaxDist), useDeltaR_(useDeltaR), maxDist_(maxDist)
00009 {
00010 std::vector<const reco::Candidate*> js;
00011 for(unsigned int i=0; i<j.size(); ++i) js.push_back( &(j[i]) );
00012 jets = js;
00013 calculate();
00014 }
00015
00016 JetPartonMatching::JetPartonMatching(const std::vector<const reco::Candidate*>& p, const std::vector<reco::CaloJet>& j,
00017 const int algorithm = totalMinDist, const bool useMaxDist = true,
00018 const bool useDeltaR = true, const double maxDist = 0.3)
00019 : partons(p), algorithm_(algorithm), useMaxDist_(useMaxDist), useDeltaR_(useDeltaR), maxDist_(maxDist)
00020 {
00021 std::vector<const reco::Candidate*> js;
00022 for(unsigned int i = 0; i < j.size(); ++i) js.push_back( &(j[i]) );
00023 jets = js;
00024 calculate();
00025 }
00026
00027 JetPartonMatching::JetPartonMatching(const std::vector<const reco::Candidate*>& p, const std::vector<pat::Jet>& j,
00028 const int algorithm = totalMinDist, const bool useMaxDist = true,
00029 const bool useDeltaR = true, const double maxDist = 0.3)
00030 : partons(p), algorithm_(algorithm), useMaxDist_(useMaxDist), useDeltaR_(useDeltaR), maxDist_(maxDist)
00031 {
00032 std::vector<const reco::Candidate*> js;
00033 for(unsigned int i = 0; i < j.size(); ++i) js.push_back( &(j[i]) );
00034 jets = js;
00035 calculate();
00036 }
00037
00038 JetPartonMatching::JetPartonMatching(const std::vector<const reco::Candidate*>& p, const std::vector<const reco::Candidate*>& j,
00039 const int algorithm = totalMinDist, const bool useMaxDist = true,
00040 const bool useDeltaR = true, const double maxDist = 0.3)
00041 : partons(p), jets(j), algorithm_(algorithm), useMaxDist_(useMaxDist), useDeltaR_(useDeltaR), maxDist_(maxDist)
00042 {
00043 calculate();
00044 }
00045
00046 void
00047 JetPartonMatching::calculate()
00048 {
00049
00050
00051 if(algorithm_==unambiguousOnly) useMaxDist_=true;
00052
00053
00054
00055
00056
00057 bool emptyParton=false;
00058 for(unsigned int ip=0; ip<partons.size(); ++ip){
00059 if( partons[ip]->pdgId() ==0 ){
00060 emptyParton=true;
00061 break;
00062 }
00063 }
00064
00065
00066
00067
00068 if( jets.empty() || emptyParton ) {
00069 MatchingCollection dummyMatch;
00070 for(unsigned int ip=0; ip<partons.size(); ++ip)
00071 dummyMatch.push_back( std::make_pair(ip, -1) );
00072 matching.push_back( dummyMatch );
00073 }
00074 else {
00075 switch(algorithm_) {
00076
00077 case totalMinDist:
00078 matchingTotalMinDist();
00079 break;
00080
00081 case minSumDist:
00082 matchingMinSumDist();
00083 break;
00084
00085 case ptOrderedMinDist:
00086 matchingPtOrderedMinDist();
00087 break;
00088
00089 case unambiguousOnly:
00090 matchingUnambiguousOnly();
00091 break;
00092
00093 default:
00094 matchingMinSumDist();
00095 }
00096 }
00097
00098 numberOfUnmatchedPartons.clear();
00099 sumDeltaE .clear();
00100 sumDeltaPt.clear();
00101 sumDeltaR .clear();
00102 for(unsigned int comb = 0; comb < matching.size(); ++comb) {
00103 MatchingCollection match = matching[comb];
00104 std::sort(match.begin(), match.end());
00105 matching[comb] = match;
00106
00107 int nUnmatchedPartons = partons.size();
00108 for(unsigned int part=0; part<partons.size(); ++part)
00109 if(getMatchForParton(part,comb)>=0) --nUnmatchedPartons;
00110
00111 double sumDE = -999.;
00112 double sumDPt = -999.;
00113 double sumDR = -999.;
00114 if(nUnmatchedPartons==0){
00115 sumDE = 0;
00116 sumDPt = 0;
00117 sumDR = 0;
00118 for(unsigned int i=0; i<match.size(); ++i){
00119 sumDE += fabs(partons[match[i].first]->energy() - jets[match[i].second]->energy());
00120 sumDPt += fabs(partons[match[i].first]->pt() - jets[match[i].second]->pt());
00121 sumDR += distance(partons[match[i].first]->p4(), jets[match[i].second]->p4());
00122 }
00123 }
00124
00125 numberOfUnmatchedPartons.push_back( nUnmatchedPartons );
00126 sumDeltaE .push_back( sumDE );
00127 sumDeltaPt.push_back( sumDPt );
00128 sumDeltaR .push_back( sumDR );
00129 }
00130 }
00131
00132 double
00133 JetPartonMatching::distance(const math::XYZTLorentzVector& v1, const math::XYZTLorentzVector& v2)
00134 {
00135
00136
00137 if(useDeltaR_) return ROOT::Math::VectorUtil::DeltaR(v1, v2);
00138 return ROOT::Math::VectorUtil::Angle(v1, v2);
00139 }
00140
00141 void
00142 JetPartonMatching::matchingTotalMinDist()
00143 {
00144
00145
00146
00147
00148
00149
00150 std::vector< std::pair<double, unsigned int> > distances;
00151 for(unsigned int ip=0; ip<partons.size(); ++ip){
00152 for(unsigned int ij=0; ij<jets.size(); ++ij){
00153 double dist = distance(jets[ij]->p4(), partons[ip]->p4());
00154 distances.push_back(std::pair<double, unsigned int>(dist, ip*jets.size()+ij));
00155 }
00156 }
00157 std::sort(distances.begin(), distances.end());
00158
00159 MatchingCollection match;
00160
00161 while(match.size() < partons.size()){
00162 unsigned int partonIndex = distances[0].second/jets.size();
00163 int jetIndex = distances[0].second-jets.size()*partonIndex;
00164
00165
00166 if(useMaxDist_&& distances[0].first>maxDist_) jetIndex = -1;
00167
00168
00169 if( distances.empty() )
00170 match.push_back(std::make_pair(partonIndex, -1));
00171 else
00172 match.push_back(std::make_pair(partonIndex, jetIndex));
00173
00174
00175
00176 for(unsigned int a=0; a<distances.size(); ++a){
00177 unsigned int pIndex = distances[a].second/jets.size();
00178 int jIndex = distances[a].second-jets.size()*pIndex;
00179 if((pIndex == partonIndex) || (jIndex == jetIndex)){
00180 distances.erase(distances.begin()+a, distances.begin()+a+1);
00181 --a;
00182 }
00183 }
00184 }
00185
00186 matching.clear();
00187 matching.push_back( match );
00188 return;
00189 }
00190
00191 void
00192 JetPartonMatching::minSumDist_recursion(const unsigned int ip, std::vector<unsigned int> & jetIndices,
00193 std::vector<bool> & usedJets, std::vector<std::pair<double, MatchingCollection> > & distMatchVec)
00194 {
00195
00196 if(ip<partons.size()){
00197 for(unsigned int ij=0; ij<jets.size(); ++ij){
00198 if(usedJets[ij]) continue;
00199 usedJets[ij] = true;
00200 jetIndices[ip] = ij;
00201 minSumDist_recursion(ip+1, jetIndices, usedJets, distMatchVec);
00202 usedJets[ij] = false;
00203 }
00204 return;
00205 }
00206
00207
00208 double sumDist = 0;
00209 MatchingCollection match;
00210 for(unsigned int ip=0; ip<partons.size(); ++ip){
00211 double dist = distance(partons[ip]->p4(), jets[jetIndices[ip]]->p4());
00212 if(useMaxDist_ && dist > maxDist_) return;
00213 sumDist += distance(partons[ip]->p4(), jets[jetIndices[ip]]->p4());
00214 match.push_back(std::make_pair(ip, jetIndices[ip]));
00215 }
00216
00217 distMatchVec.push_back( std::make_pair(sumDist, match) );
00218 return;
00219 }
00220
00221 void JetPartonMatching::matchingMinSumDist()
00222 {
00223
00224
00225
00226 std::vector<std::pair<double, MatchingCollection> > distMatchVec;
00227
00228 std::vector<bool> usedJets;
00229 for(unsigned int i=0; i<jets.size(); ++i){
00230 usedJets.push_back(false);
00231 }
00232
00233 std::vector<unsigned int> jetIndices;
00234 jetIndices.reserve(partons.size());
00235
00236 minSumDist_recursion(0, jetIndices, usedJets, distMatchVec);
00237
00238 std::sort(distMatchVec.begin(), distMatchVec.end());
00239
00240 matching.clear();
00241 for(unsigned int i=0; i<distMatchVec.size(); ++i)
00242 matching.push_back( distMatchVec[i].second );
00243 return;
00244 }
00245
00246 void
00247 JetPartonMatching::matchingPtOrderedMinDist()
00248 {
00249
00250
00251
00252 std::vector<std::pair <double, unsigned int> > ptOrderedPartons;
00253
00254 for(unsigned int ip=0; ip<partons.size(); ++ip)
00255 ptOrderedPartons.push_back(std::make_pair(partons[ip]->pt(), ip));
00256
00257 std::sort(ptOrderedPartons.begin(), ptOrderedPartons.end());
00258 std::reverse(ptOrderedPartons.begin(), ptOrderedPartons.end());
00259
00260 std::vector<unsigned int> jetIndices;
00261 for(unsigned int ij=0; ij<jets.size(); ++ij) jetIndices.push_back(ij);
00262
00263 MatchingCollection match;
00264
00265 for(unsigned int ip=0; ip<ptOrderedPartons.size(); ++ip){
00266 double minDist = 999.;
00267 int ijMin = -1;
00268
00269 for(unsigned int ij=0; ij<jetIndices.size(); ++ij){
00270 double dist = distance(partons[ptOrderedPartons[ip].second]->p4(), jets[jetIndices[ij]]->p4());
00271 if(dist < minDist){
00272 if(!useMaxDist_ || dist <= maxDist_){
00273 minDist = dist;
00274 ijMin = ij;
00275 }
00276 }
00277 }
00278
00279 if(ijMin >= 0){
00280 match.push_back( std::make_pair(ptOrderedPartons[ip].second, jetIndices[ijMin]) );
00281 jetIndices.erase(jetIndices.begin() + ijMin, jetIndices.begin() + ijMin + 1);
00282 }
00283 else
00284 match.push_back( std::make_pair(ptOrderedPartons[ip].second, -1) );
00285 }
00286
00287 matching.clear();
00288 matching.push_back( match );
00289 return;
00290 }
00291
00292 void
00293 JetPartonMatching::matchingUnambiguousOnly()
00294 {
00295
00296
00297 std::vector<bool> jetMatched;
00298 for(unsigned int ij=0; ij<jets.size(); ++ij) jetMatched.push_back(false);
00299
00300 MatchingCollection match;
00301
00302 for(unsigned int ip=0; ip<partons.size(); ++ip){
00303 int iMatch = -1;
00304 for(unsigned int ij=0; ij<jets.size(); ++ij){
00305 double dist = distance(partons[ip]->p4(), jets[ij]->p4());
00306 if(dist <= maxDist_){
00307 if(!jetMatched[ij]){
00308 jetMatched[ij] = true;
00309 if(iMatch == -1)
00310 iMatch = ij;
00311 else
00312 iMatch = -2;
00313 }
00314 else
00315 iMatch = -2;
00316 }
00317 }
00318 match.push_back(std::make_pair(ip, iMatch));
00319 }
00320
00321 matching.clear();
00322 matching.push_back( match );
00323 return;
00324 }
00325
00326 int
00327 JetPartonMatching::getMatchForParton(const unsigned int part, const unsigned int comb)
00328 {
00329
00330
00331
00332 if(comb >= matching.size()) return -9;
00333 if(part >= matching[comb].size()) return -9;
00334 return (matching[comb])[part].second;
00335 }
00336
00337 std::vector<int>
00338 JetPartonMatching::getMatchesForPartons(const unsigned int comb)
00339 {
00340
00341
00342 std::vector<int> jetIndices;
00343 for(unsigned int part=0; part<partons.size(); ++part)
00344 jetIndices.push_back( getMatchForParton(part, comb) );
00345 return jetIndices;
00346 }
00347
00348 double
00349 JetPartonMatching::getDistanceForParton(const unsigned int part, const unsigned int comb)
00350 {
00351
00352 if(getMatchForParton(part, comb) < 0) return -999.;
00353 return distance( jets[getMatchForParton(part,comb)]->p4(), partons[part]->p4() );
00354 }
00355
00356 double
00357 JetPartonMatching::getSumDistances(const unsigned int comb)
00358 {
00359
00360 double sumDists = 0.;
00361 for(unsigned int part=0; part<partons.size(); ++part){
00362 double dist = getDistanceForParton(part, comb);
00363 if(dist < 0.) return -999.;
00364 sumDists += dist;
00365 }
00366 return sumDists;
00367 }
00368
00369 void
00370 JetPartonMatching::print()
00371 {
00372
00373 edm::LogInfo log("JetPartonMatching");
00374 log << "++++++++++++++++++++++++++++++++++++++++++++++ \n";
00375 log << " algorithm : ";
00376 switch(algorithm_) {
00377 case totalMinDist : log << "totalMinDist "; break;
00378 case minSumDist : log << "minSumDist "; break;
00379 case ptOrderedMinDist : log << "ptOrderedMinDist"; break;
00380 case unambiguousOnly : log << "unambiguousOnly "; break;
00381 default : log << "UNKNOWN ";
00382 }
00383 log << "\n";
00384 log << " useDeltaR : ";
00385 switch(useDeltaR_) {
00386 case false : log << "false"; break;
00387 case true : log << "true ";
00388 }
00389 log << "\n";
00390 log << " useMaxDist: ";
00391 switch(useMaxDist_) {
00392 case false : log << "false"; break;
00393 case true : log << "true ";
00394 }
00395 log << " maxDist: " << maxDist_ << "\n";
00396 log << " number of partons / jets: " << partons.size() << " / " << jets.size() << "\n";
00397 log << " number of available combinations: " << getNumberOfAvailableCombinations() << "\n";
00398 for(unsigned int comb = 0; comb < matching.size(); ++comb) {
00399 log << " -------------------------------------------- \n";
00400 log << " ind. of matched jets:";
00401 for(unsigned int part = 0; part < partons.size(); ++part)
00402 log << std::setw(4) << getMatchForParton(part, comb);
00403 log << "\n";
00404 log << " sumDeltaR : " << getSumDeltaR(comb) << "\n";
00405 log << " sumDeltaPt / sumDeltaE: " << getSumDeltaPt(comb) << " / " << getSumDeltaE(comb);
00406 log << "\n";
00407 }
00408 log << "++++++++++++++++++++++++++++++++++++++++++++++";
00409 }