File indexing completed on 2024-04-06 12:23:33
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include "FWCore/Framework/interface/global/EDProducer.h"
0011 #include "FWCore/ParameterSet/interface/ParameterSetfwd.h"
0012
0013 #include "DataFormats/Candidate/interface/Candidate.h"
0014
0015 #include <vector>
0016 #include <iostream>
0017
0018 class CandOneToOneDeltaRMatcher : public edm::global::EDProducer<> {
0019 public:
0020 explicit CandOneToOneDeltaRMatcher(const edm::ParameterSet&);
0021
0022 using AllDist = std::vector<std::vector<float>>;
0023
0024 enum class Algo { kBruteForce, kSwitchMode, kMixMode };
0025
0026 private:
0027 void produce(edm::StreamID, edm::Event&, const edm::EventSetup&) const override;
0028 double length(const std::vector<int>&, const AllDist&) const;
0029 std::vector<int> AlgoBruteForce(int, int, const AllDist&) const;
0030 std::vector<int> AlgoSwitchMethod(int, int, AllDist&) const;
0031 static Algo algo(std::string const&);
0032 static const char* algoName(Algo);
0033
0034 const edm::EDGetTokenT<reco::CandidateView> sourceToken_;
0035 const edm::EDGetTokenT<reco::CandidateView> matchedToken_;
0036 const Algo algoMethod_;
0037 };
0038
0039 #include "PhysicsTools/JetMCUtils/interface/combination.h"
0040
0041 #include "FWCore/Framework/interface/ESHandle.h"
0042 #include "FWCore/Framework/interface/Event.h"
0043 #include "FWCore/Framework/interface/EventSetup.h"
0044 #include "FWCore/Utilities/interface/InputTag.h"
0045 #include "FWCore/Utilities/interface/EDMException.h"
0046 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0047 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0048
0049 #include "DataFormats/Common/interface/Handle.h"
0050 #include "DataFormats/Candidate/interface/LeafCandidate.h"
0051 #include "DataFormats/Candidate/interface/CandMatchMap.h"
0052 #include "DataFormats/Candidate/interface/CandidateFwd.h"
0053
0054 #include <Math/VectorUtil.h>
0055 #include <TMath.h>
0056
0057 using namespace edm;
0058 using namespace std;
0059 using namespace reco;
0060 using namespace ROOT::Math::VectorUtil;
0061 using namespace stdcomb;
0062
0063 CandOneToOneDeltaRMatcher::Algo CandOneToOneDeltaRMatcher::algo(const std::string& algoName) {
0064 if (algoName == "BruteForce") {
0065 return Algo::kBruteForce;
0066 } else if (algoName == "SwitchMode") {
0067 return Algo::kSwitchMode;
0068 } else if (algoName == "MixMode") {
0069 return Algo::kMixMode;
0070 } else {
0071 throw cms::Exception("OneToOne Constructor") << "wrong matching method in ParameterSet";
0072 }
0073 }
0074
0075 const char* CandOneToOneDeltaRMatcher::algoName(Algo iAlgo) {
0076 switch (iAlgo) {
0077 case Algo::kBruteForce:
0078 return "BruteForce";
0079 case Algo::kSwitchMode:
0080 return "SwitchMode";
0081 case Algo::kMixMode:
0082 return "MixMode";
0083 }
0084
0085 return "";
0086 }
0087
0088 CandOneToOneDeltaRMatcher::CandOneToOneDeltaRMatcher(const ParameterSet& cfg)
0089 : sourceToken_(consumes<CandidateView>(cfg.getParameter<InputTag>("src"))),
0090 matchedToken_(consumes<CandidateView>(cfg.getParameter<InputTag>("matched"))),
0091 algoMethod_(algo(cfg.getParameter<string>("algoMethod"))) {
0092 produces<CandViewMatchMap>("src2mtc");
0093 produces<CandViewMatchMap>("mtc2src");
0094 }
0095
0096 void CandOneToOneDeltaRMatcher::produce(StreamID, Event& evt, const EventSetup& es) const {
0097 Handle<CandidateView> source;
0098 Handle<CandidateView> matched;
0099 evt.getByToken(sourceToken_, source);
0100 evt.getByToken(matchedToken_, matched);
0101
0102 edm::LogVerbatim("CandOneToOneDeltaRMatcher") << "======== Source Collection =======";
0103 for (CandidateView::const_iterator c = source->begin(); c != source->end(); ++c) {
0104 edm::LogVerbatim("CandOneToOneDeltaRMatcher")
0105 << " pt source " << c->pt() << " " << c->eta() << " " << c->phi() << endl;
0106 }
0107 edm::LogVerbatim("CandOneToOneDeltaRMatcher") << "======== Matched Collection =======";
0108 for (CandidateView::const_iterator c = matched->begin(); c != matched->end(); ++c) {
0109 edm::LogVerbatim("CandOneToOneDeltaRMatcher")
0110 << " pt source " << c->pt() << " " << c->eta() << " " << c->phi() << endl;
0111 }
0112
0113 const int nSrc = source->size();
0114 const int nMtc = matched->size();
0115
0116 const int nMin = min(source->size(), matched->size());
0117 const int nMax = max(source->size(), matched->size());
0118 if (nMin < 1)
0119 return;
0120
0121 std::vector<std::vector<float>> allDist;
0122
0123 if (nSrc <= nMtc) {
0124 allDist.reserve(source->size());
0125 for (CandidateView::const_iterator iSr = source->begin(); iSr != source->end(); iSr++) {
0126 vector<float> tempAllDist;
0127 tempAllDist.reserve(matched->size());
0128 for (CandidateView::const_iterator iMt = matched->begin(); iMt != matched->end(); iMt++) {
0129 tempAllDist.push_back(DeltaR(iSr->p4(), iMt->p4()));
0130 }
0131 allDist.emplace_back(std::move(tempAllDist));
0132 }
0133 } else {
0134 allDist.reserve(matched->size());
0135 for (CandidateView::const_iterator iMt = matched->begin(); iMt != matched->end(); iMt++) {
0136 vector<float> tempAllDist;
0137 tempAllDist.reserve(source->size());
0138 for (CandidateView::const_iterator iSr = source->begin(); iSr != source->end(); iSr++) {
0139 tempAllDist.push_back(DeltaR(iSr->p4(), iMt->p4()));
0140 }
0141 allDist.emplace_back(std::move(tempAllDist));
0142 }
0143 }
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156 int nLoopToDo = (int)(TMath::Factorial(nMax) / TMath::Factorial(nMax - nMin));
0157 edm::LogVerbatim("CandOneToOneDeltaRMatcher") << "nLoop:" << nLoopToDo << endl;
0158 edm::LogVerbatim("CandOneToOneDeltaRMatcher") << "Choosen Algo is:" << algoName(algoMethod_);
0159 vector<int> bestCB;
0160
0161
0162 if (algoMethod_ == Algo::kBruteForce) {
0163 bestCB = AlgoBruteForce(nMin, nMax, allDist);
0164
0165
0166 } else if (algoMethod_ == Algo::kSwitchMode) {
0167 bestCB = AlgoSwitchMethod(nMin, nMax, allDist);
0168
0169
0170 } else if (algoMethod_ == Algo::kMixMode) {
0171 if (nLoopToDo < 10000) {
0172 bestCB = AlgoBruteForce(nMin, nMax, allDist);
0173 } else {
0174 bestCB = AlgoSwitchMethod(nMin, nMax, allDist);
0175 }
0176 }
0177
0178 for (int i1 = 0; i1 < nMin; i1++)
0179 edm::LogVerbatim("CandOneToOneDeltaRMatcher")
0180 << "min: " << i1 << " " << bestCB[i1] << " " << allDist[i1][bestCB[i1]];
0181
0182
0183
0184
0185
0186
0187
0188
0189 auto matchMapSrMt = std::make_unique<CandViewMatchMap>();
0190 auto matchMapMtSr = std::make_unique<CandViewMatchMap>();
0191
0192 for (int c = 0; c != nMin; c++) {
0193 if (source->size() <= matched->size()) {
0194 matchMapSrMt->insert(source->refAt(c), matched->refAt(bestCB[c]));
0195 matchMapMtSr->insert(matched->refAt(bestCB[c]), source->refAt(c));
0196 } else {
0197 matchMapSrMt->insert(source->refAt(bestCB[c]), matched->refAt(c));
0198 matchMapMtSr->insert(matched->refAt(c), source->refAt(bestCB[c]));
0199 }
0200 }
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213 evt.put(std::move(matchMapSrMt), "src2mtc");
0214 evt.put(std::move(matchMapMtSr), "mtc2src");
0215 }
0216
0217 double CandOneToOneDeltaRMatcher::length(const vector<int>& best, const AllDist& allDist) const {
0218 double myLength = 0;
0219 int row = 0;
0220 for (vector<int>::const_iterator it = best.begin(); it != best.end(); it++) {
0221 myLength += allDist[row][*it];
0222 row++;
0223 }
0224 return myLength;
0225 }
0226
0227
0228
0229
0230
0231
0232
0233
0234
0235
0236 vector<int> CandOneToOneDeltaRMatcher::AlgoBruteForce(int nMin, int nMax, const AllDist& allDist) const {
0237 vector<int> ca;
0238 vector<int> cb;
0239 vector<int> bestCB;
0240 float totalDeltaR = 0;
0241 float BestTotalDeltaR = 1000;
0242
0243 ca.reserve(nMax);
0244 for (int i1 = 0; i1 < nMax; i1++)
0245 ca.push_back(i1);
0246 cb.reserve(nMin);
0247 for (int i1 = 0; i1 < nMin; i1++)
0248 cb.push_back(i1);
0249
0250 do {
0251
0252 for (int cnt = 0; cnt < TMath::Factorial(nMin); cnt++) {
0253 totalDeltaR = length(cb, allDist);
0254 if (totalDeltaR < BestTotalDeltaR) {
0255 BestTotalDeltaR = totalDeltaR;
0256 bestCB = cb;
0257 }
0258 next_permutation(cb.begin(), cb.end());
0259 }
0260 } while (next_combination(ca.begin(), ca.end(), cb.begin(), cb.end()));
0261
0262 return bestCB;
0263 }
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276 vector<int> CandOneToOneDeltaRMatcher::AlgoSwitchMethod(int nMin, int nMax, AllDist& allDist) const {
0277 vector<int> bestCB;
0278 for (int i1 = 0; i1 < nMin; i1++) {
0279 int minInd = 0;
0280 for (int i2 = 1; i2 < nMax; i2++)
0281 if (allDist[i1][i2] < allDist[i1][minInd])
0282 minInd = i2;
0283 bestCB.push_back(minInd);
0284 }
0285
0286 bool inside = true;
0287 while (inside) {
0288 inside = false;
0289 for (int i1 = 0; i1 < nMin; i1++) {
0290 for (int i2 = i1 + 1; i2 < nMin; i2++) {
0291 if (bestCB[i1] == bestCB[i2]) {
0292 inside = true;
0293 if (allDist[i1][(bestCB[i1])] <= allDist[i2][(bestCB[i2])]) {
0294 allDist[i2][(bestCB[i2])] = 1000;
0295 int minInd = 0;
0296 for (int i3 = 1; i3 < nMax; i3++)
0297 if (allDist[i2][i3] < allDist[i2][minInd])
0298 minInd = i3;
0299 bestCB[i2] = minInd;
0300 } else {
0301 allDist[i1][(bestCB[i1])] = 1000;
0302 int minInd = 0;
0303 for (int i3 = 1; i3 < nMax; i3++)
0304 if (allDist[i1][i3] < allDist[i1][minInd])
0305 minInd = i3;
0306 bestCB[i1] = minInd;
0307 }
0308 }
0309 }
0310 }
0311 }
0312
0313 return bestCB;
0314 }
0315
0316 #include "FWCore/PluginManager/interface/ModuleDef.h"
0317 #include "FWCore/Framework/interface/MakerMacros.h"
0318
0319 DEFINE_FWK_MODULE(CandOneToOneDeltaRMatcher);