CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_7/src/EventFilter/GctRawToDigi/plugins/GctRawToDigi.cc

Go to the documentation of this file.
00001 #include "EventFilter/GctRawToDigi/plugins/GctRawToDigi.h"
00002 
00003 // System headers
00004 #include <vector>
00005 #include <sstream>
00006 #include <iostream>
00007 
00008 // Framework headers
00009 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00010 #include "FWCore/Framework/interface/MakerMacros.h"
00011 
00012 // Raw data collection headers
00013 #include "DataFormats/FEDRawData/interface/FEDNumbering.h"
00014 #include "DataFormats/FEDRawData/interface/FEDRawDataCollection.h"
00015 
00016 // GCT Format Translators
00017 #include "EventFilter/GctRawToDigi/src/GctFormatTranslateMCLegacy.h"
00018 #include "EventFilter/GctRawToDigi/src/GctFormatTranslateV35.h"
00019 #include "EventFilter/GctRawToDigi/src/GctFormatTranslateV38.h"
00020 
00021 // Unpack collections class
00022 #include "EventFilter/GctRawToDigi/src/GctUnpackCollections.h"
00023 
00024 
00025 // Namespace resolution
00026 using std::cout;
00027 using std::endl;
00028 using std::vector;
00029 using std::string;
00030 using std::dec;
00031 using std::hex;
00032 
00033 
00034 GctRawToDigi::GctRawToDigi(const edm::ParameterSet& iConfig) :
00035   inputLabel_(iConfig.getParameter<edm::InputTag>("inputLabel")),
00036   fedId_(iConfig.getUntrackedParameter<int>("gctFedId", FEDNumbering::MINTriggerGCTFEDID)),
00037   hltMode_(iConfig.getParameter<bool>("hltMode")),
00038   numberOfGctSamplesToUnpack_(iConfig.getParameter<unsigned>("numberOfGctSamplesToUnpack")),
00039   numberOfRctSamplesToUnpack_(iConfig.getParameter<unsigned>("numberOfRctSamplesToUnpack")),
00040   unpackSharedRegions_(iConfig.getParameter<bool>("unpackSharedRegions")),
00041   formatVersion_(iConfig.getParameter<unsigned>("unpackerVersion")),
00042   checkHeaders_(iConfig.getUntrackedParameter<bool>("checkHeaders",false)),
00043   verbose_(iConfig.getUntrackedParameter<bool>("verbose",false)),
00044   formatTranslator_(0),
00045   errors_(0),
00046   errorCounters_(MAX_ERR_CODE+1),  // initialise with the maximum error codes!
00047   unpackFailures_(0)
00048 {
00049   LogDebug("GCT") << "GctRawToDigi will unpack FED Id " << fedId_;
00050 
00051   // If the GctFormatTranslate version has been forced from config file, instantiate the relevant one.
00052   /***  THIS OBVIOUSLY STINKS - NEED TO REPLACE WITH SOMETHING BETTER THAN MASSIVE IF-ELSE SOON ***/
00053   /***  WHEN THIS MESS IS REMOVED REMEMBER THAT THE V38 FORMAT TRANSLATE HAS A DIFERENT CTOR TO THE OTHERS ***/
00054   if(formatVersion_ == 0) { edm::LogInfo("GCT") << "The required GCT Format Translator will be automatically determined from the first S-Link packet header."; }
00055   else if(formatVersion_ == 1)
00056   {
00057     edm::LogInfo("GCT") << "You have selected to use GctFormatTranslateMCLegacy";
00058     formatTranslator_ = new GctFormatTranslateMCLegacy(hltMode_, unpackSharedRegions_);
00059   }
00060   else if(formatVersion_ == 2)
00061   {
00062     edm::LogInfo("GCT") << "You have selected to use GctFormatTranslateV35";
00063     formatTranslator_ = new GctFormatTranslateV35(hltMode_, unpackSharedRegions_);
00064   }
00065   else if(formatVersion_ == 3)
00066   {
00067     edm::LogInfo("GCT") << "You have selected to use GctFormatTranslateV38";
00068     formatTranslator_ = new GctFormatTranslateV38(hltMode_, unpackSharedRegions_, numberOfGctSamplesToUnpack_, numberOfRctSamplesToUnpack_);    
00069   }
00070   else
00071   { 
00072     edm::LogWarning("GCT") << "You have requested a version of GctFormatTranslate that does not exist! Will attempt to auto-detect "
00073                               "the required GCT Format Translator from the first S-Link packet header instead.";
00074   }
00075 
00076   if(hltMode_) { edm::LogInfo("GCT") << "HLT unpack mode selected: HLT unpack optimisations will be used."; }
00077   if(unpackSharedRegions_) { edm::LogInfo("GCT") << "You have selected to unpack shared RCT calo regions - be warned: "
00078                                                     "this is for commissioning purposes only!"; }
00079 
00081   // GCT input collections
00082   produces<L1GctFibreCollection>();
00083   produces<L1CaloEmCollection>();
00084   produces<L1CaloRegionCollection>();
00085 
00086   // GCT internal collections
00087   produces<L1GctInternEmCandCollection>();
00088   produces<L1GctInternJetDataCollection>();
00089   produces<L1GctInternEtSumCollection>();
00090   produces<L1GctInternHFDataCollection>();
00091   produces<L1GctInternHtMissCollection>();
00092 
00093   // GCT output collections
00094   produces<L1GctEmCandCollection>("isoEm");
00095   produces<L1GctEmCandCollection>("nonIsoEm");
00096   produces<L1GctJetCandCollection>("cenJets");
00097   produces<L1GctJetCandCollection>("forJets");
00098   produces<L1GctJetCandCollection>("tauJets");
00099   produces<L1GctHFBitCountsCollection>();
00100   produces<L1GctHFRingEtSumsCollection>();
00101   produces<L1GctEtTotalCollection>();
00102   produces<L1GctEtHadCollection>();
00103   produces<L1GctEtMissCollection>();
00104   produces<L1GctHtMissCollection>();
00105   produces<L1GctJetCountsCollection>();  // Deprecated (empty collection still needed by GT)
00106   
00107   // Error collection
00108   produces<L1TriggerErrorCollection>();
00109 }
00110 
00111 
00112 GctRawToDigi::~GctRawToDigi()
00113 {
00114   // do anything here that needs to be done at destruction time
00115   // (e.g. close files, deallocate resources etc.)
00116   delete formatTranslator_;
00117 }
00118 
00119 
00120 //
00121 // member functions
00122 //
00123 
00124 // ------------ method called once each job just before starting event loop  ------------
00125 void GctRawToDigi::beginJob()
00126 {
00127 }
00128 
00129 
00130 // ------------ method called to produce the data  ------------
00131 void GctRawToDigi::produce(edm::Event& iEvent, const edm::EventSetup& iSetup)
00132 {
00133   using namespace edm;
00134 
00135   // Instantiate all the collections the unpacker needs; puts them in event when this object goes out of scope.
00136   std::auto_ptr<GctUnpackCollections> colls(new GctUnpackCollections(iEvent));  
00137   errors_ = colls->errors();
00138   
00139   // get raw data collection
00140   edm::Handle<FEDRawDataCollection> feds;
00141   iEvent.getByLabel(inputLabel_, feds);
00142 
00143   // if raw data collection is present, do the unpacking
00144   if (feds.isValid()) {
00145   
00146     const FEDRawData& gctRcd = feds->FEDData(fedId_);
00147  
00148     LogDebug("GCT") << "Upacking FEDRawData of size " << std::dec << gctRcd.size();
00149 
00150     // check for empty events
00151     if(gctRcd.size() < 16) {
00152       LogDebug("GCT") << "Cannot unpack: empty/invalid GCT raw data (size = "
00153                       << gctRcd.size() << "). Returning empty collections!";
00154       addError(1);
00155       return;
00156     }
00157 
00158     // If no format translator yet set, need to auto-detect from header.
00159     // If auto format detection fails, we have no concrete format
00160     // translator instantiated... set error and bail
00161     if(!formatTranslator_) {
00162       if(!autoDetectRequiredFormatTranslator(gctRcd.data())) return;
00163     }
00164     
00165     // reset collection of block headers
00166     blockHeaders_.clear();
00167 
00168     // do the unpacking
00169     unpack(gctRcd, iEvent, colls.get()); 
00170 
00171     // check headers, if enabled
00172     if (checkHeaders_) checkHeaders();
00173     
00174     // dump summary in verbose mode
00175     if(verbose_) { doVerboseOutput(blockHeaders_, colls.get()); }
00176     
00177   }
00178 
00179 }
00180 
00181 
00182 void GctRawToDigi::unpack(const FEDRawData& d, edm::Event& e, GctUnpackCollections * const colls)
00183 {
00184 
00185   // We should now have a valid formatTranslator pointer
00186   formatTranslator_->setUnpackCollections(colls);
00187 
00188   const unsigned char * data = d.data();  // The 8-bit wide raw-data array.  
00189 
00190   // Data offset - starts at 16 as there is a 64-bit S-Link header followed
00191   // by a 64-bit software-controlled header (for pipeline format version
00192   // info that is not yet used).
00193   unsigned dPtr = 16;
00194 
00195   const unsigned dEnd = d.size() - 8; // End of payload is at (packet size - final slink header)
00196 
00197   // read blocks
00198   for (unsigned nb=0; dPtr<dEnd; ++nb)
00199   {
00200     if(nb >= MAX_BLOCKS) {
00201       LogDebug("GCT") << "Reached block limit - bailing out from this event!";
00202       addError(6);
00203       break; 
00204     }
00205   
00206     // read block header
00207     GctBlockHeader blockHeader = formatTranslator_->generateBlockHeader(&data[dPtr]);
00208   
00209     // unpack the block; dPtr+4 is to get to the block data.
00210     if(!formatTranslator_->convertBlock(&data[dPtr+4], blockHeader)) // Record if we had an unpack problem then skip rest of event.
00211     {
00212       LogDebug("GCT") << "Encountered block unpack error - bailing out from this event!";
00213       addError(4);
00214       break;
00215     } 
00216 
00217     // advance pointer
00218     dPtr += 4*(blockHeader.blockLength()*blockHeader.nSamples()+1); // *4 because blockLen is in 32-bit words, +1 for header
00219 
00220     // if verbose or checking block headers, store the header
00221     if (verbose_ || checkHeaders_) blockHeaders_.push_back(blockHeader);
00222 
00223   }
00224 
00225 }
00226 
00227 
00228 // detect raw data format version from known raw data address 
00229 bool GctRawToDigi::autoDetectRequiredFormatTranslator(const unsigned char * d)
00230 {
00231   LogDebug("GCT") << "About to auto-detect the required format translator from the firmware version header.";
00232     
00233   const uint32_t * p32 = reinterpret_cast<const uint32_t *>(d);
00234   unsigned firmwareHeader = p32[2];
00235 
00236   /***  THIS OBVIOUSLY STINKS - NEED TO REPLACE WITH SOMETHING BETTER THAN MASSIVE IF-ELSE SOON ***/
00237   /***  WHEN THIS MESS IS REMOVED REMEMBER THAT THE V38 FORMAT TRANSLATE HAS A DIFERENT CTOR TO THE OTHERS ***/
00238 
00239   if( firmwareHeader >= 25 && firmwareHeader <= 35 )
00240   {
00241     edm::LogInfo("GCT") << "Firmware Version V" << firmwareHeader << " detected: GctFormatTranslateV" << firmwareHeader << " will be used to unpack.";
00242     formatTranslator_ = new GctFormatTranslateV35(hltMode_, unpackSharedRegions_);
00243     return true;
00244   }
00245   else if( firmwareHeader == 38 )
00246   {
00247     edm::LogInfo("GCT") << "Firmware Version V" << firmwareHeader << " detected: GctFormatTranslateV" << firmwareHeader << " will be used to unpack.";
00248     formatTranslator_ = new GctFormatTranslateV38(hltMode_, unpackSharedRegions_, numberOfGctSamplesToUnpack_, numberOfRctSamplesToUnpack_);
00249     return true;
00250   }
00251   else if( firmwareHeader == 0x00000000 )
00252   {
00253     edm::LogInfo("GCT") << "Legacy Monte-Carlo data detected: GctFormatTranslateMCLegacy will be used to unpack.";
00254     formatTranslator_ = new GctFormatTranslateMCLegacy(hltMode_, unpackSharedRegions_);
00255     return true;
00256   }
00257   // these lines comments otherwise error is not reported!!!
00258   //  else if(firmwareHeader == 0xdeadffff) { /* Driver detected unknown firmware version. L1TriggerError code? */ }
00259   //  else if( firmwareHeader == 0xaaaaaaaa) { /* Before driver firmware version checks implemented. L1TriggerError code?  */ }
00260   else { /* Totally unknown firmware header */
00261   
00262     LogDebug("GCT") << "Failed to determine unpacker to use from the firmware version header! "
00263       "(firmware header = 0x" << hex << firmwareHeader << dec << ")";
00264     addError(2);
00265     return false;
00266   }
00267 
00268 }
00269 
00270 
00271 void GctRawToDigi::checkHeaders() {
00272 
00273   // TODO : loop over block headers found this event and check for consistency
00274 
00275 }
00276 
00277 
00278 void GctRawToDigi::doVerboseOutput(const GctBlockHeaderCollection& bHdrs, const GctUnpackCollections * const colls) const
00279 {
00280   std::ostringstream os;
00281   os << "Found " << bHdrs.size() << " GCT block headers" << endl;
00282   for (unsigned i=0, size = bHdrs.size(); i < size; ++i)
00283   {
00284     os << "GCT Raw Data Block : " << formatTranslator_->getBlockDescription(bHdrs[i]) << " : " << bHdrs[i] << endl;
00285   }
00286   os << *colls << endl;
00287   edm::LogVerbatim("GCT") << os.str();
00288 }
00289 
00290 
00291 
00292 void GctRawToDigi::addError(const unsigned code) {
00293 
00294   // check this isn't going to break error handling
00295   if (code > MAX_ERR_CODE) {
00296     LogDebug("GCT") << "Unknown error code : " << code;
00297     return;
00298   }
00299 
00300   // print message on first instance of this error and if verbose flag set to true
00301   if (errorCounters_.at(code) == 0 && verbose_) {
00302     std::ostringstream os;
00303     switch(code) {
00304       case 0: os << "Reserved error code - not in use"; break;
00305       case 1: os << "FED record empty or too short"; break;
00306       case 2: os << "Unknown raw data version"; break;
00307       case 3: os << "Detected unknown firmware version"; break;
00308       case 4: os << "Detected unknown data block"; break;
00309       case 5: os << "Block headers out of sync"; break;
00310       case 6: os << "Too many blocks"; break;
00311       default: os << "Unknown error code";
00312     }
00313     edm::LogError("GCT") << "Unpacking error " << code << " : " << os.str();
00314   }
00315 
00316   // increment error counter
00317   ++(errorCounters_.at(code));
00318   
00319   // store error in event if possible
00320   if (errors_ != 0) {
00321     errors_->push_back(L1TriggerError(fedId_, code));
00322   }
00323   else LogDebug("GCT") << "Detected error (code=" << code << ") but no error collection available!";
00324 
00325 }
00326 
00327 // ------------ method called once each job just after ending the event loop  ------------
00328 void GctRawToDigi::endJob()
00329 {
00330   unsigned total=0;
00331   std::ostringstream os;
00332 
00333   for (unsigned i=0 ; i <= MAX_ERR_CODE ; ++i) {
00334     total+=errorCounters_.at(i);
00335     os << "Error " << i << " (" << errorCounters_.at(i) << ")";
00336     if(i < MAX_ERR_CODE) { os << ", "; }
00337   }
00338 
00339   if (total>0 && verbose_) {
00340     edm::LogError("GCT") << "Encountered " << total << " unpacking errors: " << os.str();
00341   }  
00342 }
00343 
00345 DEFINE_FWK_MODULE(GctRawToDigi);