00001 #include "PhysicsTools/CandUtils/interface/NamedCandCombinerBase.h" 00002 #include <utility> 00003 using namespace std; 00004 using namespace reco; 00005 00006 NamedCandCombinerBase::NamedCandCombinerBase(std::string name) : 00007 checkCharge_(false), dauCharge_(), overlap_(), name_(name) { 00008 } 00009 00010 NamedCandCombinerBase::NamedCandCombinerBase(std::string name, int q1, int q2) : 00011 checkCharge_(true), dauCharge_(2), overlap_(), name_(name) { 00012 dauCharge_[0] = q1; 00013 dauCharge_[1] = q2; 00014 } 00015 00016 NamedCandCombinerBase::NamedCandCombinerBase(std::string name, int q1, int q2, int q3) : 00017 checkCharge_(true), dauCharge_(3), overlap_(), name_(name) { 00018 dauCharge_[0] = q1; 00019 dauCharge_[1] = q2; 00020 dauCharge_[2] = q3; 00021 } 00022 00023 NamedCandCombinerBase::NamedCandCombinerBase(std::string name, int q1, int q2, int q3, int q4) : 00024 checkCharge_(true), dauCharge_(4), overlap_(), name_(name) { 00025 dauCharge_[0] = q1; 00026 dauCharge_[1] = q2; 00027 dauCharge_[2] = q3; 00028 dauCharge_[3] = q4; 00029 } 00030 00031 NamedCandCombinerBase::NamedCandCombinerBase(std::string name, bool checkCharge, const vector<int> & dauCharge) : 00032 checkCharge_(checkCharge), dauCharge_(dauCharge), overlap_() { 00033 } 00034 00035 NamedCandCombinerBase::~NamedCandCombinerBase() { 00036 } 00037 00038 bool NamedCandCombinerBase::preselect(const Candidate & c1, const Candidate & c2) const { 00039 if (checkCharge_) { 00040 int dq1 = dauCharge_[0], dq2 = dauCharge_[1], q1 = c1.charge(), q2 = c2.charge(); 00041 bool matchCharge = (q1 == dq1 && q2 == dq2) || (q1 == -dq1 && q2 == -dq2); 00042 if (!matchCharge) return false; 00043 } 00044 if (overlap_(c1, c2)) return false; 00045 return selectPair(c1, c2); 00046 } 00047 00048 void NamedCandCombinerBase::combine(NamedCompositeCandidate & cmp, const CandidatePtr & c1, const CandidatePtr & c2, 00049 std::string n1, std::string n2 ) const { 00050 addDaughter(cmp, c1, n1); 00051 addDaughter(cmp, c2, n2); 00052 setup(cmp); 00053 } 00054 00055 auto_ptr<NamedCompositeCandidateCollection> 00056 NamedCandCombinerBase::combine(const vector<CandidatePtrVector> & src, 00057 string_coll const & names) const { 00058 size_t srcSize = src.size(); 00059 if (checkCharge_ && dauCharge_.size() != srcSize) 00060 throw edm::Exception(edm::errors::Configuration) 00061 << "NamedCandCombiner: trying to combine " << srcSize << " collections" 00062 << " but configured to check against " << dauCharge_.size() << " charges."; 00063 00064 if ( names.size() < 2 ) 00065 throw edm::Exception(edm::errors::Configuration) 00066 << "NamedCandCombiner: need to add 2 names, but size is " << names.size(); 00067 00068 auto_ptr<NamedCompositeCandidateCollection> comps(new NamedCompositeCandidateCollection); 00069 if(srcSize == 2) { 00070 CandidatePtrVector src1 = src[0], src2 = src[1]; 00071 if(src1 == src2) { 00072 const int n = src1.size(); 00073 for(int i1 = 0; i1 < n; ++i1) { 00074 const Candidate & c1 = *(src1[i1]); 00075 for(int i2 = i1 + 1; i2 < n; ++i2) { 00076 const Candidate & c2 = *(src1[i2]); 00077 if (preselect(c1, c2)) { 00078 NamedCompositeCandidate c; 00079 combine(c, src1[i1], src1[i2], names[0], names[1]); 00080 if(select(c)) 00081 comps->push_back(c); 00082 } 00083 } 00084 } 00085 } else { 00086 const int n1 = src1.size(), n2 = src2.size(); 00087 for(int i1 = 0; i1 < n1; ++i1) { 00088 const Candidate & c1 = *(src1[i1]); 00089 for(int i2 = 0; i2 < n2; ++i2) { 00090 const Candidate & c2 = *(src2[i2]); 00091 if(preselect(c1, c2)) { 00092 NamedCompositeCandidate c; 00093 combine(c, src1[i1], src2[i2], names[0], names[1]); 00094 if(select(c)) 00095 comps->push_back(c); 00096 } 00097 } 00098 } 00099 } 00100 } else { 00101 CandStack stack; 00102 ChargeStack qStack; 00103 combine(0, stack, qStack, names, src.begin(), src.end(), comps); 00104 } 00105 00106 return comps; 00107 } 00108 00109 auto_ptr<NamedCompositeCandidateCollection> 00110 NamedCandCombinerBase::combine(const CandidatePtrVector & src, string_coll const & names) const { 00111 if(checkCharge_ && dauCharge_.size() != 2) 00112 throw edm::Exception(edm::errors::Configuration) 00113 << "NamedCandCombiner: trying to combine 2 collections" 00114 << " but configured to check against " << dauCharge_.size() << " charges."; 00115 00116 if ( names.size() < 2 ) 00117 throw edm::Exception(edm::errors::Configuration) 00118 << "NamedCandCombiner: need to add 2 names, but size is " << names.size(); 00119 00120 auto_ptr<NamedCompositeCandidateCollection> comps(new NamedCompositeCandidateCollection); 00121 const int n = src.size(); 00122 for(int i1 = 0; i1 < n; ++i1) { 00123 const Candidate & c1 = *(src[i1]); 00124 for(int i2 = i1 + 1; i2 < n; ++i2) { 00125 const Candidate & c2 = *(src[i2]); 00126 if(preselect(c1, c2)) { 00127 NamedCompositeCandidate c; 00128 combine(c, src[i1], src[i2], names[0], names[1]); 00129 if(select(c)) 00130 comps->push_back(c); 00131 } 00132 } 00133 } 00134 00135 return comps; 00136 } 00137 00138 auto_ptr<NamedCompositeCandidateCollection> 00139 NamedCandCombinerBase::combine(const CandidatePtrVector & src1, const CandidatePtrVector & src2, string_coll const & names) const { 00140 vector<CandidatePtrVector> src; 00141 src.push_back(src1); 00142 src.push_back(src2); 00143 return combine(src, names); 00144 } 00145 00146 auto_ptr<NamedCompositeCandidateCollection> 00147 NamedCandCombinerBase::combine(const CandidatePtrVector & src1, const CandidatePtrVector & src2, const CandidatePtrVector & src3, 00148 string_coll const & names) const { 00149 vector<CandidatePtrVector> src; 00150 src.push_back(src1); 00151 src.push_back(src2); 00152 src.push_back(src3); 00153 return combine(src, names); 00154 } 00155 00156 auto_ptr<NamedCompositeCandidateCollection> 00157 NamedCandCombinerBase::combine(const CandidatePtrVector & src1, const CandidatePtrVector & src2, 00158 const CandidatePtrVector & src3, const CandidatePtrVector & src4, 00159 string_coll const & names) const { 00160 vector<CandidatePtrVector> src; 00161 src.push_back(src1); 00162 src.push_back(src2); 00163 src.push_back(src3); 00164 src.push_back(src4); 00165 return combine(src, names); 00166 } 00167 00168 void NamedCandCombinerBase::combine(size_t collectionIndex, CandStack & stack, ChargeStack & qStack, 00169 string_coll const & names, 00170 vector<CandidatePtrVector>::const_iterator collBegin, 00171 vector<CandidatePtrVector>::const_iterator collEnd, 00172 auto_ptr<NamedCompositeCandidateCollection> & comps) const { 00173 if(collBegin == collEnd) { 00174 static const int undetermined = 0, sameDecay = 1, conjDecay = -1, wrongDecay = 2; 00175 int decayType = undetermined; 00176 if(checkCharge_) { 00177 assert(qStack.size() == stack.size()); 00178 for(size_t i = 0; i < qStack.size(); ++i) { 00179 int q = qStack[i], dq = dauCharge_[i]; 00180 if(decayType == undetermined) { 00181 if(q != 0 && dq != 0) { 00182 if(q == dq) decayType = sameDecay; 00183 else if(q == -dq) decayType = conjDecay; 00184 else decayType = wrongDecay; 00185 } 00186 } else if((decayType == sameDecay && q != dq) || 00187 (decayType == conjDecay && q != -dq)) { 00188 decayType = wrongDecay; 00189 } 00190 if(decayType == wrongDecay) break; 00191 } 00192 } 00193 if(decayType != wrongDecay) { 00194 NamedCompositeCandidate c; 00195 int ii = 0; 00196 for(CandStack::const_iterator i = stack.begin(); i != stack.end(); ++i, ++ii) { 00197 addDaughter(c, i->first.first, names[ii]); 00198 } 00199 setup(c); 00200 if(select(c)) 00201 comps->push_back(c); 00202 } 00203 } else { 00204 const CandidatePtrVector & src = * collBegin; 00205 size_t candBegin = 0, candEnd = src.size(); 00206 for(CandStack::const_iterator i = stack.begin(); i != stack.end(); ++i) 00207 if(src == * i->second) 00208 candBegin = i->first.second + 1; 00209 for(size_t candIndex = candBegin; candIndex != candEnd; ++ candIndex) { 00210 const CandidatePtr & candPtr(src[candIndex]); 00211 00212 bool noOverlap = true; 00213 const Candidate & cand = *candPtr; 00214 for(CandStack::const_iterator i = stack.begin(); i != stack.end(); ++i) 00215 if(overlap_(cand, *(i->first.first))) { 00216 noOverlap = false; 00217 break; 00218 } 00219 if(noOverlap) { 00220 stack.push_back(make_pair(make_pair(candPtr, candIndex), collBegin)); 00221 if(checkCharge_) qStack.push_back(cand.charge()); 00222 combine(collectionIndex + 1, stack, qStack, names, collBegin + 1, collEnd, comps); 00223 stack.pop_back(); 00224 qStack.pop_back(); 00225 } 00226 } 00227 } 00228 }