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