CMS 3D CMS Logo

EMTFBlockGEM.cc
Go to the documentation of this file.
1 // Code to unpack the "GEM Data Record"
2 
4 
5 #include "EMTFCollections.h"
6 #include "EMTFUnpackerTools.h"
7 
8 namespace l1t {
9  namespace stage2 {
10  namespace emtf {
11 
12  class GEMBlockUnpacker : public Unpacker {
13  public:
14  virtual int checkFormat(const Block& block);
15  // virtual bool checkFormat() override; // Return "false" if block format does not match expected format
16  bool unpack(const Block& block, UnpackerCollections* coll) override;
17  // virtual bool packBlock(const Block& block, UnpackerCollections *coll) override;
18  };
19 
20  // class GEMBlockPacker : public Packer {
21  // public:
22  // virtual bool unpack(const Block& block, UnpackerCollections *coll) override;
23  // };
24 
25  } // namespace emtf
26  } // namespace stage2
27 } // namespace l1t
28 
29 namespace l1t {
30  namespace stage2 {
31  namespace emtf {
32 
34  auto payload = block.payload();
35  int errors = 0;
36 
37  // Check the number of 16-bit words
38  if (payload.size() != 4) {
39  errors += 1;
40  edm::LogError("L1T|EMTF") << "Payload size in 'GEM Data Record' is different than expected";
41  }
42 
43  // Check that each word is 16 bits
44  for (size_t i = 0; i < 4; ++i) {
45  if (GetHexBits(payload[i], 16, 31) != 0) {
46  errors += 1;
47  edm::LogError("L1T|EMTF") << "Payload[" << i << "] has more than 16 bits in 'GEM Data Record'";
48  }
49  }
50 
51  uint16_t GEMa = payload[0];
52  uint16_t GEMb = payload[1];
53  uint16_t GEMc = payload[2];
54  uint16_t GEMd = payload[3];
55 
56  // Check Format
57  if (GetHexBits(GEMa, 15, 15) != 1) {
58  errors += 1;
59  edm::LogError("L1T|EMTF") << "Format identifier bits in GEMa are incorrect";
60  }
61  if (GetHexBits(GEMb, 15, 15) != 1) {
62  errors += 1;
63  edm::LogError("L1T|EMTF") << "Format identifier bits in GEMb are incorrect";
64  }
65  if (GetHexBits(GEMc, 15, 15) != 1) {
66  errors += 1;
67  edm::LogError("L1T|EMTF") << "Format identifier bits in GEMc are incorrect";
68  }
69  if (GetHexBits(GEMd, 15, 15) != 0) {
70  errors += 1;
71  edm::LogError("L1T|EMTF") << "Format identifier bits in GEMd are incorrect";
72  }
73 
74  return errors;
75  }
76 
91  int& ring,
92  int& sector,
93  int& subsector,
94  int& neighbor,
95  int& layer, // is this correct for the GEM case?
96  const int evt_sector,
97  const int cluster_id, // used to differentiate between GEM layer 1/2
98  const int link) {
99  station =
100  1; // station is not encoded in the GEM frame for now. Set station = 1 since we only have GE1/1 for Run 3.
101  ring = 1; // GEMs are only in GE1/1 and GE2/1
102  sector = -99;
103  subsector = -99;
104  neighbor = -99;
105  layer = -99; // the GEM layer is 1 or 2, depending on the cluster ID
106 
107  // Neighbor indicated by link == 6
108  sector = (link != 6 ? evt_sector : (evt_sector == 1 ? 6 : evt_sector - 1));
109  subsector = (link != 6 ? link : 0); // TODO: verify subsector 0 in the neighbouring sector?
110  neighbor = (link == 6 ? 1 : 0); // TODO: verify that 6 is for the neighbour, not 0 (as written in EMTFBlockRPC)
111  layer = (cluster_id % 8); // + 1 if layer should be 1 or 2, otherwise layer is 0 or 1
112  }
113 
123  // std::cout << "Inside EMTFBlockGEM.cc: unpack" << std::endl;
124 
125  // Get the payload for this block, made up of 16-bit words (0xffff)
126  // Format defined in MTF7Payload::getBlock() in src/Block.cc
127  // payload[0] = bits 0-15, payload[1] = 16-31, payload[3] = 32-47, etc.
128  auto payload = block.payload();
129 
130  // Run 3 has a different EMTF DAQ output format since August 26th
131  // Computed as (Year - 2000)*2^9 + Month*2^5 + Day (see Block.cc and EMTFBlockTrailers.cc)
132  bool run3_DAQ_format =
133  (getAlgoVersion() >=
134  11546); // Firmware from 26.08.22 which enabled new Run 3 DAQ format for GEMs - EY 13.09.22
135 
136  int nTPs = run3_DAQ_format ? 2 : 1;
137 
138  // Check Format of Payload
139  l1t::emtf::GEM GEM_;
140  for (int err = 0; err < checkFormat(block); ++err) {
141  GEM_.add_format_error();
142  }
143 
144  // Assign payload to 16-bit words
145  uint16_t GEMa = payload[0];
146  uint16_t GEMb = payload[1];
147  uint16_t GEMc = payload[2];
148  uint16_t GEMd = payload[3];
149 
150  // If there are 2 TPs in the block we fill them 1 by 1
151  for (int i = 1; i <= nTPs; i++) {
152  // res is a pointer to a collection of EMTFDaqOut class objects
153  // There is one EMTFDaqOut for each MTF7 (60 deg. sector) in the event
155  res = static_cast<EMTFCollections*>(coll)->getEMTFDaqOuts();
156  int iOut = res->size() - 1;
157 
158  EMTFHitCollection* res_hit;
159  res_hit = static_cast<EMTFCollections*>(coll)->getEMTFHits();
160  EMTFHit Hit_;
161 
162  // TODO: Verify this is correct for GEM
164  res_GEM = static_cast<EMTFCollections*>(coll)->getEMTFGEMPadClusters();
165 
167  // Unpack the GEM Data Record
169  if (run3_DAQ_format) { // Run 3 DAQ format has 2 TPs per block
170  if (i == 1) {
171  GEM_.set_pad(GetHexBits(GEMa, 0, 8));
172  GEM_.set_partition(GetHexBits(GEMa, 9, 11));
173  GEM_.set_cluster_size(GetHexBits(GEMa, 12, 14));
174 
175  GEM_.set_tbin(GetHexBits(GEMb, 0, 2));
176  GEM_.set_vp(GetHexBits(GEMb, 3, 3));
177  GEM_.set_bc0(GetHexBits(GEMb, 7, 7));
178  GEM_.set_cluster_id(GetHexBits(GEMb, 8, 11));
179  GEM_.set_link(GetHexBits(GEMb, 12, 14));
180  } else if (i == 2) {
181  GEM_.set_pad(GetHexBits(GEMc, 0, 8));
182  GEM_.set_partition(GetHexBits(GEMc, 9, 11));
183  GEM_.set_cluster_size(GetHexBits(GEMc, 12, 14));
184 
185  GEM_.set_tbin(GetHexBits(GEMd, 0, 2));
186  GEM_.set_vp(GetHexBits(GEMd, 3, 3));
187  GEM_.set_bc0(GetHexBits(GEMd, 7, 7));
188  GEM_.set_cluster_id(GetHexBits(GEMd, 8, 11));
189  GEM_.set_link(GetHexBits(GEMd, 12, 14));
190  }
191  } else {
192  GEM_.set_pad(GetHexBits(GEMa, 0, 8));
193  GEM_.set_partition(GetHexBits(GEMa, 9, 11));
194  GEM_.set_cluster_size(GetHexBits(GEMa, 12, 14));
195 
196  GEM_.set_cluster_id(GetHexBits(GEMb, 8, 11));
197  GEM_.set_link(GetHexBits(GEMb, 12, 14));
198 
199  GEM_.set_gem_bxn(GetHexBits(GEMc, 0, 11));
200  GEM_.set_bc0(GetHexBits(GEMc, 14, 14));
201 
202  GEM_.set_tbin(GetHexBits(GEMd, 0, 2));
203  GEM_.set_vp(GetHexBits(GEMd, 3, 3));
204 
205  // GEM_.set_dataword(uint64_t dataword);
206  }
207 
208  // Convert specially-encoded GEM quantities
209  // TODO: is the RPC or CSC method for this function better... - JS 06.07.20
210  int _station, _ring, _sector, _subsector, _neighbor, _layer;
211  convert_GEM_location(_station,
212  _ring,
213  _sector,
214  _subsector,
215  _neighbor,
216  _layer,
217  (res->at(iOut)).PtrEventHeader()->Sector(),
218  GEM_.ClusterID(),
219  GEM_.Link());
220 
221  // Rotate by 20 deg to match GEM convention in CMSSW) // FIXME VERIFY
222  // int _sector_gem = (_subsector < 5) ? _sector : (_sector % 6) + 1; //
223  int _sector_gem = _sector;
224  // Rotate by 2 to match GEM convention in CMSSW (GEMDetId.h) // FIXME VERIFY
225  int _subsector_gem = ((_subsector + 1) % 6) + 1;
226  // Define chamber number) // FIXME VERIFY
227  int _chamber = (_sector_gem - 1) * 6 + _subsector_gem;
228  // Define CSC-like subsector) // FIXME WHY?? VERIFY
229  int _subsector_csc = (_station != 1) ? 0 : ((_chamber % 6 > 2) ? 1 : 2);
230 
231  Hit_.set_station(_station);
232  Hit_.set_ring(_ring);
233  Hit_.set_sector(_sector);
234  Hit_.set_subsector(_subsector_csc);
235  Hit_.set_chamber(_chamber);
236  Hit_.set_neighbor(_neighbor);
237 
238  // Fill the EMTFHit
239  ImportGEM(Hit_, GEM_, (res->at(iOut)).PtrEventHeader()->Endcap(), (res->at(iOut)).PtrEventHeader()->Sector());
240 
241  // Set the stub number for this hit
242  // Each chamber can send up to 2 stubs per BX // FIXME is this true for GEM, are stubs relevant for GEMs?
243  // Also count stubs in corresponding CSC chamber; GEM hit counting is on top of LCT counting
244  Hit_.set_stub_num(0);
245  // See if matching hit is already in event record
246  bool exact_duplicate = false;
247  for (auto const& iHit : *res_hit) {
248  if (Hit_.BX() == iHit.BX() && Hit_.Endcap() == iHit.Endcap() && Hit_.Station() == iHit.Station() &&
249  Hit_.Chamber() == iHit.Chamber()) {
250  if ((iHit.Is_CSC() == 1 && iHit.Ring() == 2) ||
251  (iHit.Is_GEM() == 1)) { // Copied from RPC, but GEM has no ring 2/3...
252  if (Hit_.Neighbor() == iHit.Neighbor()) {
253  Hit_.set_stub_num(Hit_.Stub_num() + 1);
254  if (iHit.Is_GEM() == 1 && iHit.Ring() == Hit_.Ring() && iHit.Roll() == Hit_.Roll() &&
255  iHit.Pad() == Hit_.Pad()) {
256  exact_duplicate = true;
257  }
258  }
259  }
260  }
261  } // End loop: for (auto const & iHit : *res_hit)
262 
263  // 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
264  if (Hit_.BX() > 3 or Hit_.BX() < -3) {
265  edm::LogWarning("L1T|EMTF") << "EMTF unpacked GEM digis with out-of-range BX! BX " << Hit_.BX()
266  << ", endcap " << Hit_.Endcap() << ", station " << Hit_.Station()
267  << ", neighbor " << Hit_.Neighbor() << ", ring " << Hit_.Ring() << ", chamber "
268  << Hit_.Chamber() << ", roll " << Hit_.Roll() << ", pad " << Hit_.Pad()
269  << std::endl;
270  return true;
271  }
272 
273  // TODO: Re-enable once GEM TP data format is fixed
274  // if (exact_duplicate)
275  // edm::LogWarning("L1T|EMTF") << "EMTF unpacked duplicate GEM digis: BX " << Hit_.BX() << ", endcap "
276  // << Hit_.Endcap() << ", station " << Hit_.Station() << ", neighbor "
277  // << Hit_.Neighbor() << ", ring " << Hit_.Ring() << ", chamber " << Hit_.Chamber()
278  // << ", roll " << Hit_.Roll() << ", pad " << Hit_.Pad() << std::endl;
279 
280  (res->at(iOut)).push_GEM(GEM_);
281  if (!exact_duplicate)
282  res_hit->push_back(Hit_);
283 
284  if (!exact_duplicate)
285  res_GEM->insertDigi(Hit_.GEM_DetId(), Hit_.CreateGEMPadDigiCluster());
286 
287  // Finished with unpacking one GEM Data Record
288  }
289  return true;
290 
291  } // End bool GEMBlockUnpacker::unpack
292 
293  // bool GEMBlockPacker::pack(const Block& block, UnpackerCollections *coll) {
294  // std::cout << "Inside GEMBlockPacker::pack" << std::endl;
295  // return true;
296  // } // End bool GEMBlockPacker::pack
297 
298  } // End namespace emtf
299  } // End namespace stage2
300 } // End namespace l1t
301 
303 // DEFINE_L1T_PACKER(l1t::stage2::emtf::GEMBlockPacker);
void set_neighbor(int bits)
Definition: EMTFHit.h:147
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 set_gem_bxn(const int bits)
Definition: GEM.h:35
int Neighbor() const
Definition: EMTFHit.h:215
GEMPadDigiCluster CreateGEMPadDigiCluster() const
Definition: EMTFHit.cc:109
Definition: Event.h:15
delete x;
Definition: CaloConfig.h:22
virtual int checkFormat(const Block &block)
Definition: EMTFBlockGEM.cc:33
Log< level::Error, false > LogError
void ImportGEM(EMTFHit &_hit, const l1t::emtf::GEM &_GEM, const int _endcap, const int _evt_sector)
int Roll() const
Definition: EMTFHit.h:214
Definition: Electron.h:6
void set_ring(int bits)
Definition: EMTFHit.h:137
constexpr std::array< uint8_t, layerIndexSize > layer
int Pad() const
Repurpose "strip" as GEM pad for GEM sourced hits.
Definition: EMTFHit.h:248
void set_bc0(const int bits)
Definition: GEM.h:36
void set_link(const int bits)
Definition: GEM.h:34
void set_tbin(const int bits)
Definition: GEM.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
void set_cluster_id(const int bits)
Definition: GEM.h:33
int ClusterID() const
Returns the the cluster ID within the link.
Definition: GEM.h:49
std::vector< EMTFDaqOut > EMTFDaqOutCollection
Definition: EMTFDaqOut.h:179
int BX() const
Definition: EMTFHit.h:262
void set_partition(const int bits)
Definition: GEM.h:31
bool unpack(const Block &block, UnpackerCollections *coll) override
Unpack the GEM payload in the EMTF DAQ payload.
void set_vp(const int bits)
Definition: GEM.h:38
void set_pad(const int bits)
Definition: GEM.h:30
void add_format_error()
Definition: GEM.h:39
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
GEMDetId GEM_DetId() const
Definition: EMTFHit.h:130
void convert_GEM_location(int &station, int &ring, int &sector, int &subsector, int &neighbor, int &layer, const int evt_sector, const int cluster_id, const int link)
Converts station, ring, sector, subsector, neighbor, and segment from the GEM output.
Definition: EMTFBlockGEM.cc:90
#define DEFINE_L1T_UNPACKER(type)
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_chamber(int bits)
Definition: EMTFHit.h:143
void set_subsector(int bits)
Definition: EMTFHit.h:141
void set_cluster_size(const int bits)
Definition: GEM.h:32
int Link() const
Returns the input link of the cluster.
Definition: GEM.h:51