Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2022-09-21 02:12:28

0001 // Code to unpack the "GEM Data Record"
0002 
0003 #include "EventFilter/L1TRawToDigi/plugins/UnpackerFactory.h"
0004 
0005 #include "EMTFCollections.h"
0006 #include "EMTFUnpackerTools.h"
0007 
0008 namespace l1t {
0009   namespace stage2 {
0010     namespace emtf {
0011 
0012       class GEMBlockUnpacker : public Unpacker {
0013       public:
0014         virtual int checkFormat(const Block& block);
0015         // virtual bool checkFormat() override; // Return "false" if block format does not match expected format
0016         bool unpack(const Block& block, UnpackerCollections* coll) override;
0017         // virtual bool packBlock(const Block& block, UnpackerCollections *coll) override;
0018       };
0019 
0020       // class GEMBlockPacker : public Packer {
0021       // public:
0022       //    virtual bool unpack(const Block& block, UnpackerCollections *coll) override;
0023       // };
0024 
0025     }  // namespace emtf
0026   }    // namespace stage2
0027 }  // namespace l1t
0028 
0029 namespace l1t {
0030   namespace stage2 {
0031     namespace emtf {
0032 
0033       int GEMBlockUnpacker::checkFormat(const Block& block) {
0034         auto payload = block.payload();
0035         int errors = 0;
0036 
0037         // Check the number of 16-bit words
0038         if (payload.size() != 4) {
0039           errors += 1;
0040           edm::LogError("L1T|EMTF") << "Payload size in 'GEM Data Record' is different than expected";
0041         }
0042 
0043         // Check that each word is 16 bits
0044         for (size_t i = 0; i < 4; ++i) {
0045           if (GetHexBits(payload[i], 16, 31) != 0) {
0046             errors += 1;
0047             edm::LogError("L1T|EMTF") << "Payload[" << i << "] has more than 16 bits in 'GEM Data Record'";
0048           }
0049         }
0050 
0051         uint16_t GEMa = payload[0];
0052         uint16_t GEMb = payload[1];
0053         uint16_t GEMc = payload[2];
0054         uint16_t GEMd = payload[3];
0055 
0056         // Check Format
0057         if (GetHexBits(GEMa, 15, 15) != 1) {
0058           errors += 1;
0059           edm::LogError("L1T|EMTF") << "Format identifier bits in GEMa are incorrect";
0060         }
0061         if (GetHexBits(GEMb, 15, 15) != 1) {
0062           errors += 1;
0063           edm::LogError("L1T|EMTF") << "Format identifier bits in GEMb are incorrect";
0064         }
0065         if (GetHexBits(GEMc, 15, 15) != 1) {
0066           errors += 1;
0067           edm::LogError("L1T|EMTF") << "Format identifier bits in GEMc are incorrect";
0068         }
0069         if (GetHexBits(GEMd, 15, 15) != 0) {
0070           errors += 1;
0071           edm::LogError("L1T|EMTF") << "Format identifier bits in GEMd are incorrect";
0072         }
0073 
0074         return errors;
0075       }
0076 
0077       /**
0078        * \brief Converts station, ring, sector, subsector, neighbor, and segment from the GEM output
0079        * \param station
0080        * \param ring
0081        * \param sector
0082        * \param subsector
0083        * \param neighbor
0084        * \param segment
0085        * \param evt_sector
0086        * \param frame
0087        * \param word
0088        * \param link is the "link index" field (0 - 6) in the EMTF DAQ document, not "link number" (1 - 7)
0089       */
0090       void convert_GEM_location(int& station,
0091                                 int& ring,
0092                                 int& sector,
0093                                 int& subsector,
0094                                 int& neighbor,
0095                                 int& layer,  // is this correct for the GEM case?
0096                                 const int evt_sector,
0097                                 const int cluster_id,  // used to differentiate between GEM layer 1/2
0098                                 const int link) {
0099         station =
0100             1;  // station is not encoded in the GEM frame for now. Set station = 1 since we only have GE1/1 for Run 3.
0101         ring = 1;  // GEMs are only in GE1/1 and GE2/1
0102         sector = -99;
0103         subsector = -99;
0104         neighbor = -99;
0105         layer = -99;  // the GEM layer is 1 or 2, depending on the cluster ID
0106 
0107         // Neighbor indicated by link == 6
0108         sector = (link != 6 ? evt_sector : (evt_sector == 1 ? 6 : evt_sector - 1));
0109         subsector = (link != 6 ? link : 0);  // TODO: verify subsector 0 in the neighbouring sector?
0110         neighbor = (link == 6 ? 1 : 0);  // TODO: verify that 6 is for the neighbour, not 0 (as written in EMTFBlockRPC)
0111         layer = (cluster_id % 8);        // + 1 if layer should be 1 or 2, otherwise layer is 0 or 1
0112       }
0113 
0114       /**
0115        * \brief Unpack the GEM payload in the EMTF DAQ payload
0116        *
0117        * The GEM payload consists of up to 14 clusters per link (for the two GEM layers)
0118        * 7 links (including neighbour).
0119        * The EMTF firmware packs each cluster word into one 64-bit EMTF record, and
0120        * that is what is unpacked here.
0121        */
0122       bool GEMBlockUnpacker::unpack(const Block& block, UnpackerCollections* coll) {
0123         // std::cout << "Inside EMTFBlockGEM.cc: unpack" << std::endl;
0124 
0125         // Get the payload for this block, made up of 16-bit words (0xffff)
0126         // Format defined in MTF7Payload::getBlock() in src/Block.cc
0127         // payload[0] = bits 0-15, payload[1] = 16-31, payload[3] = 32-47, etc.
0128         auto payload = block.payload();
0129 
0130         // Run 3 has a different EMTF DAQ output format since August 26th
0131         // Computed as (Year - 2000)*2^9 + Month*2^5 + Day (see Block.cc and EMTFBlockTrailers.cc)
0132         bool run3_DAQ_format =
0133             (getAlgoVersion() >=
0134              11546);  // Firmware from 26.08.22 which enabled new Run 3 DAQ format for GEMs - EY 13.09.22
0135 
0136         int nTPs = run3_DAQ_format ? 2 : 1;
0137 
0138         // Check Format of Payload
0139         l1t::emtf::GEM GEM_;
0140         for (int err = 0; err < checkFormat(block); ++err) {
0141           GEM_.add_format_error();
0142         }
0143 
0144         // Assign payload to 16-bit words
0145         uint16_t GEMa = payload[0];
0146         uint16_t GEMb = payload[1];
0147         uint16_t GEMc = payload[2];
0148         uint16_t GEMd = payload[3];
0149 
0150         // If there are 2 TPs in the block we fill them 1 by 1
0151         for (int i = 1; i <= nTPs; i++) {
0152           // res is a pointer to a collection of EMTFDaqOut class objects
0153           // There is one EMTFDaqOut for each MTF7 (60 deg. sector) in the event
0154           EMTFDaqOutCollection* res;
0155           res = static_cast<EMTFCollections*>(coll)->getEMTFDaqOuts();
0156           int iOut = res->size() - 1;
0157 
0158           EMTFHitCollection* res_hit;
0159           res_hit = static_cast<EMTFCollections*>(coll)->getEMTFHits();
0160           EMTFHit Hit_;
0161 
0162           // TODO: Verify this is correct for GEM
0163           GEMPadDigiClusterCollection* res_GEM;
0164           res_GEM = static_cast<EMTFCollections*>(coll)->getEMTFGEMPadClusters();
0165 
0166           ////////////////////////////
0167           // Unpack the GEM Data Record
0168           ////////////////////////////
0169           if (run3_DAQ_format) {  // Run 3 DAQ format has 2 TPs per block
0170             if (i == 1) {
0171               GEM_.set_pad(GetHexBits(GEMa, 0, 8));
0172               GEM_.set_partition(GetHexBits(GEMa, 9, 11));
0173               GEM_.set_cluster_size(GetHexBits(GEMa, 12, 14));
0174 
0175               GEM_.set_tbin(GetHexBits(GEMb, 0, 2));
0176               GEM_.set_vp(GetHexBits(GEMb, 3, 3));
0177               GEM_.set_bc0(GetHexBits(GEMb, 7, 7));
0178               GEM_.set_cluster_id(GetHexBits(GEMb, 8, 11));
0179               GEM_.set_link(GetHexBits(GEMb, 12, 14));
0180             } else if (i == 2) {
0181               GEM_.set_pad(GetHexBits(GEMc, 0, 8));
0182               GEM_.set_partition(GetHexBits(GEMc, 9, 11));
0183               GEM_.set_cluster_size(GetHexBits(GEMc, 12, 14));
0184 
0185               GEM_.set_tbin(GetHexBits(GEMd, 0, 2));
0186               GEM_.set_vp(GetHexBits(GEMd, 3, 3));
0187               GEM_.set_bc0(GetHexBits(GEMd, 7, 7));
0188               GEM_.set_cluster_id(GetHexBits(GEMd, 8, 11));
0189               GEM_.set_link(GetHexBits(GEMd, 12, 14));
0190             }
0191           } else {
0192             GEM_.set_pad(GetHexBits(GEMa, 0, 8));
0193             GEM_.set_partition(GetHexBits(GEMa, 9, 11));
0194             GEM_.set_cluster_size(GetHexBits(GEMa, 12, 14));
0195 
0196             GEM_.set_cluster_id(GetHexBits(GEMb, 8, 11));
0197             GEM_.set_link(GetHexBits(GEMb, 12, 14));
0198 
0199             GEM_.set_gem_bxn(GetHexBits(GEMc, 0, 11));
0200             GEM_.set_bc0(GetHexBits(GEMc, 14, 14));
0201 
0202             GEM_.set_tbin(GetHexBits(GEMd, 0, 2));
0203             GEM_.set_vp(GetHexBits(GEMd, 3, 3));
0204 
0205             // GEM_.set_dataword(uint64_t dataword);
0206           }
0207 
0208           // Convert specially-encoded GEM quantities
0209           // TODO: is the RPC or CSC method for this function better... - JS 06.07.20
0210           int _station, _ring, _sector, _subsector, _neighbor, _layer;
0211           convert_GEM_location(_station,
0212                                _ring,
0213                                _sector,
0214                                _subsector,
0215                                _neighbor,
0216                                _layer,
0217                                (res->at(iOut)).PtrEventHeader()->Sector(),
0218                                GEM_.ClusterID(),
0219                                GEM_.Link());
0220 
0221           // Rotate by 20 deg to match GEM convention in CMSSW) // FIXME VERIFY
0222           // int _sector_gem = (_subsector < 5) ? _sector : (_sector % 6) + 1; //
0223           int _sector_gem = _sector;
0224           // Rotate by 2 to match GEM convention in CMSSW (GEMDetId.h) // FIXME VERIFY
0225           int _subsector_gem = ((_subsector + 1) % 6) + 1;
0226           // Define chamber number) // FIXME VERIFY
0227           int _chamber = (_sector_gem - 1) * 6 + _subsector_gem;
0228           // Define CSC-like subsector) // FIXME WHY?? VERIFY
0229           int _subsector_csc = (_station != 1) ? 0 : ((_chamber % 6 > 2) ? 1 : 2);
0230 
0231           Hit_.set_station(_station);
0232           Hit_.set_ring(_ring);
0233           Hit_.set_sector(_sector);
0234           Hit_.set_subsector(_subsector_csc);
0235           Hit_.set_chamber(_chamber);
0236           Hit_.set_neighbor(_neighbor);
0237 
0238           // Fill the EMTFHit
0239           ImportGEM(Hit_, GEM_, (res->at(iOut)).PtrEventHeader()->Endcap(), (res->at(iOut)).PtrEventHeader()->Sector());
0240 
0241           // Set the stub number for this hit
0242           // Each chamber can send up to 2 stubs per BX // FIXME is this true for GEM, are stubs relevant for GEMs?
0243           // Also count stubs in corresponding CSC chamber; GEM hit counting is on top of LCT counting
0244           Hit_.set_stub_num(0);
0245           // See if matching hit is already in event record
0246           bool exact_duplicate = false;
0247           for (auto const& iHit : *res_hit) {
0248             if (Hit_.BX() == iHit.BX() && Hit_.Endcap() == iHit.Endcap() && Hit_.Station() == iHit.Station() &&
0249                 Hit_.Chamber() == iHit.Chamber()) {
0250               if ((iHit.Is_CSC() == 1 && iHit.Ring() == 2) ||
0251                   (iHit.Is_GEM() == 1)) {  // Copied from RPC, but GEM has no ring 2/3...
0252                 if (Hit_.Neighbor() == iHit.Neighbor()) {
0253                   Hit_.set_stub_num(Hit_.Stub_num() + 1);
0254                   if (iHit.Is_GEM() == 1 && iHit.Ring() == Hit_.Ring() && iHit.Roll() == Hit_.Roll() &&
0255                       iHit.Pad() == Hit_.Pad()) {
0256                     exact_duplicate = true;
0257                   }
0258                 }
0259               }
0260             }
0261           }  // End loop: for (auto const & iHit : *res_hit)
0262 
0263           // 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
0264           if (Hit_.BX() > 3 or Hit_.BX() < -3) {
0265             edm::LogWarning("L1T|EMTF") << "EMTF unpacked  GEM digis with out-of-range BX! BX " << Hit_.BX()
0266                                         << ", endcap " << Hit_.Endcap() << ", station " << Hit_.Station()
0267                                         << ", neighbor " << Hit_.Neighbor() << ", ring " << Hit_.Ring() << ", chamber "
0268                                         << Hit_.Chamber() << ", roll " << Hit_.Roll() << ", pad " << Hit_.Pad()
0269                                         << std::endl;
0270             return true;
0271           }
0272 
0273           // TODO: Re-enable once GEM TP data format is fixed
0274           // if (exact_duplicate)
0275           //   edm::LogWarning("L1T|EMTF") << "EMTF unpacked duplicate GEM digis: BX " << Hit_.BX() << ", endcap "
0276           //                               << Hit_.Endcap() << ", station " << Hit_.Station() << ", neighbor "
0277           //                               << Hit_.Neighbor() << ", ring " << Hit_.Ring() << ", chamber " << Hit_.Chamber()
0278           //                               << ", roll " << Hit_.Roll() << ", pad " << Hit_.Pad() << std::endl;
0279 
0280           (res->at(iOut)).push_GEM(GEM_);
0281           if (!exact_duplicate)
0282             res_hit->push_back(Hit_);
0283 
0284           if (!exact_duplicate)
0285             res_GEM->insertDigi(Hit_.GEM_DetId(), Hit_.CreateGEMPadDigiCluster());
0286 
0287           // Finished with unpacking one GEM Data Record
0288         }
0289         return true;
0290 
0291       }  // End bool GEMBlockUnpacker::unpack
0292 
0293       // bool GEMBlockPacker::pack(const Block& block, UnpackerCollections *coll) {
0294       //    std::cout << "Inside GEMBlockPacker::pack" << std::endl;
0295       //    return true;
0296       // } // End bool GEMBlockPacker::pack
0297 
0298     }  // End namespace emtf
0299   }    // End namespace stage2
0300 }  // End namespace l1t
0301 
0302 DEFINE_L1T_UNPACKER(l1t::stage2::emtf::GEMBlockUnpacker);
0303 // DEFINE_L1T_PACKER(l1t::stage2::emtf::GEMBlockPacker);