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  // condition result condResult set to true if at least one permutation
129  // passes all requirements
130  // all possible permutations are checked
131  bool condResult = false;
132 
133  // store the indices of the muon objects
134  // from the combination evaluated in the condition
135  SingleCombInCond objectsInComb;
136  objectsInComb.reserve(nObjInCond);
137 
138  // clear the m_combinationsInCond vector
140 
141  do {
142  if (--jumpIndex)
143  continue;
144 
145  jumpIndex = jump;
146 
147  // clear the indices in the combination
148  objectsInComb.clear();
149 
150  bool tmpResult = true;
151 
152  // check if there is a permutation that matches object-parameter
153  // requirements
154  for (int i = 0; i < nObjInCond; i++) {
155  tmpResult &= checkObjectParameter(i, *(*candVec)[index[i]]);
156  objectsInComb.push_back(index[i]);
157  }
158 
159  // if permutation does not match particle conditions
160  // skip charge correlation and spatial correlations
161  if (!tmpResult) {
162  continue;
163  }
164 
165  // get the correlation parameters (chargeCorrelation included here also)
167 
168  // charge_correlation consists of 3 relevant bits (D2, D1, D0)
169  unsigned int chargeCorr = corrPar.chargeCorrelation;
170 
171  // charge ignore bit (D0) not set?
172  if ((chargeCorr & 1) == 0) {
173  for (int i = 0; i < nObjInCond; i++) {
174  // check valid charge - skip if invalid charge
175  bool chargeValid = (*candVec)[index[i]]->charge_valid();
176  tmpResult &= chargeValid;
177 
178  if (!chargeValid) {
179  continue;
180  }
181  }
182 
183  if (!tmpResult) {
184  continue;
185  }
186 
187  if (nObjInCond == 1) { // one object condition
188 
189  // D2..enable pos, D1..enable neg
190  if (!(((chargeCorr & 4) != 0 && (*candVec)[index[0]]->charge() > 0) ||
191  ((chargeCorr & 2) != 0 && (*candVec)[index[0]]->charge() < 0))) {
192  continue;
193  }
194 
195  } else { // more objects condition
196 
197  // find out if signs are equal
198  bool equalSigns = true;
199  for (int i = 0; i < nObjInCond - 1; i++) {
200  if ((*candVec)[index[i]]->charge() != (*candVec)[index[i + 1]]->charge()) {
201  equalSigns = false;
202  break;
203  }
204  }
205 
206  // two or three particle condition
207  if (nObjInCond == 2 || nObjInCond == 3) {
208  // D2..enable equal, D1..enable not equal
209  if (!(((chargeCorr & 4) != 0 && equalSigns) || ((chargeCorr & 2) != 0 && !equalSigns))) {
210  continue;
211  }
212  }
213 
214  // four particle condition
215  if (nObjInCond == 4) {
216  // counter to count positive charges to determine if there are pairs
217  unsigned int posCount = 0;
218 
219  for (int i = 0; i < nObjInCond; i++) {
220  if ((*candVec)[index[i]]->charge() > 0) {
221  posCount++;
222  }
223  }
224 
225  // D2..enable equal, D1..enable pairs
226  if (!(((chargeCorr & 4) != 0 && equalSigns) || ((chargeCorr & 2) != 0 && posCount == 2))) {
227  continue;
228  }
229  }
230  }
231  } // end signchecks
232 
233  if (m_gtMuonTemplate->wsc()) {
234  // wsc requirements have always nObjInCond = 2
235  // one can use directly index[0] and index[1] to compute
236  // eta and phi differences
237  const int ObjInWscComb = 2;
238  if (nObjInCond != ObjInWscComb) {
239  edm::LogError("L1GlobalTrigger") << "\n Error: "
240  << "number of particles in condition with spatial correlation = " << nObjInCond
241  << "\n it must be = " << ObjInWscComb << std::endl;
242  // TODO Perhaps I should throw here an exception,
243  // since something is really wrong if nObjInCond != ObjInWscComb (=2)
244  continue;
245  }
246 
247  unsigned int candDeltaEta;
248  unsigned int candDeltaPhi;
249 
250  // check candDeltaEta
251 
252  // get eta index and the sign bit of the eta index (MSB is the sign)
253  // signedEta[i] is the signed eta index of (*candVec)[index[i]]
254  int signedEta[ObjInWscComb];
255  int signBit[ObjInWscComb] = {0, 0};
256 
257  int scaleEta = 1 << (m_ifMuEtaNumberBits - 1);
258 
259  for (int i = 0; i < ObjInWscComb; ++i) {
260  signBit[i] = ((*candVec)[index[i]]->etaIndex() & scaleEta) >> (m_ifMuEtaNumberBits - 1);
261  signedEta[i] = ((*candVec)[index[i]]->etaIndex()) % scaleEta;
262 
263  if (signBit[i] == 1) {
264  signedEta[i] = (-1) * signedEta[i];
265  }
266  }
267 
268  // compute candDeltaEta - add 1 if signs are different (due to +0/-0
269  // indices)
270  candDeltaEta =
271  static_cast<int>(std::abs(signedEta[1] - signedEta[0])) + static_cast<int>(signBit[1] ^ signBit[0]);
272 
273  if (!checkBit(corrPar.deltaEtaRange, candDeltaEta)) {
274  continue;
275  }
276 
277  // check candDeltaPhi
278 
279  // calculate absolute value of candDeltaPhi
280  if ((*candVec)[index[0]]->phiIndex() > (*candVec)[index[1]]->phiIndex()) {
281  candDeltaPhi = (*candVec)[index[0]]->phiIndex() - (*candVec)[index[1]]->phiIndex();
282  } else {
283  candDeltaPhi = (*candVec)[index[1]]->phiIndex() - (*candVec)[index[0]]->phiIndex();
284  }
285 
286  // check if candDeltaPhi > 180 (via delta_phi_maxbits)
287  // delta_phi contains bits for 0..180 (0 and 180 included)
288  // protect also against infinite loop...
289 
290  int nMaxLoop = 10;
291  int iLoop = 0;
292 
293  while (candDeltaPhi >= m_corrParDeltaPhiNrBins) {
294  unsigned int candDeltaPhiInitial = candDeltaPhi;
295 
296  // candDeltaPhi > 180 ==> take 360 - candDeltaPhi
297  candDeltaPhi = (m_corrParDeltaPhiNrBins - 1) * 2 - candDeltaPhi;
298  if (m_verbosity) {
299  LogTrace("L1GlobalTrigger") << " Initial candDeltaPhi = " << candDeltaPhiInitial
300  << " > m_corrParDeltaPhiNrBins = " << m_corrParDeltaPhiNrBins
301  << " ==> candDeltaPhi rescaled to: " << candDeltaPhi << " [ loop index " << iLoop
302  << "; breaks after " << nMaxLoop << " loops ]\n"
303  << std::endl;
304  }
305 
306  iLoop++;
307  if (iLoop > nMaxLoop) {
308  return false;
309  }
310  }
311 
312  // delta_phi bitmask is saved in two uint64_t words
313  if (candDeltaPhi < 64) {
314  if (!checkBit(corrPar.deltaPhiRange0Word, candDeltaPhi)) {
315  continue;
316  }
317  } else {
318  if (!checkBit(corrPar.deltaPhiRange1Word, (candDeltaPhi - 64))) {
319  continue;
320  }
321  }
322 
323  } // end wsc check
324 
325  // if we get here all checks were successfull for this combination
326  // set the general result for evaluateCondition to "true"
327 
328  condResult = true;
329  (combinationsInCond()).push_back(objectsInComb);
330 
331  } while (std::next_permutation(index.begin(), index.end()));
332  return condResult;
333 }
334 
335 // load muon candidates
336 const L1MuGMTCand *L1GtMuonCondition::getCandidate(const int indexCand) const {
337  return (*(m_gtGTL->getCandL1Mu()))[indexCand];
338 }
339 
349 const bool L1GtMuonCondition::checkObjectParameter(const int iCondition, const L1MuGMTCand &cand) const {
350  // number of objects in condition
351  int nObjInCond = m_gtMuonTemplate->nrObjects();
352 
353  if (iCondition >= nObjInCond || iCondition < 0) {
354  return false;
355  }
356 
357  // empty candidates can not be compared
358  if (cand.empty()) {
359  return false;
360  }
361 
362  const L1GtMuonTemplate::ObjectParameter objPar = (*(m_gtMuonTemplate->objectParameter()))[iCondition];
363 
364  // using the logic table from GTL-9U-module.pdf
365  // "Truth table for Isolation bit"
366 
367  // check thresholds:
368 
369  // value < low pt threshold
370  // fail trigger
371 
372  // low pt threshold <= value < high pt threshold & non-isolated muon:
373  // requestIso true: fail trigger
374  // requestIso false, enableIso true: fail trigger
375  // requestIso false, enableIso false: OK, trigger
376 
377  // low pt threshold <= value < high pt threshold & isolated muon:
378  // requestIso true: OK, trigger
379  // requestIso false, enableIso true: OK, trigger
380  // requestIso false, enableIso false: OK, trigger
381 
382  // value >= high pt threshold & non-isolated muon:
383  // requestIso true: fail trigger
384  // requestIso false: OK, trigger
385 
386  // value >= high pt threshold & isolated muon:
387  // OK, trigger
388 
389  if (!checkThreshold(objPar.ptHighThreshold, cand.ptIndex(), m_gtMuonTemplate->condGEq())) {
390  if (!checkThreshold(objPar.ptLowThreshold, cand.ptIndex(), m_gtMuonTemplate->condGEq())) {
391  return false;
392  } else {
393  // check isolation
394  if (!cand.isol()) {
395  if (objPar.requestIso || objPar.enableIso) {
396  return false;
397  }
398  }
399  }
400 
401  } else {
402  if (!cand.isol()) {
403  if (objPar.requestIso) {
404  return false;
405  }
406  }
407  }
408 
409  // check eta
410 
411  if (!checkBit(objPar.etaRange, cand.etaIndex())) {
412  return false;
413  }
414 
415  // check phi - in the requested range (no LUT used - LUT too big for hw chip)
416  // for phiLow <= phiHigh takes [phiLow, phiHigh]
417  // for phiLow >= phiHigh takes [phiLow, phiHigh] over zero angle!
418 
419  if (objPar.phiHigh >= objPar.phiLow) {
420  if (!((objPar.phiLow <= cand.phiIndex()) && (cand.phiIndex() <= objPar.phiHigh))) {
421  return false;
422  }
423 
424  } else { // go over zero angle!!
425  if (!((objPar.phiLow <= cand.phiIndex()) || (cand.phiIndex() <= objPar.phiHigh))) {
426  return false;
427  }
428  }
429 
430  // check quality ( bit check )
431 
432  // A number of values is required to trigger (at least one).
433  // "Don’t care" means that all values are allowed.
434  // Qual = 000 means then NO MUON (GTL module)
435 
436  if (cand.quality() == 0) {
437  return false;
438  }
439 
440  if (objPar.qualityRange == 0) {
441  return false;
442  } else {
443  if (!checkBit(objPar.qualityRange, cand.quality())) {
444  return false;
445  }
446  }
447 
448  // check mip
449  if (objPar.enableMip) {
450  if (!cand.mip()) {
451  return false;
452  }
453  }
454 
455  // particle matches if we get here
456  // LogTrace("L1GlobalTrigger")
457  // << " checkObjectParameter: muon object OK, passes all requirements\n"
458  // << std::endl;
459 
460  return true;
461 }
462 
463 void L1GtMuonCondition::print(std::ostream &myCout) const {
464  m_gtMuonTemplate->print(myCout);
465 
466  myCout << " Number of bits for eta of muon objects = " << m_ifMuEtaNumberBits << std::endl;
467  myCout << " Maximum number of bins for the delta phi scales = " << m_corrParDeltaPhiNrBins << "\n " << std::endl;
468 
470 }
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