CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_4_5_patch3/src/EventFilter/L1GlobalTriggerRawToDigi/src/L1GlobaTriggerRawToDigi.cc

Go to the documentation of this file.
00001 
00018 // this class header
00019 #include "EventFilter/L1GlobalTriggerRawToDigi/interface/L1GlobalTriggerRawToDigi.h"
00020 
00021 // system include files
00022 #include <boost/cstdint.hpp>
00023 #include <iostream>
00024 #include <iomanip>
00025 #include <algorithm>
00026 
00027 // user include files
00028 #include "DataFormats/L1GlobalTrigger/interface/L1GlobalTriggerReadoutSetup.h"
00029 #include "DataFormats/L1GlobalTrigger/interface/L1GlobalTriggerReadoutRecord.h"
00030 
00031 #include "DataFormats/FEDRawData/interface/FEDNumbering.h"
00032 #include "DataFormats/FEDRawData/interface/FEDHeader.h"
00033 #include "DataFormats/FEDRawData/interface/FEDTrailer.h"
00034 #include "DataFormats/FEDRawData/interface/FEDRawDataCollection.h"
00035 
00036 #include "DataFormats/L1GlobalTrigger/interface/L1GtfeWord.h"
00037 #include "DataFormats/L1GlobalTrigger/interface/L1GtFdlWord.h"
00038 #include "DataFormats/L1GlobalTrigger/interface/L1GtPsbWord.h"
00039 
00040 #include "DataFormats/L1GlobalMuonTrigger/interface/L1MuRegionalCand.h"
00041 #include "DataFormats/L1GlobalMuonTrigger/interface/L1MuGMTExtendedCand.h"
00042 #include "DataFormats/L1GlobalMuonTrigger/interface/L1MuGMTReadoutCollection.h"
00043 
00044 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00045 #include "FWCore/Utilities/interface/InputTag.h"
00046 
00047 #include "FWCore/Framework/interface/EventSetup.h"
00048 #include "FWCore/Framework/interface/ESHandle.h"
00049 
00050 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00051 #include "FWCore/MessageLogger/interface/MessageDrop.h"
00052 
00053 #include "CondFormats/L1TObjects/interface/L1MuTriggerScales.h"
00054 #include "CondFormats/DataRecord/interface/L1MuTriggerScalesRcd.h"
00055 #include "CondFormats/L1TObjects/interface/L1MuTriggerPtScale.h"
00056 #include "CondFormats/DataRecord/interface/L1MuTriggerPtScaleRcd.h"
00057 
00058 #include "CondFormats/L1TObjects/interface/L1GtFwd.h"
00059 #include "CondFormats/L1TObjects/interface/L1GtBoard.h"
00060 
00061 #include "CondFormats/L1TObjects/interface/L1GtBoardMaps.h"
00062 #include "CondFormats/DataRecord/interface/L1GtBoardMapsRcd.h"
00063 
00064 // constructor(s)
00065 L1GlobalTriggerRawToDigi::L1GlobalTriggerRawToDigi(const edm::ParameterSet& pSet) :
00066 
00067             // input tag for DAQ GT record
00068             m_daqGtInputTag(pSet.getParameter<edm::InputTag> ("DaqGtInputTag")),
00069 
00070             // FED Id for GT DAQ record
00071             // default value defined in DataFormats/FEDRawData/src/FEDNumbering.cc
00072             // default value: assume the DAQ record is the last GT record
00073             m_daqGtFedId(pSet.getUntrackedParameter<int> (
00074                     "DaqGtFedId", FEDNumbering::MAXTriggerGTPFEDID)),
00075 
00076             // mask for active boards
00077             m_activeBoardsMaskGt(pSet.getParameter<unsigned int> ("ActiveBoardsMask")),
00078 
00079             // number of bunch crossing to be unpacked
00080             m_unpackBxInEvent(pSet.getParameter<int> ("UnpackBxInEvent")),
00081 
00082             // create GTFE, FDL, PSB cards once per producer
00083             // content will be reset whenever needed
00084 
00085             m_lowSkipBxInEvent(0), m_uppSkipBxInEvent(0),
00086 
00087             m_recordLength0(0), m_recordLength1(0),
00088 
00089             m_totalBxInEvent(0), m_verbosity(pSet.getUntrackedParameter<int> ("Verbosity", 0)),
00090 
00091             m_isDebugEnabled(edm::isDebugEnabled())
00092 
00093 {
00094 
00095     produces<L1GlobalTriggerReadoutRecord> ();
00096     produces<L1MuGMTReadoutCollection> ();
00097 
00098     produces<std::vector<L1MuRegionalCand> > ("DT");
00099     produces<std::vector<L1MuRegionalCand> > ("CSC");
00100     produces<std::vector<L1MuRegionalCand> > ("RPCb");
00101     produces<std::vector<L1MuRegionalCand> > ("RPCf");
00102     produces<std::vector<L1MuGMTCand> > ();
00103 
00104     // create GTFE, FDL, PSB cards once per producer
00105     // content will be reset whenever needed
00106     m_gtfeWord = new L1GtfeWord();
00107     m_gtFdlWord = new L1GtFdlWord();
00108     m_gtPsbWord = new L1GtPsbWord();
00109 
00110     if (m_verbosity && m_isDebugEnabled) {
00111 
00112         LogDebug("L1GlobalTriggerRawToDigi")
00113                 << "\nInput tag for DAQ GT record:             " << m_daqGtInputTag
00114                 << "\nFED Id for DAQ GT record:                " << m_daqGtFedId
00115                 << "\nMask for active boards (hex format):     " << std::hex
00116                 << std::setw(sizeof(m_activeBoardsMaskGt) * 2) << std::setfill('0')
00117                 << m_activeBoardsMaskGt
00118                 << std::dec << std::setfill(' ')
00119                 << "\nNumber of bunch crossing to be unpacked: "
00120                 << m_unpackBxInEvent << "\n"
00121                 << std::endl;
00122     }
00123 
00124     if ( ( m_unpackBxInEvent > 0 ) && ( ( m_unpackBxInEvent % 2 ) == 0 )) {
00125         m_unpackBxInEvent = m_unpackBxInEvent - 1;
00126 
00127         if (m_verbosity) {
00128             edm::LogInfo("L1GlobalTriggerRawToDigi")
00129                     << "\nWARNING: Number of bunch crossing to be unpacked rounded to: "
00130                     << m_unpackBxInEvent << "\n         The number must be an odd number!\n"
00131                     << std::endl;
00132         }
00133     }
00134 
00135 }
00136 
00137 // destructor
00138 L1GlobalTriggerRawToDigi::~L1GlobalTriggerRawToDigi() {
00139 
00140     delete m_gtfeWord;
00141     delete m_gtFdlWord;
00142     delete m_gtPsbWord;
00143 
00144 }
00145 
00146 // member functions
00147 
00148 void L1GlobalTriggerRawToDigi::beginJob() {
00149     // empty
00150 }
00151 
00152 // method called to produce the data
00153 void L1GlobalTriggerRawToDigi::produce(edm::Event& iEvent, const edm::EventSetup& evSetup) {
00154 
00155     // get records from EventSetup
00156 
00157     //  muon trigger scales
00158     edm::ESHandle<L1MuTriggerScales> trigscales_h;
00159     evSetup.get<L1MuTriggerScalesRcd> ().get(trigscales_h);
00160     m_TriggerScales = trigscales_h.product();
00161 
00162     edm::ESHandle<L1MuTriggerPtScale> trigptscale_h;
00163     evSetup.get<L1MuTriggerPtScaleRcd> ().get(trigptscale_h);
00164     m_TriggerPtScale = trigptscale_h.product();
00165 
00166     //  board maps
00167     edm::ESHandle<L1GtBoardMaps> l1GtBM;
00168     evSetup.get<L1GtBoardMapsRcd> ().get(l1GtBM);
00169 
00170     const std::vector<L1GtBoard> boardMaps = l1GtBM->gtBoardMaps();
00171     int boardMapsSize = boardMaps.size();
00172 
00173     typedef std::vector<L1GtBoard>::const_iterator CItBoardMaps;
00174 
00175     // create an ordered vector for the GT DAQ record
00176     // header (pos 0 in record) and trailer (last position in record)
00177     // not included, as they are not in board list
00178     std::vector<L1GtBoard> gtRecordMap;
00179     gtRecordMap.reserve(boardMapsSize);
00180 
00181     for (int iPos = 0; iPos < boardMapsSize; ++iPos) {
00182         for (CItBoardMaps itBoard = boardMaps.begin(); itBoard != boardMaps.end(); ++itBoard) {
00183 
00184             if (itBoard->gtPositionDaqRecord() == iPos) {
00185                 gtRecordMap.push_back(*itBoard);
00186                 break;
00187             }
00188 
00189         }
00190     }
00191 
00192     // raw collection
00193 
00194     edm::Handle<FEDRawDataCollection> fedHandle;
00195     iEvent.getByLabel(m_daqGtInputTag, fedHandle);
00196 
00197     if (!fedHandle.isValid()) {
00198         if (m_verbosity) {
00199             edm::LogWarning("L1GlobalTriggerRawToDigi")
00200                     << "\nWarning: FEDRawDataCollection with input tag " << m_daqGtInputTag
00201                     << "\nrequested in configuration, but not found in the event."
00202                     << "\nQuit unpacking this event" << std::endl;
00203         }
00204 
00205         produceEmptyProducts(iEvent);
00206 
00207         return;
00208     }
00209 
00210     // retrieve data for Global Trigger FED (GT + GMT)
00211     const FEDRawData& raw = ( fedHandle.product() )->FEDData(m_daqGtFedId);
00212 
00213     int gtSize = raw.size();
00214 
00215     // get a const pointer to the beginning of the data buffer
00216     const unsigned char* ptrGt = raw.data();
00217 
00218     // get a const pointer to the end of the data buffer
00219     const unsigned char* endPtrGt = ptrGt + gtSize;
00220 
00221     //
00222     if (m_verbosity && m_isDebugEnabled) {
00223 
00224         LogTrace("L1GlobalTriggerRawToDigi") << "\n Size of raw data: "
00225                 << gtSize << "\n" << std::endl;
00226 
00227         std::ostringstream myCoutStream;
00228         dumpFedRawData(ptrGt, gtSize, myCoutStream);
00229 
00230         LogTrace("L1GlobalTriggerRawToDigi") << "\n Dump FEDRawData\n"
00231                 << myCoutStream.str() << "\n" << std::endl;
00232 
00233     }
00234 
00235     // unpack header (we have one header only)
00236     int headerSize = 8;
00237 
00238     if ((ptrGt + headerSize) > endPtrGt) {
00239         edm::LogError("L1GlobalTriggerRawToDigi")
00240                 << "\nError: Pointer after header greater than end pointer."
00241                 << "\n Put empty products in the event!"
00242                 << "\n Quit unpacking this event." << std::endl;
00243 
00244         produceEmptyProducts(iEvent);
00245 
00246         return;
00247     }
00248 
00249 
00250     FEDHeader cmsHeader(ptrGt);
00251     FEDTrailer cmsTrailer(ptrGt + gtSize - headerSize);
00252 
00253     unpackHeader(ptrGt, cmsHeader);
00254     ptrGt += headerSize; // advance with header size
00255 
00256     // unpack first GTFE to find the length of the record and the active boards
00257     // here GTFE assumed immediately after the header
00258 
00259     // if pointer after GTFE payload is greater than pointer at
00260     // the end of GT payload, produce empty products and quit unpacking
00261     if ((ptrGt + m_gtfeWord->getSize()) > endPtrGt) {
00262         edm::LogError("L1GlobalTriggerRawToDigi")
00263                 << "\nError: Pointer after GTFE greater than end pointer."
00264                 << "\n Put empty products in the event!"
00265                 << "\n Quit unpacking this event." << std::endl;
00266 
00267         produceEmptyProducts(iEvent);
00268 
00269         return;
00270     }
00271 
00272     bool gtfeUnpacked = false;
00273 
00274     for (CItBoardMaps itBoard = boardMaps.begin(); itBoard != boardMaps.end(); ++itBoard) {
00275 
00276         if (itBoard->gtBoardType() == GTFE) {
00277 
00278             // unpack GTFE
00279             if (itBoard->gtPositionDaqRecord() == 1) {
00280 
00281                 m_gtfeWord->unpack(ptrGt);
00282                 ptrGt += m_gtfeWord->getSize(); // advance with GTFE block size
00283                 gtfeUnpacked = true;
00284 
00285                 if (m_verbosity && m_isDebugEnabled) {
00286 
00287                     std::ostringstream myCoutStream;
00288                     m_gtfeWord->print(myCoutStream);
00289                     LogTrace("L1GlobalTriggerRawToDigi") << myCoutStream.str() << "\n" << std::endl;
00290                 }
00291 
00292                 // break the loop - GTFE was found
00293                 break;
00294 
00295             } else {
00296 
00297                 if (m_verbosity) {
00298                     edm::LogWarning("L1GlobalTriggerRawToDigi")
00299                             << "\nWarning: GTFE block found in raw data does not follow header."
00300                             << "\nAssumed start position of the block is wrong!"
00301                             << "\nQuit unpacking this event" << std::endl;
00302                 }
00303 
00304                 produceEmptyProducts(iEvent);
00305 
00306                 return;
00307             }
00308 
00309         }
00310     }
00311 
00312     // quit if no GTFE found
00313     if (!gtfeUnpacked) {
00314 
00315         if (m_verbosity) {
00316             edm::LogWarning("L1GlobalTriggerRawToDigi")
00317                     << "\nWarning: no GTFE block found in raw data."
00318                     << "\nCan not find the record length (BxInEvent) and the active boards!"
00319                     << "\nQuit unpacking this event" << std::endl;
00320         }
00321 
00322         produceEmptyProducts(iEvent);
00323 
00324         return;
00325     }
00326 
00327     // life normal here, GTFE found
00328 
00329     // get list of active blocks
00330     // blocks not active are not written to the record
00331     boost::uint16_t activeBoardsGtInitial = m_gtfeWord->activeBoards();
00332     boost::uint16_t altNrBxBoardInitial = m_gtfeWord->altNrBxBoard();
00333 
00334     // mask some boards, if needed
00335     boost::uint16_t activeBoardsGt = activeBoardsGtInitial & m_activeBoardsMaskGt;
00336     m_gtfeWord->setActiveBoards(activeBoardsGt);
00337 
00338     if (m_verbosity) {
00339         LogDebug("L1GlobalTriggerRawToDigi") << "\nActive boards before masking: 0x" << std::hex
00340                 << std::setw(sizeof ( activeBoardsGtInitial ) * 2) << std::setfill('0')
00341                 << activeBoardsGtInitial << std::dec << std::setfill(' ')
00342                 << "\nActive boards after masking:  0x" << std::hex << std::setw(
00343                 sizeof ( activeBoardsGt ) * 2) << std::setfill('0') << activeBoardsGt << std::dec
00344                 << std::setfill(' ') << " \n" << std::endl;
00345     }
00346 
00347     // loop over other blocks in the raw record, count them if they are active
00348 
00349     int numberGtfeBoards = 0;
00350     int numberFdlBoards = 0;
00351     int numberPsbBoards = 0;
00352     int numberGmtBoards = 0;
00353     int numberTcsBoards = 0;
00354     int numberTimBoards = 0;
00355 
00356     for (CItBoardMaps itBoard = boardMaps.begin(); itBoard != boardMaps.end(); ++itBoard) {
00357 
00358         int iActiveBit = itBoard->gtBitDaqActiveBoards();
00359         bool activeBoardToUnpack = false;
00360 
00361         if (iActiveBit >= 0) {
00362             activeBoardToUnpack = activeBoardsGt & ( 1 << iActiveBit );
00363         } else {
00364             // board not in the ActiveBoards for the record
00365             continue;
00366         }
00367 
00368         if (activeBoardToUnpack) {
00369 
00370             switch (itBoard->gtBoardType()) {
00371                 case GTFE: {
00372                     numberGtfeBoards++;
00373                 }
00374 
00375                     break;
00376                 case FDL: {
00377                     numberFdlBoards++;
00378                 }
00379 
00380                     break;
00381                 case PSB: {
00382                     numberPsbBoards++;
00383                 }
00384 
00385                     break;
00386                 case GMT: {
00387                     numberGmtBoards++;
00388                 }
00389 
00390                     break;
00391                 case TCS: {
00392                     numberTcsBoards++;
00393                 }
00394 
00395                     break;
00396                 case TIM: {
00397                     numberTimBoards++;
00398                 }
00399 
00400                     break;
00401                 default: {
00402                     // do nothing, all blocks are given in GtBoardType enum
00403                     if (m_verbosity) {
00404                         LogDebug("L1GlobalTriggerRawToDigi") << "\nBoard of type "
00405                                 << itBoard->gtBoardType() << " not expected  in record.\n"
00406                                 << std::endl;
00407                     }
00408                 }
00409 
00410                     break;
00411             }
00412         }
00413 
00414     }
00415 
00416     // produce the L1GlobalTriggerReadoutRecord now, after we found the maximum number of
00417     // BxInEvent the record has and how many boards are active (it is just reserving space
00418     // for vectors)
00419     //LogDebug("L1GlobalTriggerRawToDigi")
00420     //<< "\nL1GlobalTriggerRawToDigi: producing L1GlobalTriggerReadoutRecord\n"
00421     //<< "\nL1GlobalTriggerRawToDigi: producing L1MuGMTReadoutCollection;\n"
00422     //<< std::endl;
00423 
00424     // get number of Bx in the event from GTFE block corresponding to alternative 0 and 1 in
00425     m_recordLength0 = m_gtfeWord->recordLength();
00426     m_recordLength1 = m_gtfeWord->recordLength1();
00427 
00428     int maxBxInEvent = std::max(m_recordLength0, m_recordLength1);
00429 
00430 
00431     std::auto_ptr<L1GlobalTriggerReadoutRecord> gtReadoutRecord(new L1GlobalTriggerReadoutRecord(
00432             maxBxInEvent, numberFdlBoards, numberPsbBoards));
00433 
00434     // produce also the GMT readout collection and set the reference in GT record
00435     std::auto_ptr<L1MuGMTReadoutCollection> gmtrc(new L1MuGMTReadoutCollection(maxBxInEvent));
00436 
00437     //edm::RefProd<L1MuGMTReadoutCollection> refProdMuGMT = iEvent.getRefBeforePut<
00438     //        L1MuGMTReadoutCollection> ();
00439 
00440     //if (m_verbosity) {
00441     //    LogDebug("L1GlobalTriggerRawToDigi")
00442     //            << "\nL1GlobalTriggerRawToDigi: set L1MuGMTReadoutCollection RefProd"
00443     //            << " in L1GlobalTriggerReadoutRecord.\n" << std::endl;
00444     //}
00445     //gtReadoutRecord->setMuCollectionRefProd(refProdMuGMT);
00446 
00447 
00448     // ... then unpack modules other than GTFE, if requested
00449 
00450     for (CItBoardMaps itBoard = gtRecordMap.begin(); itBoard != gtRecordMap.end(); ++itBoard) {
00451 
00452         int iActiveBit = itBoard->gtBitDaqActiveBoards();
00453 
00454         bool activeBoardToUnpack = false;
00455         bool activeBoardInitial = false;
00456 
00457         int altNrBxBoardVal = -1;
00458 
00459         if (iActiveBit >= 0) {
00460             activeBoardInitial = activeBoardsGtInitial & ( 1 << iActiveBit );
00461             activeBoardToUnpack = activeBoardsGt & ( 1 << iActiveBit );
00462 
00463             altNrBxBoardVal = (altNrBxBoardInitial & ( 1 << iActiveBit )) >> iActiveBit;
00464 
00465             if (altNrBxBoardVal == 1) {
00466                 m_totalBxInEvent = m_recordLength1;
00467             } else if (altNrBxBoardVal == 0) {
00468                 m_totalBxInEvent = m_recordLength0;
00469             } else {
00470                 if (m_verbosity) {
00471                     edm::LogWarning("L1GlobalTriggerRawToDigi")
00472                             << "\n\nWARNING: Wrong value altNrBxBoardVal = " << altNrBxBoardVal
00473                             << " for board " << std::hex << ( itBoard->gtBoardId() ) << std::dec
00474                             << "\n  iActiveBit =            " << iActiveBit
00475                             << "\n  altNrBxBoardInitial = 0x" << std::hex << altNrBxBoardInitial <<  std::dec
00476                             << "\n  activeBoardsGt =      0x" << std::hex << activeBoardsGt <<  std::dec
00477                             << "\n  activeBoardInitial =    " << activeBoardInitial
00478                             << "\n  activeBoardToUnpack =   " << activeBoardToUnpack
00479                             << "\n Set altNrBxBoardVal tentatively to "
00480                             << m_recordLength0 << "\n Job may crash or produce wrong results!\n\n"
00481                             << std::endl;
00482                 }
00483 
00484                 m_totalBxInEvent = m_recordLength0;
00485             }
00486 
00487             // number of BX required to be unpacked
00488 
00489             if (m_unpackBxInEvent > m_totalBxInEvent) {
00490                 if (m_verbosity) {
00491                     LogDebug("L1GlobalTriggerRawToDigi")
00492                             << "\nWARNING: Number of available bunch crosses for board"
00493                             << ( itBoard->gtBoardId() ) << " in the record ( " << m_totalBxInEvent
00494                             << " ) \n is smaller than the number of bunch crosses requested to be unpacked ("
00495                             << m_unpackBxInEvent << " )!!! \n         Unpacking only "
00496                             << m_totalBxInEvent << " bunch crosses.\n" << std::endl;
00497                 }
00498 
00499                 m_lowSkipBxInEvent = 0;
00500                 m_uppSkipBxInEvent = m_totalBxInEvent;
00501 
00502             } else if (m_unpackBxInEvent < 0) {
00503 
00504                 m_lowSkipBxInEvent = 0;
00505                 m_uppSkipBxInEvent = m_totalBxInEvent;
00506 
00507                 if (m_verbosity) {
00508                     LogDebug("L1GlobalTriggerRawToDigi") << "\nUnpacking all " << m_totalBxInEvent
00509                             << " bunch crosses available." << "\n" << std::endl;
00510                 }
00511 
00512 
00513             } else if (m_unpackBxInEvent == 0) {
00514 
00515                 m_lowSkipBxInEvent = m_totalBxInEvent;
00516                 m_uppSkipBxInEvent = m_totalBxInEvent;
00517 
00518                 if (m_verbosity) {
00519                     LogDebug("L1GlobalTriggerRawToDigi")
00520                             << "\nNo bxInEvent required to be unpacked from " << m_totalBxInEvent
00521                             << " bunch crosses available." << "\n" << std::endl;
00522                 }
00523 
00524                 // change RecordLength
00525                 // cast int to boost::uint16_t (there are normally 3 or 5 BxInEvent)
00526                 m_gtfeWord->setRecordLength(static_cast<boost::uint16_t> (m_unpackBxInEvent));
00527                 m_gtfeWord->setRecordLength1(static_cast<boost::uint16_t> (m_unpackBxInEvent));
00528 
00529             } else {
00530 
00531                 m_lowSkipBxInEvent = ( m_totalBxInEvent - m_unpackBxInEvent ) / 2;
00532                 m_uppSkipBxInEvent = m_totalBxInEvent - m_lowSkipBxInEvent;
00533 
00534                 if (m_verbosity) {
00535                     LogDebug("L1GlobalTriggerRawToDigi") << "\nUnpacking " << m_unpackBxInEvent
00536                             << " bunch crosses from " << m_totalBxInEvent
00537                             << " bunch crosses available." << "\n" << std::endl;
00538                 }
00539 
00540                 // change RecordLength
00541                 // cast int to boost::uint16_t (there are normally 3 or 5 BxInEvent)
00542                 m_gtfeWord->setRecordLength(static_cast<boost::uint16_t> (m_unpackBxInEvent));
00543                 m_gtfeWord->setRecordLength1(static_cast<boost::uint16_t> (m_unpackBxInEvent));
00544 
00545             }
00546 
00547         } else {
00548             // board not in the ActiveBoards for the record
00549             continue;
00550         }
00551 
00552         if (!activeBoardInitial) {
00553             if (m_verbosity) {
00554                 LogDebug("L1GlobalTriggerRawToDigi") << "\nBoard of type "
00555                         << itBoard->gtBoardName() << " with index " << itBoard->gtBoardIndex()
00556                         << " not active initially in raw data.\n" << std::endl;
00557             }
00558             continue;
00559         }
00560 
00561         // active board initially, could unpack it
00562         switch (itBoard->gtBoardType()) {
00563 
00564             case FDL: {
00565                 for (int iFdl = 0; iFdl < m_totalBxInEvent; ++iFdl) {
00566 
00567                     // if pointer after FDL payload is greater than pointer at
00568                     // the end of GT payload, produce empty products and quit unpacking
00569                     if ((ptrGt + m_gtFdlWord->getSize()) > endPtrGt) {
00570                         edm::LogError("L1GlobalTriggerRawToDigi")
00571                                 << "\nError: Pointer after FDL " << iFdl
00572                                 << " greater than end pointer."
00573                                 << "\n Put empty products in the event!"
00574                                 << "\n Quit unpacking this event." << std::endl;
00575 
00576                         produceEmptyProducts(iEvent);
00577 
00578                         return;
00579                     }
00580 
00581                     // unpack only if requested, otherwise skip it
00582                     if (activeBoardToUnpack) {
00583 
00584                         // unpack only bxInEvent requested, otherwise skip it
00585                         if ( ( iFdl >= m_lowSkipBxInEvent ) && ( iFdl < m_uppSkipBxInEvent )) {
00586 
00587                             m_gtFdlWord->unpack(ptrGt);
00588 
00589                             // add 1 to the GT luminosity number to use the same convention as
00590                             // offline, where LS number starts with 1;
00591                             // in GT hardware, LS starts with 0
00592                             boost::uint16_t lsNr = m_gtFdlWord->lumiSegmentNr() + 1;
00593                             m_gtFdlWord->setLumiSegmentNr(lsNr);
00594 
00595                             // add FDL block to GT readout record
00596                             gtReadoutRecord->setGtFdlWord(*m_gtFdlWord);
00597 
00598                             if (m_verbosity && m_isDebugEnabled) {
00599 
00600                                 std::ostringstream myCoutStream;
00601                                 m_gtFdlWord->print(myCoutStream);
00602                                 LogTrace("L1GlobalTriggerRawToDigi") << myCoutStream.str() << "\n"
00603                                         << std::endl;
00604                             }
00605 
00606                             // ... and reset it
00607                             m_gtFdlWord->reset();
00608                         }
00609 
00610                     }
00611 
00612                     ptrGt += m_gtFdlWord->getSize(); // advance with FDL block size
00613 
00614                 }
00615             }
00616 
00617                 break;
00618             case PSB: {
00619                 for (int iPsb = 0; iPsb < m_totalBxInEvent; ++iPsb) {
00620 
00621                     // if pointer after PSB payload is greater than pointer at
00622                     // the end of GT payload, produce empty products and quit unpacking
00623                     if ((ptrGt + m_gtPsbWord->getSize()) > endPtrGt) {
00624                         edm::LogError("L1GlobalTriggerRawToDigi")
00625                                 << "\nError: Pointer after PSB " << iPsb
00626                                 << " greater than end pointer."
00627                                 << "\n Put empty products in the event!"
00628                                 << "\n Quit unpacking this event." << std::endl;
00629 
00630                         produceEmptyProducts(iEvent);
00631 
00632                         return;
00633                     }
00634 
00635                     // unpack only if requested, otherwise skip it
00636                     if (activeBoardToUnpack) {
00637 
00638                         // unpack only bxInEvent requested, otherwise skip it
00639                         if ( ( iPsb >= m_lowSkipBxInEvent ) && ( iPsb < m_uppSkipBxInEvent )) {
00640 
00641                             unpackPSB(evSetup, ptrGt, *m_gtPsbWord);
00642 
00643                             // add PSB block to GT readout record
00644                             gtReadoutRecord->setGtPsbWord(*m_gtPsbWord);
00645 
00646                             if (m_verbosity && m_isDebugEnabled) {
00647 
00648                                 std::ostringstream myCoutStream;
00649                                 m_gtPsbWord->print(myCoutStream);
00650                                 LogTrace("L1GlobalTriggerRawToDigi") << myCoutStream.str() << "\n"
00651                                         << std::endl;
00652                             }
00653 
00654                             // ... and reset it
00655                             m_gtPsbWord->reset();
00656                         }
00657 
00658                     }
00659 
00660                     ptrGt += m_gtPsbWord->getSize(); // advance with PSB block size
00661 
00662                 }
00663             }
00664                 break;
00665             case GMT: {
00666 
00667                 // 17*64/8 TODO FIXME ask Ivan for a getSize() function for GMT record
00668                 unsigned int gmtRecordSize = 136;
00669                 unsigned int gmtCollSize = m_totalBxInEvent * gmtRecordSize;
00670 
00671                 // if pointer after GMT payload is greater than pointer at
00672                 // the end of GT payload, produce empty products and quit unpacking
00673                 if ((ptrGt + gmtCollSize) > endPtrGt) {
00674                     edm::LogError("L1GlobalTriggerRawToDigi")
00675                             << "\nError: Pointer after GMT "
00676                             << " greater than end pointer."
00677                             << "\n Put empty products in the event!"
00678                             << "\n Quit unpacking this event." << std::endl;
00679 
00680                     produceEmptyProducts(iEvent);
00681 
00682                     return;
00683                 }
00684 
00685                 // unpack only if requested, otherwise skip it
00686                 if (activeBoardToUnpack) {
00687                     unpackGMT(ptrGt, gmtrc, iEvent);
00688                 }
00689 
00690 
00691                 ptrGt += gmtCollSize; // advance with GMT block size
00692             }
00693                 break;
00694             default: {
00695                 // do nothing, all blocks are given in GtBoardType enum
00696                 if (m_verbosity) {
00697 
00698                     LogDebug("L1GlobalTriggerRawToDigi") << "\nBoard of type "
00699                             << itBoard->gtBoardType() << " not expected  in record.\n" << std::endl;
00700                 }
00701             }
00702                 break;
00703 
00704         }
00705 
00706     }
00707 
00708     // add GTFE block to GT readout record, after updating active boards and record length
00709 
00710     gtReadoutRecord->setGtfeWord(*m_gtfeWord);
00711 
00712     // ... and reset it
00713     m_gtfeWord->reset();
00714 
00715 
00716 
00717     // unpack trailer
00718 
00719     int trailerSize = 8;
00720 
00721     // if pointer after trailer is greater than pointer at
00722     // the end of GT payload, produce empty products and quit unpacking
00723     if ((ptrGt + trailerSize) > endPtrGt) {
00724         edm::LogError("L1GlobalTriggerRawToDigi")
00725                 << "\nError: Pointer after trailer "
00726                 << " greater than end pointer."
00727                 << "\n Put empty products in the event!"
00728                 << "\n Quit unpacking this event." << std::endl;
00729 
00730         produceEmptyProducts(iEvent);
00731 
00732         return;
00733     }
00734 
00735     unpackTrailer(ptrGt, cmsTrailer);
00736 
00737     //
00738     if (m_verbosity && m_isDebugEnabled) {
00739         std::ostringstream myCoutStream;
00740         gtReadoutRecord->print(myCoutStream);
00741         LogTrace("L1GlobalTriggerRawToDigi")
00742                 << "\n The following L1 GT DAQ readout record was unpacked.\n"
00743                 << myCoutStream.str() << "\n" << std::endl;
00744     }
00745 
00746     // put records into event
00747 
00748     iEvent.put(gmtrc);
00749     iEvent.put(gtReadoutRecord);
00750 
00751 }
00752 
00753 // unpack header
00754 void L1GlobalTriggerRawToDigi::unpackHeader(const unsigned char* gtPtr, FEDHeader& cmsHeader) {
00755 
00756     // TODO  if needed in another format
00757 
00758     // print the header info
00759     if (m_verbosity && m_isDebugEnabled) {
00760 
00761         const boost::uint64_t* payload =
00762                 reinterpret_cast<boost::uint64_t*> (const_cast<unsigned char*> (gtPtr));
00763 
00764         std::ostringstream myCoutStream;
00765 
00766         // one word only
00767         int iWord = 0;
00768 
00769         myCoutStream << std::setw(4) << iWord << "  " << std::hex << std::setfill('0')
00770                 << std::setw(16) << payload[iWord] << std::dec << std::setfill(' ') << "\n"
00771                 << std::endl;
00772 
00773         myCoutStream << "  Event_type:  " << std::hex << " hex: " << "     " << std::setw(1)
00774                 << std::setfill('0') << cmsHeader.triggerType() << std::setfill(' ') << std::dec
00775                 << " dec: " << cmsHeader.triggerType() << std::endl;
00776 
00777         myCoutStream << "  LVL1_Id:     " << std::hex << " hex: " << "" << std::setw(6)
00778                 << std::setfill('0') << cmsHeader.lvl1ID() << std::setfill(' ') << std::dec
00779                 << " dec: " << cmsHeader.lvl1ID() << std::endl;
00780 
00781         myCoutStream << "  BX_Id:       " << std::hex << " hex: " << "   " << std::setw(3)
00782                 << std::setfill('0') << cmsHeader.bxID() << std::setfill(' ') << std::dec
00783                 << " dec: " << cmsHeader.bxID() << std::endl;
00784 
00785         myCoutStream << "  Source_Id:   " << std::hex << " hex: " << "   " << std::setw(3)
00786                 << std::setfill('0') << cmsHeader.sourceID() << std::setfill(' ') << std::dec
00787                 << " dec: " << cmsHeader.sourceID() << std::endl;
00788 
00789         myCoutStream << "  FOV:         " << std::hex << " hex: " << "     " << std::setw(1)
00790                 << std::setfill('0') << cmsHeader.version() << std::setfill(' ') << std::dec
00791                 << " dec: " << cmsHeader.version() << std::endl;
00792 
00793         myCoutStream << "  H:           " << std::hex << " hex: " << "     " << std::setw(1)
00794                 << std::setfill('0') << cmsHeader.moreHeaders() << std::setfill(' ') << std::dec
00795                 << " dec: " << cmsHeader.moreHeaders() << std::endl;
00796 
00797         LogDebug("L1GlobalTriggerRawToDigi") << "\n CMS Header \n" << myCoutStream.str() << "\n"
00798                 << std::endl;
00799 
00800     }
00801 
00802 }
00803 
00804 // unpack PSB records
00805 // psbPtr pointer to the beginning of the each PSB block obtained from gtPtr
00806 void L1GlobalTriggerRawToDigi::unpackPSB(
00807         const edm::EventSetup& evSetup, const unsigned char* psbPtr, L1GtPsbWord& psbWord) {
00808 
00809     //LogDebug("L1GlobalTriggerRawToDigi")
00810     //<< "\nUnpacking PSB block.\n"
00811     //<< std::endl;
00812 
00813     int uLength = L1GlobalTriggerReadoutSetup::UnitLength;
00814 
00815     int psbSize = psbWord.getSize();
00816     int psbWords = psbSize / uLength;
00817 
00818     const boost::uint64_t* payload =
00819             reinterpret_cast<boost::uint64_t*> (const_cast<unsigned char*> (psbPtr));
00820 
00821     for (int iWord = 0; iWord < psbWords; ++iWord) {
00822 
00823         // fill PSB
00824         // the second argument must match the word index defined in L1GtPsbWord class
00825 
00826         psbWord.setBoardId(payload[iWord], iWord);
00827         psbWord.setBxInEvent(payload[iWord], iWord);
00828         psbWord.setBxNr(payload[iWord], iWord);
00829         psbWord.setEventNr(payload[iWord], iWord);
00830 
00831         psbWord.setAData(payload[iWord], iWord);
00832         psbWord.setBData(payload[iWord], iWord);
00833 
00834         psbWord.setLocalBxNr(payload[iWord], iWord);
00835 
00836         LogTrace("L1GlobalTriggerRawToDigi") << std::setw(4) << iWord << "  " << std::hex
00837                 << std::setfill('0') << std::setw(16) << payload[iWord] << std::dec
00838                 << std::setfill(' ') << std::endl;
00839 
00840     }
00841 
00842 }
00843 
00844 // unpack the GMT record
00845 void L1GlobalTriggerRawToDigi::unpackGMT(const unsigned char* chp, std::auto_ptr<
00846         L1MuGMTReadoutCollection>& gmtrc, edm::Event& iEvent) {
00847 
00848     //LogDebug("L1GlobalTriggerRawToDigi")
00849     //<< "\nUnpacking GMT collection.\n"
00850     //<< std::endl;
00851 
00852     // 17*64/2 TODO FIXME ask Ivan for a getSize() function for GMT record
00853     const unsigned int gmtRecordSize32 = 34;
00854 
00855     std::auto_ptr<std::vector<L1MuRegionalCand> > DTCands(new std::vector<L1MuRegionalCand>);
00856     std::auto_ptr<std::vector<L1MuRegionalCand> > CSCCands(new std::vector<L1MuRegionalCand>);
00857     std::auto_ptr<std::vector<L1MuRegionalCand> > RPCbCands(new std::vector<L1MuRegionalCand>);
00858     std::auto_ptr<std::vector<L1MuRegionalCand> > RPCfCands(new std::vector<L1MuRegionalCand>);
00859     std::auto_ptr<std::vector<L1MuGMTCand> > GMTCands(new std::vector<L1MuGMTCand>);
00860 
00861     const unsigned* p = (const unsigned*) chp;
00862 
00863     // min Bx's in the event, computed after m_totalBxInEvent is obtained from GTFE block
00864     // assume symmetrical number of BX around L1Accept
00865     int iBxInEvent = ( m_totalBxInEvent + 1 ) / 2 - m_totalBxInEvent;
00866 
00867     for (int iGmtRec = 0; iGmtRec < m_totalBxInEvent; ++iGmtRec) {
00868 
00869         // unpack only bxInEvent requested, otherwise skip it
00870         if ( ( iGmtRec >= m_lowSkipBxInEvent ) && ( iGmtRec < m_uppSkipBxInEvent )) {
00871 
00872             // Dump the block
00873             const boost::uint64_t* bp =
00874                     reinterpret_cast<boost::uint64_t*> (const_cast<unsigned*> (p));
00875             for (int iWord = 0; iWord < 17; iWord++) {
00876                 LogTrace("L1GlobalTriggerRawToDigi") << std::setw(4) << iWord << "  " << std::hex
00877                         << std::setfill('0') << std::setw(16) << *bp++ << std::dec << std::setfill(
00878                         ' ') << std::endl;
00879             }
00880 
00881             L1MuGMTReadoutRecord gmtrr(iBxInEvent);
00882 
00883             gmtrr.setEvNr( ( *p ) & 0xffffff);
00884             gmtrr.setBCERR( ( ( *p ) >> 24 ) & 0xff);
00885             p++;
00886 
00887             gmtrr.setBxNr( ( *p ) & 0xfff);
00888             if ( ( ( *p ) >> 15 ) & 1) {
00889                 gmtrr.setBxInEvent( ( ( ( *p ) >> 12 ) & 7 ) - 8);
00890             } else {
00891                 gmtrr.setBxInEvent( ( ( ( *p ) >> 12 ) & 7 ));
00892             }
00893             // to do: check here the block length and the board id
00894             p++;
00895 
00896             for (int im = 0; im < 16; im++) {
00897                 // flip the pt and quality bits -- this should better be done by GMT input chips
00898                 unsigned waux = *p++;
00899                 waux = ( waux & 0xffff00ff ) | ( ( ~waux ) & 0x0000ff00 );
00900                 L1MuRegionalCand cand(waux, iBxInEvent);
00901                 // fix the type assignment (csc=2, rpcb=1) -- should be done by GMT input chips
00902                 if (im >= 4 && im < 8) cand.setType(1);
00903                 if (im >= 8 && im < 12) cand.setType(2);
00904                 cand.setPhiValue(m_TriggerScales->getPhiScale()->getLowEdge(cand.phi_packed()));
00905                 cand.setEtaValue(m_TriggerScales->getRegionalEtaScale(cand.type_idx())->getCenter(
00906                         cand.eta_packed()));
00907                 cand.setPtValue(m_TriggerPtScale->getPtScale()->getLowEdge(cand.pt_packed()));
00908                 gmtrr.setInputCand(im, cand);
00909                 if (!cand.empty()) {
00910                     if (im < 4) DTCands->push_back(cand);
00911                     if (im >= 4 && im < 8) RPCbCands->push_back(cand);
00912                     if (im >= 8 && im < 12) CSCCands->push_back(cand);
00913                     if (im >= 12) RPCfCands->push_back(cand);
00914                 }
00915             }
00916 
00917             unsigned char* prank = (unsigned char*) ( p + 12 );
00918 
00919             for (int im = 0; im < 12; im++) {
00920                 unsigned waux = *p++;
00921                 unsigned raux = im < 8 ? *prank++ : 0; // only fwd and brl cands have valid rank
00922                 L1MuGMTExtendedCand cand(waux, raux, iBxInEvent);
00923                 cand.setPhiValue(m_TriggerScales->getPhiScale()->getLowEdge(cand.phiIndex()));
00924                 cand.setEtaValue(m_TriggerScales->getGMTEtaScale()->getCenter(cand.etaIndex()));
00925                 cand.setPtValue(m_TriggerPtScale->getPtScale()->getLowEdge(cand.ptIndex()));
00926                 if (im < 4)
00927                     gmtrr.setGMTBrlCand(im, cand);
00928                 else if (im < 8)
00929                     gmtrr.setGMTFwdCand(im - 4, cand);
00930                 else {
00931                     gmtrr.setGMTCand(im - 8, cand);
00932                     if (!cand.empty()) GMTCands->push_back(cand);
00933                 }
00934             }
00935 
00936             // skip the two sort rank words and two chip BX words
00937             p += 4;
00938 
00939             gmtrc->addRecord(gmtrr);
00940 
00941         } else {
00942             // increase the pointer with the GMT record size
00943             p += gmtRecordSize32;
00944         }
00945 
00946         // increase the BxInEvent number
00947         iBxInEvent++;
00948 
00949     }
00950 
00951     iEvent.put(DTCands, "DT");
00952     iEvent.put(CSCCands, "CSC");
00953     iEvent.put(RPCbCands, "RPCb");
00954     iEvent.put(RPCfCands, "RPCf");
00955     iEvent.put(GMTCands);
00956 
00957 }
00958 
00959 // unpack trailer word
00960 // trPtr pointer to the beginning of trailer obtained from gtPtr
00961 void L1GlobalTriggerRawToDigi::unpackTrailer(const unsigned char* trlPtr, FEDTrailer& cmsTrailer) {
00962 
00963     // TODO  if needed in another format
00964 
00965     // print the trailer info
00966     if (m_verbosity && m_isDebugEnabled) {
00967 
00968         const boost::uint64_t* payload =
00969                 reinterpret_cast<boost::uint64_t*> (const_cast<unsigned char*> (trlPtr));
00970 
00971         std::ostringstream myCoutStream;
00972 
00973         // one word only
00974         int iWord = 0;
00975 
00976         myCoutStream << std::setw(4) << iWord << "  " << std::hex << std::setfill('0')
00977                 << std::setw(16) << payload[iWord] << std::dec << std::setfill(' ') << "\n"
00978                 << std::endl;
00979 
00980         myCoutStream << "  Event_length:  " << std::hex << " hex: " << "" << std::setw(6)
00981                 << std::setfill('0') << cmsTrailer.lenght() << std::setfill(' ') << std::dec
00982                 << " dec: " << cmsTrailer.lenght() << std::endl;
00983 
00984         myCoutStream << "  CRC:           " << std::hex << " hex: " << "  " << std::setw(4)
00985                 << std::setfill('0') << cmsTrailer.crc() << std::setfill(' ') << std::dec
00986                 << " dec: " << cmsTrailer.crc() << std::endl;
00987 
00988         myCoutStream << "  Event_status:  " << std::hex << " hex: " << "    " << std::setw(2)
00989                 << std::setfill('0') << cmsTrailer.evtStatus() << std::setfill(' ') << std::dec
00990                 << " dec: " << cmsTrailer.evtStatus() << std::endl;
00991 
00992         myCoutStream << "  TTS_bits:      " << std::hex << " hex: " << "     " << std::setw(1)
00993                 << std::setfill('0') << cmsTrailer.ttsBits() << std::setfill(' ') << std::dec
00994                 << " dec: " << cmsTrailer.ttsBits() << std::endl;
00995 
00996         myCoutStream << "  More trailers: " << std::hex << " hex: " << "     " << std::setw(1)
00997                 << std::setfill('0') << cmsTrailer.moreTrailers() << std::setfill(' ') << std::dec
00998                 << " dec: " << cmsTrailer.moreTrailers() << std::endl;
00999 
01000         LogDebug("L1GlobalTriggerRawToDigi") << "\n CMS Trailer \n" << myCoutStream.str() << "\n"
01001                 << std::endl;
01002 
01003     }
01004 
01005 }
01006 
01007 // produce empty products in case of problems
01008 void L1GlobalTriggerRawToDigi::produceEmptyProducts(edm::Event& iEvent) {
01009 
01010     std::auto_ptr<L1GlobalTriggerReadoutRecord> gtReadoutRecord(
01011             new L1GlobalTriggerReadoutRecord());
01012 
01013     std::auto_ptr<L1MuGMTReadoutCollection> gmtrc(new L1MuGMTReadoutCollection());
01014 
01015     std::auto_ptr<std::vector<L1MuRegionalCand> > DTCands(new std::vector<L1MuRegionalCand>);
01016     std::auto_ptr<std::vector<L1MuRegionalCand> > CSCCands(new std::vector<L1MuRegionalCand>);
01017     std::auto_ptr<std::vector<L1MuRegionalCand> > RPCbCands(new std::vector<L1MuRegionalCand>);
01018     std::auto_ptr<std::vector<L1MuRegionalCand> > RPCfCands(new std::vector<L1MuRegionalCand>);
01019     std::auto_ptr<std::vector<L1MuGMTCand> > GMTCands(new std::vector<L1MuGMTCand>);
01020 
01021     // put empty records into event
01022 
01023     iEvent.put(gmtrc);
01024     iEvent.put(gtReadoutRecord);
01025 
01026     iEvent.put(DTCands, "DT");
01027     iEvent.put(CSCCands, "CSC");
01028     iEvent.put(RPCbCands, "RPCb");
01029     iEvent.put(RPCfCands, "RPCf");
01030     iEvent.put(GMTCands);
01031 
01032 }
01033 
01034 
01035 
01036 // dump FED raw data
01037 void L1GlobalTriggerRawToDigi::dumpFedRawData(
01038         const unsigned char* gtPtr, int gtSize, std::ostream& myCout) {
01039 
01040     LogDebug("L1GlobalTriggerRawToDigi") << "\nDump FED raw data.\n" << std::endl;
01041 
01042     int wLength = L1GlobalTriggerReadoutSetup::WordLength;
01043     int uLength = L1GlobalTriggerReadoutSetup::UnitLength;
01044 
01045     int gtWords = gtSize / uLength;
01046     LogTrace("L1GlobalTriggerRawToDigi") << "\nFED GT words (" << wLength << " bits):" << gtWords
01047             << "\n" << std::endl;
01048 
01049     const boost::uint64_t* payload =
01050             reinterpret_cast<boost::uint64_t*> (const_cast<unsigned char*> (gtPtr));
01051 
01052     for (unsigned int i = 0; i < gtSize / sizeof(boost::uint64_t); i++) {
01053         myCout << std::setw(4) << i << "  " << std::hex << std::setfill('0') << std::setw(16)
01054                 << payload[i] << std::dec << std::setfill(' ') << std::endl;
01055     }
01056 
01057 }
01058 
01059 //
01060 void L1GlobalTriggerRawToDigi::endJob() {
01061 
01062     // empty now
01063 }
01064 
01065 // static class members
01066