Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:01:03

0001 #ifndef CommonTools_CandUtils_CandCombinerBase_h
0002 #define CommonTools_CandUtils_CandCombinerBase_h
0003 /** \class CandCombinerBase

0004  *

0005  * \author Luca Lista, INFN

0006  *

0007  */
0008 #include "DataFormats/Candidate/interface/Candidate.h"
0009 #include "DataFormats/Candidate/interface/OverlapChecker.h"
0010 #include <vector>
0011 #include <string>
0012 
0013 template <typename OutputCollection, typename CandPtr>
0014 class CandCombinerBase {
0015 public:
0016   typedef std::vector<std::string> vstring;
0017   /// default construct

0018   explicit CandCombinerBase(const std::string = "");
0019   /// construct from two charge values

0020   CandCombinerBase(int, int, const std::string = "");
0021   /// construct from three charge values

0022   CandCombinerBase(int, int, int, const std::string = "");
0023   /// construct from four charge values

0024   CandCombinerBase(int, int, int, int, const std::string = "");
0025   /// constructor from a selector, specifying optionally to check for charge

0026   CandCombinerBase(bool checkCharge, bool checkOverlap, const std::vector<int> &, const std::string = "");
0027   /// destructor

0028   virtual ~CandCombinerBase();
0029   /// return all selected candidate pairs

0030   std::unique_ptr<OutputCollection> combine(const std::vector<edm::Handle<reco::CandidateView> > &,
0031                                             const vstring & = vstring()) const;
0032   /// return all selected candidate pairs

0033   std::unique_ptr<OutputCollection> combine(const edm::Handle<reco::CandidateView> &,
0034                                             const vstring & = vstring()) const;
0035   /// return all selected candidate pairs

0036   std::unique_ptr<OutputCollection> combine(const edm::Handle<reco::CandidateView> &,
0037                                             const edm::Handle<reco::CandidateView> &,
0038                                             const vstring & = vstring()) const;
0039   /// return all selected candidate pairs

0040   std::unique_ptr<OutputCollection> combine(const edm::Handle<reco::CandidateView> &,
0041                                             const edm::Handle<reco::CandidateView> &,
0042                                             const edm::Handle<reco::CandidateView> &,
0043                                             const vstring & = vstring()) const;
0044   /// return all selected candidate pairs

0045   std::unique_ptr<OutputCollection> combine(const edm::Handle<reco::CandidateView> &,
0046                                             const edm::Handle<reco::CandidateView> &,
0047                                             const edm::Handle<reco::CandidateView> &,
0048                                             const edm::Handle<reco::CandidateView> &,
0049                                             const vstring & = vstring()) const;
0050 
0051 private:
0052   /// verify that the two candidate don't overlap and check charge

0053   bool preselect(const reco::Candidate &, const reco::Candidate &) const;
0054   /// returns a composite candidate combined from two daughters

0055   void combine(typename OutputCollection::value_type &,
0056                const CandPtr &,
0057                const CandPtr &,
0058                const std::string = "",
0059                const std::string = "") const;
0060   /// temporary candidate stack

0061   typedef std::vector<
0062       std::pair<std::pair<CandPtr, size_t>, std::vector<edm::Handle<reco::CandidateView> >::const_iterator> >
0063       CandStack;
0064   typedef std::vector<int> ChargeStack;
0065   /// returns a composite candidate combined from two daughters

0066   void combine(size_t collectionIndex,
0067                CandStack &,
0068                ChargeStack &,
0069                std::vector<edm::Handle<reco::CandidateView> >::const_iterator begin,
0070                std::vector<edm::Handle<reco::CandidateView> >::const_iterator end,
0071                OutputCollection *comps,
0072                const vstring &name = vstring()) const;
0073   /// select a candidate

0074   virtual bool select(const reco::Candidate &) const = 0;
0075   /// select a candidate pair

0076   virtual bool selectPair(const reco::Candidate &c1, const reco::Candidate &c2) const = 0;
0077   /// set kinematics to reconstructed composite

0078   virtual void setup(typename OutputCollection::value_type &) const = 0;
0079   /// add candidate daughter

0080   virtual void addDaughter(typename OutputCollection::value_type &cmp,
0081                            const CandPtr &c,
0082                            const std::string = "") const = 0;
0083   /// flag to specify the checking of electric charge

0084   bool checkCharge_;
0085   /// flag to specify the checking of overlaps

0086   bool checkOverlap_;
0087   /// electric charges of the daughters

0088   std::vector<int> dauCharge_;
0089   /// utility to check candidate daughters overlap

0090   OverlapChecker overlap_;
0091   /// composite name (if applies)

0092   std::string name_;
0093 };
0094 
0095 template <typename OutputCollection, typename CandPtr>
0096 CandCombinerBase<OutputCollection, CandPtr>::CandCombinerBase(const std::string name)
0097     : checkCharge_(false), checkOverlap_(true), dauCharge_(), overlap_(), name_(name) {}
0098 
0099 template <typename OutputCollection, typename CandPtr>
0100 CandCombinerBase<OutputCollection, CandPtr>::CandCombinerBase(int q1, int q2, const std::string name)
0101     : checkCharge_(true), checkOverlap_(true), dauCharge_(2), overlap_(), name_(name) {
0102   dauCharge_[0] = q1;
0103   dauCharge_[1] = q2;
0104 }
0105 
0106 template <typename OutputCollection, typename CandPtr>
0107 CandCombinerBase<OutputCollection, CandPtr>::CandCombinerBase(int q1, int q2, int q3, const std::string name)
0108     : checkCharge_(true), checkOverlap_(true), dauCharge_(3), overlap_(), name_(name) {
0109   dauCharge_[0] = q1;
0110   dauCharge_[1] = q2;
0111   dauCharge_[2] = q3;
0112 }
0113 
0114 template <typename OutputCollection, typename CandPtr>
0115 CandCombinerBase<OutputCollection, CandPtr>::CandCombinerBase(int q1, int q2, int q3, int q4, const std::string name)
0116     : checkCharge_(true), checkOverlap_(true), dauCharge_(4), overlap_(), name_(name) {
0117   dauCharge_[0] = q1;
0118   dauCharge_[1] = q2;
0119   dauCharge_[2] = q3;
0120   dauCharge_[3] = q4;
0121 }
0122 
0123 template <typename OutputCollection, typename CandPtr>
0124 CandCombinerBase<OutputCollection, CandPtr>::CandCombinerBase(bool checkCharge,
0125                                                               bool checkOverlap,
0126                                                               const std::vector<int> &dauCharge,
0127                                                               const std::string name)
0128     : checkCharge_(checkCharge), checkOverlap_(checkOverlap), dauCharge_(dauCharge), overlap_(), name_(name) {}
0129 
0130 template <typename OutputCollection, typename CandPtr>
0131 CandCombinerBase<OutputCollection, CandPtr>::~CandCombinerBase() {}
0132 
0133 template <typename OutputCollection, typename CandPtr>
0134 bool CandCombinerBase<OutputCollection, CandPtr>::preselect(const reco::Candidate &c1,
0135                                                             const reco::Candidate &c2) const {
0136   if (checkCharge_) {
0137     int dq1 = dauCharge_[0], dq2 = dauCharge_[1], q1 = c1.charge(), q2 = c2.charge();
0138     bool matchCharge = (q1 == dq1 && q2 == dq2) || (q1 == -dq1 && q2 == -dq2);
0139     if (!matchCharge)
0140       return false;
0141   }
0142   if (checkOverlap_ && overlap_(c1, c2))
0143     return false;
0144   return selectPair(c1, c2);
0145 }
0146 
0147 template <typename OutputCollection, typename CandPtr>
0148 void CandCombinerBase<OutputCollection, CandPtr>::combine(typename OutputCollection::value_type &cmp,
0149                                                           const CandPtr &c1,
0150                                                           const CandPtr &c2,
0151                                                           const std::string name1,
0152                                                           const std::string name2) const {
0153   addDaughter(cmp, c1, name1);
0154   addDaughter(cmp, c2, name2);
0155   setup(cmp);
0156 }
0157 
0158 template <typename OutputCollection, typename CandPtr>
0159 std::unique_ptr<OutputCollection> CandCombinerBase<OutputCollection, CandPtr>::combine(
0160     const std::vector<edm::Handle<reco::CandidateView> > &src, const vstring &names) const {
0161   size_t srcSize = src.size();
0162   if (checkCharge_ && dauCharge_.size() != srcSize)
0163     throw edm::Exception(edm::errors::Configuration)
0164         << "CandCombiner: trying to combine " << srcSize << " collections"
0165         << " but configured to check against " << dauCharge_.size() << " charges.";
0166   std::unique_ptr<OutputCollection> comps(new OutputCollection);
0167   size_t namesSize = names.size();
0168   if (srcSize == 2) {
0169     std::string name1 = "", name2 = "";
0170     if (namesSize > 0) {
0171       if (namesSize != 2)
0172         throw edm::Exception(edm::errors::Configuration)
0173             << "CandCombiner: should specify exactly two "
0174             << " names in configuration (" << namesSize << " specified).\n";
0175       name1 = names[0];
0176       name2 = names[1];
0177     }
0178     edm::Handle<reco::CandidateView> src1 = src[0], src2 = src[1];
0179     if (src1.id() == src2.id()) {
0180       const reco::CandidateView &cands = *src1;
0181       const size_t n = cands.size();
0182       for (size_t i1 = 0; i1 < n; ++i1) {
0183         const reco::Candidate &c1 = cands[i1];
0184         CandPtr cr1(src1, i1);
0185         for (size_t i2 = i1 + 1; i2 < n; ++i2) {
0186           const reco::Candidate &c2 = cands[i2];
0187           if (preselect(c1, c2)) {
0188             CandPtr cr2(src2, i2);
0189             typename OutputCollection::value_type c;
0190             combine(c, cr1, cr2, name1, name2);
0191             if (select(c))
0192               comps->push_back(c);
0193           }
0194         }
0195       }
0196     } else {
0197       const reco::CandidateView &cands1 = *src1, &cands2 = *src2;
0198       const size_t n1 = cands1.size(), n2 = cands2.size();
0199       for (size_t i1 = 0; i1 < n1; ++i1) {
0200         const reco::Candidate &c1 = cands1[i1];
0201         CandPtr cr1(src1, i1);
0202         for (size_t i2 = 0; i2 < n2; ++i2) {
0203           const reco::Candidate &c2 = cands2[i2];
0204           if (preselect(c1, c2)) {
0205             CandPtr cr2(src2, i2);
0206             typename OutputCollection::value_type c;
0207             combine(c, cr1, cr2, name1, name2);
0208             if (select(c))
0209               comps->push_back(c);
0210           }
0211         }
0212       }
0213     }
0214   } else {
0215     CandStack stack;
0216     ChargeStack qStack;
0217     combine(0, stack, qStack, src.begin(), src.end(), comps.get(), names);
0218   }
0219 
0220   return comps;
0221 }
0222 
0223 template <typename OutputCollection, typename CandPtr>
0224 std::unique_ptr<OutputCollection> CandCombinerBase<OutputCollection, CandPtr>::combine(
0225     const edm::Handle<reco::CandidateView> &src, const vstring &names) const {
0226   if (checkCharge_ && dauCharge_.size() != 2)
0227     throw edm::Exception(edm::errors::Configuration)
0228         << "CandCombiner: trying to combine 2 collections"
0229         << " but configured to check against " << dauCharge_.size() << " charges.";
0230 
0231   std::unique_ptr<OutputCollection> comps(new OutputCollection);
0232   size_t namesSize = names.size();
0233   std::string name1, name2;
0234   if (namesSize > 0) {
0235     if (namesSize != 2)
0236       throw edm::Exception(edm::errors::Configuration) << "CandCombiner: should specify exactly two "
0237                                                        << " names in configuration (" << namesSize << " specified).\n";
0238     name1 = names[0];
0239     name2 = names[1];
0240   }
0241   const reco::CandidateView &cands = *src;
0242   const size_t n = cands.size();
0243   for (size_t i1 = 0; i1 < n; ++i1) {
0244     const reco::Candidate &c1 = cands[i1];
0245     CandPtr cr1(src, i1);
0246     for (size_t i2 = i1 + 1; i2 < n; ++i2) {
0247       const reco::Candidate &c2 = cands[i2];
0248       if (preselect(c1, c2)) {
0249         CandPtr cr2(src, i2);
0250         typename OutputCollection::value_type c;
0251         combine(c, cr1, cr2, name1, name2);
0252         if (select(c))
0253           comps->push_back(c);
0254       }
0255     }
0256   }
0257 
0258   return comps;
0259 }
0260 
0261 template <typename OutputCollection, typename CandPtr>
0262 std::unique_ptr<OutputCollection> CandCombinerBase<OutputCollection, CandPtr>::combine(
0263     const edm::Handle<reco::CandidateView> &src1,
0264     const edm::Handle<reco::CandidateView> &src2,
0265     const vstring &names) const {
0266   std::vector<edm::Handle<reco::CandidateView> > src;
0267   src.push_back(src1);
0268   src.push_back(src2);
0269   return combine(src, names);
0270 }
0271 
0272 template <typename OutputCollection, typename CandPtr>
0273 std::unique_ptr<OutputCollection> CandCombinerBase<OutputCollection, CandPtr>::combine(
0274     const edm::Handle<reco::CandidateView> &src1,
0275     const edm::Handle<reco::CandidateView> &src2,
0276     const edm::Handle<reco::CandidateView> &src3,
0277     const vstring &names) const {
0278   std::vector<edm::Handle<reco::CandidateView> > src;
0279   src.push_back(src1);
0280   src.push_back(src2);
0281   src.push_back(src3);
0282   return combine(src, names);
0283 }
0284 
0285 template <typename OutputCollection, typename CandPtr>
0286 std::unique_ptr<OutputCollection> CandCombinerBase<OutputCollection, CandPtr>::combine(
0287     const edm::Handle<reco::CandidateView> &src1,
0288     const edm::Handle<reco::CandidateView> &src2,
0289     const edm::Handle<reco::CandidateView> &src3,
0290     const edm::Handle<reco::CandidateView> &src4,
0291     const vstring &names) const {
0292   std::vector<edm::Handle<reco::CandidateView> > src;
0293   src.push_back(src1);
0294   src.push_back(src2);
0295   src.push_back(src3);
0296   src.push_back(src4);
0297   return combine(src, names);
0298 }
0299 
0300 template <typename OutputCollection, typename CandPtr>
0301 void CandCombinerBase<OutputCollection, CandPtr>::combine(
0302     size_t collectionIndex,
0303     CandStack &stack,
0304     ChargeStack &qStack,
0305     std::vector<edm::Handle<reco::CandidateView> >::const_iterator collBegin,
0306     std::vector<edm::Handle<reco::CandidateView> >::const_iterator collEnd,
0307     OutputCollection *comps,
0308     const vstring &names) const {
0309   if (collBegin == collEnd) {
0310     static const int undetermined = 0, sameDecay = 1, conjDecay = -1, wrongDecay = 2;
0311     int decayType = undetermined;
0312     if (checkCharge_) {
0313       assert(qStack.size() == stack.size());
0314       for (size_t i = 0; i < qStack.size(); ++i) {
0315         int q = qStack[i], dq = dauCharge_[i];
0316         if (decayType == undetermined) {
0317           if (q != 0 && dq != 0) {
0318             if (q == dq)
0319               decayType = sameDecay;
0320             else if (q == -dq)
0321               decayType = conjDecay;
0322             else
0323               decayType = wrongDecay;
0324           }
0325         } else if ((decayType == sameDecay && q != dq) || (decayType == conjDecay && q != -dq)) {
0326           decayType = wrongDecay;
0327         }
0328         if (decayType == wrongDecay)
0329           break;
0330       }
0331     }
0332     if (decayType != wrongDecay) {
0333       typename OutputCollection::value_type c;
0334       size_t nameIndex = 0;
0335       for (typename CandStack::const_iterator i = stack.begin(); i != stack.end(); ++i, ++nameIndex) {
0336         if (!names.empty())
0337           addDaughter(c, i->first.first, names[nameIndex]);
0338         else
0339           addDaughter(c, i->first.first);
0340       }
0341       setup(c);
0342       if (select(c))
0343         comps->push_back(c);
0344     }
0345   } else {
0346     const edm::Handle<reco::CandidateView> &srcRef = *collBegin;
0347     const reco::CandidateView &src = *srcRef;
0348     size_t candBegin = 0, candEnd = src.size();
0349     for (typename CandStack::const_iterator i = stack.begin(); i != stack.end(); ++i)
0350       if (srcRef.id() == i->second->id())
0351         candBegin = i->first.second + 1;
0352     for (size_t candIndex = candBegin; candIndex != candEnd; ++candIndex) {
0353       CandPtr candRef(srcRef, candIndex);
0354       bool noOverlap = true;
0355       const reco::Candidate &cand = *candRef;
0356       for (typename CandStack::const_iterator i = stack.begin(); i != stack.end(); ++i)
0357         if (checkOverlap_ && overlap_(cand, *(i->first.first))) {
0358           noOverlap = false;
0359           break;
0360         }
0361       if (noOverlap) {
0362         stack.push_back(std::make_pair(std::make_pair(candRef, candIndex), collBegin));
0363         if (checkCharge_)
0364           qStack.push_back(cand.charge());
0365         combine(collectionIndex + 1, stack, qStack, collBegin + 1, collEnd, comps, names);
0366         stack.pop_back();
0367         qStack.pop_back();
0368       }
0369     }
0370   }
0371 }
0372 
0373 #endif