CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
CandOneToOneDeltaRMatcher.cc
Go to the documentation of this file.
1 /* \class CandOneToOneDeltaRMatcher
2  *
3  * Producer for simple match map
4  * to match two collections of candidate
5  * with one-to-One matching
6  * minimizing Sum(DeltaR)
7  *
8  */
9 
12 
14 
15 #include <vector>
16 #include <iostream>
17 
19 public:
21 
22  using AllDist = std::vector<std::vector<float>>;
23 
25 
26 private:
27  void produce(edm::StreamID, edm::Event&, const edm::EventSetup&) const override;
28  double length(const std::vector<int>&, const AllDist&) const;
29  std::vector<int> AlgoBruteForce(int, int, const AllDist&) const;
30  std::vector<int> AlgoSwitchMethod(int, int, AllDist&) const;
31  static Algo algo(std::string const&);
32  static const char* algoName(Algo);
33 
37 };
38 
40 
48 
53 
54 #include <Math/VectorUtil.h>
55 #include <TMath.h>
56 
57 using namespace edm;
58 using namespace std;
59 using namespace reco;
60 using namespace ROOT::Math::VectorUtil;
61 using namespace stdcomb;
62 
64  if (algoName == "BruteForce") {
65  return Algo::kBruteForce;
66  } else if (algoName == "SwitchMode") {
67  return Algo::kSwitchMode;
68  } else if (algoName == "MixMode") {
69  return Algo::kMixMode;
70  } else {
71  throw cms::Exception("OneToOne Constructor") << "wrong matching method in ParameterSet";
72  }
73 }
74 
76  switch (iAlgo) {
77  case Algo::kBruteForce:
78  return "BruteForce";
79  case Algo::kSwitchMode:
80  return "SwitchMode";
81  case Algo::kMixMode:
82  return "MixMode";
83  }
84  //can not get here
85  return "";
86 }
87 
89  : sourceToken_(consumes<CandidateView>(cfg.getParameter<InputTag>("src"))),
90  matchedToken_(consumes<CandidateView>(cfg.getParameter<InputTag>("matched"))),
91  algoMethod_(algo(cfg.getParameter<string>("algoMethod"))) {
92  produces<CandViewMatchMap>("src2mtc");
93  produces<CandViewMatchMap>("mtc2src");
94 }
95 
98  Handle<CandidateView> matched;
99  evt.getByToken(sourceToken_, source);
100  evt.getByToken(matchedToken_, matched);
101 
102  edm::LogVerbatim("CandOneToOneDeltaRMatcher") << "======== Source Collection =======";
103  for (CandidateView::const_iterator c = source->begin(); c != source->end(); ++c) {
104  edm::LogVerbatim("CandOneToOneDeltaRMatcher")
105  << " pt source " << c->pt() << " " << c->eta() << " " << c->phi() << endl;
106  }
107  edm::LogVerbatim("CandOneToOneDeltaRMatcher") << "======== Matched Collection =======";
108  for (CandidateView::const_iterator c = matched->begin(); c != matched->end(); ++c) {
109  edm::LogVerbatim("CandOneToOneDeltaRMatcher")
110  << " pt source " << c->pt() << " " << c->eta() << " " << c->phi() << endl;
111  }
112 
113  const int nSrc = source->size();
114  const int nMtc = matched->size();
115 
116  const int nMin = min(source->size(), matched->size());
117  const int nMax = max(source->size(), matched->size());
118  if (nMin < 1)
119  return;
120 
121  std::vector<std::vector<float>> allDist;
122 
123  if (nSrc <= nMtc) {
124  allDist.reserve(source->size());
125  for (CandidateView::const_iterator iSr = source->begin(); iSr != source->end(); iSr++) {
126  vector<float> tempAllDist;
127  tempAllDist.reserve(matched->size());
128  for (CandidateView::const_iterator iMt = matched->begin(); iMt != matched->end(); iMt++) {
129  tempAllDist.push_back(DeltaR(iSr->p4(), iMt->p4()));
130  }
131  allDist.emplace_back(std::move(tempAllDist));
132  }
133  } else {
134  allDist.reserve(matched->size());
135  for (CandidateView::const_iterator iMt = matched->begin(); iMt != matched->end(); iMt++) {
136  vector<float> tempAllDist;
137  tempAllDist.reserve(source->size());
138  for (CandidateView::const_iterator iSr = source->begin(); iSr != source->end(); iSr++) {
139  tempAllDist.push_back(DeltaR(iSr->p4(), iMt->p4()));
140  }
141  allDist.emplace_back(std::move(tempAllDist));
142  }
143  }
144 
145  /*
146  edm::LogVerbatim("CandOneToOneDeltaRMatcher") << "======== The DeltaR Matrix =======";
147  for(int m0=0; m0<nMin; m0++) {
148  // for(int m1=0; m1<nMax; m1++) {
149  edm::LogVerbatim("CandOneToOneDeltaRMatcher") << setprecision(2) << fixed << (m1 AllDist[m0][m1] ;
150  //}
151  edm::LogVerbatim("CandOneToOneDeltaRMatcher") << "\n";
152  }
153  */
154 
155  // Loop size if Brute Force
156  int nLoopToDo = (int)(TMath::Factorial(nMax) / TMath::Factorial(nMax - nMin));
157  edm::LogVerbatim("CandOneToOneDeltaRMatcher") << "nLoop:" << nLoopToDo << endl;
158  edm::LogVerbatim("CandOneToOneDeltaRMatcher") << "Choosen Algo is:" << algoName(algoMethod_);
159  vector<int> bestCB;
160 
161  // Algo is Brute Force
163  bestCB = AlgoBruteForce(nMin, nMax, allDist);
164 
165  // Algo is Switch Method
166  } else if (algoMethod_ == Algo::kSwitchMode) {
167  bestCB = AlgoSwitchMethod(nMin, nMax, allDist);
168 
169  // Algo is Brute Force if nLoop < 10000
170  } else if (algoMethod_ == Algo::kMixMode) {
171  if (nLoopToDo < 10000) {
172  bestCB = AlgoBruteForce(nMin, nMax, allDist);
173  } else {
174  bestCB = AlgoSwitchMethod(nMin, nMax, allDist);
175  }
176  }
177 
178  for (int i1 = 0; i1 < nMin; i1++)
179  edm::LogVerbatim("CandOneToOneDeltaRMatcher")
180  << "min: " << i1 << " " << bestCB[i1] << " " << allDist[i1][bestCB[i1]];
181 
182  /*
183  auto matchMapSrMt = std::make_unique<CandViewMatchMap>(CandViewMatchMap::ref_type( CandidateRefProd( source ),
184  CandidateRefProd( matched ) ) );
185  auto matchMapMtSr = std::make_unique<CandViewMatchMap>(CandViewMatchMap::ref_type( CandidateRefProd( matched ),
186  CandidateRefProd( source ) ) );
187 */
188 
189  auto matchMapSrMt = std::make_unique<CandViewMatchMap>();
190  auto matchMapMtSr = std::make_unique<CandViewMatchMap>();
191 
192  for (int c = 0; c != nMin; c++) {
193  if (source->size() <= matched->size()) {
194  matchMapSrMt->insert(source->refAt(c), matched->refAt(bestCB[c]));
195  matchMapMtSr->insert(matched->refAt(bestCB[c]), source->refAt(c));
196  } else {
197  matchMapSrMt->insert(source->refAt(bestCB[c]), matched->refAt(c));
198  matchMapMtSr->insert(matched->refAt(c), source->refAt(bestCB[c]));
199  }
200  }
201 
202  /*
203  for( int c = 0; c != nMin; c ++ ) {
204  if( source->size() <= matched->size() ) {
205  matchMapSrMt->insert( CandidateRef( source, c ), CandidateRef( matched, bestCB[c] ) );
206  matchMapMtSr->insert( CandidateRef( matched, bestCB[c] ), CandidateRef( source, c ) );
207  } else {
208  matchMapSrMt->insert( CandidateRef( source, bestCB[c] ), CandidateRef( matched, c ) );
209  matchMapMtSr->insert( CandidateRef( matched, c ), CandidateRef( source, bestCB[c] ) );
210  }
211  }
212 */
213  evt.put(std::move(matchMapSrMt), "src2mtc");
214  evt.put(std::move(matchMapMtSr), "mtc2src");
215 }
216 
217 double CandOneToOneDeltaRMatcher::length(const vector<int>& best, const AllDist& allDist) const {
218  double myLength = 0;
219  int row = 0;
220  for (vector<int>::const_iterator it = best.begin(); it != best.end(); it++) {
221  myLength += allDist[row][*it];
222  row++;
223  }
224  return myLength;
225 }
226 
227 // this is the Brute Force Algorithm
228 // All the possible combination are checked
229 // The best one is always found
230 // Be carefull when you have high values for nMin and nMax --> the combinatorial could explode!
231 // Sum(DeltaR) is minimized -->
232 // 0.1 - 0.2 - 1.0 - 1.5 is lower than
233 // 0.1 - 0.2 - 0.3 - 3.0
234 // Which one do you prefer? --> BruteForce select always the first
235 
236 vector<int> CandOneToOneDeltaRMatcher::AlgoBruteForce(int nMin, int nMax, const AllDist& allDist) const {
237  vector<int> ca;
238  vector<int> cb;
239  vector<int> bestCB;
240  float totalDeltaR = 0;
241  float BestTotalDeltaR = 1000;
242 
243  ca.reserve(nMax);
244  for (int i1 = 0; i1 < nMax; i1++)
245  ca.push_back(i1);
246  cb.reserve(nMin);
247  for (int i1 = 0; i1 < nMin; i1++)
248  cb.push_back(i1);
249 
250  do {
251  //do your processing on the new combination here
252  for (int cnt = 0; cnt < TMath::Factorial(nMin); cnt++) {
253  totalDeltaR = length(cb, allDist);
254  if (totalDeltaR < BestTotalDeltaR) {
255  BestTotalDeltaR = totalDeltaR;
256  bestCB = cb;
257  }
258  next_permutation(cb.begin(), cb.end());
259  }
260  } while (next_combination(ca.begin(), ca.end(), cb.begin(), cb.end()));
261 
262  return bestCB;
263 }
264 
265 // This method (Developed originally by Daniele Benedetti) check for the best combination
266 // choosing the minimum DeltaR for each line in AllDist matrix
267 // If no repeated row is found: ie (line,col)=(1,3) and (2,3) --> same as BruteForce
268 // If repetition --> set the higher DeltaR between the 2 repetition to 1000 and re-check best combination
269 // Iterate until no repetition
270 // No guaranted minimum for Sum(DeltaR)
271 // If you have:
272 // 0.1 - 0.2 - 1.0 - 1.5 is lower than
273 // 0.1 - 0.2 - 0.3 - 3.0
274 // SwitchMethod normally select the second solution
275 
276 vector<int> CandOneToOneDeltaRMatcher::AlgoSwitchMethod(int nMin, int nMax, AllDist& allDist) const {
277  vector<int> bestCB;
278  for (int i1 = 0; i1 < nMin; i1++) {
279  int minInd = 0;
280  for (int i2 = 1; i2 < nMax; i2++)
281  if (allDist[i1][i2] < allDist[i1][minInd])
282  minInd = i2;
283  bestCB.push_back(minInd);
284  }
285 
286  bool inside = true;
287  while (inside) {
288  inside = false;
289  for (int i1 = 0; i1 < nMin; i1++) {
290  for (int i2 = i1 + 1; i2 < nMin; i2++) {
291  if (bestCB[i1] == bestCB[i2]) {
292  inside = true;
293  if (allDist[i1][(bestCB[i1])] <= allDist[i2][(bestCB[i2])]) {
294  allDist[i2][(bestCB[i2])] = 1000;
295  int minInd = 0;
296  for (int i3 = 1; i3 < nMax; i3++)
297  if (allDist[i2][i3] < allDist[i2][minInd])
298  minInd = i3;
299  bestCB[i2] = minInd;
300  } else {
301  allDist[i1][(bestCB[i1])] = 1000;
302  int minInd = 0;
303  for (int i3 = 1; i3 < nMax; i3++)
304  if (allDist[i1][i3] < allDist[i1][minInd])
305  minInd = i3;
306  bestCB[i1] = minInd;
307  }
308  } // End if
309  }
310  }
311  } // End while
312 
313  return bestCB;
314 }
315 
318 
std::vector< int > AlgoSwitchMethod(int, int, AllDist &) const
Log< level::Info, true > LogVerbatim
OrphanHandle< PROD > put(std::unique_ptr< PROD > product)
Put a new product.
Definition: Event.h:133
const edm::EventSetup & c
tuple cfg
Definition: looper.py:296
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:539
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
void produce(edm::StreamID, edm::Event &, const edm::EventSetup &) const override
CandOneToOneDeltaRMatcher(const edm::ParameterSet &)
static Algo algo(std::string const &)
std::vector< std::vector< float >> AllDist
def move
Definition: eostools.py:511
const edm::EDGetTokenT< reco::CandidateView > sourceToken_
std::vector< int > AlgoBruteForce(int, int, const AllDist &) const
double length(const std::vector< int > &, const AllDist &) const
boost::indirect_iterator< typename seq_t::const_iterator > const_iterator
Definition: View.h:86
const edm::EDGetTokenT< reco::CandidateView > matchedToken_
static const char * algoName(Algo)
bool next_combination(BidIt n_begin, BidIt n_end, BidIt r_begin, BidIt r_end)
Definition: combination.h:19
static std::string const source
Definition: EdmProvDump.cc:46
Definition: fakeMenu.h:6