CMS 3D CMS Logo

EMTFBlockRPC.cc
Go to the documentation of this file.
1 // Code to unpack the "RPC Data Record"
2 
4 
5 #include "EMTFCollections.h"
6 #include "EMTFUnpackerTools.h"
7 
8 // This is the "header" - no EMTFBlockRPC.h file is needed
9 namespace l1t {
10  namespace stage2 {
11  namespace emtf {
12 
13  class RPCBlockUnpacker : public Unpacker { // "RPCBlockUnpacker" inherits from "Unpacker"
14  public:
15  virtual int checkFormat(const Block& block);
16  // virtual bool checkFormat() override; // Return "false" if block format does not match expected format
17  bool unpack(const Block& block,
18  UnpackerCollections* coll) override; // Apparently it's always good to use override in C++
19  // virtual bool packBlock(const Block& block, UnpackerCollections *coll) override;
20  };
21 
22  // class RPCBlockPacker : public Packer { // "RPCBlockPacker" inherits from "Packer"
23  // public:
24  // virtual bool unpack(const Block& block, UnpackerCollections *coll) override; // Apparently it's always good to use override in C++
25  // };
26 
27  } // namespace emtf
28  } // namespace stage2
29 } // namespace l1t
30 
31 namespace l1t {
32  namespace stage2 {
33  namespace emtf {
34 
36  auto payload = block.payload();
37  int errors = 0;
38 
39  // Check the number of 16-bit words
40  if (payload.size() != 4) {
41  errors += 1;
42  edm::LogError("L1T|EMTF") << "Payload size in 'RPC Data Record' is different than expected";
43  }
44 
45  // Check that each word is 16 bits
46  for (unsigned int i = 0; i < 4; i++) {
47  if (GetHexBits(payload[i], 16, 31) != 0) {
48  errors += 1;
49  edm::LogError("L1T|EMTF") << "Payload[" << i << "] has more than 16 bits in 'RPC Data Record'";
50  }
51  }
52 
53  uint16_t RPCa = payload[0];
54  uint16_t RPCb = payload[1];
55  uint16_t RPCc = payload[2];
56  uint16_t RPCd = payload[3];
57 
58  // Check Format
59  if (GetHexBits(RPCa, 15, 15) != 0) {
60  errors += 1;
61  edm::LogError("L1T|EMTF") << "Format identifier bits in RPCa are incorrect";
62  }
63  if (GetHexBits(RPCb, 15, 15) != 0) {
64  errors += 1;
65  edm::LogError("L1T|EMTF") << "Format identifier bits in RPCb are incorrect";
66  }
67  if (GetHexBits(RPCc, 15, 15) != 1) {
68  errors += 1;
69  edm::LogError("L1T|EMTF") << "Format identifier bits in RPCc are incorrect";
70  }
71  if (GetHexBits(RPCd, 15, 15) != 0) {
72  errors += 1;
73  edm::LogError("L1T|EMTF") << "Format identifier bits in RPCd are incorrect";
74  }
75 
76  return errors;
77  }
78 
79  // Converts station, ring, sector, subsector, neighbor, and segment from the RPC output
81  int& ring,
82  int& sector,
83  int& subsector,
84  int& neighbor,
85  int& segment,
86  const int evt_sector,
87  const int frame,
88  const int word,
89  const int link) {
90  station = -99;
91  ring = -99;
92  sector = -99;
93  subsector = -99;
94  neighbor = -99;
95  segment = -99;
96 
97  // "link" is the "link index" field (0 - 6) in the EMTF DAQ document, not "link number" (1 - 7)
98  // Neighbor indicated by link == 0
99  sector = (link != 0 ? evt_sector : (evt_sector == 1 ? 6 : evt_sector - 1));
100  subsector = (link != 0 ? link : 6);
101  neighbor = (link == 0 ? 1 : 0);
102  segment = (word % 2);
103 
104  if (frame == 0) {
105  station = (word < 2 ? 1 : 2);
106  ring = 2;
107  } else if (frame == 1) {
108  station = 3;
109  ring = (word < 2 ? 2 : 3);
110  } else if (frame == 2) {
111  station = 4;
112  ring = (word < 2 ? 2 : 3);
113  }
114  } // End function: void convert_RPC_location()
115 
117  // std::cout << "Inside EMTFBlockRPC.cc: unpack" << std::endl;
118 
119  // Get the payload for this block, made up of 16-bit words (0xffff)
120  // Format defined in MTF7Payload::getBlock() in src/Block.cc
121  // payload[0] = bits 0-15, payload[1] = 16-31, payload[3] = 32-47, etc.
122  auto payload = block.payload();
123 
124  // Run 3 has a different EMTF DAQ output format since August 26th
125  // Computed as (Year - 2000)*2^9 + Month*2^5 + Day (see Block.cc and EMTFBlockTrailers.cc)
126  bool run3_DAQ_format =
127  (getAlgoVersion() >=
128  11546); // Firmware from 26.08.22 which enabled new Run 3 DAQ format for RPCs - EY 13.09.22
129 
130  int nTPs = run3_DAQ_format ? 2 : 1;
131 
132  // Check Format of Payload
133  l1t::emtf::RPC RPC_;
134  for (int err = 0; err < checkFormat(block); err++)
135  RPC_.add_format_error();
136 
137  // Assign payload to 16-bit words
138  uint16_t RPCa = payload[0];
139  uint16_t RPCb = payload[1];
140  uint16_t RPCc = payload[2];
141  uint16_t RPCd = payload[3];
142 
143  // If there are 2 TPs in the block we fill them 1 by 1
144  for (int i = 1; i <= nTPs; i++) {
145  // res is a pointer to a collection of EMTFDaqOut class objects
146  // There is one EMTFDaqOut for each MTF7 (60 deg. sector) in the event
148  res = static_cast<EMTFCollections*>(coll)->getEMTFDaqOuts();
149  int iOut = res->size() - 1;
150 
151  EMTFHitCollection* res_hit;
152  res_hit = static_cast<EMTFCollections*>(coll)->getEMTFHits();
153  EMTFHit Hit_;
154 
155  CPPFDigiCollection* res_CPPF;
156  res_CPPF = static_cast<EMTFCollections*>(coll)->getEMTFCPPFs();
157 
159  // Unpack the RPC Data Record
161 
162  if (run3_DAQ_format) { // Run 3 DAQ format has 2 TPs per block
163  if (i == 1) {
164  RPC_.set_phi(GetHexBits(RPCa, 0, 10));
165  RPC_.set_word(GetHexBits(RPCa, 11, 12));
166  RPC_.set_frame(GetHexBits(RPCa, 13, 14));
167 
168  RPC_.set_tbin(GetHexBits(RPCb, 0, 2));
169  RPC_.set_vp(GetHexBits(RPCb, 3, 3));
170  RPC_.set_theta(GetHexBits(RPCb, 4, 8));
171  RPC_.set_bc0(GetHexBits(RPCb, 9, 9));
172  RPC_.set_link(GetHexBits(RPCb, 12, 14)); // Link index (0 - 6); link number runs 1 - 7
173  } else if (i == 2) {
174  RPC_.set_phi(GetHexBits(RPCc, 0, 10));
175  RPC_.set_word(GetHexBits(RPCc, 11, 12));
176  RPC_.set_frame(GetHexBits(RPCc, 13, 14));
177 
178  RPC_.set_tbin(GetHexBits(RPCd, 0, 2));
179  RPC_.set_vp(GetHexBits(RPCd, 3, 3));
180  RPC_.set_theta(GetHexBits(RPCd, 4, 8));
181  RPC_.set_bc0(GetHexBits(RPCd, 9, 9));
182  RPC_.set_link(GetHexBits(RPCd, 12, 14)); // Link index (0 - 6); link number runs 1 - 7
183  }
184  } else { // Run 2 DAQ format
185  RPC_.set_phi(GetHexBits(RPCa, 0, 10));
186 
187  RPC_.set_theta(GetHexBits(RPCb, 0, 4));
188  RPC_.set_word(GetHexBits(RPCb, 8, 9));
189  RPC_.set_frame(GetHexBits(RPCb, 10, 11));
190  RPC_.set_link(GetHexBits(RPCb, 12, 14)); // Link index (0 - 6); link number runs 1 - 7
191 
192  RPC_.set_rpc_bxn(GetHexBits(RPCc, 0, 11));
193  RPC_.set_bc0(GetHexBits(RPCc, 14, 14));
194 
195  RPC_.set_tbin(GetHexBits(RPCd, 0, 2));
196  RPC_.set_vp(GetHexBits(RPCd, 3, 3));
197 
198  // RPC_.set_dataword ( uint64_t dataword);
199  }
200 
201  // Convert specially-encoded RPC quantities
202  int _station, _ring, _sector, _subsector, _neighbor, _segment;
203  convert_RPC_location(_station,
204  _ring,
205  _sector,
206  _subsector,
207  _neighbor,
208  _segment,
209  (res->at(iOut)).PtrEventHeader()->Sector(),
210  RPC_.Frame(),
211  RPC_.Word(),
212  RPC_.Link());
213 
214  // Rotate by 20 deg to match RPC convention in CMSSW
215  int _sector_rpc = (_subsector < 5) ? _sector : (_sector % 6) + 1;
216  // Rotate by 2 to match RPC convention in CMSSW (RPCDetId.h)
217  int _subsector_rpc = ((_subsector + 1) % 6) + 1;
218  // Define chamber number
219  int _chamber = (_sector_rpc - 1) * 6 + _subsector_rpc;
220  // Define CSC-like subsector
221  int _subsector_csc = (_station != 1) ? 0 : ((_chamber % 6 > 2) ? 1 : 2);
222 
223  Hit_.set_station(_station);
224  Hit_.set_ring(_ring);
225  Hit_.set_sector(_sector);
226  Hit_.set_subsector(_subsector_csc);
227  Hit_.set_sector_RPC(_sector_rpc);
228  Hit_.set_subsector_RPC(_subsector_rpc);
229  Hit_.set_chamber(_chamber);
230  Hit_.set_neighbor(_neighbor);
231  Hit_.set_pc_segment(_segment);
232  Hit_.set_fs_segment(_segment);
233  Hit_.set_bt_segment(_segment);
234 
235  // Fill the EMTFHit
236  ImportRPC(Hit_, RPC_, (res->at(iOut)).PtrEventHeader()->Endcap(), (res->at(iOut)).PtrEventHeader()->Sector());
237 
238  // Set the stub number for this hit
239  // Each chamber can send up to 2 stubs per BX
240  // Also count stubs in corresponding CSC chamber; RPC hit counting is on top of LCT counting
241  Hit_.set_stub_num(0);
242  // See if matching hit is already in event record
243  bool exact_duplicate = false;
244  for (auto const& iHit : *res_hit) {
245  if (Hit_.BX() == iHit.BX() && Hit_.Endcap() == iHit.Endcap() && Hit_.Station() == iHit.Station() &&
246  Hit_.Chamber() == iHit.Chamber()) {
247  if ((iHit.Is_CSC() == 1 && iHit.Ring() == 2) ||
248  (iHit.Is_RPC() == 1)) { // RPC rings 2 and 3 both map to CSC ring 2
249  if (Hit_.Neighbor() == iHit.Neighbor()) {
250  Hit_.set_stub_num(Hit_.Stub_num() + 1);
251  if (iHit.Is_RPC() == 1 && iHit.Ring() == Hit_.Ring() && iHit.Theta_fp() == Hit_.Theta_fp() &&
252  iHit.Phi_fp() == Hit_.Phi_fp()) {
253  exact_duplicate = true;
254  }
255  }
256  }
257  }
258  } // End loop: for (auto const & iHit : *res_hit)
259 
260  // 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
261  if (Hit_.BX() > 3 or Hit_.BX() < -3) {
262  edm::LogWarning("L1T|EMTF") << "EMTF unpacked CPPF digis with out-of-range BX! BX " << Hit_.BX()
263  << ", endcap " << Hit_.Endcap() << ", station " << Hit_.Station() << ", sector "
264  << Hit_.Sector() << ", neighbor " << Hit_.Neighbor() << ", ring " << Hit_.Ring()
265  << ", chamber " << Hit_.Chamber() << ", theta " << Hit_.Theta_fp() / 4
266  << ", phi " << Hit_.Phi_fp() / 4 << std::endl;
267  return true;
268  }
269 
270  if (exact_duplicate)
271  edm::LogWarning("L1T|EMTF") << "EMTF unpacked duplicate CPPF digis: BX " << Hit_.BX() << ", endcap "
272  << Hit_.Endcap() << ", station " << Hit_.Station() << ", sector "
273  << Hit_.Sector() << ", neighbor " << Hit_.Neighbor() << ", ring " << Hit_.Ring()
274  << ", chamber " << Hit_.Chamber() << ", theta " << Hit_.Theta_fp() / 4
275  << ", phi " << Hit_.Phi_fp() / 4 << std::endl;
276 
277  (res->at(iOut)).push_RPC(RPC_);
278  if (!exact_duplicate)
279  res_hit->push_back(Hit_);
280  if (!exact_duplicate)
281  res_CPPF->push_back(Hit_.CreateCPPFDigi());
282  }
283 
284  // Finished with unpacking one RPC Data Record
285  return true;
286 
287  } // End bool RPCBlockUnpacker::unpack
288 
289  // bool RPCBlockPacker::pack(const Block& block, UnpackerCollections *coll) {
290  // std::cout << "Inside RPCBlockPacker::pack" << std::endl;
291  // return true;
292  // } // End bool RPCBlockPacker::pack
293 
294  } // End namespace emtf
295  } // End namespace stage2
296 } // End namespace l1t
297 
299 // DEFINE_L1T_PACKER(l1t::stage2::RPCBlockPacker);
void set_subsector_RPC(int bits)
Definition: EMTFHit.h:142
void set_neighbor(int bits)
Definition: EMTFHit.h:147
int Link() const
Definition: RPC.h:46
unsigned int getAlgoVersion()
Definition: Unpacker.h:18
void set_stub_num(int bits)
Definition: EMTFHit.h:180
void set_station(int bits)
Definition: EMTFHit.h:136
void convert_RPC_location(int &station, int &ring, int &sector, int &subsector, int &neighbor, int &segment, const int evt_sector, const int frame, const int word, const int link)
Definition: EMTFBlockRPC.cc:80
void add_format_error()
Definition: RPC.h:39
int Neighbor() const
Definition: EMTFHit.h:215
int Word() const
Definition: RPC.h:44
int Phi_fp() const
Definition: EMTFHit.h:264
Definition: Event.h:15
delete x;
Definition: CaloConfig.h:22
bool unpack(const Block &block, UnpackerCollections *coll) override
Log< level::Error, false > LogError
void set_word(int bits)
Definition: RPC.h:32
Definition: Electron.h:6
void set_ring(int bits)
Definition: EMTFHit.h:137
void ImportRPC(EMTFHit &_hit, const l1t::emtf::RPC _RPC, const int _endcap, const int _evt_sector)
void set_frame(int bits)
Definition: RPC.h:33
uint64_t word
void set_theta(int bits)
Definition: RPC.h:31
CPPFDigi CreateCPPFDigi() const
Definition: EMTFHit.cc:50
void set_bt_segment(int bits)
Definition: EMTFHit.h:188
void set_tbin(int bits)
Definition: RPC.h:37
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
std::vector< EMTFHit > EMTFHitCollection
Definition: EMTFHit.h:366
std::vector< EMTFDaqOut > EMTFDaqOutCollection
Definition: EMTFDaqOut.h:179
int BX() const
Definition: EMTFHit.h:262
void set_bc0(int bits)
Definition: RPC.h:36
int Theta_fp() const
Definition: EMTFHit.h:265
void set_pc_segment(int bits)
Definition: EMTFHit.h:152
void set_fs_segment(int bits)
Definition: EMTFHit.h:185
int Frame() const
Definition: RPC.h:45
void set_sector_RPC(int bits)
Definition: EMTFHit.h:139
void set_sector(int bits)
Definition: EMTFHit.h:138
int Endcap() const
Definition: EMTFHit.h:203
int Station() const
Definition: EMTFHit.h:204
int Stub_num() const
Definition: EMTFHit.h:263
int Chamber() const
Definition: EMTFHit.h:211
void set_phi(int bits)
Definition: RPC.h:30
void set_link(int bits)
Definition: RPC.h:34
#define DEFINE_L1T_UNPACKER(type)
void set_rpc_bxn(int bits)
Definition: RPC.h:35
int Ring() const
Definition: EMTFHit.h:205
Definition: errors.py:1
uint16_t GetHexBits(uint16_t word, uint16_t lowBit, uint16_t highBit)
Log< level::Warning, false > LogWarning
void set_vp(int bits)
Definition: RPC.h:38
void set_chamber(int bits)
Definition: EMTFHit.h:143
virtual int checkFormat(const Block &block)
Definition: EMTFBlockRPC.cc:35
void set_subsector(int bits)
Definition: EMTFHit.h:141
std::vector< CPPFDigi > CPPFDigiCollection
Definition: CPPFDigi.h:83
int Sector() const
Definition: EMTFHit.h:206