File indexing completed on 2024-04-06 12:01:03
0001 #ifndef CommonTools_CandUtils_CandCombinerBase_h
0002 #define CommonTools_CandUtils_CandCombinerBase_h
0003
0004
0005
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
0018 explicit CandCombinerBase(const std::string = "");
0019
0020 CandCombinerBase(int, int, const std::string = "");
0021
0022 CandCombinerBase(int, int, int, const std::string = "");
0023
0024 CandCombinerBase(int, int, int, int, const std::string = "");
0025
0026 CandCombinerBase(bool checkCharge, bool checkOverlap, const std::vector<int> &, const std::string = "");
0027
0028 virtual ~CandCombinerBase();
0029
0030 std::unique_ptr<OutputCollection> combine(const std::vector<edm::Handle<reco::CandidateView> > &,
0031 const vstring & = vstring()) const;
0032
0033 std::unique_ptr<OutputCollection> combine(const edm::Handle<reco::CandidateView> &,
0034 const vstring & = vstring()) const;
0035
0036 std::unique_ptr<OutputCollection> combine(const edm::Handle<reco::CandidateView> &,
0037 const edm::Handle<reco::CandidateView> &,
0038 const vstring & = vstring()) const;
0039
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
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
0053 bool preselect(const reco::Candidate &, const reco::Candidate &) const;
0054
0055 void combine(typename OutputCollection::value_type &,
0056 const CandPtr &,
0057 const CandPtr &,
0058 const std::string = "",
0059 const std::string = "") const;
0060
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
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
0074 virtual bool select(const reco::Candidate &) const = 0;
0075
0076 virtual bool selectPair(const reco::Candidate &c1, const reco::Candidate &c2) const = 0;
0077
0078 virtual void setup(typename OutputCollection::value_type &) const = 0;
0079
0080 virtual void addDaughter(typename OutputCollection::value_type &cmp,
0081 const CandPtr &c,
0082 const std::string = "") const = 0;
0083
0084 bool checkCharge_;
0085
0086 bool checkOverlap_;
0087
0088 std::vector<int> dauCharge_;
0089
0090 OverlapChecker overlap_;
0091
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