CMS 3D CMS Logo

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