Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2022-09-02 08:36:07

0001 // Code to unpack the "ME Data Record"
0002 
0003 #include "EventFilter/L1TRawToDigi/plugins/UnpackerFactory.h"
0004 
0005 #include "EMTFCollections.h"
0006 #include "EMTFUnpackerTools.h"
0007 
0008 // This is the "header" - no EMTFBlockME.h file is needed
0009 namespace l1t {
0010   namespace stage2 {
0011     namespace emtf {
0012 
0013       class MEBlockUnpacker : public Unpacker {  // "MEBlockUnpacker" inherits from "Unpacker"
0014       public:
0015         virtual int checkFormat(const Block& block);
0016         bool unpack(const Block& block,
0017                     UnpackerCollections* coll) override;  // Apparently it's always good to use override in C++
0018         // virtual bool packBlock(const Block& block, UnpackerCollections *coll) override;
0019       };
0020 
0021       // class MEBlockPacker : public Packer { // "MEBlockPacker" inherits from "Packer"
0022       // public:
0023       //    virtual bool unpack(const Block& block, UnpackerCollections *coll) override; // Apparently it's always good to use override in C++
0024       // };
0025 
0026     }  // namespace emtf
0027   }    // namespace stage2
0028 }  // namespace l1t
0029 
0030 namespace l1t {
0031   namespace stage2 {
0032     namespace emtf {
0033 
0034       int MEBlockUnpacker::checkFormat(const Block& block) {
0035         auto payload = block.payload();
0036         int errors = 0;
0037 
0038         // Check the number of 16-bit words
0039         if (payload.size() != 4) {
0040           errors += 1;
0041           edm::LogError("L1T|EMTF") << "Payload size in 'ME Data Record' is different than expected";
0042         }
0043 
0044         // Check that each word is 16 bits
0045         for (unsigned int i = 0; i < 4; i++) {
0046           if (GetHexBits(payload[i], 16, 31) != 0) {
0047             errors += 1;
0048             edm::LogError("L1T|EMTF") << "Payload[" << i << "] has more than 16 bits in 'ME Data Record'";
0049           }
0050         }
0051 
0052         uint16_t MEa = payload[0];
0053         uint16_t MEb = payload[1];
0054         uint16_t MEc = payload[2];
0055         uint16_t MEd = payload[3];
0056 
0057         //Check Format
0058         if (GetHexBits(MEa, 15, 15) != 1) {
0059           errors += 1;
0060           edm::LogError("L1T|EMTF") << "Format identifier bits in MEa are incorrect";
0061         }
0062         if (GetHexBits(MEb, 15, 15) != 1) {
0063           errors += 1;
0064           edm::LogError("L1T|EMTF") << "Format identifier bits in MEb are incorrect";
0065         }
0066         if (GetHexBits(MEc, 15, 15) != 0) {
0067           errors += 1;
0068           edm::LogError("L1T|EMTF") << "Format identifier bits in MEc are incorrect";
0069         }
0070         if (GetHexBits(MEd, 15, 15) != 0) {
0071           errors += 1;
0072           edm::LogError("L1T|EMTF") << "Format identifier bits in MEd are incorrect";
0073         }
0074 
0075         return errors;
0076       }
0077 
0078       // Converts station, CSC_ID, sector, subsector, and neighbor from the ME output
0079       std::vector<int> convert_ME_location(int _station, int _csc_ID, int _sector, bool _csc_ID_shift = false) {
0080         int new_sector = _sector;
0081         int new_csc_ID = _csc_ID;
0082         if (_csc_ID_shift)
0083           new_csc_ID += 1;  // Before FW update on 05.05.16, shift by +1 from 0,1,2... convention to 1,2,3...
0084         if (_station == 0) {
0085           int arr[] = {1, new_csc_ID, new_sector, 1, 0};
0086           std::vector<int> vec(arr, arr + 5);
0087           return vec;
0088         } else if (_station == 1) {
0089           int arr[] = {1, new_csc_ID, new_sector, 2, 0};
0090           std::vector<int> vec(arr, arr + 5);
0091           return vec;
0092         } else if (_station <= 4) {
0093           int arr[] = {_station, new_csc_ID, new_sector, -1, 0};
0094           std::vector<int> vec(arr, arr + 5);
0095           return vec;
0096         } else if (_station == 5) {
0097           new_sector = (_sector != 1) ? _sector - 1 : 6;  // Indicates neighbor chamber, don't return yet
0098         } else {
0099           int arr[] = {_station, _csc_ID, _sector, -99, -99};
0100           std::vector<int> vec(arr, arr + 5);
0101           return vec;
0102         }
0103 
0104         // Mapping for chambers from neighboring sector
0105         if (new_csc_ID == 1) {
0106           int arr[] = {1, 3, new_sector, 2, 1};
0107           std::vector<int> vec(arr, arr + 5);
0108           return vec;
0109         } else if (new_csc_ID == 2) {
0110           int arr[] = {1, 6, new_sector, 2, 1};
0111           std::vector<int> vec(arr, arr + 5);
0112           return vec;
0113         } else if (new_csc_ID == 3) {
0114           int arr[] = {1, 9, new_sector, 2, 1};
0115           std::vector<int> vec(arr, arr + 5);
0116           return vec;
0117         } else if (new_csc_ID == 4) {
0118           int arr[] = {2, 3, new_sector, -1, 1};
0119           std::vector<int> vec(arr, arr + 5);
0120           return vec;
0121         } else if (new_csc_ID == 5) {
0122           int arr[] = {2, 9, new_sector, -1, 1};
0123           std::vector<int> vec(arr, arr + 5);
0124           return vec;
0125         } else if (new_csc_ID == 6) {
0126           int arr[] = {3, 3, new_sector, -1, 1};
0127           std::vector<int> vec(arr, arr + 5);
0128           return vec;
0129         } else if (new_csc_ID == 7) {
0130           int arr[] = {3, 9, new_sector, -1, 1};
0131           std::vector<int> vec(arr, arr + 5);
0132           return vec;
0133         } else if (new_csc_ID == 8) {
0134           int arr[] = {4, 3, new_sector, -1, 1};
0135           std::vector<int> vec(arr, arr + 5);
0136           return vec;
0137         } else if (new_csc_ID == 9) {
0138           int arr[] = {4, 9, new_sector, -1, 1};
0139           std::vector<int> vec(arr, arr + 5);
0140           return vec;
0141         } else {
0142           int arr[] = {_station, _csc_ID, _sector, -99, -99};
0143           std::vector<int> vec(arr, arr + 5);
0144           return vec;
0145         }
0146       }
0147 
0148       bool MEBlockUnpacker::unpack(const Block& block, UnpackerCollections* coll) {
0149         // std::cout << "Inside EMTFBlockME.cc: unpack" << std::endl;
0150 
0151         // Get the payload for this block, made up of 16-bit words (0xffff)
0152         // Format defined in MTF7Payload::getBlock() in src/Block.cc
0153         // payload[0] = bits 0-15, payload[1] = 16-31, payload[3] = 32-47, etc.
0154         auto payload = block.payload();
0155 
0156         // Assign payload to 16-bit words
0157         uint16_t MEa = payload[0];
0158         uint16_t MEb = payload[1];
0159         uint16_t MEc = payload[2];
0160         uint16_t MEd = payload[3];
0161 
0162         // Check Format of Payload
0163         l1t::emtf::ME ME_;
0164         for (int err = 0; err < checkFormat(block); err++)
0165           ME_.add_format_error();
0166 
0167         // res is a pointer to a collection of EMTFDaqOut class objects
0168         // There is one EMTFDaqOut for each MTF7 (60 deg. sector) in the event
0169         EMTFDaqOutCollection* res;
0170         res = static_cast<EMTFCollections*>(coll)->getEMTFDaqOuts();
0171         int iOut = res->size() - 1;
0172 
0173         EMTFHitCollection* res_hit;
0174         res_hit = static_cast<EMTFCollections*>(coll)->getEMTFHits();
0175         EMTFHit Hit_;
0176 
0177         CSCCorrelatedLCTDigiCollection* res_LCT;
0178         res_LCT = static_cast<EMTFCollections*>(coll)->getEMTFLCTs();
0179 
0180         CSCShowerDigiCollection* res_shower;
0181         res_shower = static_cast<EMTFCollections*>(coll)->getEMTFCSCShowers();
0182 
0183         ////////////////////////////
0184         // Unpack the ME Data Record
0185         ////////////////////////////
0186 
0187         // Run 3 has a different EMTF DAQ output format
0188         // Computed as (Year - 2000)*2^9 + Month*2^5 + Day (see Block.cc and EMTFBlockTrailers.cc)
0189         bool run3_DAQ_format =
0190             (getAlgoVersion() >= 11460);  // Firmware from 04.06.22 which enabled new Run 3 DAQ format - EY 04.07.22
0191 
0192         // Set fields assuming Run 2 format. Modify for Run 3 later
0193         ME_.set_clct_pattern(GetHexBits(MEa, 0, 3));
0194         ME_.set_quality(GetHexBits(MEa, 4, 7));
0195         ME_.set_wire(GetHexBits(MEa, 8, 14));
0196 
0197         ME_.set_strip(GetHexBits(MEb, 0, 7));
0198         ME_.set_csc_ID(GetHexBits(MEb, 8, 11));
0199         ME_.set_lr(GetHexBits(MEb, 12, 12));
0200         ME_.set_bxe(GetHexBits(MEb, 13, 13));
0201         ME_.set_bc0(GetHexBits(MEb, 14, 14));
0202 
0203         ME_.set_me_bxn(GetHexBits(MEc, 0, 11));
0204         ME_.set_nit(GetHexBits(MEc, 12, 12));
0205         ME_.set_cik(GetHexBits(MEc, 13, 13));
0206         ME_.set_afff(GetHexBits(MEc, 14, 14));
0207 
0208         ME_.set_tbin(GetHexBits(MEd, 0, 2));
0209         ME_.set_vp(GetHexBits(MEd, 3, 3));
0210         ME_.set_station(GetHexBits(MEd, 4, 6));
0211         ME_.set_af(GetHexBits(MEd, 7, 7));
0212         ME_.set_epc(GetHexBits(MEd, 8, 11));
0213         ME_.set_sm(GetHexBits(MEd, 12, 12));
0214         ME_.set_se(GetHexBits(MEd, 13, 13));
0215         ME_.set_afef(GetHexBits(MEd, 14, 14));
0216 
0217         // ME_.set_dataword     ( uint64_t dataword);
0218 
0219         // Convert specially-encoded ME quantities
0220         bool csc_ID_shift = (getAlgoVersion() <=
0221                              8348);  // For FW versions <= 28.04.2016, shift by +1 from 0,1,2... convention to 1,2,3...
0222         // Computed as (Year - 2000)*2^9 + Month*2^5 + Day (see Block.cc and EMTFBlockTrailers.cc)
0223         std::vector<int> conv_vals =
0224             convert_ME_location(ME_.Station(), ME_.CSC_ID(), (res->at(iOut)).PtrEventHeader()->Sector(), csc_ID_shift);
0225 
0226         Hit_.set_station(conv_vals.at(0));
0227         Hit_.set_csc_ID(conv_vals.at(1));
0228         Hit_.set_sector(conv_vals.at(2));
0229         Hit_.set_subsector(conv_vals.at(3));
0230         Hit_.set_neighbor(conv_vals.at(4));
0231         Hit_.set_ring(L1TMuonEndCap::calc_ring(Hit_.Station(), Hit_.CSC_ID(), ME_.Strip()));
0232 
0233         if (Hit_.Station() < 1 || Hit_.Station() > 4)
0234           edm::LogWarning("L1T|EMTF") << "EMTF unpacked LCT station = " << Hit_.Station()
0235                                       << ", outside proper [1, 4] range" << std::endl;
0236         if (Hit_.CSC_ID() < 1 || Hit_.CSC_ID() > 9)
0237           edm::LogWarning("L1T|EMTF") << "EMTF unpacked LCT CSC ID = " << Hit_.CSC_ID()
0238                                       << ", outside proper [1, 9] range" << std::endl;
0239         if (Hit_.Sector() < 1 || Hit_.Sector() > 6)
0240           edm::LogWarning("L1T|EMTF") << "EMTF unpacked LCT sector = " << Hit_.Sector()
0241                                       << ", outside proper [1, 6] range" << std::endl;
0242 
0243         // Modifications for Run 3 format - EY 04.07.22
0244         bool isOTMB = (Hit_.Ring() == 1 or
0245                        Hit_.Ring() == 4);  // Data format is different between OTMBs (MEX/1) and TMBs (MEX/2-3)
0246 
0247         bool isRun3 =
0248             isOTMB and run3_DAQ_format;  // in Run3 DAQ format, OTMB TPs are Run 3 CSC TPs with CCLUT algorithm
0249 
0250         if (run3_DAQ_format) {
0251           ME_.set_quality(GetHexBits(MEa, 4, 6));
0252           ME_.set_quarter_strip(GetHexBits(MEa, 7, 7));
0253 
0254           ME_.set_frame(GetHexBits(MEc, 12, 12));
0255 
0256           ME_.set_eighth_strip(GetHexBits(MEd, 13, 13));
0257 
0258           if (isOTMB) {  // Derive Run 2 pattern ID from Run 3 slope for OTMBs
0259 
0260             ME_.set_slope(GetHexBits(MEd, 8, 11));
0261 
0262             // convert Run-3 slope to Run-2 pattern for CSC TPs coming from MEX/1 chambers
0263             // where the CCLUT algorithm is enabled
0264             const unsigned slopeList[32] = {10, 10, 10, 8, 8, 8, 6, 6, 6, 4, 4, 4, 2, 2, 2, 2,
0265                                             10, 10, 10, 9, 9, 9, 7, 7, 7, 5, 5, 5, 3, 3, 3, 3};
0266 
0267             // this LUT follows the same convention as in CSCPatternBank.cc
0268             unsigned slope_and_sign(ME_.Slope());
0269             if (ME_.LR() == 1) {
0270               slope_and_sign += 16;
0271             }
0272             unsigned run2_converted_PID = slopeList[slope_and_sign];
0273 
0274             ME_.set_clct_pattern(run2_converted_PID);
0275 
0276           } else {  // Use Run 2 pattern directly for TMBs
0277             ME_.set_clct_pattern(GetHexBits(MEd, 8, 11));
0278           }
0279 
0280           // Frame 1 has HMT related information
0281           if (ME_.Frame() == 1) {
0282             // Run 3 pattern is unused for now. Needs to be combined with rest of the word in Frame 0 - EY 04.07.22
0283             ME_.set_run3_pattern(GetHexBits(MEa, 0, 0));
0284 
0285             // HMT[1] is in MEa, but HMT[0] is in MEb. These encode in time showers - EY 04.07.22
0286             ME_.set_hmt_inTime(GetHexBits(MEb, 13, 13, MEa, 1, 1));
0287 
0288             // HMT[3:2] encodes out-of-time showers which are not used for now
0289             ME_.set_hmt_outOfTime(GetHexBits(MEa, 2, 3));
0290 
0291             ME_.set_hmv(GetHexBits(MEd, 7, 7));
0292           } else {
0293             ME_.set_run3_pattern(GetHexBits(MEa, 0, 3));
0294 
0295             ME_.set_bxe(GetHexBits(MEb, 13, 13));
0296 
0297             ME_.set_af(GetHexBits(MEd, 7, 7));
0298           }
0299         }
0300 
0301         // Fill the EMTFHit
0302         ImportME(Hit_, ME_, (res->at(iOut)).PtrEventHeader()->Endcap(), (res->at(iOut)).PtrEventHeader()->Sector());
0303 
0304         // Fill the CSCShowerDigi
0305         CSCShowerDigi Shower_(ME_.HMT_inTime() == -99 ? 0 : ME_.HMT_inTime(),
0306                               ME_.HMT_outOfTime() == -99 ? 0 : ME_.HMT_outOfTime(),
0307                               Hit_.CSC_DetId(),
0308                               Hit_.BX(),
0309                               CSCShowerDigi::ShowerType::kEMTFShower);
0310 
0311         // Set the stub number for this hit
0312         // Each chamber can send up to 2 stubs per BX
0313         ME_.set_stub_num(0);
0314         Hit_.set_stub_num(0);
0315         // See if matching hit is already in event record: exact duplicate, or from neighboring sector
0316         bool exact_duplicate = false;
0317         bool neighbor_duplicate = false;
0318         for (auto const& iHit : *res_hit) {
0319           if (iHit.Is_CSC() == 1 && Hit_.BX() == iHit.BX() && Hit_.Endcap() == iHit.Endcap() &&
0320               Hit_.Station() == iHit.Station() && Hit_.Chamber() == iHit.Chamber() &&
0321               (Hit_.Ring() % 3) == (iHit.Ring() % 3)) {  // ME1/1a and ME1/1b (rings "4" and 1) are the same chamber
0322 
0323             if (Hit_.Ring() == iHit.Ring() && Hit_.Strip() == iHit.Strip() && Hit_.Wire() == iHit.Wire()) {
0324               exact_duplicate = (Hit_.Neighbor() == iHit.Neighbor());
0325               neighbor_duplicate = (Hit_.Neighbor() != iHit.Neighbor());
0326             } else if (Hit_.Neighbor() == iHit.Neighbor()) {
0327               ME_.set_stub_num(ME_.Stub_num() + 1);
0328               Hit_.set_stub_num(Hit_.Stub_num() + 1);
0329             }
0330           }
0331         }  // End loop: for (auto const & iHit : *res_hit)
0332 
0333         // 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
0334         if (Hit_.BX() > 3 or Hit_.BX() < -3) {
0335           edm::LogWarning("L1T|EMTF") << "EMTF unpacked LCTs with out-of-range BX! BX " << Hit_.BX() << ", endcap "
0336                                       << Hit_.Endcap() << ", station " << Hit_.Station() << ", sector " << Hit_.Sector()
0337                                       << ", neighbor " << Hit_.Neighbor() << ", ring " << Hit_.Ring() << ", chamber "
0338                                       << Hit_.Chamber() << ", strip " << Hit_.Strip() << ", wire " << Hit_.Wire()
0339                                       << std::endl;
0340           return true;
0341         }
0342 
0343         if (exact_duplicate)
0344           edm::LogWarning("L1T|EMTF") << "EMTF unpacked duplicate LCTs: BX " << Hit_.BX() << ", endcap "
0345                                       << Hit_.Endcap() << ", station " << Hit_.Station() << ", sector " << Hit_.Sector()
0346                                       << ", neighbor " << Hit_.Neighbor() << ", ring " << Hit_.Ring() << ", chamber "
0347                                       << Hit_.Chamber() << ", strip " << Hit_.Strip() << ", wire " << Hit_.Wire()
0348                                       << std::endl;
0349 
0350         (res->at(iOut)).push_ME(ME_);
0351         if (!exact_duplicate && Hit_.Valid() == 1)
0352           res_hit->push_back(Hit_);
0353         if (!exact_duplicate && !neighbor_duplicate &&
0354             Hit_.Valid() == 1)  // Don't write duplicate LCTs from adjacent sectors
0355           res_LCT->insertDigi(Hit_.CSC_DetId(), Hit_.CreateCSCCorrelatedLCTDigi(isRun3));
0356         if (ME_.HMV() == 1) {  // Only write when HMT valid bit is set to 1
0357           res_shower->insertDigi(Hit_.CSC_DetId(), Shower_);
0358         }
0359         // Finished with unpacking one ME Data Record
0360         return true;
0361 
0362       }  // End bool MEBlockUnpacker::unpack
0363 
0364       // bool MEBlockPacker::pack(const Block& block, UnpackerCollections *coll) {
0365       //    std::cout << "Inside MEBlockPacker::pack" << std::endl;
0366       //    return true;
0367       // } // End bool MEBlockPacker::pack
0368 
0369     }  // End namespace emtf
0370   }    // End namespace stage2
0371 }  // End namespace l1t
0372 
0373 DEFINE_L1T_UNPACKER(l1t::stage2::emtf::MEBlockUnpacker);
0374 // DEFINE_L1T_PACKER(l1t::stage2::MEBlockPacker);