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  bool reducedDAQWindow =
136  (getAlgoVersion() >=
137  11656); // Firmware from 08.12.22 which is used as a flag for new reduced readout window - EY 01.03.23
138 
139  int nTPs = run3_DAQ_format ? 2 : 1;
140 
141  // Check Format of Payload
142  l1t::emtf::GEM GEM_;
143  for (int err = 0; err < checkFormat(block); ++err) {
144  GEM_.add_format_error();
145  }
146 
147  // Assign payload to 16-bit words
148  uint16_t GEMa = payload[0];
149  uint16_t GEMb = payload[1];
150  uint16_t GEMc = payload[2];
151  uint16_t GEMd = payload[3];
152 
153  // If there are 2 TPs in the block we fill them 1 by 1
154  for (int i = 1; i <= nTPs; i++) {
155  // res is a pointer to a collection of EMTFDaqOut class objects
156  // There is one EMTFDaqOut for each MTF7 (60 deg. sector) in the event
158  res = static_cast<EMTFCollections*>(coll)->getEMTFDaqOuts();
159  int iOut = res->size() - 1;
160 
161  EMTFHitCollection* res_hit;
162  res_hit = static_cast<EMTFCollections*>(coll)->getEMTFHits();
163  EMTFHit Hit_;
164 
165  // TODO: Verify this is correct for GEM
167  res_GEM = static_cast<EMTFCollections*>(coll)->getEMTFGEMPadClusters();
168 
170  // Unpack the GEM Data Record
172  if (run3_DAQ_format) { // Run 3 DAQ format has 2 TPs per block
173  if (i == 1) {
174  GEM_.set_pad(GetHexBits(GEMa, 0, 8));
175  GEM_.set_partition(GetHexBits(GEMa, 9, 11));
176  GEM_.set_cluster_size(GetHexBits(GEMa, 12, 14));
177 
178  if (reducedDAQWindow) // reduced DAQ window is used only after run3 DAQ format
179  GEM_.set_tbin(GetHexBits(GEMb, 0, 2) + 1);
180  else
181  GEM_.set_tbin(GetHexBits(GEMb, 0, 2));
182  GEM_.set_vp(GetHexBits(GEMb, 3, 3));
183  GEM_.set_bc0(GetHexBits(GEMb, 7, 7));
184  GEM_.set_cluster_id(GetHexBits(GEMb, 8, 11));
185  GEM_.set_link(GetHexBits(GEMb, 12, 14));
186  } else if (i == 2) {
187  GEM_.set_pad(GetHexBits(GEMc, 0, 8));
188  GEM_.set_partition(GetHexBits(GEMc, 9, 11));
189  GEM_.set_cluster_size(GetHexBits(GEMc, 12, 14));
190 
191  if (reducedDAQWindow) // reduced DAQ window is used only after run3 DAQ format
192  GEM_.set_tbin(GetHexBits(GEMd, 0, 2) + 1);
193  else
194  GEM_.set_tbin(GetHexBits(GEMd, 0, 2));
195  GEM_.set_vp(GetHexBits(GEMd, 3, 3));
196  GEM_.set_bc0(GetHexBits(GEMd, 7, 7));
197  GEM_.set_cluster_id(GetHexBits(GEMd, 8, 11));
198  GEM_.set_link(GetHexBits(GEMd, 12, 14));
199  }
200  } else {
201  GEM_.set_pad(GetHexBits(GEMa, 0, 8));
202  GEM_.set_partition(GetHexBits(GEMa, 9, 11));
203  GEM_.set_cluster_size(GetHexBits(GEMa, 12, 14));
204 
205  GEM_.set_cluster_id(GetHexBits(GEMb, 8, 11));
206  GEM_.set_link(GetHexBits(GEMb, 12, 14));
207 
208  GEM_.set_gem_bxn(GetHexBits(GEMc, 0, 11));
209  GEM_.set_bc0(GetHexBits(GEMc, 14, 14));
210 
211  GEM_.set_tbin(GetHexBits(GEMd, 0, 2));
212  GEM_.set_vp(GetHexBits(GEMd, 3, 3));
213 
214  // GEM_.set_dataword(uint64_t dataword);
215  }
216 
217  // Convert specially-encoded GEM quantities
218  // TODO: is the RPC or CSC method for this function better... - JS 06.07.20
219  int _station, _ring, _sector, _subsector, _neighbor, _layer;
220  convert_GEM_location(_station,
221  _ring,
222  _sector,
223  _subsector,
224  _neighbor,
225  _layer,
226  (res->at(iOut)).PtrEventHeader()->Sector(),
227  GEM_.ClusterID(),
228  GEM_.Link());
229 
230  // Rotate by 20 deg to match GEM convention in CMSSW) // FIXME VERIFY
231  // int _sector_gem = (_subsector < 5) ? _sector : (_sector % 6) + 1; //
232  int _sector_gem = _sector;
233  // Rotate by 2 to match GEM convention in CMSSW (GEMDetId.h) // FIXME VERIFY
234  int _subsector_gem = ((_subsector + 1) % 6) + 1;
235  // Define chamber number) // FIXME VERIFY
236  int _chamber = (_sector_gem - 1) * 6 + _subsector_gem;
237  // Define CSC-like subsector) // FIXME WHY?? VERIFY
238  int _subsector_csc = (_station != 1) ? 0 : ((_chamber % 6 > 2) ? 1 : 2);
239 
240  Hit_.set_station(_station);
241  Hit_.set_ring(_ring);
242  Hit_.set_sector(_sector);
243  Hit_.set_subsector(_subsector_csc);
244  Hit_.set_chamber(_chamber);
245  Hit_.set_neighbor(_neighbor);
246 
247  // Fill the EMTFHit
248  ImportGEM(Hit_, GEM_, (res->at(iOut)).PtrEventHeader()->Endcap(), (res->at(iOut)).PtrEventHeader()->Sector());
249 
250  // Set the stub number for this hit
251  // Each chamber can send up to 2 stubs per BX // FIXME is this true for GEM, are stubs relevant for GEMs?
252  // Also count stubs in corresponding CSC chamber; GEM hit counting is on top of LCT counting
253  Hit_.set_stub_num(0);
254  // See if matching hit is already in event record
255  bool exact_duplicate = false;
256  for (auto const& iHit : *res_hit) {
257  if (Hit_.BX() == iHit.BX() && Hit_.Endcap() == iHit.Endcap() && Hit_.Station() == iHit.Station() &&
258  Hit_.Chamber() == iHit.Chamber()) {
259  if ((iHit.Is_CSC() == 1 && iHit.Ring() == 2) ||
260  (iHit.Is_GEM() == 1)) { // Copied from RPC, but GEM has no ring 2/3...
261  if (Hit_.Neighbor() == iHit.Neighbor()) {
262  Hit_.set_stub_num(Hit_.Stub_num() + 1);
263  if (iHit.Is_GEM() == 1 && iHit.Ring() == Hit_.Ring() && iHit.Roll() == Hit_.Roll() &&
264  iHit.Pad() == Hit_.Pad()) {
265  exact_duplicate = true;
266  }
267  }
268  }
269  }
270  } // End loop: for (auto const & iHit : *res_hit)
271 
272  // 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
273  if (Hit_.BX() > 3 or Hit_.BX() < -3) {
274  edm::LogWarning("L1T|EMTF") << "EMTF unpacked GEM digis with out-of-range BX! BX " << Hit_.BX()
275  << ", endcap " << Hit_.Endcap() << ", station " << Hit_.Station()
276  << ", neighbor " << Hit_.Neighbor() << ", ring " << Hit_.Ring() << ", chamber "
277  << Hit_.Chamber() << ", roll " << Hit_.Roll() << ", pad " << Hit_.Pad()
278  << std::endl;
279  return true;
280  }
281 
282  // TODO: Re-enable once GEM TP data format is fixed
283  // if (exact_duplicate)
284  // edm::LogWarning("L1T|EMTF") << "EMTF unpacked duplicate GEM digis: BX " << Hit_.BX() << ", endcap "
285  // << Hit_.Endcap() << ", station " << Hit_.Station() << ", neighbor "
286  // << Hit_.Neighbor() << ", ring " << Hit_.Ring() << ", chamber " << Hit_.Chamber()
287  // << ", roll " << Hit_.Roll() << ", pad " << Hit_.Pad() << std::endl;
288 
289  (res->at(iOut)).push_GEM(GEM_);
290  if (!exact_duplicate and Hit_.Valid())
291  res_hit->push_back(Hit_);
292 
293  if (!exact_duplicate and Hit_.Valid())
294  res_GEM->insertDigi(Hit_.GEM_DetId(), Hit_.CreateGEMPadDigiCluster());
295 
296  // Finished with unpacking one GEM Data Record
297  }
298  return true;
299 
300  } // End bool GEMBlockUnpacker::unpack
301 
302  // bool GEMBlockPacker::pack(const Block& block, UnpackerCollections *coll) {
303  // std::cout << "Inside GEMBlockPacker::pack" << std::endl;
304  // return true;
305  // } // End bool GEMBlockPacker::pack
306 
307  } // End namespace emtf
308  } // End namespace stage2
309 } // End namespace l1t
310 
312 // DEFINE_L1T_PACKER(l1t::stage2::emtf::GEMBlockPacker);
void set_neighbor(int bits)
Definition: EMTFHit.h:153
unsigned int getAlgoVersion()
Definition: Unpacker.h:18
void set_stub_num(int bits)
Definition: EMTFHit.h:189
void set_station(int bits)
Definition: EMTFHit.h:142
void set_gem_bxn(const int bits)
Definition: GEM.h:35
int Neighbor() const
Definition: EMTFHit.h:224
GEMPadDigiCluster CreateGEMPadDigiCluster() const
Definition: EMTFHit.cc:119
Definition: Event.h:15
delete x;
Definition: CaloConfig.h:22
int Valid() const
Definition: EMTFHit.h:247
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:223
Definition: Electron.h:6
void set_ring(int bits)
Definition: EMTFHit.h:143
int Pad() const
Repurpose "strip" as GEM pad for GEM sourced hits.
Definition: EMTFHit.h:260
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:381
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:274
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:144
int Endcap() const
Definition: EMTFHit.h:212
int Station() const
Definition: EMTFHit.h:213
int Stub_num() const
Definition: EMTFHit.h:275
int Chamber() const
Definition: EMTFHit.h:220
GEMDetId GEM_DetId() const
Definition: EMTFHit.h:136
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:214
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:149
void set_subsector(int bits)
Definition: EMTFHit.h:147
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