Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 13:15:07

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 numberGtfeBoards = 0;
0345   int numberFdlBoards = 0;
0346   int numberPsbBoards = 0;
0347   int numberGmtBoards = 0;
0348   int numberTcsBoards = 0;
0349   int numberTimBoards = 0;
0350 
0351   for (CItBoardMaps itBoard = boardMaps.begin(); itBoard != boardMaps.end(); ++itBoard) {
0352     int iActiveBit = itBoard->gtBitDaqActiveBoards();
0353     bool activeBoardToUnpack = false;
0354 
0355     if (iActiveBit >= 0) {
0356       activeBoardToUnpack = activeBoardsGt & (1 << iActiveBit);
0357     } else {
0358       // board not in the ActiveBoards for the record
0359       continue;
0360     }
0361 
0362     if (activeBoardToUnpack) {
0363       switch (itBoard->gtBoardType()) {
0364         case GTFE: {
0365           numberGtfeBoards++;
0366         }
0367 
0368         break;
0369         case FDL: {
0370           numberFdlBoards++;
0371         }
0372 
0373         break;
0374         case PSB: {
0375           numberPsbBoards++;
0376         }
0377 
0378         break;
0379         case GMT: {
0380           numberGmtBoards++;
0381         }
0382 
0383         break;
0384         case TCS: {
0385           numberTcsBoards++;
0386         }
0387 
0388         break;
0389         case TIM: {
0390           numberTimBoards++;
0391         }
0392 
0393         break;
0394         default: {
0395           // do nothing, all blocks are given in GtBoardType enum
0396           if (m_verbosity) {
0397             LogDebug("L1GlobalTriggerRawToDigi")
0398                 << "\nBoard of type " << itBoard->gtBoardType() << " not expected  in record.\n"
0399                 << std::endl;
0400           }
0401         }
0402 
0403         break;
0404       }
0405     }
0406   }
0407 
0408   // produce the L1GlobalTriggerReadoutRecord now, after we found the maximum number of
0409   // BxInEvent the record has and how many boards are active (it is just reserving space
0410   // for vectors)
0411   //LogDebug("L1GlobalTriggerRawToDigi")
0412   //<< "\nL1GlobalTriggerRawToDigi: producing L1GlobalTriggerReadoutRecord\n"
0413   //<< "\nL1GlobalTriggerRawToDigi: producing L1MuGMTReadoutCollection;\n"
0414   //<< std::endl;
0415 
0416   // get number of Bx in the event from GTFE block corresponding to alternative 0 and 1 in
0417   m_recordLength0 = m_gtfeWord->recordLength();
0418   m_recordLength1 = m_gtfeWord->recordLength1();
0419 
0420   int maxBxInEvent = std::max(m_recordLength0, m_recordLength1);
0421 
0422   std::unique_ptr<L1GlobalTriggerReadoutRecord> gtReadoutRecord(
0423       new L1GlobalTriggerReadoutRecord(maxBxInEvent, numberFdlBoards, numberPsbBoards));
0424 
0425   // produce also the GMT readout collection and set the reference in GT record
0426   std::unique_ptr<L1MuGMTReadoutCollection> gmtrc(new L1MuGMTReadoutCollection(maxBxInEvent));
0427 
0428   //edm::RefProd<L1MuGMTReadoutCollection> refProdMuGMT = iEvent.getRefBeforePut<
0429   //        L1MuGMTReadoutCollection> ();
0430 
0431   //if (m_verbosity) {
0432   //    LogDebug("L1GlobalTriggerRawToDigi")
0433   //            << "\nL1GlobalTriggerRawToDigi: set L1MuGMTReadoutCollection RefProd"
0434   //            << " in L1GlobalTriggerReadoutRecord.\n" << std::endl;
0435   //}
0436   //gtReadoutRecord->setMuCollectionRefProd(refProdMuGMT);
0437 
0438   // ... then unpack modules other than GTFE, if requested
0439 
0440   for (CItBoardMaps itBoard = gtRecordMap.begin(); itBoard != gtRecordMap.end(); ++itBoard) {
0441     int iActiveBit = itBoard->gtBitDaqActiveBoards();
0442 
0443     bool activeBoardToUnpack = false;
0444     bool activeBoardInitial = false;
0445 
0446     int altNrBxBoardVal = -1;
0447 
0448     if (iActiveBit >= 0) {
0449       activeBoardInitial = activeBoardsGtInitial & (1 << iActiveBit);
0450       activeBoardToUnpack = activeBoardsGt & (1 << iActiveBit);
0451 
0452       altNrBxBoardVal = (altNrBxBoardInitial & (1 << iActiveBit)) >> iActiveBit;
0453 
0454       if (altNrBxBoardVal == 1) {
0455         m_totalBxInEvent = m_recordLength1;
0456       } else if (altNrBxBoardVal == 0) {
0457         m_totalBxInEvent = m_recordLength0;
0458       } else {
0459         if (m_verbosity) {
0460           edm::LogWarning("L1GlobalTriggerRawToDigi")
0461               << "\n\nWARNING: Wrong value altNrBxBoardVal = " << altNrBxBoardVal << " for board " << std::hex
0462               << (itBoard->gtBoardId()) << std::dec << "\n  iActiveBit =            " << iActiveBit
0463               << "\n  altNrBxBoardInitial = 0x" << std::hex << altNrBxBoardInitial << std::dec
0464               << "\n  activeBoardsGt =      0x" << std::hex << activeBoardsGt << std::dec
0465               << "\n  activeBoardInitial =    " << activeBoardInitial
0466               << "\n  activeBoardToUnpack =   " << activeBoardToUnpack << "\n Set altNrBxBoardVal tentatively to "
0467               << m_recordLength0 << "\n Job may crash or produce wrong results!\n\n"
0468               << std::endl;
0469         }
0470 
0471         m_totalBxInEvent = m_recordLength0;
0472       }
0473 
0474       // number of BX required to be unpacked
0475 
0476       if (m_unpackBxInEvent > m_totalBxInEvent) {
0477         if (m_verbosity) {
0478           LogDebug("L1GlobalTriggerRawToDigi")
0479               << "\nWARNING: Number of available bunch crosses for board" << (itBoard->gtBoardId())
0480               << " in the record ( " << m_totalBxInEvent
0481               << " ) \n is smaller than the number of bunch crosses requested to be unpacked (" << m_unpackBxInEvent
0482               << " )!!! \n         Unpacking only " << m_totalBxInEvent << " bunch crosses.\n"
0483               << std::endl;
0484         }
0485 
0486         m_lowSkipBxInEvent = 0;
0487         m_uppSkipBxInEvent = m_totalBxInEvent;
0488 
0489       } else if (m_unpackBxInEvent < 0) {
0490         m_lowSkipBxInEvent = 0;
0491         m_uppSkipBxInEvent = m_totalBxInEvent;
0492 
0493         if (m_verbosity) {
0494           LogDebug("L1GlobalTriggerRawToDigi") << "\nUnpacking all " << m_totalBxInEvent << " bunch crosses available."
0495                                                << "\n"
0496                                                << std::endl;
0497         }
0498 
0499       } else if (m_unpackBxInEvent == 0) {
0500         m_lowSkipBxInEvent = m_totalBxInEvent;
0501         m_uppSkipBxInEvent = m_totalBxInEvent;
0502 
0503         if (m_verbosity) {
0504           LogDebug("L1GlobalTriggerRawToDigi")
0505               << "\nNo bxInEvent required to be unpacked from " << 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       } else {
0516         m_lowSkipBxInEvent = (m_totalBxInEvent - m_unpackBxInEvent) / 2;
0517         m_uppSkipBxInEvent = m_totalBxInEvent - m_lowSkipBxInEvent;
0518 
0519         if (m_verbosity) {
0520           LogDebug("L1GlobalTriggerRawToDigi") << "\nUnpacking " << m_unpackBxInEvent << " bunch crosses from "
0521                                                << m_totalBxInEvent << " bunch crosses available."
0522                                                << "\n"
0523                                                << std::endl;
0524         }
0525 
0526         // change RecordLength
0527         // cast int to cms_uint16_t (there are normally 3 or 5 BxInEvent)
0528         m_gtfeWord->setRecordLength(static_cast<cms_uint16_t>(m_unpackBxInEvent));
0529         m_gtfeWord->setRecordLength1(static_cast<cms_uint16_t>(m_unpackBxInEvent));
0530       }
0531 
0532     } else {
0533       // board not in the ActiveBoards for the record
0534       continue;
0535     }
0536 
0537     if (!activeBoardInitial) {
0538       if (m_verbosity) {
0539         LogDebug("L1GlobalTriggerRawToDigi") << "\nBoard of type " << itBoard->gtBoardName() << " with index "
0540                                              << itBoard->gtBoardIndex() << " not active initially in raw data.\n"
0541                                              << std::endl;
0542       }
0543       continue;
0544     }
0545 
0546     // active board initially, could unpack it
0547     switch (itBoard->gtBoardType()) {
0548       case FDL: {
0549         for (int iFdl = 0; iFdl < m_totalBxInEvent; ++iFdl) {
0550           // if pointer after FDL payload is greater than pointer at
0551           // the end of GT payload, produce empty products and quit unpacking
0552           if ((ptrGt + m_gtFdlWord->getSize()) > endPtrGt) {
0553             edm::LogError("L1GlobalTriggerRawToDigi")
0554                 << "\nError: Pointer after FDL " << iFdl << " greater than end pointer."
0555                 << "\n Put empty products in the event!"
0556                 << "\n Quit unpacking this event." << std::endl;
0557 
0558             produceEmptyProducts(iEvent);
0559 
0560             return;
0561           }
0562 
0563           // unpack only if requested, otherwise skip it
0564           if (activeBoardToUnpack) {
0565             // unpack only bxInEvent requested, otherwise skip it
0566             if ((iFdl >= m_lowSkipBxInEvent) && (iFdl < m_uppSkipBxInEvent)) {
0567               m_gtFdlWord->unpack(ptrGt);
0568 
0569               // add 1 to the GT luminosity number to use the same convention as
0570               // offline, where LS number starts with 1;
0571               // in GT hardware, LS starts with 0
0572               cms_uint16_t lsNr = m_gtFdlWord->lumiSegmentNr() + 1;
0573               m_gtFdlWord->setLumiSegmentNr(lsNr);
0574 
0575               // add FDL block to GT readout record
0576               gtReadoutRecord->setGtFdlWord(*m_gtFdlWord);
0577 
0578               if (m_verbosity && m_isDebugEnabled) {
0579                 std::ostringstream myCoutStream;
0580                 m_gtFdlWord->print(myCoutStream);
0581                 LogTrace("L1GlobalTriggerRawToDigi") << myCoutStream.str() << "\n" << std::endl;
0582               }
0583 
0584               // ... and reset it
0585               m_gtFdlWord->reset();
0586             }
0587           }
0588 
0589           ptrGt += m_gtFdlWord->getSize();  // advance with FDL block size
0590         }
0591       }
0592 
0593       break;
0594       case PSB: {
0595         for (int iPsb = 0; iPsb < m_totalBxInEvent; ++iPsb) {
0596           // if pointer after PSB payload is greater than pointer at
0597           // the end of GT payload, produce empty products and quit unpacking
0598           if ((ptrGt + m_gtPsbWord->getSize()) > endPtrGt) {
0599             edm::LogError("L1GlobalTriggerRawToDigi")
0600                 << "\nError: Pointer after PSB " << iPsb << " greater than end pointer."
0601                 << "\n Put empty products in the event!"
0602                 << "\n Quit unpacking this event." << std::endl;
0603 
0604             produceEmptyProducts(iEvent);
0605 
0606             return;
0607           }
0608 
0609           // unpack only if requested, otherwise skip it
0610           if (activeBoardToUnpack) {
0611             // unpack only bxInEvent requested, otherwise skip it
0612             if ((iPsb >= m_lowSkipBxInEvent) && (iPsb < m_uppSkipBxInEvent)) {
0613               unpackPSB(evSetup, ptrGt, *m_gtPsbWord);
0614 
0615               // add PSB block to GT readout record
0616               gtReadoutRecord->setGtPsbWord(*m_gtPsbWord);
0617 
0618               if (m_verbosity && m_isDebugEnabled) {
0619                 std::ostringstream myCoutStream;
0620                 m_gtPsbWord->print(myCoutStream);
0621                 LogTrace("L1GlobalTriggerRawToDigi") << myCoutStream.str() << "\n" << std::endl;
0622               }
0623 
0624               // ... and reset it
0625               m_gtPsbWord->reset();
0626             }
0627           }
0628 
0629           ptrGt += m_gtPsbWord->getSize();  // advance with PSB block size
0630         }
0631       } break;
0632       case GMT: {
0633         // 17*64/8 TODO FIXME ask Ivan for a getSize() function for GMT record
0634         unsigned int gmtRecordSize = 136;
0635         unsigned int gmtCollSize = m_totalBxInEvent * gmtRecordSize;
0636 
0637         // if pointer after GMT payload is greater than pointer at
0638         // the end of GT payload, produce empty products and quit unpacking
0639         if ((ptrGt + gmtCollSize) > endPtrGt) {
0640           edm::LogError("L1GlobalTriggerRawToDigi") << "\nError: Pointer after GMT "
0641                                                     << " greater than end pointer."
0642                                                     << "\n Put empty products in the event!"
0643                                                     << "\n Quit unpacking this event." << std::endl;
0644 
0645           produceEmptyProducts(iEvent);
0646 
0647           return;
0648         }
0649 
0650         // unpack only if requested, otherwise skip it
0651         if (activeBoardToUnpack) {
0652           unpackGMT(ptrGt, gmtrc, iEvent);
0653         }
0654 
0655         ptrGt += gmtCollSize;  // advance with GMT block size
0656       } break;
0657       default: {
0658         // do nothing, all blocks are given in GtBoardType enum
0659         if (m_verbosity) {
0660           LogDebug("L1GlobalTriggerRawToDigi")
0661               << "\nBoard of type " << itBoard->gtBoardType() << " not expected  in record.\n"
0662               << std::endl;
0663         }
0664       } break;
0665     }
0666   }
0667 
0668   // add GTFE block to GT readout record, after updating active boards and record length
0669 
0670   gtReadoutRecord->setGtfeWord(*m_gtfeWord);
0671 
0672   // ... and reset it
0673   m_gtfeWord->reset();
0674 
0675   // unpack trailer
0676 
0677   int trailerSize = 8;
0678 
0679   // if pointer after trailer is greater than pointer at
0680   // the end of GT payload, produce empty products and quit unpacking
0681   if ((ptrGt + trailerSize) > endPtrGt) {
0682     edm::LogError("L1GlobalTriggerRawToDigi") << "\nError: Pointer after trailer "
0683                                               << " greater than end pointer."
0684                                               << "\n Put empty products in the event!"
0685                                               << "\n Quit unpacking this event." << std::endl;
0686 
0687     produceEmptyProducts(iEvent);
0688 
0689     return;
0690   }
0691 
0692   unpackTrailer(ptrGt, cmsTrailer);
0693 
0694   //
0695   if (m_verbosity && m_isDebugEnabled) {
0696     std::ostringstream myCoutStream;
0697     gtReadoutRecord->print(myCoutStream);
0698     LogTrace("L1GlobalTriggerRawToDigi") << "\n The following L1 GT DAQ readout record was unpacked.\n"
0699                                          << myCoutStream.str() << "\n"
0700                                          << std::endl;
0701   }
0702 
0703   // put records into event
0704 
0705   iEvent.put(std::move(gmtrc));
0706   iEvent.put(std::move(gtReadoutRecord));
0707 }
0708 
0709 // unpack header
0710 void L1GlobalTriggerRawToDigi::unpackHeader(const unsigned char* gtPtr, FEDHeader& cmsHeader) {
0711   // TODO  if needed in another format
0712 
0713   // print the header info
0714   if (m_verbosity && m_isDebugEnabled) {
0715     const cms_uint64_t* payload = reinterpret_cast<cms_uint64_t*>(const_cast<unsigned char*>(gtPtr));
0716 
0717     std::ostringstream myCoutStream;
0718 
0719     // one word only
0720     int iWord = 0;
0721 
0722     myCoutStream << std::setw(4) << iWord << "  " << std::hex << std::setfill('0') << std::setw(16) << payload[iWord]
0723                  << std::dec << std::setfill(' ') << "\n"
0724                  << std::endl;
0725 
0726     myCoutStream << "  Event_type:  " << std::hex << " hex: "
0727                  << "     " << std::setw(1) << std::setfill('0') << cmsHeader.triggerType() << std::setfill(' ')
0728                  << std::dec << " dec: " << cmsHeader.triggerType() << std::endl;
0729 
0730     myCoutStream << "  LVL1_Id:     " << std::hex << " hex: "
0731                  << "" << std::setw(6) << std::setfill('0') << cmsHeader.lvl1ID() << std::setfill(' ') << std::dec
0732                  << " dec: " << cmsHeader.lvl1ID() << std::endl;
0733 
0734     myCoutStream << "  BX_Id:       " << std::hex << " hex: "
0735                  << "   " << std::setw(3) << std::setfill('0') << cmsHeader.bxID() << std::setfill(' ') << std::dec
0736                  << " dec: " << cmsHeader.bxID() << std::endl;
0737 
0738     myCoutStream << "  Source_Id:   " << std::hex << " hex: "
0739                  << "   " << std::setw(3) << std::setfill('0') << cmsHeader.sourceID() << std::setfill(' ') << std::dec
0740                  << " dec: " << cmsHeader.sourceID() << std::endl;
0741 
0742     myCoutStream << "  FOV:         " << std::hex << " hex: "
0743                  << "     " << std::setw(1) << std::setfill('0') << cmsHeader.version() << std::setfill(' ') << std::dec
0744                  << " dec: " << cmsHeader.version() << std::endl;
0745 
0746     myCoutStream << "  H:           " << std::hex << " hex: "
0747                  << "     " << std::setw(1) << std::setfill('0') << cmsHeader.moreHeaders() << std::setfill(' ')
0748                  << std::dec << " dec: " << cmsHeader.moreHeaders() << std::endl;
0749 
0750     LogDebug("L1GlobalTriggerRawToDigi") << "\n CMS Header \n" << myCoutStream.str() << "\n" << std::endl;
0751   }
0752 }
0753 
0754 // unpack PSB records
0755 // psbPtr pointer to the beginning of the each PSB block obtained from gtPtr
0756 void L1GlobalTriggerRawToDigi::unpackPSB(const edm::EventSetup& evSetup,
0757                                          const unsigned char* psbPtr,
0758                                          L1GtPsbWord& psbWord) {
0759   //LogDebug("L1GlobalTriggerRawToDigi")
0760   //<< "\nUnpacking PSB block.\n"
0761   //<< std::endl;
0762 
0763   int uLength = L1GlobalTriggerReadoutSetup::UnitLength;
0764 
0765   int psbSize = psbWord.getSize();
0766   int psbWords = psbSize / uLength;
0767 
0768   const cms_uint64_t* payload = reinterpret_cast<cms_uint64_t*>(const_cast<unsigned char*>(psbPtr));
0769 
0770   for (int iWord = 0; iWord < psbWords; ++iWord) {
0771     // fill PSB
0772     // the second argument must match the word index defined in L1GtPsbWord class
0773 
0774     psbWord.setBoardId(payload[iWord], iWord);
0775     psbWord.setBxInEvent(payload[iWord], iWord);
0776     psbWord.setBxNr(payload[iWord], iWord);
0777     psbWord.setEventNr(payload[iWord], iWord);
0778 
0779     psbWord.setAData(payload[iWord], iWord);
0780     psbWord.setBData(payload[iWord], iWord);
0781 
0782     psbWord.setLocalBxNr(payload[iWord], iWord);
0783 
0784     LogTrace("L1GlobalTriggerRawToDigi") << std::setw(4) << iWord << "  " << std::hex << std::setfill('0')
0785                                          << std::setw(16) << payload[iWord] << std::dec << std::setfill(' ')
0786                                          << std::endl;
0787   }
0788 }
0789 
0790 // unpack the GMT record
0791 void L1GlobalTriggerRawToDigi::unpackGMT(const unsigned char* chp,
0792                                          std::unique_ptr<L1MuGMTReadoutCollection>& gmtrc,
0793                                          edm::Event& iEvent) {
0794   //LogDebug("L1GlobalTriggerRawToDigi")
0795   //<< "\nUnpacking GMT collection.\n"
0796   //<< std::endl;
0797 
0798   // 17*64/2 TODO FIXME ask Ivan for a getSize() function for GMT record
0799   const unsigned int gmtRecordSize32 = 34;
0800 
0801   std::unique_ptr<std::vector<L1MuRegionalCand> > DTCands(new std::vector<L1MuRegionalCand>);
0802   std::unique_ptr<std::vector<L1MuRegionalCand> > CSCCands(new std::vector<L1MuRegionalCand>);
0803   std::unique_ptr<std::vector<L1MuRegionalCand> > RPCbCands(new std::vector<L1MuRegionalCand>);
0804   std::unique_ptr<std::vector<L1MuRegionalCand> > RPCfCands(new std::vector<L1MuRegionalCand>);
0805   std::unique_ptr<std::vector<L1MuGMTCand> > GMTCands(new std::vector<L1MuGMTCand>);
0806 
0807   const unsigned* p = (const unsigned*)chp;
0808 
0809   // min Bx's in the event, computed after m_totalBxInEvent is obtained from GTFE block
0810   // assume symmetrical number of BX around L1Accept
0811   int iBxInEvent = (m_totalBxInEvent + 1) / 2 - m_totalBxInEvent;
0812 
0813   for (int iGmtRec = 0; iGmtRec < m_totalBxInEvent; ++iGmtRec) {
0814     // unpack only bxInEvent requested, otherwise skip it
0815     if ((iGmtRec >= m_lowSkipBxInEvent) && (iGmtRec < m_uppSkipBxInEvent)) {
0816       // Dump the block
0817       const cms_uint64_t* bp = reinterpret_cast<cms_uint64_t*>(const_cast<unsigned*>(p));
0818       for (int iWord = 0; iWord < 17; iWord++) {
0819         LogTrace("L1GlobalTriggerRawToDigi") << std::setw(4) << iWord << "  " << std::hex << std::setfill('0')
0820                                              << std::setw(16) << *bp++ << std::dec << std::setfill(' ') << std::endl;
0821       }
0822 
0823       L1MuGMTReadoutRecord gmtrr(iBxInEvent);
0824 
0825       gmtrr.setEvNr((*p) & 0xffffff);
0826       gmtrr.setBCERR(((*p) >> 24) & 0xff);
0827       p++;
0828 
0829       gmtrr.setBxNr((*p) & 0xfff);
0830       if (((*p) >> 15) & 1) {
0831         gmtrr.setBxInEvent((((*p) >> 12) & 7) - 8);
0832       } else {
0833         gmtrr.setBxInEvent((((*p) >> 12) & 7));
0834       }
0835       // to do: check here the block length and the board id
0836       p++;
0837 
0838       for (int im = 0; im < 16; im++) {
0839         // flip the pt and quality bits -- this should better be done by GMT input chips
0840         unsigned waux = *p++;
0841         waux = (waux & 0xffff00ff) | ((~waux) & 0x0000ff00);
0842         L1MuRegionalCand cand(waux, iBxInEvent);
0843         // fix the type assignment (csc=2, rpcb=1) -- should be done by GMT input chips
0844         if (im >= 4 && im < 8)
0845           cand.setType(1);
0846         if (im >= 8 && im < 12)
0847           cand.setType(2);
0848         cand.setPhiValue(m_TriggerScales->getPhiScale()->getLowEdge(cand.phi_packed()));
0849         cand.setEtaValue(m_TriggerScales->getRegionalEtaScale(cand.type_idx())->getCenter(cand.eta_packed()));
0850         cand.setPtValue(m_TriggerPtScale->getPtScale()->getLowEdge(cand.pt_packed()));
0851         gmtrr.setInputCand(im, cand);
0852         if (!cand.empty()) {
0853           if (im < 4)
0854             DTCands->push_back(cand);
0855           if (im >= 4 && im < 8)
0856             RPCbCands->push_back(cand);
0857           if (im >= 8 && im < 12)
0858             CSCCands->push_back(cand);
0859           if (im >= 12)
0860             RPCfCands->push_back(cand);
0861         }
0862       }
0863 
0864       unsigned char* prank = (unsigned char*)(p + 12);
0865 
0866       for (int im = 0; im < 12; im++) {
0867         unsigned waux = *p++;
0868         unsigned raux = im < 8 ? *prank++ : 0;  // only fwd and brl cands have valid rank
0869         L1MuGMTExtendedCand cand(waux, raux, iBxInEvent);
0870         cand.setPhiValue(m_TriggerScales->getPhiScale()->getLowEdge(cand.phiIndex()));
0871         cand.setEtaValue(m_TriggerScales->getGMTEtaScale()->getCenter(cand.etaIndex()));
0872         cand.setPtValue(m_TriggerPtScale->getPtScale()->getLowEdge(cand.ptIndex()));
0873         if (im < 4)
0874           gmtrr.setGMTBrlCand(im, cand);
0875         else if (im < 8)
0876           gmtrr.setGMTFwdCand(im - 4, cand);
0877         else {
0878           gmtrr.setGMTCand(im - 8, cand);
0879           if (!cand.empty())
0880             GMTCands->push_back(cand);
0881         }
0882       }
0883 
0884       // skip the two sort rank words and two chip BX words
0885       p += 4;
0886 
0887       gmtrc->addRecord(gmtrr);
0888 
0889     } else {
0890       // increase the pointer with the GMT record size
0891       p += gmtRecordSize32;
0892     }
0893 
0894     // increase the BxInEvent number
0895     iBxInEvent++;
0896   }
0897 
0898   iEvent.put(std::move(DTCands), "DT");
0899   iEvent.put(std::move(CSCCands), "CSC");
0900   iEvent.put(std::move(RPCbCands), "RPCb");
0901   iEvent.put(std::move(RPCfCands), "RPCf");
0902   iEvent.put(std::move(GMTCands));
0903 }
0904 
0905 // unpack trailer word
0906 // trPtr pointer to the beginning of trailer obtained from gtPtr
0907 void L1GlobalTriggerRawToDigi::unpackTrailer(const unsigned char* trlPtr, FEDTrailer& cmsTrailer) {
0908   // TODO  if needed in another format
0909 
0910   // print the trailer info
0911   if (m_verbosity && m_isDebugEnabled) {
0912     const cms_uint64_t* payload = reinterpret_cast<cms_uint64_t*>(const_cast<unsigned char*>(trlPtr));
0913 
0914     std::ostringstream myCoutStream;
0915 
0916     // one word only
0917     int iWord = 0;
0918 
0919     myCoutStream << std::setw(4) << iWord << "  " << std::hex << std::setfill('0') << std::setw(16) << payload[iWord]
0920                  << std::dec << std::setfill(' ') << "\n"
0921                  << std::endl;
0922 
0923     myCoutStream << "  Event_length:  " << std::hex << " hex: "
0924                  << "" << std::setw(6) << std::setfill('0') << cmsTrailer.fragmentLength() << std::setfill(' ')
0925                  << std::dec << " dec: " << cmsTrailer.fragmentLength() << std::endl;
0926 
0927     myCoutStream << "  CRC:           " << std::hex << " hex: "
0928                  << "  " << std::setw(4) << std::setfill('0') << cmsTrailer.crc() << std::setfill(' ') << std::dec
0929                  << " dec: " << cmsTrailer.crc() << std::endl;
0930 
0931     myCoutStream << "  Event_status:  " << std::hex << " hex: "
0932                  << "    " << std::setw(2) << std::setfill('0') << cmsTrailer.evtStatus() << std::setfill(' ')
0933                  << std::dec << " dec: " << cmsTrailer.evtStatus() << std::endl;
0934 
0935     myCoutStream << "  TTS_bits:      " << std::hex << " hex: "
0936                  << "     " << std::setw(1) << std::setfill('0') << cmsTrailer.ttsBits() << std::setfill(' ')
0937                  << std::dec << " dec: " << cmsTrailer.ttsBits() << std::endl;
0938 
0939     myCoutStream << "  More trailers: " << std::hex << " hex: "
0940                  << "     " << std::setw(1) << std::setfill('0') << cmsTrailer.moreTrailers() << std::setfill(' ')
0941                  << std::dec << " dec: " << cmsTrailer.moreTrailers() << std::endl;
0942 
0943     LogDebug("L1GlobalTriggerRawToDigi") << "\n CMS Trailer \n" << myCoutStream.str() << "\n" << std::endl;
0944   }
0945 }
0946 
0947 // produce empty products in case of problems
0948 void L1GlobalTriggerRawToDigi::produceEmptyProducts(edm::Event& iEvent) {
0949   std::unique_ptr<L1GlobalTriggerReadoutRecord> gtReadoutRecord(new L1GlobalTriggerReadoutRecord());
0950 
0951   std::unique_ptr<L1MuGMTReadoutCollection> gmtrc(new L1MuGMTReadoutCollection());
0952 
0953   std::unique_ptr<std::vector<L1MuRegionalCand> > DTCands(new std::vector<L1MuRegionalCand>);
0954   std::unique_ptr<std::vector<L1MuRegionalCand> > CSCCands(new std::vector<L1MuRegionalCand>);
0955   std::unique_ptr<std::vector<L1MuRegionalCand> > RPCbCands(new std::vector<L1MuRegionalCand>);
0956   std::unique_ptr<std::vector<L1MuRegionalCand> > RPCfCands(new std::vector<L1MuRegionalCand>);
0957   std::unique_ptr<std::vector<L1MuGMTCand> > GMTCands(new std::vector<L1MuGMTCand>);
0958 
0959   // put empty records into event
0960 
0961   iEvent.put(std::move(gmtrc));
0962   iEvent.put(std::move(gtReadoutRecord));
0963 
0964   iEvent.put(std::move(DTCands), "DT");
0965   iEvent.put(std::move(CSCCands), "CSC");
0966   iEvent.put(std::move(RPCbCands), "RPCb");
0967   iEvent.put(std::move(RPCfCands), "RPCf");
0968   iEvent.put(std::move(GMTCands));
0969 }
0970 
0971 // dump FED raw data
0972 void L1GlobalTriggerRawToDigi::dumpFedRawData(const unsigned char* gtPtr, int gtSize, std::ostream& myCout) {
0973   LogDebug("L1GlobalTriggerRawToDigi") << "\nDump FED raw data.\n" << std::endl;
0974 
0975   int wLength = L1GlobalTriggerReadoutSetup::WordLength;
0976   int uLength = L1GlobalTriggerReadoutSetup::UnitLength;
0977 
0978   int gtWords = gtSize / uLength;
0979   LogTrace("L1GlobalTriggerRawToDigi") << "\nFED GT words (" << wLength << " bits):" << gtWords << "\n" << std::endl;
0980 
0981   const cms_uint64_t* payload = reinterpret_cast<cms_uint64_t*>(const_cast<unsigned char*>(gtPtr));
0982 
0983   for (unsigned int i = 0; i < gtSize / sizeof(cms_uint64_t); i++) {
0984     myCout << std::setw(4) << i << "  " << std::hex << std::setfill('0') << std::setw(16) << payload[i] << std::dec
0985            << std::setfill(' ') << std::endl;
0986   }
0987 }
0988 
0989 // static class members