![]() |
![]() |
00001 #ifndef CommonTools_CandUtils_CandCombinerBase_h 00002 #define CommonTools_CandUtils_CandCombinerBase_h 00003 00008 #include "DataFormats/Candidate/interface/Candidate.h" 00009 #include "DataFormats/Candidate/interface/OverlapChecker.h" 00010 #include <vector> 00011 #include <string> 00012 00013 template<typename OutputCollection, typename CandPtr> 00014 class CandCombinerBase { 00015 public: 00016 typedef std::vector<std::string> vstring; 00018 explicit CandCombinerBase(const std::string = ""); 00020 CandCombinerBase(int, int, const std::string = ""); 00022 CandCombinerBase(int, int, int, const std::string = ""); 00024 CandCombinerBase(int, int, int, int, const std::string = ""); 00026 CandCombinerBase(bool checkCharge, bool checkOverlap, const std::vector <int> &, const std::string = ""); 00028 virtual ~CandCombinerBase(); 00030 std::auto_ptr<OutputCollection> 00031 combine(const std::vector<edm::Handle<reco::CandidateView> > &, const vstring = vstring()) const; 00033 std::auto_ptr<OutputCollection> 00034 combine(const edm::Handle<reco::CandidateView> &, const vstring = vstring()) const; 00036 std::auto_ptr<OutputCollection> 00037 combine(const edm::Handle<reco::CandidateView> &, 00038 const edm::Handle<reco::CandidateView> &, const vstring = vstring()) const; 00040 std::auto_ptr<OutputCollection> 00041 combine(const edm::Handle<reco::CandidateView> &, 00042 const edm::Handle<reco::CandidateView> &, 00043 const edm::Handle<reco::CandidateView> &, const vstring = vstring()) const; 00045 std::auto_ptr<OutputCollection> 00046 combine(const edm::Handle<reco::CandidateView> &, 00047 const edm::Handle<reco::CandidateView> &, 00048 const edm::Handle<reco::CandidateView> &, 00049 const edm::Handle<reco::CandidateView> &, const vstring = vstring()) const; 00050 00051 private: 00053 bool preselect(const reco::Candidate &, const reco::Candidate &) const; 00055 void combine(typename OutputCollection::value_type &, 00056 const CandPtr &, 00057 const CandPtr &, const std::string = "", const std::string = "") const; 00059 typedef std::vector<std::pair<std::pair<CandPtr, size_t>, 00060 std::vector<edm::Handle<reco::CandidateView> >::const_iterator> > CandStack; 00061 typedef std::vector<int> ChargeStack; 00063 void combine(size_t collectionIndex, CandStack &, ChargeStack &, 00064 std::vector<edm::Handle<reco::CandidateView> >::const_iterator begin, 00065 std::vector<edm::Handle<reco::CandidateView> >::const_iterator end, 00066 std::auto_ptr<OutputCollection> & comps, 00067 const vstring name = vstring()) const; 00069 virtual bool select(const reco::Candidate &) const = 0; 00071 virtual bool selectPair(const reco::Candidate & c1, const reco::Candidate & c2) const = 0; 00073 virtual void setup(typename OutputCollection::value_type &) const = 0; 00075 virtual void addDaughter(typename OutputCollection::value_type & cmp, const CandPtr & c, const std::string = "") const = 0; 00077 bool checkCharge_; 00079 bool checkOverlap_; 00081 std::vector<int> dauCharge_; 00083 OverlapChecker overlap_; 00085 std::string name_; 00086 }; 00087 00088 template<typename OutputCollection, typename CandPtr> 00089 CandCombinerBase<OutputCollection, CandPtr>::CandCombinerBase(const std::string name) : 00090 checkCharge_(false), checkOverlap_(true), dauCharge_(), overlap_(), name_(name) { 00091 } 00092 00093 template<typename OutputCollection, typename CandPtr> 00094 CandCombinerBase<OutputCollection, CandPtr>::CandCombinerBase(int q1, int q2, const std::string name) : 00095 checkCharge_(true), checkOverlap_(true), dauCharge_(2), overlap_(), name_(name) { 00096 dauCharge_[0] = q1; 00097 dauCharge_[1] = q2; 00098 } 00099 00100 template<typename OutputCollection, typename CandPtr> 00101 CandCombinerBase<OutputCollection, CandPtr>::CandCombinerBase(int q1, int q2, int q3, const std::string name) : 00102 checkCharge_(true), checkOverlap_(true), dauCharge_(3), overlap_(), name_(name) { 00103 dauCharge_[0] = q1; 00104 dauCharge_[1] = q2; 00105 dauCharge_[2] = q3; 00106 } 00107 00108 template<typename OutputCollection, typename CandPtr> 00109 CandCombinerBase<OutputCollection, CandPtr>::CandCombinerBase(int q1, int q2, int q3, int q4, const std::string name) : 00110 checkCharge_(true), checkOverlap_(true), dauCharge_(4), overlap_(), name_(name) { 00111 dauCharge_[0] = q1; 00112 dauCharge_[1] = q2; 00113 dauCharge_[2] = q3; 00114 dauCharge_[3] = q4; 00115 } 00116 00117 template<typename OutputCollection, typename CandPtr> 00118 CandCombinerBase<OutputCollection, CandPtr>::CandCombinerBase(bool checkCharge, bool checkOverlap, const std::vector<int> & dauCharge, const std::string name) : 00119 checkCharge_(checkCharge), checkOverlap_(checkOverlap), dauCharge_(dauCharge), overlap_(), name_(name) { 00120 } 00121 00122 template<typename OutputCollection, typename CandPtr> 00123 CandCombinerBase<OutputCollection, CandPtr>::~CandCombinerBase() { 00124 } 00125 00126 template<typename OutputCollection, typename CandPtr> 00127 bool CandCombinerBase<OutputCollection, CandPtr>::preselect(const reco::Candidate & c1, const reco::Candidate & c2) const { 00128 if (checkCharge_) { 00129 int dq1 = dauCharge_[0], dq2 = dauCharge_[1], q1 = c1.charge(), q2 = c2.charge(); 00130 bool matchCharge = (q1 == dq1 && q2 == dq2) || (q1 == -dq1 && q2 == -dq2); 00131 if (!matchCharge) return false; 00132 } 00133 if (checkOverlap_ && overlap_(c1, c2)) return false; 00134 return selectPair(c1, c2); 00135 } 00136 00137 template<typename OutputCollection, typename CandPtr> 00138 void CandCombinerBase<OutputCollection, CandPtr>::combine(typename OutputCollection::value_type & cmp, 00139 const CandPtr & c1, const CandPtr & c2, 00140 const std::string name1, const std::string name2) const { 00141 addDaughter(cmp, c1, name1); 00142 addDaughter(cmp, c2, name2); 00143 setup(cmp); 00144 } 00145 00146 template<typename OutputCollection, typename CandPtr> 00147 std::auto_ptr<OutputCollection> 00148 CandCombinerBase<OutputCollection, CandPtr>::combine(const std::vector<edm::Handle<reco::CandidateView> > & src, 00149 const vstring names) const { 00150 size_t srcSize = src.size(); 00151 if (checkCharge_ && dauCharge_.size() != srcSize) 00152 throw edm::Exception(edm::errors::Configuration) 00153 << "CandCombiner: trying to combine " << srcSize << " collections" 00154 << " but configured to check against " << dauCharge_.size() << " charges."; 00155 std::auto_ptr<OutputCollection> comps(new OutputCollection); 00156 size_t namesSize = names.size(); 00157 if(srcSize == 2) { 00158 std::string name1="", name2=""; 00159 if(namesSize > 0) { 00160 if(namesSize != 2) 00161 throw edm::Exception(edm::errors::Configuration) 00162 << "CandCombiner: should specify exactly two " 00163 << " names in configuration (" << namesSize << " specified).\n"; 00164 name1 = names[0]; 00165 name2 = names[1]; 00166 } 00167 edm::Handle<reco::CandidateView> src1 = src[0], src2 = src[1]; 00168 if(src1.id() == src2.id()) { 00169 const reco::CandidateView & cands = * src1; 00170 const size_t n = cands.size(); 00171 for(size_t i1 = 0; i1 < n; ++i1) { 00172 const reco::Candidate & c1 = cands[i1]; 00173 CandPtr cr1(src1, i1); 00174 for(size_t i2 = i1 + 1; i2 < n; ++i2) { 00175 const reco::Candidate & c2 = cands[i2]; 00176 if(preselect(c1, c2)) { 00177 CandPtr cr2(src2, i2); 00178 typename OutputCollection::value_type c; 00179 combine(c, cr1, cr2, name1, name2); 00180 if(select(c)) 00181 comps->push_back(c); 00182 } 00183 } 00184 } 00185 } else { 00186 const reco::CandidateView & cands1 = * src1, & cands2 = * src2; 00187 const size_t n1 = cands1.size(), n2 = cands2.size(); 00188 for(size_t i1 = 0; i1 < n1; ++i1) { 00189 const reco::Candidate & c1 = cands1[i1]; 00190 CandPtr cr1(src1, i1); 00191 for(size_t i2 = 0; i2 < n2; ++i2) { 00192 const reco::Candidate & c2 = cands2[i2]; 00193 if(preselect(c1, c2)) { 00194 CandPtr cr2(src2, i2); 00195 typename OutputCollection::value_type c; 00196 combine(c, cr1, cr2, name1, name2); 00197 if(select(c)) 00198 comps->push_back(c); 00199 } 00200 } 00201 } 00202 } 00203 } else { 00204 CandStack stack; 00205 ChargeStack qStack; 00206 combine(0, stack, qStack, src.begin(), src.end(), comps, names); 00207 } 00208 00209 return comps; 00210 } 00211 00212 template<typename OutputCollection, typename CandPtr> 00213 std::auto_ptr<OutputCollection> 00214 CandCombinerBase<OutputCollection, CandPtr>::combine(const edm::Handle<reco::CandidateView> & src, 00215 const vstring names) const { 00216 if(checkCharge_ && dauCharge_.size() != 2) 00217 throw edm::Exception(edm::errors::Configuration) 00218 << "CandCombiner: trying to combine 2 collections" 00219 << " but configured to check against " << dauCharge_.size() << " charges."; 00220 00221 std::auto_ptr<OutputCollection> comps(new OutputCollection); 00222 size_t namesSize = names.size(); 00223 std::string name1, name2; 00224 if(namesSize > 0) { 00225 if(namesSize != 2) 00226 throw edm::Exception(edm::errors::Configuration) 00227 << "CandCombiner: should specify exactly two " 00228 << " names in configuration (" << namesSize << " specified).\n"; 00229 name1 = names[0]; 00230 name2 = names[1]; 00231 } 00232 const reco::CandidateView & cands = * src; 00233 const size_t n = cands.size(); 00234 for(size_t i1 = 0; i1 < n; ++i1) { 00235 const reco::Candidate & c1 = cands[i1]; 00236 CandPtr cr1(src, i1); 00237 for(size_t i2 = i1 + 1; i2 < n; ++i2) { 00238 const reco::Candidate & c2 = cands[i2]; 00239 if(preselect(c1, c2)) { 00240 CandPtr cr2(src, i2); 00241 typename OutputCollection::value_type c; 00242 combine(c, cr1, cr2, name1, name2); 00243 if(select(c)) 00244 comps->push_back(c); 00245 } 00246 } 00247 } 00248 00249 return comps; 00250 } 00251 00252 template<typename OutputCollection, typename CandPtr> 00253 std::auto_ptr<OutputCollection> 00254 CandCombinerBase<OutputCollection, CandPtr>::combine(const edm::Handle<reco::CandidateView> & src1, 00255 const edm::Handle<reco::CandidateView> & src2, 00256 const vstring names) const { 00257 std::vector<edm::Handle<reco::CandidateView> > src; 00258 src.push_back(src1); 00259 src.push_back(src2); 00260 return combine(src, names); 00261 } 00262 00263 template<typename OutputCollection, typename CandPtr> 00264 std::auto_ptr<OutputCollection> 00265 CandCombinerBase<OutputCollection, CandPtr>::combine(const edm::Handle<reco::CandidateView> & src1, 00266 const edm::Handle<reco::CandidateView> & src2, 00267 const edm::Handle<reco::CandidateView> & src3, 00268 const vstring names) const { 00269 std::vector<edm::Handle<reco::CandidateView> > src; 00270 src.push_back(src1); 00271 src.push_back(src2); 00272 src.push_back(src3); 00273 return combine(src, names); 00274 } 00275 00276 template<typename OutputCollection, typename CandPtr> 00277 std::auto_ptr<OutputCollection> 00278 CandCombinerBase<OutputCollection, CandPtr>::combine(const edm::Handle<reco::CandidateView> & src1, 00279 const edm::Handle<reco::CandidateView> & src2, 00280 const edm::Handle<reco::CandidateView> & src3, 00281 const edm::Handle<reco::CandidateView> & src4, 00282 const vstring names) const { 00283 std::vector<edm::Handle<reco::CandidateView> > src; 00284 src.push_back(src1); 00285 src.push_back(src2); 00286 src.push_back(src3); 00287 src.push_back(src4); 00288 return combine(src, names); 00289 } 00290 00291 template<typename OutputCollection, typename CandPtr> 00292 void CandCombinerBase<OutputCollection, CandPtr>::combine(size_t collectionIndex, CandStack & stack, ChargeStack & qStack, 00293 std::vector<edm::Handle<reco::CandidateView> >::const_iterator collBegin, 00294 std::vector<edm::Handle<reco::CandidateView> >::const_iterator collEnd, 00295 std::auto_ptr<OutputCollection> & comps, 00296 const vstring names) const { 00297 if(collBegin == collEnd) { 00298 static const int undetermined = 0, sameDecay = 1, conjDecay = -1, wrongDecay = 2; 00299 int decayType = undetermined; 00300 if(checkCharge_) { 00301 assert(qStack.size() == stack.size()); 00302 for(size_t i = 0; i < qStack.size(); ++i) { 00303 int q = qStack[i], dq = dauCharge_[i]; 00304 if(decayType == undetermined) { 00305 if(q != 0 && dq != 0) { 00306 if(q == dq) decayType = sameDecay; 00307 else if(q == -dq) decayType = conjDecay; 00308 else decayType = wrongDecay; 00309 } 00310 } else if((decayType == sameDecay && q != dq) || 00311 (decayType == conjDecay && q != -dq)) { 00312 decayType = wrongDecay; 00313 } 00314 if(decayType == wrongDecay) break; 00315 } 00316 } 00317 if(decayType != wrongDecay) { 00318 typename OutputCollection::value_type c; 00319 size_t nameIndex = 0; 00320 for(typename CandStack::const_iterator i = stack.begin(); i != stack.end(); ++i, ++ nameIndex) { 00321 if ( names.size() > 0 ) 00322 addDaughter(c, i->first.first, names[nameIndex]); 00323 else 00324 addDaughter(c, i->first.first); 00325 } 00326 setup(c); 00327 if(select(c)) 00328 comps->push_back(c); 00329 } 00330 } else { 00331 const edm::Handle<reco::CandidateView> & srcRef = * collBegin; 00332 const reco::CandidateView & src = * srcRef; 00333 size_t candBegin = 0, candEnd = src.size(); 00334 for(typename CandStack::const_iterator i = stack.begin(); i != stack.end(); ++i) 00335 if(srcRef.id() == i->second->id()) 00336 candBegin = i->first.second + 1; 00337 for(size_t candIndex = candBegin; candIndex != candEnd; ++ candIndex) { 00338 CandPtr candRef(srcRef, candIndex); 00339 bool noOverlap = true; 00340 const reco::Candidate & cand = * candRef; 00341 for(typename CandStack::const_iterator i = stack.begin(); i != stack.end(); ++i) 00342 if(checkOverlap_ && overlap_(cand, *(i->first.first))) { 00343 noOverlap = false; 00344 break; 00345 } 00346 if(noOverlap) { 00347 stack.push_back(std::make_pair(std::make_pair(candRef, candIndex), collBegin)); 00348 if(checkCharge_) qStack.push_back(cand.charge()); 00349 combine(collectionIndex + 1, stack, qStack, collBegin + 1, collEnd, comps, names); 00350 stack.pop_back(); 00351 qStack.pop_back(); 00352 } 00353 } 00354 } 00355 } 00356 00357 #endif