CMS 3D CMS Logo

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