Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2022-08-04 22:45:00

0001 // Code to unpack the "SP Output 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 EMTFBlockSP.h file is needed
0009 namespace l1t {
0010   namespace stage2 {
0011     namespace emtf {
0012 
0013       class SPBlockUnpacker : public Unpacker {  // "SPBlockUnpacker" 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 SPBlockPacker : public Packer { // "SPBlockPacker" 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 SPBlockUnpacker::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() != 8) {
0040           errors += 1;
0041           edm::LogError("L1T|EMTF") << "Payload size in 'SP Output Data Record' is different than expected";
0042         }
0043 
0044         // Check that each word is 16 bits
0045         for (unsigned int i = 0; i < 8; 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 'SP Output Data Record'";
0049           }
0050         }
0051 
0052         uint16_t SP1a = payload[0];
0053         uint16_t SP1b = payload[1];
0054         uint16_t SP1c = payload[2];
0055         uint16_t SP1d = payload[3];
0056         uint16_t SP2a = payload[4];
0057         uint16_t SP2b = payload[5];
0058         uint16_t SP2c = payload[6];
0059         uint16_t SP2d = payload[7];
0060 
0061         // Check Format
0062         if (GetHexBits(SP1a, 15, 15) != 1) {
0063           errors += 1;
0064           edm::LogError("L1T|EMTF") << "Format identifier bits in SP1a are incorrect";
0065         }
0066         if (GetHexBits(SP1b, 15, 15) != 0) {
0067           errors += 1;
0068           edm::LogError("L1T|EMTF") << "Format identifier bits in SP1b are incorrect";
0069         }
0070         if (GetHexBits(SP1c, 15, 15) != 1) {
0071           errors += 1;
0072           edm::LogError("L1T|EMTF") << "Format identifier bits in SP1c are incorrect";
0073         }
0074         if (GetHexBits(SP1d, 15, 15) != 0) {
0075           errors += 1;
0076           edm::LogError("L1T|EMTF") << "Format identifier bits in SP1d are incorrect";
0077         }
0078         if (GetHexBits(SP2a, 15, 15) != 0) {
0079           errors += 1;
0080           edm::LogError("L1T|EMTF") << "Format identifier bits in SP2a are incorrect";
0081         }
0082         if (GetHexBits(SP2b, 15, 15) != 1) {
0083           errors += 1;
0084           edm::LogError("L1T|EMTF") << "Format identifier bits in SP2b are incorrect";
0085         }
0086         if (GetHexBits(SP2c, 15, 15) != 1) {
0087           errors += 1;
0088           edm::LogError("L1T|EMTF") << "Format identifier bits in SP2c are incorrect";
0089         }
0090         if (GetHexBits(SP2d, 15, 15) != 0) {
0091           errors += 1;
0092           edm::LogError("L1T|EMTF") << "Format identifier bits in SP2d are incorrect";
0093         }
0094 
0095         return errors;
0096       }
0097 
0098       // Converts CSC_ID, sector, subsector, and neighbor
0099       std::vector<int> convert_SP_location(int _csc_ID, int _sector, int _subsector, int _station) {
0100         int new_sector = _sector;
0101         if (_station == 1) {
0102           if (_csc_ID < 0) {
0103             int arr[] = {_csc_ID, -99, -99, -99};
0104             std::vector<int> vec(arr, arr + 4);
0105             return vec;
0106           } else if (_csc_ID == 0) {
0107             int arr[] = {-1, -1, -1, -1};
0108             std::vector<int> vec(arr, arr + 4);
0109             return vec;
0110           } else if (_csc_ID <= 9) {
0111             int arr[] = {_csc_ID, new_sector, _subsector + 1, 0};
0112             std::vector<int> vec(arr, arr + 4);
0113             return vec;
0114           } else
0115             new_sector = (_sector != 1) ? _sector - 1 : 6;
0116 
0117           if (_csc_ID == 10) {
0118             int arr[] = {3, new_sector, 2, 1};
0119             std::vector<int> vec(arr, arr + 4);
0120             return vec;
0121           } else if (_csc_ID == 11) {
0122             int arr[] = {6, new_sector, 2, 1};
0123             std::vector<int> vec(arr, arr + 4);
0124             return vec;
0125           } else if (_csc_ID == 12) {
0126             int arr[] = {9, new_sector, 2, 1};
0127             std::vector<int> vec(arr, arr + 4);
0128             return vec;
0129           } else {
0130             int arr[] = {_csc_ID, -99, -99, -99};
0131             std::vector<int> vec(arr, arr + 4);
0132             return vec;
0133           }
0134         } else if (_station == 2 || _station == 3 || _station == 4) {
0135           if (_csc_ID < 0) {
0136             int arr[] = {_csc_ID, -99, -99, -99};
0137             std::vector<int> vec(arr, arr + 4);
0138             return vec;
0139           } else if (_csc_ID == 0) {
0140             int arr[] = {-1, -1, -1, -1};
0141             std::vector<int> vec(arr, arr + 4);
0142             return vec;
0143           } else if (_csc_ID <= 9) {
0144             int arr[] = {_csc_ID, new_sector, -1, 0};
0145             std::vector<int> vec(arr, arr + 4);
0146             return vec;
0147           } else
0148             new_sector = (_sector != 1) ? _sector - 1 : 6;
0149 
0150           if (_csc_ID == 10) {
0151             int arr[] = {3, new_sector, -1, 1};
0152             std::vector<int> vec(arr, arr + 4);
0153             return vec;
0154           } else if (_csc_ID == 11) {
0155             int arr[] = {9, new_sector, -1, 1};
0156             std::vector<int> vec(arr, arr + 4);
0157             return vec;
0158           } else {
0159             int arr[] = {_csc_ID, -99, -99, -99};
0160             std::vector<int> vec(arr, arr + 4);
0161             return vec;
0162           }
0163         } else {
0164           int arr[] = {-99, -99, -99, -99};
0165           std::vector<int> vec(arr, arr + 4);
0166           return vec;
0167         }
0168       }
0169 
0170       bool SPBlockUnpacker::unpack(const Block& block, UnpackerCollections* coll) {
0171         // std::cout << "Inside EMTFBlockSP.cc: unpack" << std::endl;
0172         // LogDebug("L1T|EMTF") << "Inside EMTFBlockSP.cc: unpack"; // Why doesn't this work? - AWB 09.04.16
0173 
0174         // Get the payload for this block, made up of 16-bit words (0xffff)
0175         // Format defined in MTF7Payload::getBlock() in src/Block.cc
0176         // payload[0] = bits 0-15, payload[1] = 16-31, payload[3] = 32-47, etc.
0177         auto payload = block.payload();
0178 
0179         // FW version is computed as (Year - 2000)*2^9 + Month*2^5 + Day (see Block.cc and EMTFBlockTrailers.cc)
0180         bool useNNBits_ = getAlgoVersion() >= 11098;   // FW versions >= 26.10.2021
0181         bool useHMTBits_ = getAlgoVersion() >= 11306;  // FW versions >= 10.01.2022
0182 
0183         static constexpr int nominalShower_ = 1;
0184         static constexpr int tightShower_ = 3;
0185 
0186         // Check Format of Payload
0187         l1t::emtf::SP SP_;
0188         for (int err = 0; err < checkFormat(block); err++)
0189           SP_.add_format_error();
0190 
0191         // Assign payload to 16-bit words
0192         uint16_t SP1a = payload[0];
0193         uint16_t SP1b = payload[1];
0194         uint16_t SP1c = payload[2];
0195         uint16_t SP1d = payload[3];
0196         uint16_t SP2a = payload[4];
0197         uint16_t SP2b = payload[5];
0198         uint16_t SP2c = payload[6];
0199         uint16_t SP2d = payload[7];
0200 
0201         // res is a pointer to a collection of EMTFDaqOut class objects
0202         // There is one EMTFDaqOut for each MTF7 (60 deg. sector) in the event
0203         EMTFDaqOutCollection* res;
0204         res = static_cast<EMTFCollections*>(coll)->getEMTFDaqOuts();
0205         int iOut = res->size() - 1;
0206         std::vector<int> conv_vals_SP;
0207         std::vector<int> conv_vals_pT_LUT;
0208 
0209         EMTFHitCollection* res_hit;
0210         res_hit = static_cast<EMTFCollections*>(coll)->getEMTFHits();
0211 
0212         EMTFTrackCollection* res_track;
0213         res_track = static_cast<EMTFCollections*>(coll)->getEMTFTracks();
0214         EMTFTrack Track_;
0215 
0216         RegionalMuonCandBxCollection* res_cand;
0217         res_cand = static_cast<EMTFCollections*>(coll)->getRegionalMuonCands();
0218         RegionalMuonCand mu_(0, 0, 0, 0, 0, 0, 0, tftype::emtf_pos);
0219 
0220         RegionalMuonShowerBxCollection* res_shower;
0221         res_shower = static_cast<EMTFCollections*>(coll)->getRegionalMuonShowers();
0222         RegionalMuonShower muShower_(false, false, false, false, false, false);
0223 
0224         ///////////////////////////////////
0225         // Unpack the SP Output Data Record
0226         ///////////////////////////////////
0227 
0228         SP_.set_phi_full(GetHexBits(SP1a, 0, 12));
0229         SP_.set_c(GetHexBits(SP1a, 13, 13));
0230         SP_.set_hl(GetHexBits(SP1a, 14, 14));
0231 
0232         SP_.set_phi_GMT(TwosCompl(8, GetHexBits(SP1b, 0, 7)));
0233         SP_.set_quality_GMT(GetHexBits(SP1b, 8, 11));
0234         SP_.set_bc0(GetHexBits(SP1b, 12, 12));
0235         SP_.set_se(GetHexBits(SP1b, 13, 13));
0236         SP_.set_vc(GetHexBits(SP1b, 14, 14));
0237 
0238         SP_.set_eta_GMT(TwosCompl(9, GetHexBits(SP1c, 0, 8)));
0239         SP_.set_mode(GetHexBits(SP1c, 9, 12));
0240 
0241         if (useHMTBits_) {
0242           SP_.set_hmt(GetHexBits(SP1c, 13, 14));
0243         } else {
0244           SP_.set_bx(GetHexBits(SP1c, 13, 14));
0245         }
0246 
0247         SP_.set_pt_GMT(GetHexBits(SP1d, 0, 8));
0248         SP_.set_me1_stub_num(GetHexBits(SP1d, 9, 9));
0249         SP_.set_me1_CSC_ID(GetHexBits(SP1d, 10, 13));
0250         SP_.set_me1_subsector(GetHexBits(SP1d, 14, 14));
0251 
0252         SP_.set_me2_stub_num(GetHexBits(SP2a, 0, 0));
0253         SP_.set_me2_CSC_ID(GetHexBits(SP2a, 1, 4));
0254         SP_.set_me3_stub_num(GetHexBits(SP2a, 5, 5));
0255         SP_.set_me3_CSC_ID(GetHexBits(SP2a, 6, 9));
0256         SP_.set_me4_stub_num(GetHexBits(SP2a, 10, 10));
0257         SP_.set_me4_CSC_ID(GetHexBits(SP2a, 11, 14));
0258 
0259         SP_.set_me1_delay(GetHexBits(SP2b, 0, 2));
0260         SP_.set_me2_delay(GetHexBits(SP2b, 3, 5));
0261         SP_.set_me3_delay(GetHexBits(SP2b, 6, 8));
0262         SP_.set_me4_delay(GetHexBits(SP2b, 9, 11));
0263         SP_.set_tbin(GetHexBits(SP2b, 12, 14));
0264 
0265         if (useNNBits_) {
0266           SP_.set_pt_dxy_GMT(GetHexBits(SP2c, 0, 7));
0267           SP_.set_dxy_GMT(GetHexBits(SP2c, 8, 10));
0268           SP_.set_nn_pt_valid(GetHexBits(SP2c, 11, 11));
0269         } else {
0270           SP_.set_pt_LUT_addr(GetHexBits(SP2c, 0, 14, SP2d, 0, 14));
0271         }
0272 
0273         // SP_.set_dataword     ( uint64_t dataword );
0274 
0275         ImportSP(Track_, SP_, (res->at(iOut)).PtrEventHeader()->Endcap(), (res->at(iOut)).PtrEventHeader()->Sector());
0276         // Track_.ImportPtLUT( Track_.Mode(), Track_.Pt_LUT_addr() );  // Deprecated ... replace? - AWB 15.03.17
0277 
0278         if (!(res->at(iOut)).PtrSPCollection()->empty())
0279           if (SP_.TBIN() == (res->at(iOut)).PtrSPCollection()->at((res->at(iOut)).PtrSPCollection()->size() - 1).TBIN())
0280             Track_.set_track_num((res->at(iOut)).PtrSPCollection()->size());
0281           else
0282             Track_.set_track_num(0);
0283         else
0284           Track_.set_track_num(0);
0285 
0286         // For single-LCT tracks, "Track_num" = 2 (last in collection)
0287         if (SP_.Quality_GMT() == 0)
0288           Track_.set_track_num(2);
0289 
0290         mu_.setHwSign(SP_.C());
0291         mu_.setHwSignValid(SP_.VC());
0292         mu_.setHwQual(SP_.Quality_GMT());
0293         mu_.setHwEta(SP_.Eta_GMT());
0294         mu_.setHwPhi(SP_.Phi_GMT());
0295         mu_.setHwPt(SP_.Pt_GMT());
0296         if (useNNBits_) {
0297           mu_.setHwPtUnconstrained(SP_.Pt_dxy_GMT());
0298           mu_.setHwDXY(SP_.Dxy_GMT());
0299         }
0300         mu_.setTFIdentifiers(Track_.Sector() - 1, (Track_.Endcap() == 1) ? emtf_pos : emtf_neg);
0301         mu_.setTrackSubAddress(RegionalMuonCand::kTrkNum, Track_.Track_num());
0302         // Truncated to 11 bits and offset by 25 from global event BX in EMTF firmware
0303         int EMTF_kBX = ((res->at(iOut)).PtrEventHeader()->L1A_BXN() % 2048) - 25 + Track_.BX();
0304         if (EMTF_kBX < 0)
0305           EMTF_kBX += 2048;
0306         mu_.setTrackSubAddress(RegionalMuonCand::kBX, EMTF_kBX);
0307         // mu_.set_dataword   ( SP_.Dataword() );
0308         // Track_.set_GMT(mu_);
0309 
0310         // Set Regional Muon Showers
0311         if (useHMTBits_) {
0312           muShower_.setTFIdentifiers(Track_.Sector() - 1, (Track_.Endcap() == 1) ? emtf_pos : emtf_neg);
0313           muShower_.setOneNominalInTime(SP_.HMT() == nominalShower_ ? true : false);
0314           muShower_.setOneTightInTime(SP_.HMT() == tightShower_ ? true : false);
0315         }
0316 
0317         ///////////////////////
0318         // Match hits to tracks
0319         ///////////////////////
0320 
0321         // Find the track delay
0322         int nDelay[3] = {0, 0, 0};  // Number of hits in the track with delay 0, 1, or 2
0323         if (Track_.Mode() >= 8)
0324           nDelay[SP_.ME1_delay()] += 1;
0325         if ((Track_.Mode() % 8) >= 4)
0326           nDelay[SP_.ME2_delay()] += 1;
0327         if ((Track_.Mode() % 4) >= 2)
0328           nDelay[SP_.ME3_delay()] += 1;
0329         if ((Track_.Mode() % 2) == 1)
0330           nDelay[SP_.ME4_delay()] += 1;
0331 
0332         int trk_delay = -99;
0333         // Assume 2nd-earliest LCT configuration
0334         if (nDelay[2] >= 2)
0335           trk_delay = 2;
0336         else if (nDelay[2] + nDelay[1] >= 2)
0337           trk_delay = 1;
0338         else if (nDelay[2] + nDelay[1] + nDelay[0] >= 2)
0339           trk_delay = 0;
0340 
0341         // // For earliest LCT configuration
0342         // if      (nDelay[2]                         >= 1) trk_delay = 2;
0343         // else if (nDelay[2] + nDelay[1]             >= 1) trk_delay = 1;
0344         // else if (nDelay[2] + nDelay[1] + nDelay[0] >= 1) trk_delay = 0;
0345 
0346         // Reverse 'rotate by 2' to get CPPF subsector number
0347         auto get_subsector_rpc_cppf = [](int subsector_rpc) { return ((subsector_rpc + 3) % 6) + 1; };
0348 
0349         std::array<int, 4> St_hits{{0, 0, 0, 0}};  // Number of matched hits in each station
0350 
0351         for (auto const& Hit : *res_hit) {
0352           if (Track_.Mode() == 1)
0353             continue;  // Special case dealt with later
0354           if (Hit.Endcap() != Track_.Endcap())
0355             continue;
0356 
0357           int hit_delay = -99;
0358           if (Hit.Station() == 1)
0359             hit_delay = SP_.ME1_delay();
0360           else if (Hit.Station() == 2)
0361             hit_delay = SP_.ME2_delay();
0362           else if (Hit.Station() == 3)
0363             hit_delay = SP_.ME3_delay();
0364           else if (Hit.Station() == 4)
0365             hit_delay = SP_.ME4_delay();
0366 
0367           // Require exact matching according to TBIN and delays
0368           if (Hit.BX() + 3 + hit_delay != SP_.TBIN() + trk_delay)
0369             continue;
0370 
0371           // Match hit in station 1
0372           conv_vals_SP =
0373               convert_SP_location(SP_.ME1_CSC_ID(), (res->at(iOut)).PtrEventHeader()->Sector(), SP_.ME1_subsector(), 1);
0374 
0375           if (Hit.Station() == 1 && Hit.Sector() == conv_vals_SP.at(1) && Hit.Neighbor() == conv_vals_SP.at(3) &&
0376               Hit.Stub_num() == SP_.ME1_stub_num()) {
0377             if (Hit.Is_CSC() == 1 && (Hit.CSC_ID() != conv_vals_SP.at(0) || Hit.Subsector() != conv_vals_SP.at(2)))
0378               continue;
0379 
0380             int tmp_subsector = get_subsector_rpc_cppf(Hit.Subsector_RPC());
0381             int RPC_subsector = ((tmp_subsector - 1) / 3) + 1;  // Map RPC subsector to equivalent CSC subsector
0382             int RPC_CSC_ID = ((tmp_subsector - 1) % 3) + 4;     // Map RPC subsector and ring to equivalent CSC ID
0383 
0384             if (Hit.Is_RPC() == 1 && (RPC_CSC_ID != conv_vals_SP.at(0) || RPC_subsector != conv_vals_SP.at(2)))
0385               continue;
0386 
0387             if (St_hits.at(0) == 0) {  // Only add the first matched hit to the track
0388               Track_.push_Hit((Hit));
0389               mu_.setTrackSubAddress(RegionalMuonCand::kME1Seg, SP_.ME1_stub_num());
0390               mu_.setTrackSubAddress(
0391                   RegionalMuonCand::kME1Ch,
0392                   L1TMuonEndCap::calc_uGMT_chamber(conv_vals_SP.at(0), conv_vals_SP.at(2), conv_vals_SP.at(3), 1));
0393             }
0394             St_hits.at(0) += 1;  // Count the total number of matches for debugging purposes
0395           }                      // End conditional: if ( Hit.Station() == 1
0396 
0397           // Match hit in station 2
0398           conv_vals_SP = convert_SP_location(SP_.ME2_CSC_ID(), (res->at(iOut)).PtrEventHeader()->Sector(), -99, 2);
0399 
0400           if (Hit.Station() == 2 && Hit.Sector() == conv_vals_SP.at(1) && Hit.Neighbor() == conv_vals_SP.at(3) &&
0401               Hit.Stub_num() == SP_.ME2_stub_num()) {
0402             if (Hit.Is_CSC() == 1 && Hit.CSC_ID() != conv_vals_SP.at(0))
0403               continue;
0404 
0405             int tmp_subsector = get_subsector_rpc_cppf(Hit.Subsector_RPC());
0406             if (Hit.Is_RPC() == 1 && tmp_subsector + 3 != conv_vals_SP.at(0))
0407               continue;
0408 
0409             if (St_hits.at(1) == 0) {
0410               Track_.push_Hit((Hit));
0411               mu_.setTrackSubAddress(RegionalMuonCand::kME2Seg, SP_.ME2_stub_num());
0412               mu_.setTrackSubAddress(
0413                   RegionalMuonCand::kME2Ch,
0414                   L1TMuonEndCap::calc_uGMT_chamber(conv_vals_SP.at(0), conv_vals_SP.at(2), conv_vals_SP.at(3), 2));
0415             }
0416             St_hits.at(1) += 1;
0417           }  // End conditional: if ( Hit.Station() == 2
0418 
0419           // Match hit in station 3
0420           conv_vals_SP = convert_SP_location(SP_.ME3_CSC_ID(), (res->at(iOut)).PtrEventHeader()->Sector(), -99, 3);
0421 
0422           if (Hit.Station() == 3 && Hit.Sector() == conv_vals_SP.at(1) && Hit.Neighbor() == conv_vals_SP.at(3) &&
0423               Hit.Stub_num() == SP_.ME3_stub_num()) {
0424             if (Hit.Is_CSC() == 1 && Hit.CSC_ID() != conv_vals_SP.at(0))
0425               continue;
0426 
0427             int tmp_subsector = get_subsector_rpc_cppf(Hit.Subsector_RPC());
0428             if (Hit.Is_RPC() == 1 && tmp_subsector + 3 != conv_vals_SP.at(0))
0429               continue;
0430 
0431             if (St_hits.at(2) == 0) {
0432               Track_.push_Hit((Hit));
0433               mu_.setTrackSubAddress(RegionalMuonCand::kME3Seg, SP_.ME3_stub_num());
0434               mu_.setTrackSubAddress(
0435                   RegionalMuonCand::kME3Ch,
0436                   L1TMuonEndCap::calc_uGMT_chamber(conv_vals_SP.at(0), conv_vals_SP.at(2), conv_vals_SP.at(3), 3));
0437             }
0438             St_hits.at(2) += 1;
0439           }  // End conditional: if ( Hit.Station() == 3
0440 
0441           // Match hit in station 4
0442           conv_vals_SP = convert_SP_location(SP_.ME4_CSC_ID(), (res->at(iOut)).PtrEventHeader()->Sector(), -99, 4);
0443 
0444           if (Hit.Station() == 4 && Hit.Sector() == conv_vals_SP.at(1) && Hit.Neighbor() == conv_vals_SP.at(3) &&
0445               Hit.Stub_num() == SP_.ME4_stub_num()) {
0446             if (Hit.Is_CSC() == 1 && Hit.CSC_ID() != conv_vals_SP.at(0))
0447               continue;
0448 
0449             int tmp_subsector = get_subsector_rpc_cppf(Hit.Subsector_RPC());
0450             if (Hit.Is_RPC() == 1 && tmp_subsector + 3 != conv_vals_SP.at(0))
0451               continue;
0452 
0453             if (St_hits.at(3) == 0) {
0454               Track_.push_Hit((Hit));
0455               mu_.setTrackSubAddress(RegionalMuonCand::kME4Seg, SP_.ME4_stub_num());
0456               mu_.setTrackSubAddress(
0457                   RegionalMuonCand::kME4Ch,
0458                   L1TMuonEndCap::calc_uGMT_chamber(conv_vals_SP.at(0), conv_vals_SP.at(2), conv_vals_SP.at(3), 4));
0459             }
0460             St_hits.at(3) += 1;
0461           }  // End conditional: if ( Hit.Station() == 4
0462 
0463         }  // End loop: for (auto const & Hit : *res_hit)
0464 
0465         // Special configuration for single-stub tracks from ME1/1
0466         if (Track_.Mode() == 1) {
0467           // Infer ME1/1 chamber based on track phi
0468           int chamber_min = ((Track_.GMT_phi() - 17) / 16) + Track_.Sector() * 6 - 3;
0469           int chamber_max = ((Track_.GMT_phi() + 1) / 16) + Track_.Sector() * 6 - 3;
0470           for (int iChamb = chamber_max; iChamb >= chamber_min; iChamb--) {
0471             int chamber = (iChamb < 37 ? iChamb : (iChamb % 36));
0472 
0473             for (auto const& Hit : *res_hit) {
0474               if (Hit.Sector_idx() != Track_.Sector_idx())
0475                 continue;
0476               if (Hit.BX() != Track_.BX())
0477                 continue;
0478               if (Hit.Chamber() != chamber)
0479                 continue;
0480               if (Hit.Is_CSC() != 1)
0481                 continue;
0482               if (Hit.Station() != 1)
0483                 continue;
0484               if ((Hit.Ring() % 3) != 1)
0485                 continue;
0486               if (Hit.Neighbor() == 1)
0487                 continue;
0488 
0489               // Don't use LCTs that were already used in a multi-station track
0490               bool hit_already_used = false;
0491               for (auto const& Trk : *res_track) {
0492                 if (Trk.Sector_idx() != Track_.Sector_idx())
0493                   continue;
0494                 if (Trk.NumHits() < 1)
0495                   continue;
0496 
0497                 if (Trk.Hits().at(0).Station() == 1 && Trk.Hits().at(0).Chamber() == chamber &&
0498                     Trk.Hits().at(0).BX() == Hit.BX() && Trk.Hits().at(0).Ring() == Hit.Ring() &&
0499                     Trk.Hits().at(0).Strip() == Hit.Strip() && Trk.Hits().at(0).Wire() == Hit.Wire()) {
0500                   hit_already_used = true;
0501                   break;
0502                 }
0503               }  // End loop: for (auto const & Trk : *res_track)
0504 
0505               if (!hit_already_used) {
0506                 Track_.push_Hit((Hit));
0507                 break;
0508               }
0509             }  // End loop: for (auto const & Hit : *res_hit)
0510             if (Track_.NumHits() > 0)
0511               break;
0512           }  // End loop: for (int iChamb = chamber_max; iChamb >= chamber_min; iChamb--)
0513 
0514           // if (Track_.NumHits() != 1) {
0515           //   std::cout << "\n\n***********************************************************" << std::endl;
0516           //   std::cout << "Bug in unpacked EMTF event! Mode " << Track_.Mode() << " track in sector " << Track_.Sector()*Track_.Endcap()
0517           //          << ", BX " << Track_.BX() << ", GMT phi " << Track_.GMT_phi() << ", GMT eta " << Track_.GMT_eta()
0518           //          << " should have found an LCT between chamber " << chamber_min << " and " << chamber_max << std::endl;
0519           //   std::cout << "All available LCTs as follows:" << std::endl;
0520           //   for (auto const & Hit : *res_hit) {
0521           //     std::cout << "Hit: Is CSC = " << Hit.Is_CSC() << ", CSC ID = " << Hit.CSC_ID()
0522           //        << ", sector = " << Hit.Sector()*Hit.Endcap() << ", sub = " << Hit.Subsector()
0523           //        << ", neighbor = " << Hit.Neighbor() << ", station = " << Hit.Station()
0524           //        << ", ring = " << Hit.Ring() << ", chamber = " << Hit.Chamber()
0525           //        << ", stub = " << Hit.Stub_num() << ", BX = " << Hit.BX() << std::endl;
0526           //   std::cout << "All other tracks are as follows:" << std::endl;
0527           //   for (auto Trk = res_hit->begin(); Trk != res_hit->end(); ++Trk) {
0528           //     std::cout << "Track: mode " << Trk.Mode() << " track in sector " << Trk.Sector()*Trk.Endcap()
0529           //        << ", BX " << Trk.BX() << ", GMT phi " << Trk.GMT_phi() << ", GMT eta " << Trk.GMT_eta() << std::endl;
0530           //   }
0531           //   std::cout << "***********************************************************\n\n" << std::endl;
0532           // } // End conditional: if (Track_.NumHits() != 1)
0533 
0534         }  // End conditional: if (Track_.Mode() == 1)
0535 
0536         // if ( Track_.Mode() != St_hits.at(0)*8 + St_hits.at(1)*4 + St_hits.at(2)*2 + St_hits.at(3) && Track_.BX() == 0) {
0537         //   std::cout << "\n\n***********************************************************" << std::endl;
0538         //   std::cout << "Bug in unpacked EMTF event! Mode " << Track_.Mode() << " track in sector " << Track_.Sector()*Track_.Endcap()
0539         //      << ", BX " << Track_.BX() << " (delay = " << trk_delay << ") with (" << St_hits.at(0) << ", " << St_hits.at(1)
0540         //      << ", " << St_hits.at(2) << ", " << St_hits.at(3) << ") hits in stations (1, 2, 3, 4)" << std::endl;
0541 
0542         //   std::cout << "\nME1_stub_num = " << SP_.ME1_stub_num() << ", ME1_delay = " <<  SP_.ME1_delay()
0543         //      << ", ME1_CSC_ID = " << SP_.ME1_CSC_ID() <<  ", ME1_subsector = " << SP_.ME1_subsector() << std::endl;
0544         //   std::cout << "ME2_stub_num = " << SP_.ME2_stub_num() << ", ME2_delay = " <<  SP_.ME2_delay()
0545         //      << ", ME2_CSC_ID = " << SP_.ME2_CSC_ID() << std::endl;
0546         //   std::cout << "ME3_stub_num = " << SP_.ME3_stub_num() << ", ME3_delay = " <<  SP_.ME3_delay()
0547         //      << ", ME3_CSC_ID = " << SP_.ME3_CSC_ID() << std::endl;
0548         //   std::cout << "ME4_stub_num = " << SP_.ME4_stub_num() << ", ME4_delay = " <<  SP_.ME4_delay()
0549         //      << ", ME4_CSC_ID = " << SP_.ME4_CSC_ID() << std::endl;
0550 
0551         //   conv_vals_SP = convert_SP_location( SP_.ME1_CSC_ID(), (res->at(iOut)).PtrEventHeader()->Sector(), SP_.ME1_subsector(), 1 );
0552         //   std::cout << "\nConverted ME1 CSC ID = " << conv_vals_SP.at(0) << ", sector = " << conv_vals_SP.at(1)
0553         //      << ", subsector = " << conv_vals_SP.at(2) << ", neighbor = " << conv_vals_SP.at(3) << std::endl;
0554         //   conv_vals_SP = convert_SP_location( SP_.ME2_CSC_ID(), (res->at(iOut)).PtrEventHeader()->Sector(), -99, 2 );
0555         //   std::cout << "Converted ME2 CSC ID = " << conv_vals_SP.at(0) << ", sector = " << conv_vals_SP.at(1)
0556         //      << ", subsector = " << conv_vals_SP.at(2) << ", neighbor = " << conv_vals_SP.at(3) << std::endl;
0557         //   conv_vals_SP = convert_SP_location( SP_.ME3_CSC_ID(), (res->at(iOut)).PtrEventHeader()->Sector(), -99, 3 );
0558         //   std::cout << "Converted ME3 CSC ID = " << conv_vals_SP.at(0) << ", sector = " << conv_vals_SP.at(1)
0559         //      << ", subsector = " << conv_vals_SP.at(2) << ", neighbor = " << conv_vals_SP.at(3) << std::endl;
0560         //   conv_vals_SP = convert_SP_location( SP_.ME4_CSC_ID(), (res->at(iOut)).PtrEventHeader()->Sector(), -99, 4 );
0561         //   std::cout << "Converted ME4 CSC ID = " << conv_vals_SP.at(0) << ", sector = " << conv_vals_SP.at(1)
0562         //      << ", subsector = " << conv_vals_SP.at(2) << ", neighbor = " << conv_vals_SP.at(3) << "\n" << std::endl;
0563 
0564         //   for (auto const & Hit : *res_hit)
0565         //     std::cout << "Hit: Is CSC = " << Hit.Is_CSC() << ", CSC ID = " << Hit.CSC_ID()
0566         //        << ", sector = " << Hit.Sector() << ", sub = " << Hit.Subsector()
0567         //        << ", neighbor = " << Hit.Neighbor() << ", station = " << Hit.Station()
0568         //        << ", ring = " << Hit.Ring() << ", chamber = " << Hit.Chamber()
0569         //        << ", stub = " << Hit.Stub_num() << ", BX = " << Hit.BX() << std::endl;
0570 
0571         //   // int iHit = 0;
0572         //   // for (auto const & Hit : *res_hit) {
0573         //   //   if (iHit == 0) Hit.PrintSimulatorHeader();
0574         //   //   Hit.PrintForSimulator();
0575         //   //   iHit += 1;
0576         //   // }
0577         //   std::cout << "***********************************************************\n\n" << std::endl;
0578         // }
0579 
0580         // Reject tracks with out-of-range BX values. This needs to be adjusted if we increase l1a_window parameter in EMTF config - EY 03.08.2022
0581         if (Track_.BX() > 3 or Track_.BX() < -3) {
0582           edm::LogWarning("L1T|EMTF") << "EMTF unpacked track with out-of-range BX! BX: " << Track_.BX()
0583                                       << " endcap: " << (Track_.Endcap() == 1 ? 1 : 2) << " sector: " << Track_.Sector()
0584                                       << " address: " << Track_.PtLUT().address << " mode: " << Track_.Mode()
0585                                       << " eta: " << (Track_.GMT_eta() >= 0 ? Track_.GMT_eta() : Track_.GMT_eta() + 512)
0586                                       << " phi: " << Track_.GMT_phi() << " charge: " << Track_.GMT_charge()
0587                                       << " qual: " << Track_.GMT_quality() << " pt: " << Track_.Pt()
0588                                       << " pt_dxy: " << Track_.Pt_dxy() << std::endl;
0589           return true;
0590         }
0591 
0592         (res->at(iOut)).push_SP(SP_);
0593 
0594         res_track->push_back(Track_);
0595 
0596         // TBIN_num can range from 0 through 7, i.e. BX = -3 through +4. - AWB 04.04.16
0597         res_cand->setBXRange(-3, 4);
0598         res_cand->push_back(SP_.TBIN() - 3, mu_);
0599 
0600         res_shower->setBXRange(-3, 4);
0601         res_shower->push_back(SP_.TBIN() - 3, muShower_);
0602 
0603         // Finished with unpacking one SP Output Data Record
0604         return true;
0605 
0606       }  // End bool SPBlockUnpacker::unpack
0607 
0608       // bool SPBlockPacker::pack(const Block& block, UnpackerCollections *coll) {
0609       //    std::cout << "Inside SPBlockPacker::pack" << std::endl;
0610       //    return true;
0611       // } // End bool SPBlockPacker::pack
0612 
0613     }  // End namespace emtf
0614   }    // End namespace stage2
0615 }  // End namespace l1t
0616 
0617 DEFINE_L1T_UNPACKER(l1t::stage2::emtf::SPBlockUnpacker);
0618 // DEFINE_L1T_PACKER(l1t::stage2::SPBlockPacker);