CMS 3D CMS Logo

CandCombinerBase.h

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

Generated on Tue Jun 9 17:41:02 2009 for CMSSW by  doxygen 1.5.4