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 == 4
108  sector = (link != 4 ? evt_sector : (evt_sector == 1 ? 6 : evt_sector - 1));
109  subsector = (link < 4 ? link : (link == 4 ? 5 : link - 1));
110  neighbor = (link == 4 ? 1 : 0);
111  layer = (cluster_id / 4) % 2 + 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 
166  res_GEM = static_cast<EMTFCollections*>(coll)->getEMTFGEMPadClusters();
167 
169  // Unpack the GEM Data Record
171  if (run3_DAQ_format) { // Run 3 DAQ format has 2 TPs per block
172  if (i == 1) { // GE1/1 layer 1, GE2/1 not know yet
173  GEM_.set_pad(GetHexBits(GEMa, 0, 8));
174  GEM_.set_partition(GetHexBits(GEMa, 9, 11));
175  GEM_.set_cluster_size(GetHexBits(GEMa, 12, 14));
176 
177  if (reducedDAQWindow) // reduced DAQ window is used only after run3 DAQ format
178  GEM_.set_tbin(GetHexBits(GEMb, 0, 2) + 1);
179  else
180  GEM_.set_tbin(GetHexBits(GEMb, 0, 2));
181  GEM_.set_vp(GetHexBits(GEMb, 3, 3));
182  GEM_.set_bc0(GetHexBits(GEMb, 7, 7));
183  GEM_.set_cluster_id(GetHexBits(GEMb, 8, 11));
184  GEM_.set_link(GetHexBits(GEMb, 12, 14));
185  } else if (i == 2) { // GE1/1 layer2, GE2/1 not know yet
186  GEM_.set_pad(GetHexBits(GEMc, 0, 8));
187  GEM_.set_partition(GetHexBits(GEMc, 9, 11));
188  GEM_.set_cluster_size(GetHexBits(GEMc, 12, 14));
189 
190  if (reducedDAQWindow) // reduced DAQ window is used only after run3 DAQ format
191  GEM_.set_tbin(GetHexBits(GEMd, 0, 2) + 1);
192  else
193  GEM_.set_tbin(GetHexBits(GEMd, 0, 2));
194  GEM_.set_vp(GetHexBits(GEMd, 3, 3));
195  GEM_.set_bc0(GetHexBits(GEMd, 7, 7));
196  GEM_.set_cluster_id(GetHexBits(GEMd, 8, 11));
197  GEM_.set_link(GetHexBits(GEMd, 12, 14));
198  }
199  } else {
200  GEM_.set_pad(GetHexBits(GEMa, 0, 8));
201  GEM_.set_partition(GetHexBits(GEMa, 9, 11));
202  GEM_.set_cluster_size(GetHexBits(GEMa, 12, 14));
203 
204  GEM_.set_cluster_id(GetHexBits(GEMb, 8, 11));
205  GEM_.set_link(GetHexBits(GEMb, 12, 14));
206 
207  GEM_.set_gem_bxn(GetHexBits(GEMc, 0, 11));
208  GEM_.set_bc0(GetHexBits(GEMc, 14, 14));
209 
210  GEM_.set_tbin(GetHexBits(GEMd, 0, 2));
211  GEM_.set_vp(GetHexBits(GEMd, 3, 3));
212 
213  // GEM_.set_dataword(uint64_t dataword);
214  }
215 
216  // Convert specially-encoded GEM quantities
217  int _station, _ring, _sector, _subsector, _neighbor, _layer;
218  convert_GEM_location(_station,
219  _ring,
220  _sector,
221  _subsector,
222  _neighbor,
223  _layer,
224  (res->at(iOut)).PtrEventHeader()->Sector(),
225  GEM_.ClusterID(),
226  GEM_.Link());
227 
228  int _sector_gem = _sector;
229  int _subsector_gem = _subsector;
230  int _chamber = ((_sector_gem - 1) * 6 + _subsector_gem + 2) % 36 + 1;
231  // Define CSC-like subsector)
232  int _subsector_csc = (_station != 1) ? 0 : ((_chamber % 6 > 2) ? 1 : 2);
233 
234  Hit_.set_station(_station);
235  Hit_.set_ring(_ring);
236  Hit_.set_sector(_sector);
237  Hit_.set_subsector(_subsector_csc);
238  Hit_.set_chamber(_chamber);
239  Hit_.set_neighbor(_neighbor);
240  Hit_.set_layer(_layer);
241 
242  // Fill the EMTFHit
243  ImportGEM(Hit_, GEM_, (res->at(iOut)).PtrEventHeader()->Endcap(), (res->at(iOut)).PtrEventHeader()->Sector());
244 
245  // Set the stub number for this hit
246  // Each GEM superchamber can send up to 8 clusters per layer per BX
247  // Also count stubs in corresponding CSC chamber; GEM hit counting is on top of LCT counting
248  Hit_.set_stub_num(0);
249  // See if matching hit is already in event record
250  bool exact_duplicate = false;
251  for (auto const& iHit : *res_hit) {
252  if (Hit_.BX() == iHit.BX() && Hit_.Endcap() == iHit.Endcap() && Hit_.Station() == iHit.Station() &&
253  Hit_.Chamber() == iHit.Chamber()) {
254  if ((iHit.Is_CSC() == 1 && iHit.Ring() == 2) ||
255  (iHit.Is_GEM() == 1)) { // Copied from RPC, but GEM has no ring 2/3...
256  if (Hit_.Neighbor() == iHit.Neighbor()) {
257  Hit_.set_stub_num(Hit_.Stub_num() + 1);
258  if (iHit.Is_GEM() == 1 && iHit.Ring() == Hit_.Ring() && iHit.Roll() == Hit_.Roll() &&
259  iHit.Pad() == Hit_.Pad()) {
260  exact_duplicate = true;
261  }
262  }
263  }
264  }
265  } // End loop: for (auto const & iHit : *res_hit)
266 
267  // 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
268  if (Hit_.BX() > 3 or Hit_.BX() < -3) {
269  edm::LogWarning("L1T|EMTF") << "EMTF unpacked GEM digis with out-of-range BX! BX " << Hit_.BX()
270  << ", endcap " << Hit_.Endcap() << ", station " << Hit_.Station()
271  << ", neighbor " << Hit_.Neighbor() << ", ring " << Hit_.Ring() << ", chamber "
272  << Hit_.Chamber() << ", roll " << Hit_.Roll() << ", pad " << Hit_.Pad()
273  << std::endl;
274  return true;
275  }
276 
277  // TODO: Re-enable once GEM TP data format is fixed
278  // if (exact_duplicate)
279  // edm::LogWarning("L1T|EMTF") << "EMTF unpacked duplicate GEM digis: BX " << Hit_.BX() << ", endcap "
280  // << Hit_.Endcap() << ", station " << Hit_.Station() << ", neighbor "
281  // << Hit_.Neighbor() << ", ring " << Hit_.Ring() << ", chamber " << Hit_.Chamber()
282  // << ", roll " << Hit_.Roll() << ", pad " << Hit_.Pad() << std::endl;
283 
284  (res->at(iOut)).push_GEM(GEM_);
285  if (!exact_duplicate and Hit_.Valid())
286  res_hit->push_back(Hit_);
287 
288  if (!exact_duplicate and Hit_.Valid())
289  res_GEM->insertDigi(Hit_.GEM_DetId(), Hit_.CreateGEMPadDigiCluster());
290 
291  // Finished with unpacking one GEM Data Record
292  }
293  return true;
294 
295  } // End bool GEMBlockUnpacker::unpack
296 
297  // bool GEMBlockPacker::pack(const Block& block, UnpackerCollections *coll) {
298  // std::cout << "Inside GEMBlockPacker::pack" << std::endl;
299  // return true;
300  // } // End bool GEMBlockPacker::pack
301 
302  } // End namespace emtf
303  } // End namespace stage2
304 } // End namespace l1t
305 
307 // 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 set_layer(int bits)
Definition: EMTFHit.h:183
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