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