Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-07-05 02:30:26

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 useMUSBits_ = getAlgoVersion() >= 11306;  // FW versions >= 10.01.2022
0182         bool reducedDAQWindow =
0183             (getAlgoVersion() >=
0184              11656);  // Firmware from 08.12.22 which is used as a flag for new reduced readout window - EY 01.03.23
0185 
0186         static constexpr int looseShower_ = 1;
0187         static constexpr int nominalShower_ = 2;
0188         static constexpr int tightShower_ = 4;
0189 
0190         // Check Format of Payload
0191         l1t::emtf::SP SP_;
0192         for (int err = 0; err < checkFormat(block); err++)
0193           SP_.add_format_error();
0194 
0195         // Assign payload to 16-bit words
0196         uint16_t SP1a = payload[0];
0197         uint16_t SP1b = payload[1];
0198         uint16_t SP1c = payload[2];
0199         uint16_t SP1d = payload[3];
0200         uint16_t SP2a = payload[4];
0201         uint16_t SP2b = payload[5];
0202         uint16_t SP2c = payload[6];
0203         uint16_t SP2d = payload[7];
0204 
0205         // res is a pointer to a collection of EMTFDaqOut class objects
0206         // There is one EMTFDaqOut for each MTF7 (60 deg. sector) in the event
0207         EMTFDaqOutCollection* res;
0208         res = static_cast<EMTFCollections*>(coll)->getEMTFDaqOuts();
0209         int iOut = res->size() - 1;
0210         std::vector<int> conv_vals_SP;
0211         std::vector<int> conv_vals_pT_LUT;
0212 
0213         EMTFHitCollection* res_hit;
0214         res_hit = static_cast<EMTFCollections*>(coll)->getEMTFHits();
0215 
0216         EMTFTrackCollection* res_track;
0217         res_track = static_cast<EMTFCollections*>(coll)->getEMTFTracks();
0218         EMTFTrack Track_;
0219 
0220         RegionalMuonCandBxCollection* res_cand;
0221         res_cand = static_cast<EMTFCollections*>(coll)->getRegionalMuonCands();
0222         RegionalMuonCand mu_(0, 0, 0, 0, 0, 0, 0, tftype::emtf_pos);
0223 
0224         RegionalMuonShowerBxCollection* res_shower;
0225         res_shower = static_cast<EMTFCollections*>(coll)->getRegionalMuonShowers();
0226         RegionalMuonShower muShower_(false, false, false, false, false, false);
0227 
0228         ///////////////////////////////////
0229         // Unpack the SP Output Data Record
0230         ///////////////////////////////////
0231 
0232         SP_.set_phi_full(GetHexBits(SP1a, 0, 12));
0233         SP_.set_c(GetHexBits(SP1a, 13, 13));
0234         SP_.set_hl(GetHexBits(SP1a, 14, 14));
0235 
0236         SP_.set_phi_GMT(TwosCompl(8, GetHexBits(SP1b, 0, 7)));
0237         SP_.set_quality_GMT(GetHexBits(SP1b, 8, 11));
0238         SP_.set_bc0(GetHexBits(SP1b, 12, 12));
0239         SP_.set_vc(GetHexBits(SP1b, 14, 14));
0240 
0241         SP_.set_eta_GMT(TwosCompl(9, GetHexBits(SP1c, 0, 8)));
0242         SP_.set_mode(GetHexBits(SP1c, 9, 12));
0243 
0244         if (useMUSBits_) {
0245           SP_.set_mus(GetHexBits(SP1b, 13, 13, SP1c, 13, 14));
0246         } else {
0247           SP_.set_se(GetHexBits(SP1b, 13, 13));
0248           SP_.set_bx(GetHexBits(SP1c, 13, 14));
0249         }
0250 
0251         SP_.set_pt_GMT(GetHexBits(SP1d, 0, 8));
0252         SP_.set_me1_stub_num(GetHexBits(SP1d, 9, 9));
0253         SP_.set_me1_CSC_ID(GetHexBits(SP1d, 10, 13));
0254         SP_.set_me1_subsector(GetHexBits(SP1d, 14, 14));
0255 
0256         SP_.set_me2_stub_num(GetHexBits(SP2a, 0, 0));
0257         SP_.set_me2_CSC_ID(GetHexBits(SP2a, 1, 4));
0258         SP_.set_me3_stub_num(GetHexBits(SP2a, 5, 5));
0259         SP_.set_me3_CSC_ID(GetHexBits(SP2a, 6, 9));
0260         SP_.set_me4_stub_num(GetHexBits(SP2a, 10, 10));
0261         SP_.set_me4_CSC_ID(GetHexBits(SP2a, 11, 14));
0262 
0263         SP_.set_me1_delay(GetHexBits(SP2b, 0, 2));
0264         SP_.set_me2_delay(GetHexBits(SP2b, 3, 5));
0265         SP_.set_me3_delay(GetHexBits(SP2b, 6, 8));
0266         SP_.set_me4_delay(GetHexBits(SP2b, 9, 11));
0267         if (reducedDAQWindow)  // reduced DAQ window is used only after run3 DAQ format
0268           SP_.set_tbin(GetHexBits(SP2b, 12, 14) + 1);
0269         else
0270           SP_.set_tbin(GetHexBits(SP2b, 12, 14));
0271 
0272         if (useNNBits_) {
0273           SP_.set_pt_dxy_GMT(GetHexBits(SP2c, 0, 7));
0274           SP_.set_dxy_GMT(GetHexBits(SP2c, 8, 10));
0275           SP_.set_nn_pt_valid(GetHexBits(SP2c, 11, 11));
0276         } else {
0277           SP_.set_pt_LUT_addr(GetHexBits(SP2c, 0, 14, SP2d, 0, 14));
0278         }
0279 
0280         // SP_.set_dataword     ( uint64_t dataword );
0281 
0282         ImportSP(Track_, SP_, (res->at(iOut)).PtrEventHeader()->Endcap(), (res->at(iOut)).PtrEventHeader()->Sector());
0283         // Track_.ImportPtLUT( Track_.Mode(), Track_.Pt_LUT_addr() );  // Deprecated ... replace? - AWB 15.03.17
0284 
0285         if (!(res->at(iOut)).PtrSPCollection()->empty())
0286           if (SP_.TBIN() == (res->at(iOut)).PtrSPCollection()->at((res->at(iOut)).PtrSPCollection()->size() - 1).TBIN())
0287             Track_.set_track_num((res->at(iOut)).PtrSPCollection()->size());
0288           else
0289             Track_.set_track_num(0);
0290         else
0291           Track_.set_track_num(0);
0292 
0293         // For single-LCT tracks, "Track_num" = 2 (last in collection)
0294         if (SP_.Quality_GMT() == 0)
0295           Track_.set_track_num(2);
0296 
0297         mu_.setHwSign(SP_.C());
0298         mu_.setHwSignValid(SP_.VC());
0299         mu_.setHwQual(SP_.Quality_GMT());
0300         mu_.setHwEta(SP_.Eta_GMT());
0301         mu_.setHwPhi(SP_.Phi_GMT());
0302         mu_.setHwPt(SP_.Pt_GMT());
0303         if (useNNBits_) {
0304           mu_.setHwPtUnconstrained(SP_.Pt_dxy_GMT());
0305           mu_.setHwDXY(SP_.Dxy_GMT());
0306         }
0307         mu_.setTFIdentifiers(Track_.Sector() - 1, (Track_.Endcap() == 1) ? emtf_pos : emtf_neg);
0308         mu_.setTrackSubAddress(RegionalMuonCand::kTrkNum, Track_.Track_num());
0309         // Truncated to 11 bits and offset by 25 from global event BX in EMTF firmware
0310         int EMTF_kBX = ((res->at(iOut)).PtrEventHeader()->L1A_BXN() % 2048) - 25 + Track_.BX();
0311         if (EMTF_kBX < 0)
0312           EMTF_kBX += 2048;
0313         mu_.setTrackSubAddress(RegionalMuonCand::kBX, EMTF_kBX);
0314         // mu_.set_dataword   ( SP_.Dataword() );
0315         // Track_.set_GMT(mu_);
0316 
0317         // Set Regional Muon Showers
0318         if (useMUSBits_) {
0319           muShower_.setTFIdentifiers(Track_.Sector() - 1, (Track_.Endcap() == 1) ? emtf_pos : emtf_neg);
0320           muShower_.setOneLooseInTime(SP_.MUS() >= looseShower_ ? true : false);
0321           muShower_.setOneNominalInTime(SP_.MUS() >= nominalShower_ ? true : false);
0322           muShower_.setOneTightInTime(SP_.MUS() >= tightShower_ ? true : false);
0323         }
0324 
0325         ///////////////////////
0326         // Match hits to tracks
0327         ///////////////////////
0328 
0329         // Find the track delay
0330         int nDelay[3] = {0, 0, 0};  // Number of hits in the track with delay 0, 1, or 2
0331         if (Track_.Mode() >= 8)
0332           nDelay[SP_.ME1_delay()] += 1;
0333         if ((Track_.Mode() % 8) >= 4)
0334           nDelay[SP_.ME2_delay()] += 1;
0335         if ((Track_.Mode() % 4) >= 2)
0336           nDelay[SP_.ME3_delay()] += 1;
0337         if ((Track_.Mode() % 2) == 1)
0338           nDelay[SP_.ME4_delay()] += 1;
0339 
0340         int trk_delay = -99;
0341         // Assume 2nd-earliest LCT configuration
0342         if (nDelay[2] >= 2)
0343           trk_delay = 2;
0344         else if (nDelay[2] + nDelay[1] >= 2)
0345           trk_delay = 1;
0346         else if (nDelay[2] + nDelay[1] + nDelay[0] >= 2)
0347           trk_delay = 0;
0348 
0349         // // For earliest LCT configuration
0350         // if      (nDelay[2]                         >= 1) trk_delay = 2;
0351         // else if (nDelay[2] + nDelay[1]             >= 1) trk_delay = 1;
0352         // else if (nDelay[2] + nDelay[1] + nDelay[0] >= 1) trk_delay = 0;
0353 
0354         // Reverse 'rotate by 2' to get CPPF subsector number
0355         auto get_subsector_rpc_cppf = [](int subsector_rpc) { return ((subsector_rpc + 3) % 6) + 1; };
0356 
0357         std::array<int, 4> St_hits{{0, 0, 0, 0}};  // Number of matched hits in each station
0358 
0359         for (auto const& Hit : *res_hit) {
0360           if (Track_.Mode() == 1)
0361             continue;  // Special case dealt with later
0362           if (Hit.Endcap() != Track_.Endcap())
0363             continue;
0364 
0365           int hit_delay = -99;
0366           if (Hit.Station() == 1)
0367             hit_delay = SP_.ME1_delay();
0368           else if (Hit.Station() == 2)
0369             hit_delay = SP_.ME2_delay();
0370           else if (Hit.Station() == 3)
0371             hit_delay = SP_.ME3_delay();
0372           else if (Hit.Station() == 4)
0373             hit_delay = SP_.ME4_delay();
0374 
0375           // Require exact matching according to TBIN and delays
0376           if (Hit.BX() + 3 + hit_delay != SP_.TBIN() + trk_delay)
0377             continue;
0378 
0379           // Match hit in station 1
0380           conv_vals_SP =
0381               convert_SP_location(SP_.ME1_CSC_ID(), (res->at(iOut)).PtrEventHeader()->Sector(), SP_.ME1_subsector(), 1);
0382 
0383           if (Hit.Station() == 1 && Hit.Sector() == conv_vals_SP.at(1) && Hit.Neighbor() == conv_vals_SP.at(3) &&
0384               Hit.Stub_num() == SP_.ME1_stub_num()) {
0385             if (Hit.Is_CSC() == 1 && (Hit.CSC_ID() != conv_vals_SP.at(0) || Hit.Subsector() != conv_vals_SP.at(2)))
0386               continue;
0387 
0388             int tmp_subsector = get_subsector_rpc_cppf(Hit.Subsector_RPC());
0389             int RPC_subsector = ((tmp_subsector - 1) / 3) + 1;  // Map RPC subsector to equivalent CSC subsector
0390             int RPC_CSC_ID = ((tmp_subsector - 1) % 3) + 4;     // Map RPC subsector and ring to equivalent CSC ID
0391 
0392             if (Hit.Is_RPC() == 1 && (RPC_CSC_ID != conv_vals_SP.at(0) || RPC_subsector != conv_vals_SP.at(2)))
0393               continue;
0394 
0395             if (St_hits.at(0) == 0) {  // Only add the first matched hit to the track
0396               Track_.push_Hit((Hit));
0397               mu_.setTrackSubAddress(RegionalMuonCand::kME1Seg, SP_.ME1_stub_num());
0398               mu_.setTrackSubAddress(
0399                   RegionalMuonCand::kME1Ch,
0400                   L1TMuonEndCap::calc_uGMT_chamber(conv_vals_SP.at(0), conv_vals_SP.at(2), conv_vals_SP.at(3), 1));
0401             }
0402             St_hits.at(0) += 1;  // Count the total number of matches for debugging purposes
0403           }                      // End conditional: if ( Hit.Station() == 1
0404 
0405           // Match hit in station 2
0406           conv_vals_SP = convert_SP_location(SP_.ME2_CSC_ID(), (res->at(iOut)).PtrEventHeader()->Sector(), -99, 2);
0407 
0408           if (Hit.Station() == 2 && Hit.Sector() == conv_vals_SP.at(1) && Hit.Neighbor() == conv_vals_SP.at(3) &&
0409               Hit.Stub_num() == SP_.ME2_stub_num()) {
0410             if (Hit.Is_CSC() == 1 && Hit.CSC_ID() != conv_vals_SP.at(0))
0411               continue;
0412 
0413             int tmp_subsector = get_subsector_rpc_cppf(Hit.Subsector_RPC());
0414             if (Hit.Is_RPC() == 1 && tmp_subsector + 3 != conv_vals_SP.at(0))
0415               continue;
0416 
0417             if (St_hits.at(1) == 0) {
0418               Track_.push_Hit((Hit));
0419               mu_.setTrackSubAddress(RegionalMuonCand::kME2Seg, SP_.ME2_stub_num());
0420               mu_.setTrackSubAddress(
0421                   RegionalMuonCand::kME2Ch,
0422                   L1TMuonEndCap::calc_uGMT_chamber(conv_vals_SP.at(0), conv_vals_SP.at(2), conv_vals_SP.at(3), 2));
0423             }
0424             St_hits.at(1) += 1;
0425           }  // End conditional: if ( Hit.Station() == 2
0426 
0427           // Match hit in station 3
0428           conv_vals_SP = convert_SP_location(SP_.ME3_CSC_ID(), (res->at(iOut)).PtrEventHeader()->Sector(), -99, 3);
0429 
0430           if (Hit.Station() == 3 && Hit.Sector() == conv_vals_SP.at(1) && Hit.Neighbor() == conv_vals_SP.at(3) &&
0431               Hit.Stub_num() == SP_.ME3_stub_num()) {
0432             if (Hit.Is_CSC() == 1 && Hit.CSC_ID() != conv_vals_SP.at(0))
0433               continue;
0434 
0435             int tmp_subsector = get_subsector_rpc_cppf(Hit.Subsector_RPC());
0436             if (Hit.Is_RPC() == 1 && tmp_subsector + 3 != conv_vals_SP.at(0))
0437               continue;
0438 
0439             if (St_hits.at(2) == 0) {
0440               Track_.push_Hit((Hit));
0441               mu_.setTrackSubAddress(RegionalMuonCand::kME3Seg, SP_.ME3_stub_num());
0442               mu_.setTrackSubAddress(
0443                   RegionalMuonCand::kME3Ch,
0444                   L1TMuonEndCap::calc_uGMT_chamber(conv_vals_SP.at(0), conv_vals_SP.at(2), conv_vals_SP.at(3), 3));
0445             }
0446             St_hits.at(2) += 1;
0447           }  // End conditional: if ( Hit.Station() == 3
0448 
0449           // Match hit in station 4
0450           conv_vals_SP = convert_SP_location(SP_.ME4_CSC_ID(), (res->at(iOut)).PtrEventHeader()->Sector(), -99, 4);
0451 
0452           if (Hit.Station() == 4 && Hit.Sector() == conv_vals_SP.at(1) && Hit.Neighbor() == conv_vals_SP.at(3) &&
0453               Hit.Stub_num() == SP_.ME4_stub_num()) {
0454             if (Hit.Is_CSC() == 1 && Hit.CSC_ID() != conv_vals_SP.at(0))
0455               continue;
0456 
0457             int tmp_subsector = get_subsector_rpc_cppf(Hit.Subsector_RPC());
0458             if (Hit.Is_RPC() == 1 && tmp_subsector + 3 != conv_vals_SP.at(0))
0459               continue;
0460 
0461             if (St_hits.at(3) == 0) {
0462               Track_.push_Hit((Hit));
0463               mu_.setTrackSubAddress(RegionalMuonCand::kME4Seg, SP_.ME4_stub_num());
0464               mu_.setTrackSubAddress(
0465                   RegionalMuonCand::kME4Ch,
0466                   L1TMuonEndCap::calc_uGMT_chamber(conv_vals_SP.at(0), conv_vals_SP.at(2), conv_vals_SP.at(3), 4));
0467             }
0468             St_hits.at(3) += 1;
0469           }  // End conditional: if ( Hit.Station() == 4
0470 
0471         }  // End loop: for (auto const & Hit : *res_hit)
0472 
0473         // Special configuration for single-stub tracks from ME1/1
0474         if (Track_.Mode() == 1) {
0475           // Infer ME1/1 chamber based on track phi
0476           int chamber_min = ((Track_.GMT_phi() - 17) / 16) + Track_.Sector() * 6 - 3;
0477           int chamber_max = ((Track_.GMT_phi() + 1) / 16) + Track_.Sector() * 6 - 3;
0478           for (int iChamb = chamber_max; iChamb >= chamber_min; iChamb--) {
0479             int chamber = (iChamb < 37 ? iChamb : (iChamb % 36));
0480 
0481             for (auto const& Hit : *res_hit) {
0482               if (Hit.Sector_idx() != Track_.Sector_idx())
0483                 continue;
0484               if (Hit.BX() != Track_.BX())
0485                 continue;
0486               if (Hit.Chamber() != chamber)
0487                 continue;
0488               if (Hit.Is_CSC() != 1)
0489                 continue;
0490               if (Hit.Station() != 1)
0491                 continue;
0492               if ((Hit.Ring() % 3) != 1)
0493                 continue;
0494               if (Hit.Neighbor() == 1)
0495                 continue;
0496 
0497               // Don't use LCTs that were already used in a multi-station track
0498               bool hit_already_used = false;
0499               for (auto const& Trk : *res_track) {
0500                 if (Trk.Sector_idx() != Track_.Sector_idx())
0501                   continue;
0502                 if (Trk.NumHits() < 1)
0503                   continue;
0504 
0505                 if (Trk.Hits().at(0).Station() == 1 && Trk.Hits().at(0).Chamber() == chamber &&
0506                     Trk.Hits().at(0).BX() == Hit.BX() && Trk.Hits().at(0).Ring() == Hit.Ring() &&
0507                     Trk.Hits().at(0).Strip() == Hit.Strip() && Trk.Hits().at(0).Wire() == Hit.Wire()) {
0508                   hit_already_used = true;
0509                   break;
0510                 }
0511               }  // End loop: for (auto const & Trk : *res_track)
0512 
0513               if (!hit_already_used) {
0514                 Track_.push_Hit((Hit));
0515                 break;
0516               }
0517             }  // End loop: for (auto const & Hit : *res_hit)
0518             if (Track_.NumHits() > 0)
0519               break;
0520           }  // End loop: for (int iChamb = chamber_max; iChamb >= chamber_min; iChamb--)
0521 
0522           // if (Track_.NumHits() != 1) {
0523           //   std::cout << "\n\n***********************************************************" << std::endl;
0524           //   std::cout << "Bug in unpacked EMTF event! Mode " << Track_.Mode() << " track in sector " << Track_.Sector()*Track_.Endcap()
0525           //          << ", BX " << Track_.BX() << ", GMT phi " << Track_.GMT_phi() << ", GMT eta " << Track_.GMT_eta()
0526           //          << " should have found an LCT between chamber " << chamber_min << " and " << chamber_max << std::endl;
0527           //   std::cout << "All available LCTs as follows:" << std::endl;
0528           //   for (auto const & Hit : *res_hit) {
0529           //     std::cout << "Hit: Is CSC = " << Hit.Is_CSC() << ", CSC ID = " << Hit.CSC_ID()
0530           //        << ", sector = " << Hit.Sector()*Hit.Endcap() << ", sub = " << Hit.Subsector()
0531           //        << ", neighbor = " << Hit.Neighbor() << ", station = " << Hit.Station()
0532           //        << ", ring = " << Hit.Ring() << ", chamber = " << Hit.Chamber()
0533           //        << ", stub = " << Hit.Stub_num() << ", BX = " << Hit.BX() << std::endl;
0534           //   std::cout << "All other tracks are as follows:" << std::endl;
0535           //   for (auto Trk = res_hit->begin(); Trk != res_hit->end(); ++Trk) {
0536           //     std::cout << "Track: mode " << Trk.Mode() << " track in sector " << Trk.Sector()*Trk.Endcap()
0537           //        << ", BX " << Trk.BX() << ", GMT phi " << Trk.GMT_phi() << ", GMT eta " << Trk.GMT_eta() << std::endl;
0538           //   }
0539           //   std::cout << "***********************************************************\n\n" << std::endl;
0540           // } // End conditional: if (Track_.NumHits() != 1)
0541 
0542         }  // End conditional: if (Track_.Mode() == 1)
0543 
0544         // 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) {
0545         //   std::cout << "\n\n***********************************************************" << std::endl;
0546         //   std::cout << "Bug in unpacked EMTF event! Mode " << Track_.Mode() << " track in sector " << Track_.Sector()*Track_.Endcap()
0547         //      << ", BX " << Track_.BX() << " (delay = " << trk_delay << ") with (" << St_hits.at(0) << ", " << St_hits.at(1)
0548         //      << ", " << St_hits.at(2) << ", " << St_hits.at(3) << ") hits in stations (1, 2, 3, 4)" << std::endl;
0549 
0550         //   std::cout << "\nME1_stub_num = " << SP_.ME1_stub_num() << ", ME1_delay = " <<  SP_.ME1_delay()
0551         //      << ", ME1_CSC_ID = " << SP_.ME1_CSC_ID() <<  ", ME1_subsector = " << SP_.ME1_subsector() << std::endl;
0552         //   std::cout << "ME2_stub_num = " << SP_.ME2_stub_num() << ", ME2_delay = " <<  SP_.ME2_delay()
0553         //      << ", ME2_CSC_ID = " << SP_.ME2_CSC_ID() << std::endl;
0554         //   std::cout << "ME3_stub_num = " << SP_.ME3_stub_num() << ", ME3_delay = " <<  SP_.ME3_delay()
0555         //      << ", ME3_CSC_ID = " << SP_.ME3_CSC_ID() << std::endl;
0556         //   std::cout << "ME4_stub_num = " << SP_.ME4_stub_num() << ", ME4_delay = " <<  SP_.ME4_delay()
0557         //      << ", ME4_CSC_ID = " << SP_.ME4_CSC_ID() << std::endl;
0558 
0559         //   conv_vals_SP = convert_SP_location( SP_.ME1_CSC_ID(), (res->at(iOut)).PtrEventHeader()->Sector(), SP_.ME1_subsector(), 1 );
0560         //   std::cout << "\nConverted ME1 CSC ID = " << conv_vals_SP.at(0) << ", sector = " << conv_vals_SP.at(1)
0561         //      << ", subsector = " << conv_vals_SP.at(2) << ", neighbor = " << conv_vals_SP.at(3) << std::endl;
0562         //   conv_vals_SP = convert_SP_location( SP_.ME2_CSC_ID(), (res->at(iOut)).PtrEventHeader()->Sector(), -99, 2 );
0563         //   std::cout << "Converted ME2 CSC ID = " << conv_vals_SP.at(0) << ", sector = " << conv_vals_SP.at(1)
0564         //      << ", subsector = " << conv_vals_SP.at(2) << ", neighbor = " << conv_vals_SP.at(3) << std::endl;
0565         //   conv_vals_SP = convert_SP_location( SP_.ME3_CSC_ID(), (res->at(iOut)).PtrEventHeader()->Sector(), -99, 3 );
0566         //   std::cout << "Converted ME3 CSC ID = " << conv_vals_SP.at(0) << ", sector = " << conv_vals_SP.at(1)
0567         //      << ", subsector = " << conv_vals_SP.at(2) << ", neighbor = " << conv_vals_SP.at(3) << std::endl;
0568         //   conv_vals_SP = convert_SP_location( SP_.ME4_CSC_ID(), (res->at(iOut)).PtrEventHeader()->Sector(), -99, 4 );
0569         //   std::cout << "Converted ME4 CSC ID = " << conv_vals_SP.at(0) << ", sector = " << conv_vals_SP.at(1)
0570         //      << ", subsector = " << conv_vals_SP.at(2) << ", neighbor = " << conv_vals_SP.at(3) << "\n" << std::endl;
0571 
0572         //   for (auto const & Hit : *res_hit)
0573         //     std::cout << "Hit: Is CSC = " << Hit.Is_CSC() << ", CSC ID = " << Hit.CSC_ID()
0574         //        << ", sector = " << Hit.Sector() << ", sub = " << Hit.Subsector()
0575         //        << ", neighbor = " << Hit.Neighbor() << ", station = " << Hit.Station()
0576         //        << ", ring = " << Hit.Ring() << ", chamber = " << Hit.Chamber()
0577         //        << ", stub = " << Hit.Stub_num() << ", BX = " << Hit.BX() << std::endl;
0578 
0579         //   // int iHit = 0;
0580         //   // for (auto const & Hit : *res_hit) {
0581         //   //   if (iHit == 0) Hit.PrintSimulatorHeader();
0582         //   //   Hit.PrintForSimulator();
0583         //   //   iHit += 1;
0584         //   // }
0585         //   std::cout << "***********************************************************\n\n" << std::endl;
0586         // }
0587 
0588         // 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
0589         if (Track_.BX() > 3 or Track_.BX() < -3) {
0590           edm::LogWarning("L1T|EMTF") << "EMTF unpacked track with out-of-range BX! BX: " << Track_.BX()
0591                                       << " endcap: " << (Track_.Endcap() == 1 ? 1 : 2) << " sector: " << Track_.Sector()
0592                                       << " address: " << Track_.PtLUT().address << " mode: " << Track_.Mode()
0593                                       << " eta: " << (Track_.GMT_eta() >= 0 ? Track_.GMT_eta() : Track_.GMT_eta() + 512)
0594                                       << " phi: " << Track_.GMT_phi() << " charge: " << Track_.GMT_charge()
0595                                       << " qual: " << Track_.GMT_quality() << " pt: " << Track_.Pt()
0596                                       << " pt_dxy: " << Track_.Pt_dxy() << std::endl;
0597           return true;
0598         }
0599 
0600         (res->at(iOut)).push_SP(SP_);
0601 
0602         if (Track_.Mode() != 0) {  // Mode == 0 means no track was found (only muon shower)
0603           res_track->push_back(Track_);
0604 
0605           // TBIN_num can range from 0 through 7, i.e. BX = -3 through +4. - AWB 04.04.16
0606           res_cand->setBXRange(-3, 4);
0607           res_cand->push_back(SP_.TBIN() - 3, mu_);
0608         }
0609 
0610         res_shower->setBXRange(-3, 4);
0611         res_shower->push_back(SP_.TBIN() - 3, muShower_);
0612 
0613         // Finished with unpacking one SP Output Data Record
0614         return true;
0615 
0616       }  // End bool SPBlockUnpacker::unpack
0617 
0618       // bool SPBlockPacker::pack(const Block& block, UnpackerCollections *coll) {
0619       //    std::cout << "Inside SPBlockPacker::pack" << std::endl;
0620       //    return true;
0621       // } // End bool SPBlockPacker::pack
0622 
0623     }  // End namespace emtf
0624   }    // End namespace stage2
0625 }  // End namespace l1t
0626 
0627 DEFINE_L1T_UNPACKER(l1t::stage2::emtf::SPBlockUnpacker);
0628 // DEFINE_L1T_PACKER(l1t::stage2::SPBlockPacker);