CMS 3D CMS Logo

EMTFBlockME.cc
Go to the documentation of this file.
1 // Code to unpack the "ME Data Record"
2 
4 
5 #include "EMTFCollections.h"
6 #include "EMTFUnpackerTools.h"
7 
8 // This is the "header" - no EMTFBlockME.h file is needed
9 namespace l1t {
10  namespace stage2 {
11  namespace emtf {
12 
13  class MEBlockUnpacker : public Unpacker { // "MEBlockUnpacker" inherits from "Unpacker"
14  public:
15  virtual int checkFormat(const Block& block);
16  bool unpack(const Block& block,
17  UnpackerCollections* coll) override; // Apparently it's always good to use override in C++
18  // virtual bool packBlock(const Block& block, UnpackerCollections *coll) override;
19  };
20 
21  // class MEBlockPacker : public Packer { // "MEBlockPacker" inherits from "Packer"
22  // public:
23  // virtual bool unpack(const Block& block, UnpackerCollections *coll) override; // Apparently it's always good to use override in C++
24  // };
25 
26  } // namespace emtf
27  } // namespace stage2
28 } // namespace l1t
29 
30 namespace l1t {
31  namespace stage2 {
32  namespace emtf {
33 
35  auto payload = block.payload();
36  int errors = 0;
37 
38  // Check the number of 16-bit words
39  if (payload.size() != 4) {
40  errors += 1;
41  edm::LogError("L1T|EMTF") << "Payload size in 'ME Data Record' is different than expected";
42  }
43 
44  // Check that each word is 16 bits
45  for (unsigned int i = 0; i < 4; i++) {
46  if (GetHexBits(payload[i], 16, 31) != 0) {
47  errors += 1;
48  edm::LogError("L1T|EMTF") << "Payload[" << i << "] has more than 16 bits in 'ME Data Record'";
49  }
50  }
51 
52  uint16_t MEa = payload[0];
53  uint16_t MEb = payload[1];
54  uint16_t MEc = payload[2];
55  uint16_t MEd = payload[3];
56 
57  //Check Format
58  if (GetHexBits(MEa, 15, 15) != 1) {
59  errors += 1;
60  edm::LogError("L1T|EMTF") << "Format identifier bits in MEa are incorrect";
61  }
62  if (GetHexBits(MEb, 15, 15) != 1) {
63  errors += 1;
64  edm::LogError("L1T|EMTF") << "Format identifier bits in MEb are incorrect";
65  }
66  if (GetHexBits(MEc, 15, 15) != 0) {
67  errors += 1;
68  edm::LogError("L1T|EMTF") << "Format identifier bits in MEc are incorrect";
69  }
70  if (GetHexBits(MEd, 15, 15) != 0) {
71  errors += 1;
72  edm::LogError("L1T|EMTF") << "Format identifier bits in MEd are incorrect";
73  }
74 
75  return errors;
76  }
77 
78  // Converts station, CSC_ID, sector, subsector, and neighbor from the ME output
79  std::vector<int> convert_ME_location(int _station, int _csc_ID, int _sector, bool _csc_ID_shift = false) {
80  int new_sector = _sector;
81  int new_csc_ID = _csc_ID;
82  if (_csc_ID_shift)
83  new_csc_ID += 1; // Before FW update on 05.05.16, shift by +1 from 0,1,2... convention to 1,2,3...
84  if (_station == 0) {
85  int arr[] = {1, new_csc_ID, new_sector, 1, 0};
86  std::vector<int> vec(arr, arr + 5);
87  return vec;
88  } else if (_station == 1) {
89  int arr[] = {1, new_csc_ID, new_sector, 2, 0};
90  std::vector<int> vec(arr, arr + 5);
91  return vec;
92  } else if (_station <= 4) {
93  int arr[] = {_station, new_csc_ID, new_sector, -1, 0};
94  std::vector<int> vec(arr, arr + 5);
95  return vec;
96  } else if (_station == 5) {
97  new_sector = (_sector != 1) ? _sector - 1 : 6; // Indicates neighbor chamber, don't return yet
98  } else {
99  int arr[] = {_station, _csc_ID, _sector, -99, -99};
100  std::vector<int> vec(arr, arr + 5);
101  return vec;
102  }
103 
104  // Mapping for chambers from neighboring sector
105  if (new_csc_ID == 1) {
106  int arr[] = {1, 3, new_sector, 2, 1};
107  std::vector<int> vec(arr, arr + 5);
108  return vec;
109  } else if (new_csc_ID == 2) {
110  int arr[] = {1, 6, new_sector, 2, 1};
111  std::vector<int> vec(arr, arr + 5);
112  return vec;
113  } else if (new_csc_ID == 3) {
114  int arr[] = {1, 9, new_sector, 2, 1};
115  std::vector<int> vec(arr, arr + 5);
116  return vec;
117  } else if (new_csc_ID == 4) {
118  int arr[] = {2, 3, new_sector, -1, 1};
119  std::vector<int> vec(arr, arr + 5);
120  return vec;
121  } else if (new_csc_ID == 5) {
122  int arr[] = {2, 9, new_sector, -1, 1};
123  std::vector<int> vec(arr, arr + 5);
124  return vec;
125  } else if (new_csc_ID == 6) {
126  int arr[] = {3, 3, new_sector, -1, 1};
127  std::vector<int> vec(arr, arr + 5);
128  return vec;
129  } else if (new_csc_ID == 7) {
130  int arr[] = {3, 9, new_sector, -1, 1};
131  std::vector<int> vec(arr, arr + 5);
132  return vec;
133  } else if (new_csc_ID == 8) {
134  int arr[] = {4, 3, new_sector, -1, 1};
135  std::vector<int> vec(arr, arr + 5);
136  return vec;
137  } else if (new_csc_ID == 9) {
138  int arr[] = {4, 9, new_sector, -1, 1};
139  std::vector<int> vec(arr, arr + 5);
140  return vec;
141  } else {
142  int arr[] = {_station, _csc_ID, _sector, -99, -99};
143  std::vector<int> vec(arr, arr + 5);
144  return vec;
145  }
146  }
147 
149  // std::cout << "Inside EMTFBlockME.cc: unpack" << std::endl;
150 
151  // Get the payload for this block, made up of 16-bit words (0xffff)
152  // Format defined in MTF7Payload::getBlock() in src/Block.cc
153  // payload[0] = bits 0-15, payload[1] = 16-31, payload[3] = 32-47, etc.
154  auto payload = block.payload();
155 
156  // Assign payload to 16-bit words
157  uint16_t MEa = payload[0];
158  uint16_t MEb = payload[1];
159  uint16_t MEc = payload[2];
160  uint16_t MEd = payload[3];
161 
162  // Check Format of Payload
163  l1t::emtf::ME ME_;
164  for (int err = 0; err < checkFormat(block); err++)
165  ME_.add_format_error();
166 
167  // res is a pointer to a collection of EMTFDaqOut class objects
168  // There is one EMTFDaqOut for each MTF7 (60 deg. sector) in the event
170  res = static_cast<EMTFCollections*>(coll)->getEMTFDaqOuts();
171  int iOut = res->size() - 1;
172 
173  EMTFHitCollection* res_hit;
174  res_hit = static_cast<EMTFCollections*>(coll)->getEMTFHits();
175  EMTFHit Hit_;
176 
178  res_LCT = static_cast<EMTFCollections*>(coll)->getEMTFLCTs();
179 
180  CSCShowerDigiCollection* res_shower;
181  res_shower = static_cast<EMTFCollections*>(coll)->getEMTFCSCShowers();
182 
184  // Unpack the ME Data Record
186 
187  // Run 3 has a different EMTF DAQ output format
188  // Computed as (Year - 2000)*2^9 + Month*2^5 + Day (see Block.cc and EMTFBlockTrailers.cc)
189  bool run3_DAQ_format =
190  (getAlgoVersion() >= 11460); // Firmware from 04.06.22 which enabled new Run 3 DAQ format - EY 04.07.22
191  bool reducedDAQWindow =
192  (getAlgoVersion() >=
193  11656); // Firmware from 08.12.22 which is used as a flag for new reduced readout window - EY 01.03.23
194 
195  // Set fields assuming Run 2 format. Modify for Run 3 later
196  ME_.set_clct_pattern(GetHexBits(MEa, 0, 3));
197  ME_.set_quality(GetHexBits(MEa, 4, 7));
198  ME_.set_wire(GetHexBits(MEa, 8, 14));
199 
200  ME_.set_strip(GetHexBits(MEb, 0, 7));
201  ME_.set_csc_ID(GetHexBits(MEb, 8, 11));
202  ME_.set_lr(GetHexBits(MEb, 12, 12));
203  ME_.set_bxe(GetHexBits(MEb, 13, 13));
204  ME_.set_bc0(GetHexBits(MEb, 14, 14));
205 
206  ME_.set_me_bxn(GetHexBits(MEc, 0, 11));
207  ME_.set_nit(GetHexBits(MEc, 12, 12));
208  ME_.set_cik(GetHexBits(MEc, 13, 13));
209  ME_.set_afff(GetHexBits(MEc, 14, 14));
210 
211  if (reducedDAQWindow) // reduced DAQ window is used only after run3 DAQ format
212  ME_.set_tbin(GetHexBits(MEd, 0, 2) + 1);
213  else
214  ME_.set_tbin(GetHexBits(MEd, 0, 2));
215  ME_.set_vp(GetHexBits(MEd, 3, 3));
216  ME_.set_station(GetHexBits(MEd, 4, 6));
217  ME_.set_af(GetHexBits(MEd, 7, 7));
218  ME_.set_epc(GetHexBits(MEd, 8, 11));
219  ME_.set_sm(GetHexBits(MEd, 12, 12));
220  ME_.set_se(GetHexBits(MEd, 13, 13));
221  ME_.set_afef(GetHexBits(MEd, 14, 14));
222 
223  // ME_.set_dataword ( uint64_t dataword);
224 
225  // Convert specially-encoded ME quantities
226  bool csc_ID_shift = (getAlgoVersion() <=
227  8348); // For FW versions <= 28.04.2016, shift by +1 from 0,1,2... convention to 1,2,3...
228  // Computed as (Year - 2000)*2^9 + Month*2^5 + Day (see Block.cc and EMTFBlockTrailers.cc)
229  std::vector<int> conv_vals =
230  convert_ME_location(ME_.Station(), ME_.CSC_ID(), (res->at(iOut)).PtrEventHeader()->Sector(), csc_ID_shift);
231 
232  Hit_.set_station(conv_vals.at(0));
233  Hit_.set_csc_ID(conv_vals.at(1));
234  Hit_.set_sector(conv_vals.at(2));
235  Hit_.set_subsector(conv_vals.at(3));
236  Hit_.set_neighbor(conv_vals.at(4));
237  Hit_.set_ring(L1TMuonEndCap::calc_ring(Hit_.Station(), Hit_.CSC_ID(), ME_.Strip()));
238 
239  if (Hit_.Station() < 1 || Hit_.Station() > 4)
240  edm::LogWarning("L1T|EMTF") << "EMTF unpacked LCT station = " << Hit_.Station()
241  << ", outside proper [1, 4] range" << std::endl;
242  if (Hit_.CSC_ID() < 1 || Hit_.CSC_ID() > 9)
243  edm::LogWarning("L1T|EMTF") << "EMTF unpacked LCT CSC ID = " << Hit_.CSC_ID()
244  << ", outside proper [1, 9] range" << std::endl;
245  if (Hit_.Sector() < 1 || Hit_.Sector() > 6)
246  edm::LogWarning("L1T|EMTF") << "EMTF unpacked LCT sector = " << Hit_.Sector()
247  << ", outside proper [1, 6] range" << std::endl;
248 
249  // Modifications for Run 3 format - EY 04.07.22
250  bool isOTMB = (Hit_.Ring() == 1 or
251  Hit_.Ring() == 4); // Data format is different between OTMBs (MEX/1) and TMBs (MEX/2-3)
252 
253  bool isRun3 =
254  isOTMB and run3_DAQ_format; // in Run3 DAQ format, OTMB TPs are Run 3 CSC TPs with CCLUT algorithm
255 
256  if (run3_DAQ_format) {
257  ME_.set_quality(GetHexBits(MEa, 4, 6));
258  ME_.set_quarter_strip(GetHexBits(MEa, 7, 7));
259 
260  ME_.set_frame(GetHexBits(MEc, 12, 12));
261 
262  ME_.set_eighth_strip(GetHexBits(MEd, 13, 13));
263 
264  if (isOTMB) { // Derive Run 2 pattern ID from Run 3 slope for OTMBs
265 
266  ME_.set_slope(GetHexBits(MEd, 8, 11));
267 
268  // convert Run-3 slope to Run-2 pattern for CSC TPs coming from MEX/1 chambers
269  // where the CCLUT algorithm is enabled
270  const unsigned slopeList[32] = {10, 10, 10, 8, 8, 8, 6, 6, 6, 4, 4, 4, 2, 2, 2, 2,
271  10, 10, 10, 9, 9, 9, 7, 7, 7, 5, 5, 5, 3, 3, 3, 3};
272 
273  // this LUT follows the same convention as in CSCPatternBank.cc
274  unsigned slope_and_sign(ME_.Slope());
275  if (ME_.LR() == 1) {
276  slope_and_sign += 16;
277  }
278  unsigned run2_converted_PID = slopeList[slope_and_sign];
279 
280  ME_.set_clct_pattern(run2_converted_PID);
281 
282  } else { // Use Run 2 pattern directly for TMBs
283  ME_.set_clct_pattern(GetHexBits(MEd, 8, 11));
284  }
285 
286  // Frame 1 has muon shower related information
287  if (ME_.Frame() == 1) {
288  // Run 3 pattern is unused for now. Needs to be combined with rest of the word in Frame 0 - EY 04.07.22
289  ME_.set_run3_pattern(GetHexBits(MEa, 0, 0));
290 
291  // MUS[1] is in MEa, but MUS[0] is in MEb. These encode in time showers - EY 04.07.22
292  ME_.set_mus_inTime(GetHexBits(MEb, 13, 13, MEa, 1, 1));
293 
294  // MUS[3:2] encodes out-of-time showers which are not used for now
295  ME_.set_mus_outOfTime(GetHexBits(MEa, 2, 3));
296 
297  ME_.set_musv(GetHexBits(MEd, 7, 7));
298  } else {
299  ME_.set_run3_pattern(GetHexBits(MEa, 0, 3));
300 
301  ME_.set_bxe(GetHexBits(MEb, 13, 13));
302 
303  ME_.set_af(GetHexBits(MEd, 7, 7));
304  }
305  }
306 
307  // Fill the EMTFHit
308  ImportME(Hit_, ME_, (res->at(iOut)).PtrEventHeader()->Endcap(), (res->at(iOut)).PtrEventHeader()->Sector());
309 
310  // Set the stub number for this hit
311  // Each chamber can send up to 2 stubs per BX
312  ME_.set_stub_num(0);
313  Hit_.set_stub_num(0);
314  // See if matching hit is already in event record: exact duplicate, or from neighboring sector
315  bool exact_duplicate = false;
316  bool neighbor_duplicate = false;
317  for (auto const& iHit : *res_hit) {
318  if (iHit.Is_CSC() == 1 && Hit_.BX() == iHit.BX() && Hit_.Endcap() == iHit.Endcap() &&
319  Hit_.Station() == iHit.Station() && Hit_.Chamber() == iHit.Chamber() &&
320  (Hit_.Ring() % 3) == (iHit.Ring() % 3)) { // ME1/1a and ME1/1b (rings "4" and 1) are the same chamber
321 
322  if (Hit_.Ring() == iHit.Ring() && Hit_.Strip() == iHit.Strip() && Hit_.Wire() == iHit.Wire()) {
323  exact_duplicate = (Hit_.Neighbor() == iHit.Neighbor());
324  neighbor_duplicate = (Hit_.Neighbor() != iHit.Neighbor());
325  } else if (Hit_.Neighbor() == iHit.Neighbor()) {
326  ME_.set_stub_num(ME_.Stub_num() + 1);
327  Hit_.set_stub_num(Hit_.Stub_num() + 1);
328  }
329  }
330  } // End loop: for (auto const & iHit : *res_hit)
331 
332  // Reject TPs with out-of-range BX values. This needs to be adjusted if we increase l1a_window parameter in EMTF config - EY 03.08.2022
333  if (Hit_.BX() > 3 or Hit_.BX() < -3) {
334  edm::LogWarning("L1T|EMTF") << "EMTF unpacked LCTs with out-of-range BX! BX " << Hit_.BX() << ", endcap "
335  << Hit_.Endcap() << ", station " << Hit_.Station() << ", sector " << Hit_.Sector()
336  << ", neighbor " << Hit_.Neighbor() << ", ring " << Hit_.Ring() << ", chamber "
337  << Hit_.Chamber() << ", strip " << Hit_.Strip() << ", wire " << Hit_.Wire()
338  << std::endl;
339  return true;
340  }
341 
342  if (exact_duplicate)
343  edm::LogWarning("L1T|EMTF") << "EMTF unpacked duplicate LCTs: BX " << Hit_.BX() << ", endcap "
344  << Hit_.Endcap() << ", station " << Hit_.Station() << ", sector " << Hit_.Sector()
345  << ", neighbor " << Hit_.Neighbor() << ", ring " << Hit_.Ring() << ", chamber "
346  << Hit_.Chamber() << ", strip " << Hit_.Strip() << ", wire " << Hit_.Wire()
347  << std::endl;
348 
349  // Set the hit as invalid if quality == 0 (indicates muon shower)
350  if (Hit_.Quality() == 0)
351  Hit_.set_valid(0);
352 
353  (res->at(iOut)).push_ME(ME_);
354  if (!exact_duplicate && Hit_.Valid() == 1)
355  res_hit->push_back(Hit_);
356  if (!exact_duplicate && !neighbor_duplicate &&
357  Hit_.Valid() == 1) // Don't write duplicate LCTs from adjacent sectors
358  res_LCT->insertDigi(Hit_.CSC_DetId(), Hit_.CreateCSCCorrelatedLCTDigi(isRun3));
359  if (Hit_.Muon_shower_valid() == 1) { // Only write when muon shower valid bit is set to 1
360  res_shower->insertDigi(Hit_.CSC_DetId(), Hit_.CreateCSCShowerDigi());
361  }
362  // Finished with unpacking one ME Data Record
363  return true;
364 
365  } // End bool MEBlockUnpacker::unpack
366 
367  // bool MEBlockPacker::pack(const Block& block, UnpackerCollections *coll) {
368  // std::cout << "Inside MEBlockPacker::pack" << std::endl;
369  // return true;
370  // } // End bool MEBlockPacker::pack
371 
372  } // End namespace emtf
373  } // End namespace stage2
374 } // End namespace l1t
375 
377 // DEFINE_L1T_PACKER(l1t::stage2::MEBlockPacker);
void set_bxe(int bits)
Definition: ME.h:57
void set_neighbor(int bits)
Definition: EMTFHit.h:153
void set_af(int bits)
Definition: ME.h:69
void set_bc0(int bits)
Definition: ME.h:56
int Strip() const
Definition: ME.h:95
int Frame() const
Definition: ME.h:109
int Slope() const
Definition: ME.h:112
int Wire() const
Definition: EMTFHit.h:230
unsigned int getAlgoVersion()
Definition: Unpacker.h:18
void ImportME(EMTFHit &_hit, const l1t::emtf::ME _ME, const int _endcap, const int _evt_sector)
void set_stub_num(int bits)
Definition: EMTFHit.h:189
void set_station(int bits)
Definition: EMTFHit.h:142
int CSC_ID() const
Definition: ME.h:94
int Neighbor() const
Definition: EMTFHit.h:224
void set_vp(int bits)
Definition: ME.h:71
int Station() const
Definition: ME.h:105
Definition: Event.h:15
void insertDigi(const IndexType &index, const DigiType &digi)
insert a digi for a given DetUnit
delete x;
Definition: CaloConfig.h:22
int Valid() const
Definition: EMTFHit.h:247
void set_epc(int bits)
Definition: ME.h:68
void set_musv(int bits)
Definition: ME.h:80
Log< level::Error, false > LogError
void set_mus_outOfTime(int bits)
Definition: ME.h:82
CSCCorrelatedLCTDigi CreateCSCCorrelatedLCTDigi(const bool isRun3) const
Definition: EMTFHit.cc:75
void set_wire(int bits)
Definition: ME.h:53
std::vector< int > convert_ME_location(int _station, int _csc_ID, int _sector, bool _csc_ID_shift=false)
Definition: EMTFBlockME.cc:79
Definition: Electron.h:6
void set_ring(int bits)
Definition: EMTFHit.h:143
int CSC_ID() const
Definition: EMTFHit.h:221
void set_eighth_strip(int bits)
Definition: ME.h:76
int LR() const
Definition: ME.h:93
void add_format_error()
Definition: ME.h:85
int Quality() const
Definition: EMTFHit.h:242
void set_tbin(int bits)
Definition: ME.h:72
virtual int checkFormat(const Block &block)
Definition: EMTFBlockME.cc:34
bool unpack(const Block &block, UnpackerCollections *coll) override
Definition: EMTFBlockME.cc:148
void set_se(int bits)
Definition: ME.h:66
void set_stub_num(int bits)
Definition: ME.h:84
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e< void, edm::EventID const &, edm::Timestamp const & > We also list in braces which AR_WATCH_USING_METHOD_ is used for those or
Definition: Activities.doc:12
void set_csc_ID(int bits)
Definition: EMTFHit.h:150
void set_quality(int bits)
Definition: ME.h:54
std::vector< EMTFHit > EMTFHitCollection
Definition: EMTFHit.h:381
std::vector< EMTFDaqOut > EMTFDaqOutCollection
Definition: EMTFDaqOut.h:179
int BX() const
Definition: EMTFHit.h:274
void set_csc_ID(int bits)
Definition: ME.h:59
void set_afef(int bits)
Definition: ME.h:65
void set_run3_pattern(int bits)
Definition: ME.h:78
int Strip() const
Definition: EMTFHit.h:231
void set_afff(int bits)
Definition: ME.h:61
void set_nit(int bits)
Definition: ME.h:63
void set_frame(int bits)
Definition: ME.h:74
void set_slope(int bits)
Definition: ME.h:77
int Muon_shower_valid() const
Definition: EMTFHit.h:238
void set_strip(int bits)
Definition: ME.h:60
void set_lr(int bits)
Definition: ME.h:58
void set_sector(int bits)
Definition: EMTFHit.h:144
int Endcap() const
Definition: EMTFHit.h:212
int Station() const
Definition: EMTFHit.h:213
CSCShowerDigi CreateCSCShowerDigi() const
Definition: EMTFHit.cc:104
void set_valid(int bits)
Definition: EMTFHit.h:176
int calc_ring(int station, int csc_ID, int strip)
Definition: TrackTools.cc:5
int Stub_num() const
Definition: EMTFHit.h:275
int Chamber() const
Definition: EMTFHit.h:220
CSCDetId CSC_DetId() const
Definition: EMTFHit.h:134
void set_cik(int bits)
Definition: ME.h:62
void set_station(int bits)
Definition: ME.h:70
#define DEFINE_L1T_UNPACKER(type)
int Ring() const
Definition: EMTFHit.h:214
Definition: errors.py:1
void set_me_bxn(int bits)
Definition: ME.h:64
uint16_t GetHexBits(uint16_t word, uint16_t lowBit, uint16_t highBit)
void set_sm(int bits)
Definition: ME.h:67
Log< level::Warning, false > LogWarning
void set_quarter_strip(int bits)
Definition: ME.h:75
int Stub_num() const
Definition: ME.h:119
void set_clct_pattern(int bits)
Definition: ME.h:55
void set_subsector(int bits)
Definition: EMTFHit.h:147
void set_mus_inTime(int bits)
Definition: ME.h:81
int Sector() const
Definition: EMTFHit.h:215
A container for a generic type of digis indexed by some index, implemented with a map<IndexType...