CMS 3D CMS Logo

L1GtMuonCondition.cc
Go to the documentation of this file.
1 
15 // this class header
17 
18 // system include files
19 #include <iomanip>
20 #include <iostream>
21 
22 #include <algorithm>
23 #include <string>
24 #include <vector>
25 
26 // user include files
27 // base classes
30 
32 
34 
37 
40 
41 // constructors
42 // default
44  // empty
45 }
46 
47 // from base template condition (from event setup usually)
49  const L1GlobalTriggerGTL *ptrGTL,
50  const int nrL1Mu,
51  const int ifMuEtaNumberBits)
53  m_gtMuonTemplate(static_cast<const L1GtMuonTemplate *>(muonTemplate)),
54  m_gtGTL(ptrGTL),
55  m_ifMuEtaNumberBits(ifMuEtaNumberBits) {
57  m_condMaxNumberObjects = nrL1Mu;
58 }
59 
60 // copy constructor
62  m_gtMuonTemplate = cp.gtMuonTemplate();
63  m_gtGTL = cp.gtGTL();
64 
65  m_ifMuEtaNumberBits = cp.gtIfMuEtaNumberBits();
66  m_corrParDeltaPhiNrBins = cp.m_corrParDeltaPhiNrBins;
67 
68  m_condMaxNumberObjects = cp.condMaxNumberObjects();
69  m_condLastResult = cp.condLastResult();
70  m_combinationsInCond = cp.getCombinationsInCond();
71 
72  m_verbosity = cp.m_verbosity;
73 }
74 
76 
77 // destructor
79  // empty
80 }
81 
82 // equal operator
84  copy(cp);
85  return *this;
86 }
87 
88 // methods
90 
92 void L1GtMuonCondition::setGtGTL(const L1GlobalTriggerGTL *ptrGTL) { m_gtGTL = ptrGTL; }
93 
94 // set the number of bits for eta of muon objects
95 void L1GtMuonCondition::setGtIfMuEtaNumberBits(const int &ifMuEtaNumberBitsValue) {
96  m_ifMuEtaNumberBits = ifMuEtaNumberBitsValue;
97 }
98 
99 // set the maximum number of bins for the delta phi scales
100 void L1GtMuonCondition::setGtCorrParDeltaPhiNrBins(const int &corrParDeltaPhiNrBins) {
101  m_corrParDeltaPhiNrBins = corrParDeltaPhiNrBins;
102 }
103 
104 // try all object permutations and check spatial correlations, if required
106  // number of trigger objects in the condition
107  int nObjInCond = m_gtMuonTemplate->nrObjects();
108 
109  // the candidates
110  const std::vector<const L1MuGMTCand *> *candVec = m_gtGTL->getCandL1Mu();
111 
112  int numberObjects = candVec->size();
113  // LogTrace("L1GlobalTrigger") << " numberObjects: " << numberObjects
114  // << std::endl;
115  if (numberObjects < nObjInCond) {
116  return false;
117  }
118 
119  std::vector<int> index(numberObjects);
120 
121  for (int i = 0; i < numberObjects; ++i) {
122  index[i] = i;
123  }
124 
125  int jumpIndex = 1;
126  int jump = factorial(numberObjects - nObjInCond);
127 
128  int totalLoops = 0;
129  int passLoops = 0;
130 
131  // condition result condResult set to true if at least one permutation
132  // passes all requirements
133  // all possible permutations are checked
134  bool condResult = false;
135 
136  // store the indices of the muon objects
137  // from the combination evaluated in the condition
138  SingleCombInCond objectsInComb;
139  objectsInComb.reserve(nObjInCond);
140 
141  // clear the m_combinationsInCond vector
143 
144  do {
145  if (--jumpIndex)
146  continue;
147 
148  jumpIndex = jump;
149  totalLoops++;
150 
151  // clear the indices in the combination
152  objectsInComb.clear();
153 
154  bool tmpResult = true;
155 
156  // check if there is a permutation that matches object-parameter
157  // requirements
158  for (int i = 0; i < nObjInCond; i++) {
159  tmpResult &= checkObjectParameter(i, *(*candVec)[index[i]]);
160  objectsInComb.push_back(index[i]);
161  }
162 
163  // if permutation does not match particle conditions
164  // skip charge correlation and spatial correlations
165  if (!tmpResult) {
166  continue;
167  }
168 
169  // get the correlation parameters (chargeCorrelation included here also)
171 
172  // charge_correlation consists of 3 relevant bits (D2, D1, D0)
173  unsigned int chargeCorr = corrPar.chargeCorrelation;
174 
175  // charge ignore bit (D0) not set?
176  if ((chargeCorr & 1) == 0) {
177  for (int i = 0; i < nObjInCond; i++) {
178  // check valid charge - skip if invalid charge
179  bool chargeValid = (*candVec)[index[i]]->charge_valid();
180  tmpResult &= chargeValid;
181 
182  if (!chargeValid) {
183  continue;
184  }
185  }
186 
187  if (!tmpResult) {
188  continue;
189  }
190 
191  if (nObjInCond == 1) { // one object condition
192 
193  // D2..enable pos, D1..enable neg
194  if (!(((chargeCorr & 4) != 0 && (*candVec)[index[0]]->charge() > 0) ||
195  ((chargeCorr & 2) != 0 && (*candVec)[index[0]]->charge() < 0))) {
196  continue;
197  }
198 
199  } else { // more objects condition
200 
201  // find out if signs are equal
202  bool equalSigns = true;
203  for (int i = 0; i < nObjInCond - 1; i++) {
204  if ((*candVec)[index[i]]->charge() != (*candVec)[index[i + 1]]->charge()) {
205  equalSigns = false;
206  break;
207  }
208  }
209 
210  // two or three particle condition
211  if (nObjInCond == 2 || nObjInCond == 3) {
212  // D2..enable equal, D1..enable not equal
213  if (!(((chargeCorr & 4) != 0 && equalSigns) || ((chargeCorr & 2) != 0 && !equalSigns))) {
214  continue;
215  }
216  }
217 
218  // four particle condition
219  if (nObjInCond == 4) {
220  // counter to count positive charges to determine if there are pairs
221  unsigned int posCount = 0;
222 
223  for (int i = 0; i < nObjInCond; i++) {
224  if ((*candVec)[index[i]]->charge() > 0) {
225  posCount++;
226  }
227  }
228 
229  // D2..enable equal, D1..enable pairs
230  if (!(((chargeCorr & 4) != 0 && equalSigns) || ((chargeCorr & 2) != 0 && posCount == 2))) {
231  continue;
232  }
233  }
234  }
235  } // end signchecks
236 
237  if (m_gtMuonTemplate->wsc()) {
238  // wsc requirements have always nObjInCond = 2
239  // one can use directly index[0] and index[1] to compute
240  // eta and phi differences
241  const int ObjInWscComb = 2;
242  if (nObjInCond != ObjInWscComb) {
243  edm::LogError("L1GlobalTrigger") << "\n Error: "
244  << "number of particles in condition with spatial correlation = " << nObjInCond
245  << "\n it must be = " << ObjInWscComb << std::endl;
246  // TODO Perhaps I should throw here an exception,
247  // since something is really wrong if nObjInCond != ObjInWscComb (=2)
248  continue;
249  }
250 
251  unsigned int candDeltaEta;
252  unsigned int candDeltaPhi;
253 
254  // check candDeltaEta
255 
256  // get eta index and the sign bit of the eta index (MSB is the sign)
257  // signedEta[i] is the signed eta index of (*candVec)[index[i]]
258  int signedEta[ObjInWscComb];
259  int signBit[ObjInWscComb] = {0, 0};
260 
261  int scaleEta = 1 << (m_ifMuEtaNumberBits - 1);
262 
263  for (int i = 0; i < ObjInWscComb; ++i) {
264  signBit[i] = ((*candVec)[index[i]]->etaIndex() & scaleEta) >> (m_ifMuEtaNumberBits - 1);
265  signedEta[i] = ((*candVec)[index[i]]->etaIndex()) % scaleEta;
266 
267  if (signBit[i] == 1) {
268  signedEta[i] = (-1) * signedEta[i];
269  }
270  }
271 
272  // compute candDeltaEta - add 1 if signs are different (due to +0/-0
273  // indices)
274  candDeltaEta =
275  static_cast<int>(std::abs(signedEta[1] - signedEta[0])) + static_cast<int>(signBit[1] ^ signBit[0]);
276 
277  if (!checkBit(corrPar.deltaEtaRange, candDeltaEta)) {
278  continue;
279  }
280 
281  // check candDeltaPhi
282 
283  // calculate absolute value of candDeltaPhi
284  if ((*candVec)[index[0]]->phiIndex() > (*candVec)[index[1]]->phiIndex()) {
285  candDeltaPhi = (*candVec)[index[0]]->phiIndex() - (*candVec)[index[1]]->phiIndex();
286  } else {
287  candDeltaPhi = (*candVec)[index[1]]->phiIndex() - (*candVec)[index[0]]->phiIndex();
288  }
289 
290  // check if candDeltaPhi > 180 (via delta_phi_maxbits)
291  // delta_phi contains bits for 0..180 (0 and 180 included)
292  // protect also against infinite loop...
293 
294  int nMaxLoop = 10;
295  int iLoop = 0;
296 
297  while (candDeltaPhi >= m_corrParDeltaPhiNrBins) {
298  unsigned int candDeltaPhiInitial = candDeltaPhi;
299 
300  // candDeltaPhi > 180 ==> take 360 - candDeltaPhi
301  candDeltaPhi = (m_corrParDeltaPhiNrBins - 1) * 2 - candDeltaPhi;
302  if (m_verbosity) {
303  LogTrace("L1GlobalTrigger") << " Initial candDeltaPhi = " << candDeltaPhiInitial
304  << " > m_corrParDeltaPhiNrBins = " << m_corrParDeltaPhiNrBins
305  << " ==> candDeltaPhi rescaled to: " << candDeltaPhi << " [ loop index " << iLoop
306  << "; breaks after " << nMaxLoop << " loops ]\n"
307  << std::endl;
308  }
309 
310  iLoop++;
311  if (iLoop > nMaxLoop) {
312  return false;
313  }
314  }
315 
316  // delta_phi bitmask is saved in two uint64_t words
317  if (candDeltaPhi < 64) {
318  if (!checkBit(corrPar.deltaPhiRange0Word, candDeltaPhi)) {
319  continue;
320  }
321  } else {
322  if (!checkBit(corrPar.deltaPhiRange1Word, (candDeltaPhi - 64))) {
323  continue;
324  }
325  }
326 
327  } // end wsc check
328 
329  // if we get here all checks were successfull for this combination
330  // set the general result for evaluateCondition to "true"
331 
332  condResult = true;
333  passLoops++;
334  (combinationsInCond()).push_back(objectsInComb);
335 
336  } while (std::next_permutation(index.begin(), index.end()));
337 
338  // LogTrace("L1GlobalTrigger")
339  // << "\n L1GtMuonCondition: total number of permutations found: " <<
340  // totalLoops
341  // << "\n L1GtMuonCondition: number of permutations passing requirements:
342  // " << passLoops
343  // << "\n" << std::endl;
344 
345  return condResult;
346 }
347 
348 // load muon candidates
349 const L1MuGMTCand *L1GtMuonCondition::getCandidate(const int indexCand) const {
350  return (*(m_gtGTL->getCandL1Mu()))[indexCand];
351 }
352 
362 const bool L1GtMuonCondition::checkObjectParameter(const int iCondition, const L1MuGMTCand &cand) const {
363  // number of objects in condition
364  int nObjInCond = m_gtMuonTemplate->nrObjects();
365 
366  if (iCondition >= nObjInCond || iCondition < 0) {
367  return false;
368  }
369 
370  // empty candidates can not be compared
371  if (cand.empty()) {
372  return false;
373  }
374 
375  const L1GtMuonTemplate::ObjectParameter objPar = (*(m_gtMuonTemplate->objectParameter()))[iCondition];
376 
377  // using the logic table from GTL-9U-module.pdf
378  // "Truth table for Isolation bit"
379 
380  // check thresholds:
381 
382  // value < low pt threshold
383  // fail trigger
384 
385  // low pt threshold <= value < high pt threshold & non-isolated muon:
386  // requestIso true: fail trigger
387  // requestIso false, enableIso true: fail trigger
388  // requestIso false, enableIso false: OK, trigger
389 
390  // low pt threshold <= value < high pt threshold & isolated muon:
391  // requestIso true: OK, trigger
392  // requestIso false, enableIso true: OK, trigger
393  // requestIso false, enableIso false: OK, trigger
394 
395  // value >= high pt threshold & non-isolated muon:
396  // requestIso true: fail trigger
397  // requestIso false: OK, trigger
398 
399  // value >= high pt threshold & isolated muon:
400  // OK, trigger
401 
402  if (!checkThreshold(objPar.ptHighThreshold, cand.ptIndex(), m_gtMuonTemplate->condGEq())) {
403  if (!checkThreshold(objPar.ptLowThreshold, cand.ptIndex(), m_gtMuonTemplate->condGEq())) {
404  return false;
405  } else {
406  // check isolation
407  if (!cand.isol()) {
408  if (objPar.requestIso || objPar.enableIso) {
409  return false;
410  }
411  }
412  }
413 
414  } else {
415  if (!cand.isol()) {
416  if (objPar.requestIso) {
417  return false;
418  }
419  }
420  }
421 
422  // check eta
423 
424  if (!checkBit(objPar.etaRange, cand.etaIndex())) {
425  return false;
426  }
427 
428  // check phi - in the requested range (no LUT used - LUT too big for hw chip)
429  // for phiLow <= phiHigh takes [phiLow, phiHigh]
430  // for phiLow >= phiHigh takes [phiLow, phiHigh] over zero angle!
431 
432  if (objPar.phiHigh >= objPar.phiLow) {
433  if (!((objPar.phiLow <= cand.phiIndex()) && (cand.phiIndex() <= objPar.phiHigh))) {
434  return false;
435  }
436 
437  } else { // go over zero angle!!
438  if (!((objPar.phiLow <= cand.phiIndex()) || (cand.phiIndex() <= objPar.phiHigh))) {
439  return false;
440  }
441  }
442 
443  // check quality ( bit check )
444 
445  // A number of values is required to trigger (at least one).
446  // "Don’t care" means that all values are allowed.
447  // Qual = 000 means then NO MUON (GTL module)
448 
449  if (cand.quality() == 0) {
450  return false;
451  }
452 
453  if (objPar.qualityRange == 0) {
454  return false;
455  } else {
456  if (!checkBit(objPar.qualityRange, cand.quality())) {
457  return false;
458  }
459  }
460 
461  // check mip
462  if (objPar.enableMip) {
463  if (!cand.mip()) {
464  return false;
465  }
466  }
467 
468  // particle matches if we get here
469  // LogTrace("L1GlobalTrigger")
470  // << " checkObjectParameter: muon object OK, passes all requirements\n"
471  // << std::endl;
472 
473  return true;
474 }
475 
476 void L1GtMuonCondition::print(std::ostream &myCout) const {
477  m_gtMuonTemplate->print(myCout);
478 
479  myCout << " Number of bits for eta of muon objects = " << m_ifMuEtaNumberBits << std::endl;
480  myCout << " Maximum number of bins for the delta phi scales = " << m_corrParDeltaPhiNrBins << "\n " << std::endl;
481 
483 }
L1GtMuonCondition & operator=(const L1GtMuonCondition &)
bool m_condLastResult
the last result of evaluateCondition()
const bool checkBit(const Type1 &mask, const unsigned int bitNumber) const
check if a bit with a given number is set in a mask
CombinationsInCond m_combinationsInCond
store all the object combinations evaluated to true in the condition
void setGtIfMuEtaNumberBits(const int &)
unsigned int m_corrParDeltaPhiNrBins
void copy(const L1GtMuonCondition &cp)
copy function for copy constructor and operator=
std::vector< int > SingleCombInCond
typedefs
const bool evaluateCondition() const override
the core function to check if the condition matches
int m_ifMuEtaNumberBits
number of bits for eta of muon objects
CombinationsInCond & combinationsInCond() const
get all the object combinations (to fill it...)
Log< level::Error, false > LogError
virtual void print(std::ostream &myCout) const
print condition
const std::vector< const L1MuGMTCand * > * getCandL1Mu() const
return global muon trigger candidate
const L1GtMuonTemplate * m_gtMuonTemplate
pointer to a L1GtMuonTemplate
const bool checkObjectParameter(const int iCondition, const L1MuGMTCand &cand) const
function to check a single object if it matches a condition
#define LogTrace(id)
const bool checkThreshold(const Type1 &threshold, const Type2 &value, const bool condGEqValue) const
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
const CorrelationParameter * correlationParameter() const
~L1GtMuonCondition() override
const bool condGEq() const
get / set condition GEq flag
Definition: L1GtCondition.h:72
void print(std::ostream &myCout) const override
print the condition
void setGtGTL(const L1GlobalTriggerGTL *)
set the pointer to GTL
void setGtMuonTemplate(const L1GtMuonTemplate *)
const bool wsc() const
const std::vector< ObjectParameter > * objectParameter() const
const L1GlobalTriggerGTL * m_gtGTL
pointer to GTL, to be able to get the trigger objects
void print(std::ostream &myCout) const override
print condition
deadvectors [0] push_back({0.0175431, 0.538005, 6.80997, 13.29})
void setGtCorrParDeltaPhiNrBins(const int &)
int factorial(int n)
factorial function
const int nrObjects() const
get number of trigger objects
void clear(EGIsoObj &c)
Definition: egamma.h:82
const L1MuGMTCand * getCandidate(const int indexCand) const
load muon candidates