CMS 3D CMS Logo

/data/doxygen/doxygen-1.7.3/gen/CMSSW_4_2_8/src/CommonTools/CandUtils/interface/CandCombinerBase.h

Go to the documentation of this file.
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