CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
PrimitiveSelection.cc
Go to the documentation of this file.
3 
4 #include "helper.h" // merge_map_into_map
5 
6 // 18 in ME1; 9x3 in ME2,3,4; 9 from neighbor sector.
7 // Arranged in FW as 6 stations, 9 chambers per station.
8 #define NUM_CSC_CHAMBERS 6 * 9
9 // 6x2 in RE1,2; 12x2 in RE3,4; 6 from neighbor sector.
10 // Arranged in FW as 7 stations, 6 chambers per station.
11 // For Phase 2, add RE1/3, RE2/3, RE3/1, RE4/1 -> 10 chambers per station
12 #define NUM_RPC_CHAMBERS 7 * 10
13 // 6 in GE1/1; 3 in GE2/1; 3 in ME0; 3 from neighbor sector. (unconfirmed!)
14 #define NUM_GEM_CHAMBERS 15
15 // 2x4 in MB1,2,3,4; 4 from neighbor sector. (unconfirmed!)
16 #define NUM_DT_CHAMBERS 3 * 4
17 
19  int endcap,
20  int sector,
21  int bx,
22  int bxShiftCSC,
23  int bxShiftRPC,
24  int bxShiftGEM,
25  int bxShiftME0,
26  bool includeNeighbor,
27  bool duplicateTheta,
28  bool bugME11Dupes) {
29  verbose_ = verbose;
30  endcap_ = endcap;
31  sector_ = sector;
32  bx_ = bx;
33 
34  bxShiftCSC_ = bxShiftCSC;
35  bxShiftRPC_ = bxShiftRPC;
36  bxShiftGEM_ = bxShiftGEM;
37  bxShiftME0_ = bxShiftME0;
38 
39  includeNeighbor_ = includeNeighbor;
40  duplicateTheta_ = duplicateTheta;
41  bugME11Dupes_ = bugME11Dupes;
42 }
43 
44 // _____________________________________________________________________________
45 // Specialized process() for CSC
46 template <>
48  const TriggerPrimitiveCollection& muon_primitives,
49  std::map<int, TriggerPrimitiveCollection>& selected_csc_map) const {
50  TriggerPrimitiveCollection::const_iterator tp_it = muon_primitives.begin();
51  TriggerPrimitiveCollection::const_iterator tp_end = muon_primitives.end();
52 
53  for (; tp_it != tp_end; ++tp_it) {
54  int selected_csc = select_csc(*tp_it); // Returns CSC "link" index (0 - 53)
55 
56  if (selected_csc >= 0) {
57  emtf_assert(selected_csc < NUM_CSC_CHAMBERS);
58 
59  //FIXME
60  if (selected_csc_map[selected_csc].size() < 2) {
61  selected_csc_map[selected_csc].push_back(*tp_it);
62  } else {
63  edm::LogWarning("L1T") << "\n******************* EMTF EMULATOR: SUPER-BIZZARE CASE *******************";
64  edm::LogWarning("L1T") << "Found 3 CSC trigger primitives in the same chamber";
65  for (int ii = 0; ii < 3; ii++) {
66  TriggerPrimitive tp_err = (ii < 2 ? selected_csc_map[selected_csc].at(ii) : *tp_it);
67  edm::LogWarning("L1T") << "LCT #" << ii + 1 << ": BX " << tp_err.getBX() << ", endcap "
68  << tp_err.detId<CSCDetId>().endcap() << ", sector "
69  << tp_err.detId<CSCDetId>().triggerSector() << ", station "
70  << tp_err.detId<CSCDetId>().station() << ", ring " << tp_err.detId<CSCDetId>().ring()
71  << ", chamber " << tp_err.detId<CSCDetId>().chamber() << ", CSC ID "
72  << tp_err.getCSCData().cscID << ": strip " << tp_err.getStrip() << ", wire "
73  << tp_err.getWire();
74  }
75  edm::LogWarning("L1T") << "************************* ONLY KEEP FIRST TWO *************************\n\n";
76  }
77 
78  } // End conditional: if (selected_csc >= 0)
79  } // End loop: for (; tp_it != tp_end; ++tp_it)
80 
81  // Duplicate CSC muon primitives
82  // If there are 2 LCTs in the same chamber with (strip, wire) = (s1, w1) and (s2, w2)
83  // make all combinations with (s1, w1), (s2, w1), (s1, w2), (s2, w2)
84  if (duplicateTheta_) {
85  std::map<int, TriggerPrimitiveCollection>::iterator map_tp_it = selected_csc_map.begin();
86  std::map<int, TriggerPrimitiveCollection>::iterator map_tp_end = selected_csc_map.end();
87 
88  for (; map_tp_it != map_tp_end; ++map_tp_it) {
89  int selected = map_tp_it->first;
90  TriggerPrimitiveCollection& tmp_primitives = map_tp_it->second; // pass by reference
91 
92  if (tmp_primitives.size() >= 4) {
93  edm::LogWarning("L1T") << "EMTF found 4 or more CSC LCTs in one chamber: keeping only two";
94  tmp_primitives.erase(tmp_primitives.begin() + 4, tmp_primitives.end()); // erase 5th element++
95  tmp_primitives.erase(tmp_primitives.begin() + 2); // erase 3rd element
96  tmp_primitives.erase(tmp_primitives.begin() + 1); // erase 2nd element
97  } else if (tmp_primitives.size() == 3) {
98  edm::LogWarning("L1T") << "EMTF found 3 CSC LCTs in one chamber: keeping only two";
99  tmp_primitives.erase(tmp_primitives.begin() + 2); // erase 3rd element
100  }
101  emtf_assert(tmp_primitives.size() <= 2); // at most 2 hits
102 
103  if (tmp_primitives.size() == 2) {
104  if ((tmp_primitives.at(0).getStrip() != tmp_primitives.at(1).getStrip()) &&
105  (tmp_primitives.at(0).getWire() != tmp_primitives.at(1).getWire())) {
106  // Swap wire numbers
107  TriggerPrimitive tp0 = tmp_primitives.at(0); // (s1,w1)
108  TriggerPrimitive tp1 = tmp_primitives.at(1); // (s2,w2)
109  uint16_t tmp_keywire = tp0.accessCSCData().keywire;
110  tp0.accessCSCData().keywire = tp1.accessCSCData().keywire; // (s1,w2)
111  tp1.accessCSCData().keywire = tmp_keywire; // (s2,w1)
112 
113  tmp_primitives.insert(tmp_primitives.begin() + 1, tp1); // (s2,w1) at 2nd pos
114  tmp_primitives.insert(tmp_primitives.begin() + 2, tp0); // (s1,w2) at 3rd pos
115  }
116 
117  const bool is_csc_me11 = (0 <= selected && selected <= 2) || (9 <= selected && selected <= 11) ||
118  (selected == 45); // ME1/1 sub 1 or ME1/1 sub 2 or ME1/1 from neighbor
119 
120  if (bugME11Dupes_ && is_csc_me11) {
121  // For ME1/1, always make 4 LCTs without checking strip & wire combination
122  if (tmp_primitives.size() == 2) {
123  // Swap wire numbers
124  TriggerPrimitive tp0 = tmp_primitives.at(0); // (s1,w1)
125  TriggerPrimitive tp1 = tmp_primitives.at(1); // (s2,w2)
126  uint16_t tmp_keywire = tp0.accessCSCData().keywire;
127  tp0.accessCSCData().keywire = tp1.accessCSCData().keywire; // (s1,w2)
128  tp1.accessCSCData().keywire = tmp_keywire; // (s2,w1)
129 
130  tmp_primitives.insert(tmp_primitives.begin() + 1, tp1); // (s2,w1) at 2nd pos
131  tmp_primitives.insert(tmp_primitives.begin() + 2, tp0); // (s1,w2) at 3rd pos
132  }
133  emtf_assert(tmp_primitives.size() == 1 || tmp_primitives.size() == 4);
134  }
135 
136  } // end if tmp_primitives.size() == 2
137  } // end loop over selected_csc_map
138  } // end if duplicate theta
139 }
140 
141 // _____________________________________________________________________________
142 // Specialized process() for RPC
143 template <>
145  const TriggerPrimitiveCollection& muon_primitives,
146  std::map<int, TriggerPrimitiveCollection>& selected_rpc_map) const {
147  TriggerPrimitiveCollection::const_iterator tp_it = muon_primitives.begin();
148  TriggerPrimitiveCollection::const_iterator tp_end = muon_primitives.end();
149 
150  for (; tp_it != tp_end; ++tp_it) {
151  int selected_rpc = select_rpc(*tp_it); // Returns RPC "link" index
152 
153  if (selected_rpc >= 0) {
154  emtf_assert(selected_rpc < NUM_RPC_CHAMBERS);
155  selected_rpc_map[selected_rpc].push_back(*tp_it);
156  }
157  }
158 
159  // Apply truncation as in firmware: keep first 2 clusters, max cluster
160  // size = 3 strips.
161  // According to Karol Bunkowski, for one chamber (so 3 eta rolls) only up
162  // to 2 hits (cluster centres) are produced. First two 'first' clusters are
163  // chosen, and only after the cut on the cluster size is applied. So if
164  // there are 1 large cluster and 2 small clusters, it is possible that
165  // one of the two small clusters is discarded first, and the large cluster
166  // then is removed by the cluster size cut, leaving only one cluster.
167  // Note: this needs to be modified for Phase 2 with additional iRPC chambers.
168  bool apply_truncation = true;
169  if (apply_truncation) {
170  struct {
172  bool operator()(const value_type& x) const {
173  // Skip cluster size cut if primitives are from CPPF emulator or EMTF unpacker (already clustered)
174  if (x.getRPCData().isCPPF)
175  return false;
176 
177  int sz = x.getRPCData().strip_hi - x.getRPCData().strip_low + 1;
178 
179  const RPCDetId& tp_detId = x.detId<RPCDetId>();
180  int tp_station = tp_detId.station();
181  int tp_ring = tp_detId.ring();
182  const bool is_irpc = (tp_station == 3 || tp_station == 4) && (tp_ring == 1);
183  if (is_irpc)
184  return sz > 6; // iRPC strip pitch is 1.5 times smaller than traditional RPC
185  return sz > 3;
186  }
187  } cluster_size_cut;
188 
189  std::map<int, TriggerPrimitiveCollection>::iterator map_tp_it = selected_rpc_map.begin();
190  std::map<int, TriggerPrimitiveCollection>::iterator map_tp_end = selected_rpc_map.end();
191 
192  for (; map_tp_it != map_tp_end; ++map_tp_it) {
193  int selected = map_tp_it->first;
194  TriggerPrimitiveCollection& tmp_primitives = map_tp_it->second; // pass by reference
195 
196  //FIXME
197  // Check to see if unpacked CPPF digis have <= 2 digis per chamber, as expected
198  if (tmp_primitives.size() > 2 && tmp_primitives.at(0).getRPCData().isCPPF) {
199  edm::LogWarning("L1T") << "\n******************* EMTF EMULATOR: SUPER-BIZZARE CASE *******************";
200  edm::LogWarning("L1T") << "Found " << tmp_primitives.size() << " CPPF digis in the same chamber";
201  for (const auto& tp : tmp_primitives)
202  tp.print(std::cout);
203  edm::LogWarning("L1T") << "************************* ONLY KEEP FIRST TWO *************************\n\n";
204  }
205 
206  if ((selected % 10) == 8 || (selected % 10) == 9) { // RE3/1 or RE4/1 (iRPC)
207  // Keep the first 4 clusters
208  if (tmp_primitives.size() > 4)
209  tmp_primitives.erase(tmp_primitives.begin() + 4, tmp_primitives.end());
210  } else {
211  // Keep the first 2 clusters
212  if (tmp_primitives.size() > 2)
213  tmp_primitives.erase(tmp_primitives.begin() + 2, tmp_primitives.end());
214  }
215 
216  // Apply cluster size cut
217  tmp_primitives.erase(std::remove_if(tmp_primitives.begin(), tmp_primitives.end(), cluster_size_cut),
218  tmp_primitives.end());
219  }
220  } // end if apply_truncation
221 
222  // Map RPC subsector and chamber to CSC chambers
223  // Note: RE3/2 & RE3/3 are considered as one chamber; RE4/2 & RE4/3 too.
224  bool map_rpc_to_csc = true;
225  if (map_rpc_to_csc) {
226  std::map<int, TriggerPrimitiveCollection> tmp_selected_rpc_map;
227 
228  std::map<int, TriggerPrimitiveCollection>::iterator map_tp_it = selected_rpc_map.begin();
229  std::map<int, TriggerPrimitiveCollection>::iterator map_tp_end = selected_rpc_map.end();
230 
231  for (; map_tp_it != map_tp_end; ++map_tp_it) {
232  int selected = map_tp_it->first;
233  TriggerPrimitiveCollection& tmp_primitives = map_tp_it->second; // pass by reference
234 
235  int rpc_sub = selected / 10;
236  int rpc_chm = selected % 10;
237 
238  int pc_station = -1;
239  int pc_chamber = -1;
240 
241  if (rpc_sub != 6) { // native
242  if (rpc_chm == 0) { // RE1/2: 3-5, 12-14
243  if (0 <= rpc_sub && rpc_sub < 3) {
244  pc_station = 0;
245  pc_chamber = 3 + rpc_sub;
246  } else if (3 <= rpc_sub && rpc_sub < 6) {
247  pc_station = 1;
248  pc_chamber = 3 + (rpc_sub - 3);
249  }
250  } else if (rpc_chm == 6) { // RE1/3: 6-8, 15-17
251  if (0 <= rpc_sub && rpc_sub < 3) {
252  pc_station = 0;
253  pc_chamber = 6 + rpc_sub;
254  } else if (3 <= rpc_sub && rpc_sub < 6) {
255  pc_station = 1;
256  pc_chamber = 6 + (rpc_sub - 3);
257  }
258  } else if (rpc_chm == 1 || rpc_chm == 7) { // RE2/2, RE2/3: 21-26
259  pc_station = 2;
260  pc_chamber = 3 + rpc_sub;
261  } else if (2 <= rpc_chm && rpc_chm <= 3) { // RE3/2, RE3/3: 30-35
262  pc_station = 3;
263  pc_chamber = 3 + rpc_sub;
264  } else if (4 <= rpc_chm && rpc_chm <= 5) { // RE4/2, RE4/3: 39-44
265  pc_station = 4;
266  pc_chamber = 3 + rpc_sub;
267  } else if (rpc_chm == 8) { // RE3/1: 27-29
268  pc_station = 3;
269  pc_chamber = rpc_sub;
270  } else if (rpc_chm == 9) { // RE4/1: 36-38
271  pc_station = 4;
272  pc_chamber = rpc_sub;
273  }
274 
275  } else { // neighbor
276  pc_station = 5;
277  if (rpc_chm == 0) { // RE1/2: 46
278  pc_chamber = 1;
279  } else if (rpc_chm == 6) { // RE1/3: 47
280  pc_chamber = 2;
281  } else if (rpc_chm == 1 || rpc_chm == 7) { // RE2/2, RE2/3: 49
282  pc_chamber = 4;
283  } else if (2 <= rpc_chm && rpc_chm <= 3) { // RE3/2, RE3/3: 51
284  pc_chamber = 6;
285  } else if (4 <= rpc_chm && rpc_chm <= 5) { // RE4/2, RE4/3: 53
286  pc_chamber = 8;
287  } else if (rpc_chm == 8) { // RE3/1: 50
288  pc_chamber = 5;
289  } else if (rpc_chm == 9) { // RE4/1: 52
290  pc_chamber = 7;
291  }
292  }
293  emtf_assert(pc_station != -1 && pc_chamber != -1);
294  emtf_assert(pc_station < 6 && pc_chamber < 9);
295 
296  selected = (pc_station * 9) + pc_chamber;
297 
298  bool ignore_this_rpc_chm = false;
299  if (rpc_chm == 3 || rpc_chm == 5) { // special case of RE3,4/2 and RE3,4/3 chambers
300  // if RE3,4/2 exists, ignore RE3,4/3. In C++, this assumes that the loop
301  // over selected_rpc_map will always find RE3,4/2 before RE3,4/3
302  if (tmp_selected_rpc_map.find(selected) != tmp_selected_rpc_map.end())
303  ignore_this_rpc_chm = true;
304  }
305 
306  if (rpc_chm == 6 || rpc_chm == 7) { // RE1/3 and RE2/3 chambers are not part of EMTF
307  ignore_this_rpc_chm = true;
308  }
309 
310  if (rpc_chm == 8 || rpc_chm == 9) { // RE3/1 and RE4/1 chambers are not available until Phase-2
311  ignore_this_rpc_chm = true;
312  }
313 
314  if (ignore_this_rpc_chm) {
315  // Set RPC stubs as invalid, but we keep them
316  for (auto&& tp : tmp_primitives) {
317  tp.accessRPCData().valid = 0;
318  }
319  }
320 
321  // Keep the stubs in the temporary map
322  if (tmp_selected_rpc_map.find(selected) == tmp_selected_rpc_map.end()) {
323  tmp_selected_rpc_map[selected] = tmp_primitives;
324  } else {
325  tmp_selected_rpc_map[selected].insert(
326  tmp_selected_rpc_map[selected].end(), tmp_primitives.begin(), tmp_primitives.end());
327  }
328  } // end loop over selected_rpc_map
329 
330  std::swap(selected_rpc_map, tmp_selected_rpc_map); // replace the original map
331  } // end if map_rpc_to_csc
332 }
333 
334 // _____________________________________________________________________________
335 // Specialized process() for GEM
336 template <>
338  const TriggerPrimitiveCollection& muon_primitives,
339  std::map<int, TriggerPrimitiveCollection>& selected_gem_map) const {
340  TriggerPrimitiveCollection::const_iterator tp_it = muon_primitives.begin();
341  TriggerPrimitiveCollection::const_iterator tp_end = muon_primitives.end();
342 
343  for (; tp_it != tp_end; ++tp_it) {
344  int selected_gem = select_gem(*tp_it); // Returns GEM "link" index
345 
346  if (selected_gem >= 0) {
347  emtf_assert(selected_gem < NUM_GEM_CHAMBERS);
348  selected_gem_map[selected_gem].push_back(*tp_it);
349  }
350  }
351 
352  // Apply truncation: max cluster size = 8 pads, keep first 8 clusters.
353  bool apply_truncation = true;
354  if (apply_truncation) {
355  struct {
357  bool operator()(const value_type& x) const {
358  int sz = x.getGEMData().pad_hi - x.getGEMData().pad_low + 1;
359  return sz > 8;
360  }
361  } cluster_size_cut;
362 
363  std::map<int, TriggerPrimitiveCollection>::iterator map_tp_it = selected_gem_map.begin();
364  std::map<int, TriggerPrimitiveCollection>::iterator map_tp_end = selected_gem_map.end();
365 
366  for (; map_tp_it != map_tp_end; ++map_tp_it) {
367  //int selected = map_tp_it->first;
368  TriggerPrimitiveCollection& tmp_primitives = map_tp_it->second; // pass by reference
369 
370  // Apply cluster size cut
371  tmp_primitives.erase(std::remove_if(tmp_primitives.begin(), tmp_primitives.end(), cluster_size_cut),
372  tmp_primitives.end());
373 
374  // Keep the first 8 clusters
375  if (tmp_primitives.size() > 8)
376  tmp_primitives.erase(tmp_primitives.begin() + 8, tmp_primitives.end());
377  }
378  } // end if apply_truncation
379 }
380 
381 // _____________________________________________________________________________
382 // Specialized process() for ME0
383 template <>
385  const TriggerPrimitiveCollection& muon_primitives,
386  std::map<int, TriggerPrimitiveCollection>& selected_me0_map) const {
387  TriggerPrimitiveCollection::const_iterator tp_it = muon_primitives.begin();
388  TriggerPrimitiveCollection::const_iterator tp_end = muon_primitives.end();
389 
390  for (; tp_it != tp_end; ++tp_it) {
391  int selected_me0 = select_me0(*tp_it); // Returns ME0 "link" index
392 
393  if (selected_me0 >= 0) {
394  emtf_assert(selected_me0 < NUM_GEM_CHAMBERS);
395  selected_me0_map[selected_me0].push_back(*tp_it);
396  }
397  }
398 
399  // Apply truncation
400  bool apply_truncation = true;
401  if (apply_truncation) {
402  std::map<int, TriggerPrimitiveCollection>::iterator map_tp_it = selected_me0_map.begin();
403  std::map<int, TriggerPrimitiveCollection>::iterator map_tp_end = selected_me0_map.end();
404 
405  for (; map_tp_it != map_tp_end; ++map_tp_it) {
406  //int selected = map_tp_it->first;
407  TriggerPrimitiveCollection& tmp_primitives = map_tp_it->second; // pass by reference
408 
409  // Keep the first 20 clusters
410  if (tmp_primitives.size() > 20)
411  tmp_primitives.erase(tmp_primitives.begin() + 20, tmp_primitives.end());
412  }
413  }
414 }
415 
416 // _____________________________________________________________________________
417 // Specialized process() for DT
418 template <>
420  const TriggerPrimitiveCollection& muon_primitives,
421  std::map<int, TriggerPrimitiveCollection>& selected_dt_map) const {
422  TriggerPrimitiveCollection::const_iterator tp_it = muon_primitives.begin();
423  TriggerPrimitiveCollection::const_iterator tp_end = muon_primitives.end();
424 
425  for (; tp_it != tp_end; ++tp_it) {
426  int selected_dt = select_dt(*tp_it); // Returns DT "link" index
427 
428  if (selected_dt >= 0) {
429  emtf_assert(selected_dt < NUM_DT_CHAMBERS);
430  selected_dt_map[selected_dt].push_back(*tp_it);
431  }
432  }
433 
434  // Duplicate DT muon primitives
435  if (duplicateTheta_) {
436  std::map<int, TriggerPrimitiveCollection>::iterator map_tp_it = selected_dt_map.begin();
437  std::map<int, TriggerPrimitiveCollection>::iterator map_tp_end = selected_dt_map.end();
438 
439  for (; map_tp_it != map_tp_end; ++map_tp_it) {
440  //int selected = map_tp_it->first;
441  TriggerPrimitiveCollection& tmp_primitives = map_tp_it->second; // pass by reference
442 
443  emtf_assert(tmp_primitives.size() <= 2); // at most 2 hits
444 
445  if (tmp_primitives.size() == 2) {
446  if ((tmp_primitives.at(0).getStrip() != tmp_primitives.at(1).getStrip()) &&
447  (tmp_primitives.at(0).getWire() != tmp_primitives.at(1).getWire())) {
448  // Swap wire numbers
449  TriggerPrimitive tp0 = tmp_primitives.at(0); // (s1,w1)
450  TriggerPrimitive tp1 = tmp_primitives.at(1); // (s2,w2)
451  uint16_t tmp_keywire = tp0.accessDTData().theta_bti_group;
452  tp0.accessDTData().theta_bti_group = tp1.accessDTData().theta_bti_group; // (s1,w2)
453  tp1.accessDTData().theta_bti_group = tmp_keywire; // (s2,w1)
454 
455  tmp_primitives.insert(tmp_primitives.begin() + 1, tp1); // (s2,w1) at 2nd pos
456  tmp_primitives.insert(tmp_primitives.begin() + 2, tp0); // (s1,w2) at 3rd pos
457  }
458  } // end if tmp_primitives.size() == 2
459  } // end loop over selected_dt_map
460  } // end if duplicate theta
461 }
462 
463 // _____________________________________________________________________________
464 // Put the hits from DT, CSC, RPC, GEM, ME0 together in one collection
465 
466 // Notes from Alex (2017-03-28):
467 //
468 // The RPC inclusion logic is very simple currently:
469 // - each CSC is analyzed for having track stubs in each BX
470 // - IF a CSC chamber is missing at least one track stub,
471 // AND there is an RPC overlapping with it in phi and theta,
472 // AND that RPC has hits,
473 // THEN RPC hit is inserted instead of missing CSC stub.
474 //
475 // This is done at the output of coord_delay module, so such
476 // inserted RPC hits can be matched to patterns by match_ph_segments
477 // module, just like any CSC stubs. Note that substitution of missing
478 // CSC stubs with RPC hits happens regardless of what's going on in
479 // other chambers, regardless of whether a pattern has been detected
480 // or not, basically regardless of anything. RPCs are treated as a
481 // supplemental source of stubs for CSCs.
482 
483 void PrimitiveSelection::merge(const std::map<int, TriggerPrimitiveCollection>& selected_dt_map,
484  const std::map<int, TriggerPrimitiveCollection>& selected_csc_map,
485  const std::map<int, TriggerPrimitiveCollection>& selected_rpc_map,
486  const std::map<int, TriggerPrimitiveCollection>& selected_gem_map,
487  const std::map<int, TriggerPrimitiveCollection>& selected_me0_map,
488  std::map<int, TriggerPrimitiveCollection>& selected_prim_map) const {
489  // First, put CSC hits
490  std::map<int, TriggerPrimitiveCollection>::const_iterator map_tp_it = selected_csc_map.begin();
491  std::map<int, TriggerPrimitiveCollection>::const_iterator map_tp_end = selected_csc_map.end();
492 
493  for (; map_tp_it != map_tp_end; ++map_tp_it) {
494  int selected_csc = map_tp_it->first;
495  const TriggerPrimitiveCollection& csc_primitives = map_tp_it->second;
496  emtf_assert(csc_primitives.size() <= 4); // at most 4 hits, including duplicated hits
497 
498  // Insert all CSC hits
499  selected_prim_map[selected_csc] = csc_primitives;
500  }
501 
502  // Second, insert GEM stubs if there is no CSC hits
503  map_tp_it = selected_gem_map.begin();
504  map_tp_end = selected_gem_map.end();
505 
506  for (; map_tp_it != map_tp_end; ++map_tp_it) {
507  int selected_gem = map_tp_it->first;
508  const TriggerPrimitiveCollection& gem_primitives = map_tp_it->second;
509  if (gem_primitives.empty())
510  continue;
511  emtf_assert(gem_primitives.size() <= 8); // at most 8 hits
512 
513  bool found = (selected_prim_map.find(selected_gem) != selected_prim_map.end());
514  if (!found) {
515  // No CSC hits, insert all GEM hits
516  selected_prim_map[selected_gem] = gem_primitives;
517 
518  } else {
519  // Do nothing
520  }
521  }
522 
523  // Third, insert RPC stubs if there is no CSC/GEM hits
524  map_tp_it = selected_rpc_map.begin();
525  map_tp_end = selected_rpc_map.end();
526 
527  for (; map_tp_it != map_tp_end; ++map_tp_it) {
528  int selected_rpc = map_tp_it->first;
529  const TriggerPrimitiveCollection& rpc_primitives = map_tp_it->second;
530  if (rpc_primitives.empty())
531  continue;
532  emtf_assert(rpc_primitives.size() <= 4); // at most 4 hits
533 
534  bool found = (selected_prim_map.find(selected_rpc) != selected_prim_map.end());
535  if (!found) {
536  // No CSC/GEM hits, insert all RPC hits
537  //selected_prim_map[selected_rpc] = rpc_primitives;
538 
539  // No CSC/GEM hits, insert the valid RPC hits
540  TriggerPrimitiveCollection tmp_rpc_primitives;
541  for (const auto& tp : rpc_primitives) {
542  if (tp.getRPCData().valid != 0) {
543  tmp_rpc_primitives.push_back(tp);
544  }
545  }
546  emtf_assert(tmp_rpc_primitives.size() <= 2); // at most 2 hits
547 
548  selected_prim_map[selected_rpc] = tmp_rpc_primitives;
549 
550  } else {
551  // Initial FW in 2017; was disabled on June 7.
552  // If only one CSC/GEM hit, insert the first RPC hit
553  //TriggerPrimitiveCollection& tmp_primitives = selected_prim_map[selected_rpc]; // pass by reference
554 
555  //if (tmp_primitives.size() < 2) {
556  // tmp_primitives.push_back(rpc_primitives.front());
557  //}
558  }
559  }
560 }
561 
562 void PrimitiveSelection::merge_no_truncate(const std::map<int, TriggerPrimitiveCollection>& selected_dt_map,
563  const std::map<int, TriggerPrimitiveCollection>& selected_csc_map,
564  const std::map<int, TriggerPrimitiveCollection>& selected_rpc_map,
565  const std::map<int, TriggerPrimitiveCollection>& selected_gem_map,
566  const std::map<int, TriggerPrimitiveCollection>& selected_me0_map,
567  std::map<int, TriggerPrimitiveCollection>& selected_prim_map) const {
568  // First, put CSC hits
569  merge_map_into_map(selected_csc_map, selected_prim_map);
570 
571  // Second, insert ME0 hits
572  merge_map_into_map(selected_me0_map, selected_prim_map);
573 
574  // Third, insert GEM hits
575  merge_map_into_map(selected_gem_map, selected_prim_map);
576 
577  // Fourth, insert RPC hits
578  merge_map_into_map(selected_rpc_map, selected_prim_map);
579 
580  // Fifth, insert DT hits
581  merge_map_into_map(selected_dt_map, selected_prim_map);
582 }
583 
584 // _____________________________________________________________________________
585 // CSC functions
586 int PrimitiveSelection::select_csc(const TriggerPrimitive& muon_primitive) const {
587  int selected = -1;
588 
589  if (muon_primitive.subsystem() == L1TMuon::kCSC) {
590  const CSCDetId& tp_detId = muon_primitive.detId<CSCDetId>();
591  const CSCData& tp_data = muon_primitive.getCSCData();
592 
593  int tp_endcap = tp_detId.endcap();
594  int tp_sector = tp_detId.triggerSector();
595  int tp_station = tp_detId.station();
596  int tp_ring = tp_detId.ring();
597  int tp_chamber = tp_detId.chamber();
598 
599  int tp_bx = tp_data.bx;
600  int tp_csc_ID = tp_data.cscID;
601 
602  const auto& [max_strip, max_wire] = emtf::get_csc_max_strip_and_wire(tp_station, tp_ring);
603  const auto& [max_pattern, max_quality] = emtf::get_csc_max_pattern_and_quality(tp_station, tp_ring);
604 
605  if (endcap_ == 1 && sector_ == 1 && bx_ == -3) { // do assertion checks only once
606  emtf_assert(emtf::MIN_ENDCAP <= tp_endcap && tp_endcap <= emtf::MAX_ENDCAP);
607  emtf_assert(emtf::MIN_TRIGSECTOR <= tp_sector && tp_sector <= emtf::MAX_TRIGSECTOR);
608  emtf_assert(1 <= tp_station && tp_station <= 4);
609  emtf_assert(1 <= tp_csc_ID && tp_csc_ID <= 9);
610  emtf_assert(tp_data.strip < max_strip);
611  emtf_assert(tp_data.keywire < max_wire);
612  emtf_assert(tp_data.valid == true);
613  emtf_assert(tp_data.pattern < max_pattern);
614  emtf_assert(0 < tp_data.quality && tp_data.quality < max_quality);
615  }
616 
617  // Check for corrupted LCT data. Data corruption could occur due to software or hardware issues, If corrupted, reject the LCT.
618  // Note that the checks are performed in every sector processor for every BX. As a result, the same LCT may be reported multiple times by all 12 sector processors from BX=-3 to BX=+3.
619  {
620  if (!(tp_data.strip < max_strip)) {
621  edm::LogWarning("L1T") << "Found error in LCT strip: " << tp_data.strip << " (allowed range: 0-"
622  << max_strip - 1 << ").";
623  edm::LogWarning("L1T")
624  << "From endcap " << tp_endcap << ", sector " << tp_sector << ", station " << tp_station << ", ring "
625  << tp_ring << ", cscid " << tp_csc_ID
626  << ". (Note that this LCT may be reported multiple times. See source code for explanations.)";
627  return selected;
628  }
629 
630  if (!(tp_data.keywire < max_wire)) {
631  edm::LogWarning("L1T") << "Found error in LCT wire: " << tp_data.keywire << " (allowed range: 0-"
632  << max_wire - 1 << ").";
633  edm::LogWarning("L1T")
634  << "From endcap " << tp_endcap << ", sector " << tp_sector << ", station " << tp_station << ", ring "
635  << tp_ring << ", cscid " << tp_csc_ID
636  << ". (Note that this LCT may be reported multiple times. See source code for explanations.)";
637  return selected;
638  }
639 
640  if (!(tp_data.valid == true)) {
641  edm::LogWarning("L1T") << "Found error in LCT valid: " << tp_data.valid << " (allowed value: 1).";
642  edm::LogWarning("L1T")
643  << "From endcap " << tp_endcap << ", sector " << tp_sector << ", station " << tp_station << ", ring "
644  << tp_ring << ", cscid " << tp_csc_ID
645  << ". (Note that this LCT may be reported multiple times. See source code for explanations.)";
646  return selected;
647  }
648 
649  if (!(tp_data.pattern < max_pattern)) {
650  edm::LogWarning("L1T") << "Found error in LCT pattern: " << tp_data.pattern << " (allowed range: 0-"
651  << max_pattern - 1 << ").";
652  edm::LogWarning("L1T")
653  << "From endcap " << tp_endcap << ", sector " << tp_sector << ", station " << tp_station << ", ring "
654  << tp_ring << ", cscid " << tp_csc_ID
655  << ". (Note that this LCT may be reported multiple times. See source code for explanations.)";
656  return selected;
657  }
658 
659  if (!(0 < tp_data.quality && tp_data.quality < max_quality)) {
660  edm::LogWarning("L1T") << "Found error in LCT quality: " << tp_data.quality << " (allowed range: 1-"
661  << max_quality - 1 << ").";
662  edm::LogWarning("L1T")
663  << "From endcap " << tp_endcap << ", sector " << tp_sector << ", station " << tp_station << ", ring "
664  << tp_ring << ", cscid " << tp_csc_ID
665  << ". (Note that this LCT may be reported multiple times. See source code for explanations.)";
666  return selected;
667  }
668  } // end check for corrupted LCT data
669 
670  // station 1 --> subsector 1 or 2
671  // station 2,3,4 --> subsector 0
672  int tp_subsector = (tp_station != 1) ? 0 : ((tp_chamber % 6 > 2) ? 1 : 2);
673 
674  // Check if the chamber belongs to this sector processor at this BX.
675  selected = get_index_csc(tp_endcap, tp_sector, tp_subsector, tp_station, tp_csc_ID, tp_bx);
676  }
677  return selected;
678 }
679 
680 bool PrimitiveSelection::is_in_sector_csc(int tp_endcap, int tp_sector) const {
681  return ((endcap_ == tp_endcap) && (sector_ == tp_sector));
682 }
683 
685  int tp_endcap, int tp_sector, int tp_subsector, int tp_station, int tp_csc_ID) const {
686  auto get_neighbor = [](int sector) { return (sector == 1) ? 6 : sector - 1; };
687 
688  if (includeNeighbor_) {
689  if ((endcap_ == tp_endcap) && (get_neighbor(sector_) == tp_sector)) {
690  if (tp_station == 1) {
691  if ((tp_subsector == 2) && (tp_csc_ID == 3 || tp_csc_ID == 6 || tp_csc_ID == 9))
692  return true;
693 
694  } else {
695  if (tp_csc_ID == 3 || tp_csc_ID == 9)
696  return true;
697  }
698  }
699  }
700  return false;
701 }
702 
703 bool PrimitiveSelection::is_in_bx_csc(int tp_bx) const {
704  tp_bx += bxShiftCSC_;
705  return (bx_ == tp_bx);
706 }
707 
708 // Returns CSC input "link". Index used by FW for unique chamber identification.
710  int tp_endcap, int tp_sector, int tp_subsector, int tp_station, int tp_csc_ID, int tp_bx) const {
711  int selected = -1;
712 
713  bool is_native = false;
714  bool is_neighbor = false;
715  if (is_in_bx_csc(tp_bx)) {
716  if (is_in_sector_csc(tp_endcap, tp_sector)) {
717  is_native = true;
718  } else if (is_in_neighbor_sector_csc(tp_endcap, tp_sector, tp_subsector, tp_station, tp_csc_ID)) {
719  is_neighbor = true;
720  }
721  }
722  if (!is_native && !is_neighbor)
723  return selected;
724 
725  if (!is_neighbor) {
726  if (tp_station == 1) { // ME1: 0 - 8, 9 - 17
727  selected = (tp_subsector - 1) * 9 + (tp_csc_ID - 1);
728  } else { // ME2,3,4: 18 - 26, 27 - 35, 36 - 44
729  selected = (tp_station)*9 + (tp_csc_ID - 1);
730  }
731 
732  } else {
733  if (tp_station == 1) { // ME1n: 45 - 47
734  selected = (5) * 9 + (tp_csc_ID - 1) / 3;
735  } else { // ME2n,3n,4n: 48 - 53
736  selected = (5) * 9 + (tp_station)*2 - 1 + (tp_csc_ID - 1 < 3 ? 0 : 1);
737  }
738  }
739  emtf_assert(selected != -1);
740  return selected;
741 }
742 
743 // _____________________________________________________________________________
744 // RPC functions
745 int PrimitiveSelection::select_rpc(const TriggerPrimitive& muon_primitive) const {
746  int selected = -1;
747 
748  if (muon_primitive.subsystem() == L1TMuon::kRPC) {
749  const RPCDetId& tp_detId = muon_primitive.detId<RPCDetId>();
750  const RPCData& tp_data = muon_primitive.getRPCData();
751 
752  int tp_region = tp_detId.region(); // 0 for Barrel, +/-1 for +/- Endcap
753  int tp_endcap = (tp_region == -1) ? 2 : tp_region;
754  int tp_sector = tp_detId.sector(); // 1 - 6 (60 degrees in phi, sector 1 begins at -5 deg)
755  int tp_subsector = tp_detId.subsector(); // 1 - 6 (10 degrees in phi; staggered in z)
756  int tp_station = tp_detId.station(); // 1 - 4
757  int tp_ring = tp_detId.ring(); // 2 - 3 (increasing theta)
758  int tp_roll = tp_detId.roll(); // 1 - 3 (decreasing theta; aka A - C; space between rolls is 9 - 15 in theta_fp)
759  //int tp_layer = tp_detId.layer();
760 
761  int tp_bx = tp_data.bx;
762  int tp_strip = tp_data.strip;
763  int tp_emtf_sect = tp_data.emtf_sector;
764  bool tp_CPPF = tp_data.isCPPF;
765 
766  // In neighbor chambers, have two separate CPPFDigis for the two EMTF sectors
767  if (tp_CPPF && (tp_emtf_sect != sector_))
768  return selected;
769 
770  const bool is_irpc = (tp_station == 3 || tp_station == 4) && (tp_ring == 1);
771 
772  if (endcap_ == 1 && sector_ == 1 && bx_ == -3) { // do assertion checks only once
773  emtf_assert(tp_region != 0);
774  emtf_assert(emtf::MIN_ENDCAP <= tp_endcap && tp_endcap <= emtf::MAX_ENDCAP);
775  emtf_assert(emtf::MIN_TRIGSECTOR <= tp_sector && tp_sector <= emtf::MAX_TRIGSECTOR);
776  emtf_assert(1 <= tp_subsector && tp_subsector <= 6);
777  emtf_assert(1 <= tp_station && tp_station <= 4);
778  emtf_assert((!is_irpc && 2 <= tp_ring && tp_ring <= 3) || (is_irpc && tp_ring == 1));
779  emtf_assert((!is_irpc && 1 <= tp_roll && tp_roll <= 3) || (is_irpc && 1 <= tp_roll && tp_roll <= 5));
780  //emtf_assert((!is_irpc && (tp_CPPF || (1 <= tp_strip && tp_strip <= 32))) || (is_irpc && 1 <= tp_strip && tp_strip <= 96));
781  emtf_assert((!is_irpc && (tp_CPPF || (1 <= tp_strip && tp_strip <= 32))) ||
782  (is_irpc && 1 <= tp_strip && tp_strip <= 96 * 2)); // in CMSSW, the iRPC chamber has 192 strips
783  //emtf_assert(tp_station > 2 || tp_ring != 3); // stations 1 and 2 do not receive RPCs from ring 3
784  emtf_assert(tp_data.valid == true);
785  }
786 
787  // Check if the chamber belongs to this sector processor at this BX.
788  selected = get_index_rpc(tp_endcap, tp_station, tp_ring, tp_sector, tp_subsector, tp_bx);
789  }
790  return selected;
791 }
792 
794  int tp_endcap, int tp_station, int tp_ring, int tp_sector, int tp_subsector) const {
795  // RPC sector X, subsectors 1-2 correspond to CSC sector X-1
796  // RPC sector X, subsectors 3-6 correspond to CSC sector X
797  // iRPC sector X, subsectors 1 correspond to CSC sector X-1
798  // iRPC sector X, subsectors 2-3 correspind to CSC sector X
799  auto get_csc_sector = [](int tp_station, int tp_ring, int tp_sector, int tp_subsector) {
800  const bool is_irpc = (tp_station == 3 || tp_station == 4) && (tp_ring == 1);
801  if (is_irpc) {
802  // 20 degree chamber
803  int corr = (tp_subsector < 2) ? (tp_sector == 1 ? +5 : -1) : 0;
804  return tp_sector + corr;
805  } else {
806  // 10 degree chamber
807  int corr = (tp_subsector < 3) ? (tp_sector == 1 ? +5 : -1) : 0;
808  return tp_sector + corr;
809  }
810  };
811  return ((endcap_ == tp_endcap) && (sector_ == get_csc_sector(tp_station, tp_ring, tp_sector, tp_subsector)));
812 }
813 
815  int tp_endcap, int tp_station, int tp_ring, int tp_sector, int tp_subsector) const {
816  auto get_neighbor_subsector = [](int tp_station, int tp_ring) {
817  const bool is_irpc = (tp_station == 3 || tp_station == 4) && (tp_ring == 1);
818  if (is_irpc) {
819  // 20 degree chamber
820  return 1;
821  } else {
822  // 10 degree chamber
823  return 2;
824  }
825  };
826  return (includeNeighbor_ && (endcap_ == tp_endcap) && (sector_ == tp_sector) &&
827  (tp_subsector == get_neighbor_subsector(tp_station, tp_ring)));
828 }
829 
830 bool PrimitiveSelection::is_in_bx_rpc(int tp_bx) const {
831  tp_bx += bxShiftRPC_;
832  return (bx_ == tp_bx);
833 }
834 
836  int tp_endcap, int tp_station, int tp_ring, int tp_sector, int tp_subsector, int tp_bx) const {
837  int selected = -1;
838 
839  bool is_native = false;
840  bool is_neighbor = false;
841  if (is_in_bx_rpc(tp_bx)) {
842  if (is_in_sector_rpc(tp_endcap, tp_station, tp_ring, tp_sector, tp_subsector)) {
843  is_native = true;
844  } else if (is_in_neighbor_sector_rpc(tp_endcap, tp_station, tp_ring, tp_sector, tp_subsector)) {
845  is_neighbor = true;
846  }
847  }
848  if (!is_native && !is_neighbor)
849  return selected;
850 
851  // CPPF RX data come in 3 frames x 64 bits, for 7 links. Each 64-bit data
852  // carry 2 words of 32 bits. Each word carries phi (11 bits) and theta (5 bits)
853  // of 2 segments (x2).
854  //
855  // Firmware uses 'rpc_sub' as RPC subsector index and 'rpc_chm' as RPC chamber index
856  // rpc_sub [0,6] = RPC subsector 3, 4, 5, 6, 1 from neighbor, 2 from neighbor, 2. They correspond to
857  // CSC sector phi 0-10 deg, 10-20, 20-30, 30-40, 40-50, 50-60, 50-60 from neighbor
858  // rpc_chm [0,5] = RPC chamber RE1/2, RE2/2, RE3/2, RE3/3, RE4/2, RE4/3
859  // For Phase 2, add RE1/3, RE2/3, RE3/1, RE4/1 -> rpc_chm [0,9]
860  //
861  int rpc_sub = -1;
862  int rpc_chm = -1;
863 
864  const bool is_irpc = (tp_station == 3 || tp_station == 4) && (tp_ring == 1);
865 
866  if (!is_neighbor) {
867  if (!is_irpc) {
868  rpc_sub = ((tp_subsector + 3) % 6);
869  } else {
870  rpc_sub = ((tp_subsector + 1) % 3);
871  }
872  } else {
873  rpc_sub = 6;
874  }
875 
876  if (tp_station <= 2 && tp_ring == 2) { // RE1/2, RE2/2
877  rpc_chm = (tp_station - 1);
878  } else if (tp_station >= 3 && tp_ring >= 2) { // RE3/2, RE3/3, RE4/2, RE4/3
879  rpc_chm = 2 + (tp_station - 3) * 2 + (tp_ring - 2);
880  } else if (tp_station <= 2 && tp_ring == 3) { // RE1/3, RE2/3
881  rpc_chm = 6 + (tp_station - 1);
882  } else if (tp_station >= 3 && tp_ring == 1) { // RE3/1, RE4/1
883  rpc_chm = 8 + (tp_station - 3);
884  }
885 
886  selected = (rpc_sub * 10) + rpc_chm;
887  emtf_assert(selected != -1);
888  return selected;
889 }
890 
891 // _____________________________________________________________________________
892 // GEM functions
893 //
894 // According to what I know at the moment
895 // - GE1/1: 10 degree chamber, 8 rolls, 384 strips = 192 pads
896 // - GE2/1: 20 degree chamber, 8 rolls, 768 strips = 384 pads
897 int PrimitiveSelection::select_gem(const TriggerPrimitive& muon_primitive) const {
898  int selected = -1;
899 
900  if (muon_primitive.subsystem() == L1TMuon::kGEM) {
901  const GEMDetId& tp_detId = muon_primitive.detId<GEMDetId>();
902  const GEMData& tp_data = muon_primitive.getGEMData();
903 
904  int tp_region = tp_detId.region(); // 0 for Barrel, +/-1 for +/- Endcap
905  int tp_endcap = (tp_region == -1) ? 2 : tp_region;
906  int tp_station = tp_detId.station();
907  int tp_ring = tp_detId.ring();
908  int tp_roll = tp_detId.roll();
909  int tp_layer = tp_detId.layer();
910  int tp_chamber = tp_detId.chamber();
911 
912  int tp_bx = tp_data.bx;
913  int tp_pad = ((tp_data.pad_low + tp_data.pad_hi) / 2);
914 
915  int tp_sector = emtf::get_trigger_sector(tp_ring, tp_station, tp_chamber);
916  int tp_csc_ID = emtf::get_trigger_csc_ID(tp_ring, tp_station, tp_chamber);
917 
918  // station 1 --> subsector 1 or 2
919  // station 2,3,4 --> subsector 0
920  int tp_subsector = (tp_station != 1) ? 0 : ((tp_chamber % 6 > 2) ? 1 : 2);
921 
922  if (endcap_ == 1 && sector_ == 1 && bx_ == -3) { // do assertion checks only once
923  emtf_assert(tp_region != 0);
924  emtf_assert(emtf::MIN_ENDCAP <= tp_endcap && tp_endcap <= emtf::MAX_ENDCAP);
925  emtf_assert(emtf::MIN_TRIGSECTOR <= tp_sector && tp_sector <= emtf::MAX_TRIGSECTOR);
926  emtf_assert(1 <= tp_station && tp_station <= 2);
927  emtf_assert(tp_ring == 1);
928  emtf_assert(1 <= tp_roll && tp_roll <= 8);
929  emtf_assert(1 <= tp_layer && tp_layer <= 2);
930  emtf_assert(1 <= tp_csc_ID && tp_csc_ID <= 3);
931  emtf_assert((tp_station == 1 && 0 <= tp_pad && tp_pad <= 191) || (tp_station != 1));
932  emtf_assert((tp_station == 2 && 0 <= tp_pad && tp_pad <= 383) || (tp_station != 2));
933  }
934 
935  // Check if the chamber belongs to this sector processor at this BX.
936  selected = get_index_gem(tp_endcap, tp_sector, tp_subsector, tp_station, tp_csc_ID, tp_bx);
937  }
938  return selected;
939 }
940 
941 bool PrimitiveSelection::is_in_sector_gem(int tp_endcap, int tp_sector) const {
942  // Identical to the corresponding CSC function
943  return is_in_sector_csc(tp_endcap, tp_sector);
944 }
945 
947  int tp_endcap, int tp_sector, int tp_subsector, int tp_station, int tp_csc_ID) const {
948  // Identical to the corresponding CSC function
949  return is_in_neighbor_sector_csc(tp_endcap, tp_sector, tp_subsector, tp_station, tp_csc_ID);
950 }
951 
952 bool PrimitiveSelection::is_in_bx_gem(int tp_bx) const {
953  tp_bx += bxShiftGEM_;
954  return (bx_ == tp_bx);
955 }
956 
958  int tp_endcap, int tp_sector, int tp_subsector, int tp_station, int tp_csc_ID, int tp_bx) const {
959  int selected = -1;
960 
961  bool is_native = false;
962  bool is_neighbor = false;
963  if (is_in_bx_gem(tp_bx)) {
964  if (is_in_sector_gem(tp_endcap, tp_sector)) {
965  is_native = true;
966  } else if (is_in_neighbor_sector_gem(tp_endcap, tp_sector, tp_subsector, tp_station, tp_csc_ID)) {
967  is_neighbor = true;
968  }
969  }
970  if (!is_native && !is_neighbor)
971  return selected;
972 
973  if (!is_neighbor) {
974  if (tp_station == 1) { // GE1/1: 0 - 5
975  selected = (tp_subsector - 1) * 3 + (tp_csc_ID - 1);
976  } else { // GE2/1: 6 - 8
977  selected = 6 + (tp_csc_ID - 1);
978  }
979 
980  } else {
981  if (tp_station == 1) { // GE1/1n: 12
982  selected = 12;
983  } else { // GE2/1n: 13
984  selected = 13;
985  }
986  }
987  emtf_assert(selected != -1);
988  return selected;
989 }
990 
991 // _____________________________________________________________________________
992 // ME0 functions
993 //
994 // According to what I know at the moment
995 // - ME0: 20 degree chamber, 8 rolls, 384 strips = 192 pads
996 int PrimitiveSelection::select_me0(const TriggerPrimitive& muon_primitive) const {
997  int selected = -1;
998 
999  if (muon_primitive.subsystem() == L1TMuon::kME0) {
1000  const ME0DetId& tp_detId = muon_primitive.detId<ME0DetId>();
1001  const ME0Data& tp_data = muon_primitive.getME0Data();
1002 
1003  int tp_region = tp_detId.region(); // 0 for Barrel, +/-1 for +/- Endcap
1004  int tp_endcap = (tp_region == -1) ? 2 : tp_region;
1005  int tp_station = tp_detId.station();
1006  int tp_ring = 1; // tp_detId.ring() does not exist
1007  //int tp_roll = tp_detId.roll();
1008  //int tp_layer = tp_detId.layer();
1009  int tp_chamber = tp_detId.chamber();
1010 
1011  int tp_bx = tp_data.bx;
1012  int tp_pad = tp_data.phiposition;
1013  int tp_partition = tp_data.partition;
1014 
1015  // The ME0 geometry is similar to ME2/1, so I use tp_station = 2, tp_ring = 1
1016  // when calling get_trigger_sector() and get_trigger_csc_ID()
1017  int tp_sector = emtf::get_trigger_sector(1, 2, tp_chamber);
1018  int tp_csc_ID = emtf::get_trigger_csc_ID(1, 2, tp_chamber);
1019  int tp_subsector = 0;
1020 
1021  if (endcap_ == 1 && sector_ == 1 && bx_ == -3) { // do assertion checks only once
1022  emtf_assert(tp_region != 0);
1023  emtf_assert(emtf::MIN_ENDCAP <= tp_endcap && tp_endcap <= emtf::MAX_ENDCAP);
1024  emtf_assert(emtf::MIN_TRIGSECTOR <= tp_sector && tp_sector <= emtf::MAX_TRIGSECTOR);
1025  emtf_assert(tp_station == 1);
1026  emtf_assert(tp_ring == 1);
1027  //emtf_assert(1 <= tp_roll && tp_roll <= 8); // not set
1028  //emtf_assert(1 <= tp_layer && tp_layer <= 6); // not set
1029  emtf_assert(1 <= tp_csc_ID && tp_csc_ID <= 3);
1030  emtf_assert(0 <= tp_pad && tp_pad <= 767);
1031  emtf_assert(0 <= tp_partition && tp_partition <= 15);
1032  }
1033 
1034  // Check if the chamber belongs to this sector processor at this BX.
1035  selected = get_index_me0(tp_endcap, tp_sector, tp_subsector, tp_station, tp_csc_ID, tp_pad, tp_bx);
1036  }
1037  return selected;
1038 }
1039 
1040 bool PrimitiveSelection::is_in_sector_me0(int tp_endcap, int tp_sector, int tp_csc_ID, int tp_pad) const {
1041  // Similar to the corresponding CSC function, but requires a 5 deg shift
1042  // because the CSC chamber 1 starts at -5 deg, but the ME0 chamber 1 starts
1043  // at -10 deg.
1044  // This means that in sector 1, CSC chambers cover 15 to 75 deg, but ME0
1045  // chambers cover 10 to 70 deg. 5 deg (1/4 of chamber) needs to be added
1046  // to cover 70 to 75 deg, and 5 deg needs to be subtracted from 10 to 15 deg.
1047  auto get_other_neighbor = [](int sector) { return (sector == 6) ? 1 : sector + 1; };
1048 
1049  bool add5deg = false;
1050  bool sub5deg = false;
1051  if (includeNeighbor_) {
1052  if ((endcap_ == tp_endcap) && (get_other_neighbor(sector_) == tp_sector)) {
1053  if (tp_csc_ID == 1 && tp_endcap == 1 && tp_pad >= (767 - 192)) { // higher 1/4 of chamber
1054  add5deg = true;
1055  } else if (tp_csc_ID == 1 && tp_endcap == 2 && tp_pad <= 191) { // lower 1/4 of chamber
1056  add5deg = true;
1057  }
1058  }
1059  if ((endcap_ == tp_endcap) && (sector_ == tp_sector)) {
1060  if (tp_csc_ID == 1 && tp_endcap == 1 && tp_pad >= (767 - 192)) { // higher 1/4 of chamber
1061  sub5deg = true;
1062  } else if (tp_csc_ID == 1 && tp_endcap == 2 && tp_pad <= 191) { // lower 1/4 of chamber
1063  sub5deg = true;
1064  }
1065  }
1066  }
1067  return (is_in_sector_csc(tp_endcap, tp_sector) && !sub5deg) || add5deg;
1068 }
1069 
1070 bool PrimitiveSelection::is_in_neighbor_sector_me0(int tp_endcap, int tp_sector, int tp_csc_ID, int tp_pad) const {
1071  // Similar to the corresponding CSC function, but requires a 5 deg shift
1072  // because the CSC chamber 1 starts at -5 deg, but the ME0 chamber 1 starts
1073  // at -10 deg.
1074  // This means that in sector 1, CSC chamber from the neighbor sector
1075  // covers -5 to 15 deg, but ME0 chamber from the neighbor sector covers
1076  // -10 to 10 deg. 5 deg (1/4 of chamber) needs to be subtracted from
1077  // -10 to -5 deg, and 5 deg needs to be added to cover 10 to 15 deg.
1078  auto get_neighbor = [](int sector) { return (sector == 1) ? 6 : sector - 1; };
1079 
1080  bool add5deg = false;
1081  bool sub5deg = false;
1082  if (includeNeighbor_) {
1083  if ((endcap_ == tp_endcap) && (get_neighbor(sector_) == tp_sector)) {
1084  if (tp_csc_ID == 3 && tp_endcap == 1 && tp_pad >= (767 - 192)) { // higher 1/4 of chamber
1085  sub5deg = true;
1086  } else if (tp_csc_ID == 3 && tp_endcap == 2 && tp_pad <= 191) { // lower 1/4 of chamber
1087  sub5deg = true;
1088  }
1089  }
1090  if ((endcap_ == tp_endcap) && (sector_ == tp_sector)) {
1091  if (tp_csc_ID == 1 && tp_endcap == 1 && tp_pad >= (767 - 192)) { // higher 1/4 of chamber
1092  add5deg = true;
1093  } else if (tp_csc_ID == 1 && tp_endcap == 2 && tp_pad <= 191) { // lower 1/4 of chamber
1094  add5deg = true;
1095  }
1096  }
1097  }
1098  // (Note: use tp_subsector = 0, tp_station = 2)
1099  return (is_in_neighbor_sector_csc(tp_endcap, tp_sector, 0, 2, tp_csc_ID) && !sub5deg) || add5deg;
1100 }
1101 
1102 bool PrimitiveSelection::is_in_bx_me0(int tp_bx) const {
1103  tp_bx += bxShiftME0_;
1104  return (bx_ == tp_bx);
1105 }
1106 
1108  int tp_endcap, int tp_sector, int tp_subsector, int tp_station, int tp_csc_ID, int tp_pad, int tp_bx) const {
1109  int selected = -1;
1110 
1111  bool is_native = false;
1112  bool is_neighbor = false;
1113  if (is_in_bx_me0(tp_bx)) {
1114  if (is_in_sector_me0(tp_endcap, tp_sector, tp_csc_ID, tp_pad)) {
1115  is_native = true;
1116  } else if (is_in_neighbor_sector_me0(tp_endcap, tp_sector, tp_csc_ID, tp_pad)) {
1117  is_neighbor = true;
1118  }
1119  }
1120  if (!is_native && !is_neighbor)
1121  return selected;
1122 
1123  if (!is_neighbor) { // ME0: 9 - 11
1124  selected = 9 + (tp_csc_ID - 1);
1125  } else { // ME0n: 14
1126  selected = 14;
1127  }
1128  emtf_assert(selected != -1);
1129  return selected;
1130 }
1131 
1132 // _____________________________________________________________________________
1133 // DT functions
1134 int PrimitiveSelection::select_dt(const TriggerPrimitive& muon_primitive) const {
1135  int selected = -1;
1136 
1137  if (muon_primitive.subsystem() == L1TMuon::kDT) {
1138  const DTChamberId& tp_detId = muon_primitive.detId<DTChamberId>();
1139  const DTData& tp_data = muon_primitive.getDTData();
1140 
1141  int tp_wheel = tp_detId.wheel();
1142  int tp_station = tp_detId.station();
1143  int tp_sector = tp_detId.sector(); // sectors are 1-12, starting at phi=0 and increasing with phi
1144 
1145  // In station 4, where the top and bottom sectors are made of two chambers,
1146  // two additional sector numbers are used, 13 (after sector 4, top)
1147  // and 14 (after sector 10, bottom).
1148  if (tp_station == 4) {
1149  if (tp_sector == 13)
1150  tp_sector = 4;
1151  else if (tp_sector == 14)
1152  tp_sector = 10;
1153  }
1154 
1155  int tp_bx = tp_data.bx;
1156  int tp_phi = tp_data.radialAngle;
1157  //int tp_phiB = tp_data.bendingAngle;
1158 
1159  // Mimic 10 deg CSC chamber. I use tp_station = 2, tp_ring = 2
1160  // when calling get_trigger_sector() and get_trigger_csc_ID()
1161  int tp_chamber =
1162  tp_sector * 3 - 1; // DT chambers are 30 deg. Multiply sector number by 3 to mimic 10 deg CSC chamber number
1163  int tp_endcap = (tp_wheel > 0) ? 1 : ((tp_wheel < 0) ? 2 : 0);
1164  int csc_tp_sector = emtf::get_trigger_sector(2, 2, tp_chamber);
1165  int tp_csc_ID = emtf::get_trigger_csc_ID(2, 2, tp_chamber);
1166  int tp_subsector = 0;
1167 
1168  if (endcap_ == 1 && sector_ == 1 && bx_ == -3) { // do assertion checks only once
1169  //emtf_assert(-2 <= tp_wheel && tp_wheel <= +2);
1170  emtf_assert(tp_wheel == -2 || tp_wheel == +2); // do not include wheels -1, 0, +1
1171  //emtf_assert(1 <= tp_station && tp_station <= 4);
1172  emtf_assert(1 <= tp_station && tp_station <= 3); // do not include MB4
1173  emtf_assert(1 <= tp_sector && tp_sector <= 12);
1174  emtf_assert(emtf::MIN_ENDCAP <= tp_endcap && tp_endcap <= emtf::MAX_ENDCAP);
1175  emtf_assert(emtf::MIN_TRIGSECTOR <= csc_tp_sector && csc_tp_sector <= emtf::MAX_TRIGSECTOR);
1176  //emtf_assert(4 <= tp_csc_ID && tp_csc_ID <= 9);
1177  emtf_assert(tp_csc_ID == 6 || tp_csc_ID == 9);
1178  emtf_assert(-2048 <= tp_phi && tp_phi <= 2047); // 12-bit
1179  //emtf_assert(-512 <= tp_phiB && tp_phiB <= 511); // 10-bit
1180  }
1181 
1182  // Check if the chamber belongs to this sector processor at this BX.
1183  selected = get_index_dt(tp_endcap, csc_tp_sector, tp_subsector, tp_station, tp_csc_ID, tp_bx);
1184  }
1185  return selected;
1186 }
1187 
1188 bool PrimitiveSelection::is_in_sector_dt(int tp_endcap, int tp_sector) const {
1189  // Identical to the corresponding CSC function
1190  return is_in_sector_csc(tp_endcap, tp_sector);
1191 }
1192 
1193 bool PrimitiveSelection::is_in_neighbor_sector_dt(int tp_endcap, int tp_sector, int tp_csc_ID) const {
1194  // Identical to the corresponding CSC function
1195  // (Note: use tp_subsector = 0, tp_station = 2)
1196  return is_in_neighbor_sector_csc(tp_endcap, tp_sector, 0, 2, tp_csc_ID);
1197 }
1198 
1199 bool PrimitiveSelection::is_in_bx_dt(int tp_bx) const {
1200  //tp_bx += bxShiftDT_;
1201  return (bx_ == tp_bx);
1202 }
1203 
1205  int tp_endcap, int csc_tp_sector, int tp_subsector, int tp_station, int tp_csc_ID, int tp_bx) const {
1206  int selected = -1;
1207 
1208  bool is_native = false;
1209  bool is_neighbor = false;
1210  if (is_in_bx_dt(tp_bx)) {
1211  if (is_in_sector_dt(tp_endcap, csc_tp_sector)) {
1212  is_native = true;
1213  } else if (is_in_neighbor_sector_dt(tp_endcap, csc_tp_sector, tp_csc_ID)) {
1214  is_neighbor = true;
1215  }
1216  }
1217  if (!is_native && !is_neighbor)
1218  return selected;
1219 
1220  if (!is_neighbor) { // MB1,2,3,4: 0-7
1221  selected = (tp_station - 1) * 2 + (tp_csc_ID - 6) / 3; // tp_csc_ID should be either 6 or 9
1222  } else { // ME1,2,3,4n: 8-11
1223  selected = 8 + (tp_station - 1);
1224  }
1225  emtf_assert(selected != -1);
1226  return selected;
1227 }
int chamber() const
Definition: CSCDetId.h:62
constexpr int MIN_ENDCAP
Definition: Common.h:45
int get_index_rpc(int tp_endcap, int tp_station, int tp_ring, int tp_sector, int tp_subsector, int tp_bx) const
bool is_in_sector_dt(int tp_endcap, int tp_sector) const
bool is_in_sector_csc(int tp_endcap, int tp_sector) const
int get_trigger_sector(int ring, int station, int chamber)
Definition: TrackTools.cc:85
bool is_in_sector_me0(int tp_endcap, int tp_sector, int tp_csc_ID, int tp_pad) const
#define NUM_GEM_CHAMBERS
int get_index_gem(int tp_endcap, int tp_sector, int tp_subsector, int tp_station, int tp_csc_ID, int tp_bx) const
constexpr int roll() const
Definition: GEMDetId.h:194
int select_me0(const TriggerPrimitive &muon_primitive) const
#define NUM_RPC_CHAMBERS
#define NUM_DT_CHAMBERS
std::pair< int, int > get_csc_max_pattern_and_quality(int station, int ring)
Definition: TrackTools.cc:169
int ii
Definition: cuy.py:589
int station() const
Definition: ME0DetId.h:58
int select_gem(const TriggerPrimitive &muon_primitive) const
bool is_in_sector_gem(int tp_endcap, int tp_sector) const
bool is_in_sector_rpc(int tp_endcap, int tp_station, int tp_ring, int tp_sector, int tp_subsector) const
int get_trigger_csc_ID(int ring, int station, int chamber)
Definition: TrackTools.cc:100
bool is_in_neighbor_sector_me0(int tp_endcap, int tp_sector, int tp_csc_ID, int tp_pad) const
int endcap() const
Definition: CSCDetId.h:85
void configure(int verbose, int endcap, int sector, int bx, int bxShiftCSC, int bxShiftRPC, int bxShiftGEM, int bxShiftME0, bool includeNeighbor, bool duplicateTheta, bool bugME11Dupes)
constexpr int MIN_TRIGSECTOR
Definition: Common.h:49
int chamber() const
Chamber id: it identifies a chamber in a ring it goes from 1 to 36.
Definition: ME0DetId.h:41
bool is_in_bx_gem(int tp_bx) const
int roll() const
Definition: RPCDetId.h:92
static constexpr int verbose
void swap(edm::DataFrameContainer &lhs, edm::DataFrameContainer &rhs)
int ring() const
Definition: RPCDetId.h:59
bool is_in_bx_me0(int tp_bx) const
constexpr int region() const
Definition: GEMDetId.h:171
int select_rpc(const TriggerPrimitive &muon_primitive) const
int select_csc(const TriggerPrimitive &muon_primitive) const
void process(T tag, const TriggerPrimitiveCollection &muon_primitives, std::map< int, TriggerPrimitiveCollection > &selected_prim_map) const
bool is_in_neighbor_sector_csc(int tp_endcap, int tp_sector, int tp_subsector, int tp_station, int tp_csc_ID) const
bool is_in_bx_csc(int tp_bx) const
subsystem_type subsystem() const
int select_dt(const TriggerPrimitive &muon_primitive) const
int ring() const
Definition: CSCDetId.h:68
constexpr int chamber() const
Definition: GEMDetId.h:183
int get_index_me0(int tp_endcap, int tp_sector, int tp_subsector, int tp_station, int tp_csc_ID, int tp_pad, int tp_bx) const
constexpr int ring() const
Definition: GEMDetId.h:176
bool is_in_bx_rpc(int tp_bx) const
constexpr int layer() const
Definition: GEMDetId.h:190
bool is_in_neighbor_sector_dt(int tp_endcap, int tp_sector, int tp_csc_ID) const
int region() const
Region id: 0 for Barrel Not in use, +/-1 For +/- Endcap.
Definition: ME0DetId.h:38
#define emtf_assert(expr)
Definition: DebugTools.h:18
constexpr int station() const
Definition: GEMDetId.h:179
void merge_no_truncate(const std::map< int, TriggerPrimitiveCollection > &selected_dt_map, const std::map< int, TriggerPrimitiveCollection > &selected_csc_map, const std::map< int, TriggerPrimitiveCollection > &selected_rpc_map, const std::map< int, TriggerPrimitiveCollection > &selected_gem_map, const std::map< int, TriggerPrimitiveCollection > &selected_me0_map, std::map< int, TriggerPrimitiveCollection > &selected_prim_map) const
int triggerSector() const
Definition: CSCDetId.cc:3
std::pair< int, int > get_csc_max_strip_and_wire(int station, int ring)
Definition: TrackTools.cc:141
int sector() const
Sector id: the group of chambers at same phi (and increasing r)
Definition: RPCDetId.h:81
int subsector() const
SubSector id : some sectors are divided along the phi direction in subsectors (from 1 to 4 in Barrel...
Definition: RPCDetId.h:88
void merge(const std::map< int, TriggerPrimitiveCollection > &selected_dt_map, const std::map< int, TriggerPrimitiveCollection > &selected_csc_map, const std::map< int, TriggerPrimitiveCollection > &selected_rpc_map, const std::map< int, TriggerPrimitiveCollection > &selected_gem_map, const std::map< int, TriggerPrimitiveCollection > &selected_me0_map, std::map< int, TriggerPrimitiveCollection > &selected_prim_map) const
constexpr int MAX_ENDCAP
Definition: Common.h:46
int sector() const
Definition: DTChamberId.h:49
string end
Definition: dataset.py:937
int get_index_dt(int tp_endcap, int csc_tp_sector, int tp_subsector, int tp_station, int tp_csc_ID, int tp_bx) const
int station() const
Definition: CSCDetId.h:79
tuple cout
Definition: gather_cfg.py:144
constexpr int MAX_TRIGSECTOR
Definition: Common.h:50
bool is_in_bx_dt(int tp_bx) const
Log< level::Warning, false > LogWarning
int get_index_csc(int tp_endcap, int tp_sector, int tp_subsector, int tp_station, int tp_csc_ID, int tp_bx) const
int station() const
Return the station number.
Definition: DTChamberId.h:42
#define NUM_CSC_CHAMBERS
int wheel() const
Return the wheel number.
Definition: DTChamberId.h:39
Int_t triggerSector(Int_t station, Int_t ring, Int_t chamber) const
L1TMuon::TriggerPrimitiveCollection TriggerPrimitiveCollection
Definition: Common.h:32
tuple size
Write out results.
bool is_in_neighbor_sector_rpc(int tp_endcap, int tp_station, int tp_ring, int tp_sector, int tp_subsector) const
bool is_in_neighbor_sector_gem(int tp_endcap, int tp_sector, int tp_subsector, int tp_station, int tp_csc_ID) const
int region() const
Region id: 0 for Barrel, +/-1 For +/- Endcap.
Definition: RPCDetId.h:53
int station() const
Definition: RPCDetId.h:78