Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:10:46

0001 /**
0002  * \class L1GlobalTriggerRawToDigi
0003  *
0004  *
0005  * Description: unpack raw data into digitized data.
0006  *
0007  * Implementation:
0008  *    <TODO: enter implementation details>
0009  *
0010  * \author: Vasile Mihai Ghete - HEPHY Vienna -  GT
0011  * \author: Ivan Mikulec       - HEPHY Vienna - GMT
0012  *
0013  *
0014  */
0015 
0016 // this class header
0017 #include "EventFilter/L1GlobalTriggerRawToDigi/interface/L1GlobalTriggerRawToDigi.h"
0018 
0019 // system include files
0020 #include <iostream>
0021 #include <iomanip>
0022 #include <algorithm>
0023 
0024 // user include files
0025 #include "DataFormats/L1GlobalTrigger/interface/L1GlobalTriggerReadoutSetup.h"
0026 #include "DataFormats/L1GlobalTrigger/interface/L1GlobalTriggerReadoutRecord.h"
0027 
0028 #include "DataFormats/FEDRawData/interface/FEDNumbering.h"
0029 #include "DataFormats/FEDRawData/interface/FEDHeader.h"
0030 #include "DataFormats/FEDRawData/interface/FEDTrailer.h"
0031 #include "DataFormats/FEDRawData/interface/FEDRawDataCollection.h"
0032 
0033 #include "DataFormats/L1GlobalTrigger/interface/L1GtfeWord.h"
0034 #include "DataFormats/L1GlobalTrigger/interface/L1GtFdlWord.h"
0035 #include "DataFormats/L1GlobalTrigger/interface/L1GtPsbWord.h"
0036 
0037 #include "DataFormats/L1GlobalMuonTrigger/interface/L1MuRegionalCand.h"
0038 #include "DataFormats/L1GlobalMuonTrigger/interface/L1MuGMTExtendedCand.h"
0039 #include "DataFormats/L1GlobalMuonTrigger/interface/L1MuGMTReadoutCollection.h"
0040 
0041 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0042 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
0043 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
0044 #include "FWCore/Utilities/interface/InputTag.h"
0045 
0046 #include "FWCore/Framework/interface/EventSetup.h"
0047 #include "FWCore/Framework/interface/ESHandle.h"
0048 
0049 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0050 #include "FWCore/MessageLogger/interface/MessageDrop.h"
0051 
0052 #include "CondFormats/L1TObjects/interface/L1GtFwd.h"
0053 #include "CondFormats/L1TObjects/interface/L1GtBoard.h"
0054 
0055 // constructor(s)
0056 L1GlobalTriggerRawToDigi::L1GlobalTriggerRawToDigi(const edm::ParameterSet& pSet)
0057     :
0058 
0059       // input tag for DAQ GT record
0060       m_daqGtInputTag(pSet.getParameter<edm::InputTag>("DaqGtInputTag")),
0061 
0062       // FED Id for GT DAQ record
0063       // default value defined in DataFormats/FEDRawData/src/FEDNumbering.cc
0064       // default value: assume the DAQ record is the last GT record
0065       m_daqGtFedId(pSet.getUntrackedParameter<int>("DaqGtFedId", FEDNumbering::MAXTriggerGTPFEDID)),
0066 
0067       // mask for active boards
0068       m_activeBoardsMaskGt(pSet.getParameter<unsigned int>("ActiveBoardsMask")),
0069 
0070       // EventSetup Tokens
0071       m_trigScalesToken(esConsumes<L1MuTriggerScales, L1MuTriggerScalesRcd>()),
0072       m_trigPtScaleToken(esConsumes<L1MuTriggerPtScale, L1MuTriggerPtScaleRcd>()),
0073       m_l1GtBMToken(esConsumes<L1GtBoardMaps, L1GtBoardMapsRcd>()),
0074 
0075       // number of bunch crossing to be unpacked
0076       m_unpackBxInEvent(pSet.getParameter<int>("UnpackBxInEvent")),
0077 
0078       // create GTFE, FDL, PSB cards once per producer
0079       // content will be reset whenever needed
0080 
0081       m_lowSkipBxInEvent(0),
0082       m_uppSkipBxInEvent(0),
0083 
0084       m_recordLength0(0),
0085       m_recordLength1(0),
0086 
0087       m_totalBxInEvent(0),
0088 
0089       m_verbosity(pSet.getUntrackedParameter<int>("Verbosity", 0)),
0090 
0091       m_isDebugEnabled(edm::isDebugEnabled())
0092 
0093 {
0094   produces<L1GlobalTriggerReadoutRecord>();
0095   produces<L1MuGMTReadoutCollection>();
0096 
0097   produces<std::vector<L1MuRegionalCand> >("DT");
0098   produces<std::vector<L1MuRegionalCand> >("CSC");
0099   produces<std::vector<L1MuRegionalCand> >("RPCb");
0100   produces<std::vector<L1MuRegionalCand> >("RPCf");
0101   produces<std::vector<L1MuGMTCand> >();
0102   consumes<FEDRawDataCollection>(m_daqGtInputTag);
0103 
0104   // create GTFE, FDL, PSB cards once per producer
0105   // content will be reset whenever needed
0106   m_gtfeWord = new L1GtfeWord();
0107   m_gtFdlWord = new L1GtFdlWord();
0108   m_gtPsbWord = new L1GtPsbWord();
0109 
0110   if (m_verbosity && m_isDebugEnabled) {
0111     LogDebug("L1GlobalTriggerRawToDigi") << "\nInput tag for DAQ GT record:             " << m_daqGtInputTag
0112                                          << "\nFED Id for DAQ GT record:                " << m_daqGtFedId
0113                                          << "\nMask for active boards (hex format):     " << std::hex
0114                                          << std::setw(sizeof(m_activeBoardsMaskGt) * 2) << std::setfill('0')
0115                                          << m_activeBoardsMaskGt << std::dec << std::setfill(' ')
0116                                          << "\nNumber of bunch crossing to be unpacked: " << m_unpackBxInEvent << "\n"
0117                                          << std::endl;
0118   }
0119 
0120   if ((m_unpackBxInEvent > 0) && ((m_unpackBxInEvent % 2) == 0)) {
0121     m_unpackBxInEvent = m_unpackBxInEvent - 1;
0122 
0123     if (m_verbosity) {
0124       edm::LogInfo("L1GlobalTriggerRawToDigi")
0125           << "\nWARNING: Number of bunch crossing to be unpacked rounded to: " << m_unpackBxInEvent
0126           << "\n         The number must be an odd number!\n"
0127           << std::endl;
0128     }
0129   }
0130 }
0131 
0132 // destructor
0133 L1GlobalTriggerRawToDigi::~L1GlobalTriggerRawToDigi() {
0134   delete m_gtfeWord;
0135   delete m_gtFdlWord;
0136   delete m_gtPsbWord;
0137 }
0138 
0139 void L1GlobalTriggerRawToDigi::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
0140   edm::ParameterSetDescription desc;
0141   static const char* const kComm1 =
0142       "# input tag for GT readout collection: \n"
0143       "#     source = hardware record, \n"
0144       "#     l1GtPack = GT packer (DigiToRaw)";
0145   desc.add<edm::InputTag>("DaqGtInputTag", edm::InputTag("l1GtPack"))->setComment(kComm1);
0146   static const char* const kComm2 =
0147       "# FED Id for GT DAQ record \n"
0148       "# default value defined in DataFormats/FEDRawData/src/FEDNumbering.cc";
0149   desc.addUntracked<int>("DaqGtFedId", FEDNumbering::MAXTriggerGTPFEDID)->setComment(kComm2);
0150   static const char* const kComm3 =
0151       "# mask for active boards (actually 16 bits) \n"
0152       "#      if bit is zero, the corresponding board will not be unpacked \n"
0153       "#      default: no board masked";
0154   desc.add<unsigned int>("ActiveBoardsMask", 0xFFFF)->setComment(kComm3);
0155   static const char* const kComm4 =
0156       "# number of 'bunch crossing in the event' (bxInEvent) to be unpacked \n"
0157       "# symmetric around L1Accept (bxInEvent = 0): \n"
0158       "#    1 (bxInEvent = 0); 3 (F 0 1) (standard record); 5 (E F 0 1 2) (debug record) \n"
0159       "# even numbers (except 0) 'rounded' to the nearest lower odd number \n"
0160       "# negative value: unpack all available bxInEvent \n"
0161       "# if more bxInEvent than available are required, unpack what exists and write a warning";
0162   desc.add<int>("UnpackBxInEvent", -1)->setComment(kComm4);
0163   desc.addUntracked<int>("Verbosity", 0);
0164   descriptions.add("l1GlobalTriggerRawToDigi", desc);
0165 }
0166 
0167 // member functions
0168 
0169 // method called to produce the data
0170 void L1GlobalTriggerRawToDigi::produce(edm::Event& iEvent, const edm::EventSetup& evSetup) {
0171   // get records from EventSetup
0172 
0173   //  muon trigger scales
0174   edm::ESHandle<L1MuTriggerScales> trigscales_h = evSetup.getHandle(m_trigScalesToken);
0175   m_TriggerScales = trigscales_h.product();
0176 
0177   edm::ESHandle<L1MuTriggerPtScale> trigptscale_h = evSetup.getHandle(m_trigPtScaleToken);
0178   m_TriggerPtScale = trigptscale_h.product();
0179 
0180   //  board maps
0181   edm::ESHandle<L1GtBoardMaps> l1GtBM = evSetup.getHandle(m_l1GtBMToken);
0182 
0183   const std::vector<L1GtBoard> boardMaps = l1GtBM->gtBoardMaps();
0184   int boardMapsSize = boardMaps.size();
0185 
0186   typedef std::vector<L1GtBoard>::const_iterator CItBoardMaps;
0187 
0188   // create an ordered vector for the GT DAQ record
0189   // header (pos 0 in record) and trailer (last position in record)
0190   // not included, as they are not in board list
0191   std::vector<L1GtBoard> gtRecordMap;
0192   gtRecordMap.reserve(boardMapsSize);
0193 
0194   for (int iPos = 0; iPos < boardMapsSize; ++iPos) {
0195     for (CItBoardMaps itBoard = boardMaps.begin(); itBoard != boardMaps.end(); ++itBoard) {
0196       if (itBoard->gtPositionDaqRecord() == iPos) {
0197         gtRecordMap.push_back(*itBoard);
0198         break;
0199       }
0200     }
0201   }
0202 
0203   // raw collection
0204 
0205   edm::Handle<FEDRawDataCollection> fedHandle;
0206   iEvent.getByLabel(m_daqGtInputTag, fedHandle);
0207 
0208   if (!fedHandle.isValid()) {
0209     if (m_verbosity) {
0210       edm::LogWarning("L1GlobalTriggerRawToDigi")
0211           << "\nWarning: FEDRawDataCollection with input tag " << m_daqGtInputTag
0212           << "\nrequested in configuration, but not found in the event."
0213           << "\nQuit unpacking this event" << std::endl;
0214     }
0215 
0216     produceEmptyProducts(iEvent);
0217 
0218     return;
0219   }
0220 
0221   // retrieve data for Global Trigger FED (GT + GMT)
0222   const FEDRawData& raw = (fedHandle.product())->FEDData(m_daqGtFedId);
0223 
0224   int gtSize = raw.size();
0225 
0226   // get a const pointer to the beginning of the data buffer
0227   const unsigned char* ptrGt = raw.data();
0228 
0229   // get a const pointer to the end of the data buffer
0230   const unsigned char* endPtrGt = ptrGt + gtSize;
0231 
0232   //
0233   if (m_verbosity && m_isDebugEnabled) {
0234     LogTrace("L1GlobalTriggerRawToDigi") << "\n Size of raw data: " << gtSize << "\n" << std::endl;
0235 
0236     std::ostringstream myCoutStream;
0237     dumpFedRawData(ptrGt, gtSize, myCoutStream);
0238 
0239     LogTrace("L1GlobalTriggerRawToDigi") << "\n Dump FEDRawData\n" << myCoutStream.str() << "\n" << std::endl;
0240   }
0241 
0242   // unpack header (we have one header only)
0243   int headerSize = 8;
0244 
0245   if ((ptrGt + headerSize) > endPtrGt) {
0246     // a common error - no need to print an error anymore
0247     produceEmptyProducts(iEvent);
0248 
0249     return;
0250   }
0251 
0252   FEDHeader cmsHeader(ptrGt);
0253   FEDTrailer cmsTrailer(ptrGt + gtSize - headerSize);
0254 
0255   unpackHeader(ptrGt, cmsHeader);
0256   ptrGt += headerSize;  // advance with header size
0257 
0258   // unpack first GTFE to find the length of the record and the active boards
0259   // here GTFE assumed immediately after the header
0260 
0261   // if pointer after GTFE payload is greater than pointer at
0262   // the end of GT payload, produce empty products and quit unpacking
0263   if ((ptrGt + m_gtfeWord->getSize()) > endPtrGt) {
0264     edm::LogError("L1GlobalTriggerRawToDigi") << "\nError: Pointer after GTFE greater than end pointer."
0265                                               << "\n Put empty products in the event!"
0266                                               << "\n Quit unpacking this event." << std::endl;
0267 
0268     produceEmptyProducts(iEvent);
0269 
0270     return;
0271   }
0272 
0273   bool gtfeUnpacked = false;
0274 
0275   for (CItBoardMaps itBoard = boardMaps.begin(); itBoard != boardMaps.end(); ++itBoard) {
0276     if (itBoard->gtBoardType() == GTFE) {
0277       // unpack GTFE
0278       if (itBoard->gtPositionDaqRecord() == 1) {
0279         m_gtfeWord->unpack(ptrGt);
0280         ptrGt += m_gtfeWord->getSize();  // advance with GTFE block size
0281         gtfeUnpacked = true;
0282 
0283         if (m_verbosity && m_isDebugEnabled) {
0284           std::ostringstream myCoutStream;
0285           m_gtfeWord->print(myCoutStream);
0286           LogTrace("L1GlobalTriggerRawToDigi") << myCoutStream.str() << "\n" << std::endl;
0287         }
0288 
0289         // break the loop - GTFE was found
0290         break;
0291 
0292       } else {
0293         if (m_verbosity) {
0294           edm::LogWarning("L1GlobalTriggerRawToDigi")
0295               << "\nWarning: GTFE block found in raw data does not follow header."
0296               << "\nAssumed start position of the block is wrong!"
0297               << "\nQuit unpacking this event" << std::endl;
0298         }
0299 
0300         produceEmptyProducts(iEvent);
0301 
0302         return;
0303       }
0304     }
0305   }
0306 
0307   // quit if no GTFE found
0308   if (!gtfeUnpacked) {
0309     if (m_verbosity) {
0310       edm::LogWarning("L1GlobalTriggerRawToDigi")
0311           << "\nWarning: no GTFE block found in raw data."
0312           << "\nCan not find the record length (BxInEvent) and the active boards!"
0313           << "\nQuit unpacking this event" << std::endl;
0314     }
0315 
0316     produceEmptyProducts(iEvent);
0317 
0318     return;
0319   }
0320 
0321   // life normal here, GTFE found
0322 
0323   // get list of active blocks
0324   // blocks not active are not written to the record
0325   cms_uint16_t activeBoardsGtInitial = m_gtfeWord->activeBoards();
0326   cms_uint16_t altNrBxBoardInitial = m_gtfeWord->altNrBxBoard();
0327 
0328   // mask some boards, if needed
0329   cms_uint16_t activeBoardsGt = activeBoardsGtInitial & m_activeBoardsMaskGt;
0330   m_gtfeWord->setActiveBoards(activeBoardsGt);
0331 
0332   if (m_verbosity) {
0333     LogDebug("L1GlobalTriggerRawToDigi") << "\nActive boards before masking: 0x" << std::hex
0334                                          << std::setw(sizeof(activeBoardsGtInitial) * 2) << std::setfill('0')
0335                                          << activeBoardsGtInitial << std::dec << std::setfill(' ')
0336                                          << "\nActive boards after masking:  0x" << std::hex
0337                                          << std::setw(sizeof(activeBoardsGt) * 2) << std::setfill('0') << activeBoardsGt
0338                                          << std::dec << std::setfill(' ') << " \n"
0339                                          << std::endl;
0340   }
0341 
0342   // loop over other blocks in the raw record, count them if they are active
0343 
0344   int numberFdlBoards = 0;
0345   int numberPsbBoards = 0;
0346 
0347   for (CItBoardMaps itBoard = boardMaps.begin(); itBoard != boardMaps.end(); ++itBoard) {
0348     int iActiveBit = itBoard->gtBitDaqActiveBoards();
0349     bool activeBoardToUnpack = false;
0350 
0351     if (iActiveBit >= 0) {
0352       activeBoardToUnpack = activeBoardsGt & (1 << iActiveBit);
0353     } else {
0354       // board not in the ActiveBoards for the record
0355       continue;
0356     }
0357 
0358     if (activeBoardToUnpack) {
0359       switch (itBoard->gtBoardType()) {
0360         case GTFE:
0361           break;
0362         case FDL: {
0363           numberFdlBoards++;
0364         }
0365 
0366         break;
0367         case PSB: {
0368           numberPsbBoards++;
0369         }
0370 
0371         break;
0372         case GMT:
0373           break;
0374         case TCS:
0375           break;
0376         case TIM:
0377           break;
0378         default: {
0379           // do nothing, all blocks are given in GtBoardType enum
0380           if (m_verbosity) {
0381             LogDebug("L1GlobalTriggerRawToDigi")
0382                 << "\nBoard of type " << itBoard->gtBoardType() << " not expected  in record.\n"
0383                 << std::endl;
0384           }
0385         }
0386 
0387         break;
0388       }
0389     }
0390   }
0391 
0392   // produce the L1GlobalTriggerReadoutRecord now, after we found the maximum number of
0393   // BxInEvent the record has and how many boards are active (it is just reserving space
0394   // for vectors)
0395   //LogDebug("L1GlobalTriggerRawToDigi")
0396   //<< "\nL1GlobalTriggerRawToDigi: producing L1GlobalTriggerReadoutRecord\n"
0397   //<< "\nL1GlobalTriggerRawToDigi: producing L1MuGMTReadoutCollection;\n"
0398   //<< std::endl;
0399 
0400   // get number of Bx in the event from GTFE block corresponding to alternative 0 and 1 in
0401   m_recordLength0 = m_gtfeWord->recordLength();
0402   m_recordLength1 = m_gtfeWord->recordLength1();
0403 
0404   int maxBxInEvent = std::max(m_recordLength0, m_recordLength1);
0405 
0406   std::unique_ptr<L1GlobalTriggerReadoutRecord> gtReadoutRecord(
0407       new L1GlobalTriggerReadoutRecord(maxBxInEvent, numberFdlBoards, numberPsbBoards));
0408 
0409   // produce also the GMT readout collection and set the reference in GT record
0410   std::unique_ptr<L1MuGMTReadoutCollection> gmtrc(new L1MuGMTReadoutCollection(maxBxInEvent));
0411 
0412   //edm::RefProd<L1MuGMTReadoutCollection> refProdMuGMT = iEvent.getRefBeforePut<
0413   //        L1MuGMTReadoutCollection> ();
0414 
0415   //if (m_verbosity) {
0416   //    LogDebug("L1GlobalTriggerRawToDigi")
0417   //            << "\nL1GlobalTriggerRawToDigi: set L1MuGMTReadoutCollection RefProd"
0418   //            << " in L1GlobalTriggerReadoutRecord.\n" << std::endl;
0419   //}
0420   //gtReadoutRecord->setMuCollectionRefProd(refProdMuGMT);
0421 
0422   // ... then unpack modules other than GTFE, if requested
0423 
0424   for (CItBoardMaps itBoard = gtRecordMap.begin(); itBoard != gtRecordMap.end(); ++itBoard) {
0425     int iActiveBit = itBoard->gtBitDaqActiveBoards();
0426 
0427     bool activeBoardToUnpack = false;
0428     bool activeBoardInitial = false;
0429 
0430     int altNrBxBoardVal = -1;
0431 
0432     if (iActiveBit >= 0) {
0433       activeBoardInitial = activeBoardsGtInitial & (1 << iActiveBit);
0434       activeBoardToUnpack = activeBoardsGt & (1 << iActiveBit);
0435 
0436       altNrBxBoardVal = (altNrBxBoardInitial & (1 << iActiveBit)) >> iActiveBit;
0437 
0438       if (altNrBxBoardVal == 1) {
0439         m_totalBxInEvent = m_recordLength1;
0440       } else if (altNrBxBoardVal == 0) {
0441         m_totalBxInEvent = m_recordLength0;
0442       } else {
0443         if (m_verbosity) {
0444           edm::LogWarning("L1GlobalTriggerRawToDigi")
0445               << "\n\nWARNING: Wrong value altNrBxBoardVal = " << altNrBxBoardVal << " for board " << std::hex
0446               << (itBoard->gtBoardId()) << std::dec << "\n  iActiveBit =            " << iActiveBit
0447               << "\n  altNrBxBoardInitial = 0x" << std::hex << altNrBxBoardInitial << std::dec
0448               << "\n  activeBoardsGt =      0x" << std::hex << activeBoardsGt << std::dec
0449               << "\n  activeBoardInitial =    " << activeBoardInitial
0450               << "\n  activeBoardToUnpack =   " << activeBoardToUnpack << "\n Set altNrBxBoardVal tentatively to "
0451               << m_recordLength0 << "\n Job may crash or produce wrong results!\n\n"
0452               << std::endl;
0453         }
0454 
0455         m_totalBxInEvent = m_recordLength0;
0456       }
0457 
0458       // number of BX required to be unpacked
0459 
0460       if (m_unpackBxInEvent > m_totalBxInEvent) {
0461         if (m_verbosity) {
0462           LogDebug("L1GlobalTriggerRawToDigi")
0463               << "\nWARNING: Number of available bunch crosses for board" << (itBoard->gtBoardId())
0464               << " in the record ( " << m_totalBxInEvent
0465               << " ) \n is smaller than the number of bunch crosses requested to be unpacked (" << m_unpackBxInEvent
0466               << " )!!! \n         Unpacking only " << m_totalBxInEvent << " bunch crosses.\n"
0467               << std::endl;
0468         }
0469 
0470         m_lowSkipBxInEvent = 0;
0471         m_uppSkipBxInEvent = m_totalBxInEvent;
0472 
0473       } else if (m_unpackBxInEvent < 0) {
0474         m_lowSkipBxInEvent = 0;
0475         m_uppSkipBxInEvent = m_totalBxInEvent;
0476 
0477         if (m_verbosity) {
0478           LogDebug("L1GlobalTriggerRawToDigi") << "\nUnpacking all " << m_totalBxInEvent << " bunch crosses available."
0479                                                << "\n"
0480                                                << std::endl;
0481         }
0482 
0483       } else if (m_unpackBxInEvent == 0) {
0484         m_lowSkipBxInEvent = m_totalBxInEvent;
0485         m_uppSkipBxInEvent = m_totalBxInEvent;
0486 
0487         if (m_verbosity) {
0488           LogDebug("L1GlobalTriggerRawToDigi")
0489               << "\nNo bxInEvent required to be unpacked from " << m_totalBxInEvent << " bunch crosses available."
0490               << "\n"
0491               << std::endl;
0492         }
0493 
0494         // change RecordLength
0495         // cast int to cms_uint16_t (there are normally 3 or 5 BxInEvent)
0496         m_gtfeWord->setRecordLength(static_cast<cms_uint16_t>(m_unpackBxInEvent));
0497         m_gtfeWord->setRecordLength1(static_cast<cms_uint16_t>(m_unpackBxInEvent));
0498 
0499       } else {
0500         m_lowSkipBxInEvent = (m_totalBxInEvent - m_unpackBxInEvent) / 2;
0501         m_uppSkipBxInEvent = m_totalBxInEvent - m_lowSkipBxInEvent;
0502 
0503         if (m_verbosity) {
0504           LogDebug("L1GlobalTriggerRawToDigi") << "\nUnpacking " << m_unpackBxInEvent << " bunch crosses from "
0505                                                << m_totalBxInEvent << " bunch crosses available."
0506                                                << "\n"
0507                                                << std::endl;
0508         }
0509 
0510         // change RecordLength
0511         // cast int to cms_uint16_t (there are normally 3 or 5 BxInEvent)
0512         m_gtfeWord->setRecordLength(static_cast<cms_uint16_t>(m_unpackBxInEvent));
0513         m_gtfeWord->setRecordLength1(static_cast<cms_uint16_t>(m_unpackBxInEvent));
0514       }
0515 
0516     } else {
0517       // board not in the ActiveBoards for the record
0518       continue;
0519     }
0520 
0521     if (!activeBoardInitial) {
0522       if (m_verbosity) {
0523         LogDebug("L1GlobalTriggerRawToDigi") << "\nBoard of type " << itBoard->gtBoardName() << " with index "
0524                                              << itBoard->gtBoardIndex() << " not active initially in raw data.\n"
0525                                              << std::endl;
0526       }
0527       continue;
0528     }
0529 
0530     // active board initially, could unpack it
0531     switch (itBoard->gtBoardType()) {
0532       case FDL: {
0533         for (int iFdl = 0; iFdl < m_totalBxInEvent; ++iFdl) {
0534           // if pointer after FDL payload is greater than pointer at
0535           // the end of GT payload, produce empty products and quit unpacking
0536           if ((ptrGt + m_gtFdlWord->getSize()) > endPtrGt) {
0537             edm::LogError("L1GlobalTriggerRawToDigi")
0538                 << "\nError: Pointer after FDL " << iFdl << " greater than end pointer."
0539                 << "\n Put empty products in the event!"
0540                 << "\n Quit unpacking this event." << std::endl;
0541 
0542             produceEmptyProducts(iEvent);
0543 
0544             return;
0545           }
0546 
0547           // unpack only if requested, otherwise skip it
0548           if (activeBoardToUnpack) {
0549             // unpack only bxInEvent requested, otherwise skip it
0550             if ((iFdl >= m_lowSkipBxInEvent) && (iFdl < m_uppSkipBxInEvent)) {
0551               m_gtFdlWord->unpack(ptrGt);
0552 
0553               // add 1 to the GT luminosity number to use the same convention as
0554               // offline, where LS number starts with 1;
0555               // in GT hardware, LS starts with 0
0556               cms_uint16_t lsNr = m_gtFdlWord->lumiSegmentNr() + 1;
0557               m_gtFdlWord->setLumiSegmentNr(lsNr);
0558 
0559               // add FDL block to GT readout record
0560               gtReadoutRecord->setGtFdlWord(*m_gtFdlWord);
0561 
0562               if (m_verbosity && m_isDebugEnabled) {
0563                 std::ostringstream myCoutStream;
0564                 m_gtFdlWord->print(myCoutStream);
0565                 LogTrace("L1GlobalTriggerRawToDigi") << myCoutStream.str() << "\n" << std::endl;
0566               }
0567 
0568               // ... and reset it
0569               m_gtFdlWord->reset();
0570             }
0571           }
0572 
0573           ptrGt += m_gtFdlWord->getSize();  // advance with FDL block size
0574         }
0575       }
0576 
0577       break;
0578       case PSB: {
0579         for (int iPsb = 0; iPsb < m_totalBxInEvent; ++iPsb) {
0580           // if pointer after PSB payload is greater than pointer at
0581           // the end of GT payload, produce empty products and quit unpacking
0582           if ((ptrGt + m_gtPsbWord->getSize()) > endPtrGt) {
0583             edm::LogError("L1GlobalTriggerRawToDigi")
0584                 << "\nError: Pointer after PSB " << iPsb << " greater than end pointer."
0585                 << "\n Put empty products in the event!"
0586                 << "\n Quit unpacking this event." << std::endl;
0587 
0588             produceEmptyProducts(iEvent);
0589 
0590             return;
0591           }
0592 
0593           // unpack only if requested, otherwise skip it
0594           if (activeBoardToUnpack) {
0595             // unpack only bxInEvent requested, otherwise skip it
0596             if ((iPsb >= m_lowSkipBxInEvent) && (iPsb < m_uppSkipBxInEvent)) {
0597               unpackPSB(evSetup, ptrGt, *m_gtPsbWord);
0598 
0599               // add PSB block to GT readout record
0600               gtReadoutRecord->setGtPsbWord(*m_gtPsbWord);
0601 
0602               if (m_verbosity && m_isDebugEnabled) {
0603                 std::ostringstream myCoutStream;
0604                 m_gtPsbWord->print(myCoutStream);
0605                 LogTrace("L1GlobalTriggerRawToDigi") << myCoutStream.str() << "\n" << std::endl;
0606               }
0607 
0608               // ... and reset it
0609               m_gtPsbWord->reset();
0610             }
0611           }
0612 
0613           ptrGt += m_gtPsbWord->getSize();  // advance with PSB block size
0614         }
0615       } break;
0616       case GMT: {
0617         // 17*64/8 TODO FIXME ask Ivan for a getSize() function for GMT record
0618         unsigned int gmtRecordSize = 136;
0619         unsigned int gmtCollSize = m_totalBxInEvent * gmtRecordSize;
0620 
0621         // if pointer after GMT payload is greater than pointer at
0622         // the end of GT payload, produce empty products and quit unpacking
0623         if ((ptrGt + gmtCollSize) > endPtrGt) {
0624           edm::LogError("L1GlobalTriggerRawToDigi") << "\nError: Pointer after GMT "
0625                                                     << " greater than end pointer."
0626                                                     << "\n Put empty products in the event!"
0627                                                     << "\n Quit unpacking this event." << std::endl;
0628 
0629           produceEmptyProducts(iEvent);
0630 
0631           return;
0632         }
0633 
0634         // unpack only if requested, otherwise skip it
0635         if (activeBoardToUnpack) {
0636           unpackGMT(ptrGt, gmtrc, iEvent);
0637         }
0638 
0639         ptrGt += gmtCollSize;  // advance with GMT block size
0640       } break;
0641       default: {
0642         // do nothing, all blocks are given in GtBoardType enum
0643         if (m_verbosity) {
0644           LogDebug("L1GlobalTriggerRawToDigi")
0645               << "\nBoard of type " << itBoard->gtBoardType() << " not expected  in record.\n"
0646               << std::endl;
0647         }
0648       } break;
0649     }
0650   }
0651 
0652   // add GTFE block to GT readout record, after updating active boards and record length
0653 
0654   gtReadoutRecord->setGtfeWord(*m_gtfeWord);
0655 
0656   // ... and reset it
0657   m_gtfeWord->reset();
0658 
0659   // unpack trailer
0660 
0661   int trailerSize = 8;
0662 
0663   // if pointer after trailer is greater than pointer at
0664   // the end of GT payload, produce empty products and quit unpacking
0665   if ((ptrGt + trailerSize) > endPtrGt) {
0666     edm::LogError("L1GlobalTriggerRawToDigi") << "\nError: Pointer after trailer "
0667                                               << " greater than end pointer."
0668                                               << "\n Put empty products in the event!"
0669                                               << "\n Quit unpacking this event." << std::endl;
0670 
0671     produceEmptyProducts(iEvent);
0672 
0673     return;
0674   }
0675 
0676   unpackTrailer(ptrGt, cmsTrailer);
0677 
0678   //
0679   if (m_verbosity && m_isDebugEnabled) {
0680     std::ostringstream myCoutStream;
0681     gtReadoutRecord->print(myCoutStream);
0682     LogTrace("L1GlobalTriggerRawToDigi") << "\n The following L1 GT DAQ readout record was unpacked.\n"
0683                                          << myCoutStream.str() << "\n"
0684                                          << std::endl;
0685   }
0686 
0687   // put records into event
0688 
0689   iEvent.put(std::move(gmtrc));
0690   iEvent.put(std::move(gtReadoutRecord));
0691 }
0692 
0693 // unpack header
0694 void L1GlobalTriggerRawToDigi::unpackHeader(const unsigned char* gtPtr, FEDHeader& cmsHeader) {
0695   // TODO  if needed in another format
0696 
0697   // print the header info
0698   if (m_verbosity && m_isDebugEnabled) {
0699     const cms_uint64_t* payload = reinterpret_cast<cms_uint64_t*>(const_cast<unsigned char*>(gtPtr));
0700 
0701     std::ostringstream myCoutStream;
0702 
0703     // one word only
0704     int iWord = 0;
0705 
0706     myCoutStream << std::setw(4) << iWord << "  " << std::hex << std::setfill('0') << std::setw(16) << payload[iWord]
0707                  << std::dec << std::setfill(' ') << "\n"
0708                  << std::endl;
0709 
0710     myCoutStream << "  Event_type:  " << std::hex << " hex: "
0711                  << "     " << std::setw(1) << std::setfill('0') << cmsHeader.triggerType() << std::setfill(' ')
0712                  << std::dec << " dec: " << cmsHeader.triggerType() << std::endl;
0713 
0714     myCoutStream << "  LVL1_Id:     " << std::hex << " hex: "
0715                  << "" << std::setw(6) << std::setfill('0') << cmsHeader.lvl1ID() << std::setfill(' ') << std::dec
0716                  << " dec: " << cmsHeader.lvl1ID() << std::endl;
0717 
0718     myCoutStream << "  BX_Id:       " << std::hex << " hex: "
0719                  << "   " << std::setw(3) << std::setfill('0') << cmsHeader.bxID() << std::setfill(' ') << std::dec
0720                  << " dec: " << cmsHeader.bxID() << std::endl;
0721 
0722     myCoutStream << "  Source_Id:   " << std::hex << " hex: "
0723                  << "   " << std::setw(3) << std::setfill('0') << cmsHeader.sourceID() << std::setfill(' ') << std::dec
0724                  << " dec: " << cmsHeader.sourceID() << std::endl;
0725 
0726     myCoutStream << "  FOV:         " << std::hex << " hex: "
0727                  << "     " << std::setw(1) << std::setfill('0') << cmsHeader.version() << std::setfill(' ') << std::dec
0728                  << " dec: " << cmsHeader.version() << std::endl;
0729 
0730     myCoutStream << "  H:           " << std::hex << " hex: "
0731                  << "     " << std::setw(1) << std::setfill('0') << cmsHeader.moreHeaders() << std::setfill(' ')
0732                  << std::dec << " dec: " << cmsHeader.moreHeaders() << std::endl;
0733 
0734     LogDebug("L1GlobalTriggerRawToDigi") << "\n CMS Header \n" << myCoutStream.str() << "\n" << std::endl;
0735   }
0736 }
0737 
0738 // unpack PSB records
0739 // psbPtr pointer to the beginning of the each PSB block obtained from gtPtr
0740 void L1GlobalTriggerRawToDigi::unpackPSB(const edm::EventSetup& evSetup,
0741                                          const unsigned char* psbPtr,
0742                                          L1GtPsbWord& psbWord) {
0743   //LogDebug("L1GlobalTriggerRawToDigi")
0744   //<< "\nUnpacking PSB block.\n"
0745   //<< std::endl;
0746 
0747   int uLength = L1GlobalTriggerReadoutSetup::UnitLength;
0748 
0749   int psbSize = psbWord.getSize();
0750   int psbWords = psbSize / uLength;
0751 
0752   const cms_uint64_t* payload = reinterpret_cast<cms_uint64_t*>(const_cast<unsigned char*>(psbPtr));
0753 
0754   for (int iWord = 0; iWord < psbWords; ++iWord) {
0755     // fill PSB
0756     // the second argument must match the word index defined in L1GtPsbWord class
0757 
0758     psbWord.setBoardId(payload[iWord], iWord);
0759     psbWord.setBxInEvent(payload[iWord], iWord);
0760     psbWord.setBxNr(payload[iWord], iWord);
0761     psbWord.setEventNr(payload[iWord], iWord);
0762 
0763     psbWord.setAData(payload[iWord], iWord);
0764     psbWord.setBData(payload[iWord], iWord);
0765 
0766     psbWord.setLocalBxNr(payload[iWord], iWord);
0767 
0768     LogTrace("L1GlobalTriggerRawToDigi") << std::setw(4) << iWord << "  " << std::hex << std::setfill('0')
0769                                          << std::setw(16) << payload[iWord] << std::dec << std::setfill(' ')
0770                                          << std::endl;
0771   }
0772 }
0773 
0774 // unpack the GMT record
0775 void L1GlobalTriggerRawToDigi::unpackGMT(const unsigned char* chp,
0776                                          std::unique_ptr<L1MuGMTReadoutCollection>& gmtrc,
0777                                          edm::Event& iEvent) {
0778   //LogDebug("L1GlobalTriggerRawToDigi")
0779   //<< "\nUnpacking GMT collection.\n"
0780   //<< std::endl;
0781 
0782   // 17*64/2 TODO FIXME ask Ivan for a getSize() function for GMT record
0783   const unsigned int gmtRecordSize32 = 34;
0784 
0785   std::unique_ptr<std::vector<L1MuRegionalCand> > DTCands(new std::vector<L1MuRegionalCand>);
0786   std::unique_ptr<std::vector<L1MuRegionalCand> > CSCCands(new std::vector<L1MuRegionalCand>);
0787   std::unique_ptr<std::vector<L1MuRegionalCand> > RPCbCands(new std::vector<L1MuRegionalCand>);
0788   std::unique_ptr<std::vector<L1MuRegionalCand> > RPCfCands(new std::vector<L1MuRegionalCand>);
0789   std::unique_ptr<std::vector<L1MuGMTCand> > GMTCands(new std::vector<L1MuGMTCand>);
0790 
0791   const unsigned* p = (const unsigned*)chp;
0792 
0793   // min Bx's in the event, computed after m_totalBxInEvent is obtained from GTFE block
0794   // assume symmetrical number of BX around L1Accept
0795   int iBxInEvent = (m_totalBxInEvent + 1) / 2 - m_totalBxInEvent;
0796 
0797   for (int iGmtRec = 0; iGmtRec < m_totalBxInEvent; ++iGmtRec) {
0798     // unpack only bxInEvent requested, otherwise skip it
0799     if ((iGmtRec >= m_lowSkipBxInEvent) && (iGmtRec < m_uppSkipBxInEvent)) {
0800       // Dump the block
0801       const cms_uint64_t* bp = reinterpret_cast<cms_uint64_t*>(const_cast<unsigned*>(p));
0802       for (int iWord = 0; iWord < 17; iWord++) {
0803         LogTrace("L1GlobalTriggerRawToDigi") << std::setw(4) << iWord << "  " << std::hex << std::setfill('0')
0804                                              << std::setw(16) << *bp++ << std::dec << std::setfill(' ') << std::endl;
0805       }
0806 
0807       L1MuGMTReadoutRecord gmtrr(iBxInEvent);
0808 
0809       gmtrr.setEvNr((*p) & 0xffffff);
0810       gmtrr.setBCERR(((*p) >> 24) & 0xff);
0811       p++;
0812 
0813       gmtrr.setBxNr((*p) & 0xfff);
0814       if (((*p) >> 15) & 1) {
0815         gmtrr.setBxInEvent((((*p) >> 12) & 7) - 8);
0816       } else {
0817         gmtrr.setBxInEvent((((*p) >> 12) & 7));
0818       }
0819       // to do: check here the block length and the board id
0820       p++;
0821 
0822       for (int im = 0; im < 16; im++) {
0823         // flip the pt and quality bits -- this should better be done by GMT input chips
0824         unsigned waux = *p++;
0825         waux = (waux & 0xffff00ff) | ((~waux) & 0x0000ff00);
0826         L1MuRegionalCand cand(waux, iBxInEvent);
0827         // fix the type assignment (csc=2, rpcb=1) -- should be done by GMT input chips
0828         if (im >= 4 && im < 8)
0829           cand.setType(1);
0830         if (im >= 8 && im < 12)
0831           cand.setType(2);
0832         cand.setPhiValue(m_TriggerScales->getPhiScale()->getLowEdge(cand.phi_packed()));
0833         cand.setEtaValue(m_TriggerScales->getRegionalEtaScale(cand.type_idx())->getCenter(cand.eta_packed()));
0834         cand.setPtValue(m_TriggerPtScale->getPtScale()->getLowEdge(cand.pt_packed()));
0835         gmtrr.setInputCand(im, cand);
0836         if (!cand.empty()) {
0837           if (im < 4)
0838             DTCands->push_back(cand);
0839           if (im >= 4 && im < 8)
0840             RPCbCands->push_back(cand);
0841           if (im >= 8 && im < 12)
0842             CSCCands->push_back(cand);
0843           if (im >= 12)
0844             RPCfCands->push_back(cand);
0845         }
0846       }
0847 
0848       unsigned char* prank = (unsigned char*)(p + 12);
0849 
0850       for (int im = 0; im < 12; im++) {
0851         unsigned waux = *p++;
0852         unsigned raux = im < 8 ? *prank++ : 0;  // only fwd and brl cands have valid rank
0853         L1MuGMTExtendedCand cand(waux, raux, iBxInEvent);
0854         cand.setPhiValue(m_TriggerScales->getPhiScale()->getLowEdge(cand.phiIndex()));
0855         cand.setEtaValue(m_TriggerScales->getGMTEtaScale()->getCenter(cand.etaIndex()));
0856         cand.setPtValue(m_TriggerPtScale->getPtScale()->getLowEdge(cand.ptIndex()));
0857         if (im < 4)
0858           gmtrr.setGMTBrlCand(im, cand);
0859         else if (im < 8)
0860           gmtrr.setGMTFwdCand(im - 4, cand);
0861         else {
0862           gmtrr.setGMTCand(im - 8, cand);
0863           if (!cand.empty())
0864             GMTCands->push_back(cand);
0865         }
0866       }
0867 
0868       // skip the two sort rank words and two chip BX words
0869       p += 4;
0870 
0871       gmtrc->addRecord(gmtrr);
0872 
0873     } else {
0874       // increase the pointer with the GMT record size
0875       p += gmtRecordSize32;
0876     }
0877 
0878     // increase the BxInEvent number
0879     iBxInEvent++;
0880   }
0881 
0882   iEvent.put(std::move(DTCands), "DT");
0883   iEvent.put(std::move(CSCCands), "CSC");
0884   iEvent.put(std::move(RPCbCands), "RPCb");
0885   iEvent.put(std::move(RPCfCands), "RPCf");
0886   iEvent.put(std::move(GMTCands));
0887 }
0888 
0889 // unpack trailer word
0890 // trPtr pointer to the beginning of trailer obtained from gtPtr
0891 void L1GlobalTriggerRawToDigi::unpackTrailer(const unsigned char* trlPtr, FEDTrailer& cmsTrailer) {
0892   // TODO  if needed in another format
0893 
0894   // print the trailer info
0895   if (m_verbosity && m_isDebugEnabled) {
0896     const cms_uint64_t* payload = reinterpret_cast<cms_uint64_t*>(const_cast<unsigned char*>(trlPtr));
0897 
0898     std::ostringstream myCoutStream;
0899 
0900     // one word only
0901     int iWord = 0;
0902 
0903     myCoutStream << std::setw(4) << iWord << "  " << std::hex << std::setfill('0') << std::setw(16) << payload[iWord]
0904                  << std::dec << std::setfill(' ') << "\n"
0905                  << std::endl;
0906 
0907     myCoutStream << "  Event_length:  " << std::hex << " hex: "
0908                  << "" << std::setw(6) << std::setfill('0') << cmsTrailer.fragmentLength() << std::setfill(' ')
0909                  << std::dec << " dec: " << cmsTrailer.fragmentLength() << std::endl;
0910 
0911     myCoutStream << "  CRC:           " << std::hex << " hex: "
0912                  << "  " << std::setw(4) << std::setfill('0') << cmsTrailer.crc() << std::setfill(' ') << std::dec
0913                  << " dec: " << cmsTrailer.crc() << std::endl;
0914 
0915     myCoutStream << "  Event_status:  " << std::hex << " hex: "
0916                  << "    " << std::setw(2) << std::setfill('0') << cmsTrailer.evtStatus() << std::setfill(' ')
0917                  << std::dec << " dec: " << cmsTrailer.evtStatus() << std::endl;
0918 
0919     myCoutStream << "  TTS_bits:      " << std::hex << " hex: "
0920                  << "     " << std::setw(1) << std::setfill('0') << cmsTrailer.ttsBits() << std::setfill(' ')
0921                  << std::dec << " dec: " << cmsTrailer.ttsBits() << std::endl;
0922 
0923     myCoutStream << "  More trailers: " << std::hex << " hex: "
0924                  << "     " << std::setw(1) << std::setfill('0') << cmsTrailer.moreTrailers() << std::setfill(' ')
0925                  << std::dec << " dec: " << cmsTrailer.moreTrailers() << std::endl;
0926 
0927     LogDebug("L1GlobalTriggerRawToDigi") << "\n CMS Trailer \n" << myCoutStream.str() << "\n" << std::endl;
0928   }
0929 }
0930 
0931 // produce empty products in case of problems
0932 void L1GlobalTriggerRawToDigi::produceEmptyProducts(edm::Event& iEvent) {
0933   std::unique_ptr<L1GlobalTriggerReadoutRecord> gtReadoutRecord(new L1GlobalTriggerReadoutRecord());
0934 
0935   std::unique_ptr<L1MuGMTReadoutCollection> gmtrc(new L1MuGMTReadoutCollection());
0936 
0937   std::unique_ptr<std::vector<L1MuRegionalCand> > DTCands(new std::vector<L1MuRegionalCand>);
0938   std::unique_ptr<std::vector<L1MuRegionalCand> > CSCCands(new std::vector<L1MuRegionalCand>);
0939   std::unique_ptr<std::vector<L1MuRegionalCand> > RPCbCands(new std::vector<L1MuRegionalCand>);
0940   std::unique_ptr<std::vector<L1MuRegionalCand> > RPCfCands(new std::vector<L1MuRegionalCand>);
0941   std::unique_ptr<std::vector<L1MuGMTCand> > GMTCands(new std::vector<L1MuGMTCand>);
0942 
0943   // put empty records into event
0944 
0945   iEvent.put(std::move(gmtrc));
0946   iEvent.put(std::move(gtReadoutRecord));
0947 
0948   iEvent.put(std::move(DTCands), "DT");
0949   iEvent.put(std::move(CSCCands), "CSC");
0950   iEvent.put(std::move(RPCbCands), "RPCb");
0951   iEvent.put(std::move(RPCfCands), "RPCf");
0952   iEvent.put(std::move(GMTCands));
0953 }
0954 
0955 // dump FED raw data
0956 void L1GlobalTriggerRawToDigi::dumpFedRawData(const unsigned char* gtPtr, int gtSize, std::ostream& myCout) {
0957   LogDebug("L1GlobalTriggerRawToDigi") << "\nDump FED raw data.\n" << std::endl;
0958 
0959   int wLength = L1GlobalTriggerReadoutSetup::WordLength;
0960   int uLength = L1GlobalTriggerReadoutSetup::UnitLength;
0961 
0962   int gtWords = gtSize / uLength;
0963   LogTrace("L1GlobalTriggerRawToDigi") << "\nFED GT words (" << wLength << " bits):" << gtWords << "\n" << std::endl;
0964 
0965   const cms_uint64_t* payload = reinterpret_cast<cms_uint64_t*>(const_cast<unsigned char*>(gtPtr));
0966 
0967   for (unsigned int i = 0; i < gtSize / sizeof(cms_uint64_t); i++) {
0968     myCout << std::setw(4) << i << "  " << std::hex << std::setfill('0') << std::setw(16) << payload[i] << std::dec
0969            << std::setfill(' ') << std::endl;
0970   }
0971 }
0972 
0973 // static class members