CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_2_9_HLT1_bphpatch4/src/EventFilter/EcalRawToDigi/plugins/MatacqProducer.cc

Go to the documentation of this file.
00001 #include "EventFilter/EcalRawToDigi/interface/MatacqProducer.h"
00002 #include "EventFilter/EcalRawToDigi/src/Majority.h"
00003 #include "FWCore/Framework/interface/Event.h"
00004 #include "FWCore/Framework/interface/EventSetup.h"
00005 #include "Geometry/Records/interface/IdealGeometryRecord.h"
00006 #include "FWCore/Framework/interface/ESHandle.h"
00007 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00008 #include "DataFormats/FEDRawData/interface/FEDRawData.h"
00009 #include "DataFormats/FEDRawData/interface/FEDNumbering.h"
00010 #include "DataFormats/FEDRawData/interface/FEDRawDataCollection.h"
00011 #include "DataFormats/EcalDigi/interface/EcalMatacqDigi.h"
00012 #include "DataFormats/EcalDigi/interface/EcalDigiCollections.h"
00013 #include <boost/algorithm/string.hpp>
00014 #include <boost/format.hpp>
00015 
00016 #include <memory>
00017 
00018 #include <stdio.h>
00019 
00020 #include <fstream>
00021 
00022 #include "DataFormats/EcalDigi/interface/EcalMatacqDigi.h"
00023 
00024 #include <sys/types.h>
00025 #include <unistd.h>
00026 #include <signal.h>
00027 #include <sys/stat.h>
00028 
00029 using namespace std;
00030 using namespace boost;
00031 using namespace edm;
00032 
00033 // #undef LogInfo
00034 // #define LogInfo(a) cout << "INFO " << a << ": "
00035 // #undef LogWarning
00036 // #define LogWarning(a) cout << "WARN " << a << ": "
00037 // #undef LogDebug
00038 // #define LogDebug(a) cout << "DBG " << a << ": "
00039 
00040 
00041 //verbose mode for matacq event retrieval debugging:
00042 //static const bool searchDbg = false;
00043 
00044 //laser freq is 1 every 112 orbit => >80 orbit
00045 int MatacqProducer::orbitTolerance_ = 80; 
00046 
00047 MatacqProducer::stats_t MatacqProducer::stats_init = {0,0,0};
00048 
00049 MatacqProducer::MatacqProducer(const edm::ParameterSet& params):
00050   fileNames_(params.getParameter<std::vector<std::string> >("fileNames")),
00051   digiInstanceName_(params.getParameter<string>("digiInstanceName")),
00052   rawInstanceName_(params.getParameter<string>("rawInstanceName")),
00053   timing_(params.getUntrackedParameter<bool>("timing", false)),
00054   disabled_(params.getParameter<bool>("disabled")),
00055   verbosity_(params.getUntrackedParameter<int>("verbosity", 0)),
00056   produceDigis_(params.getParameter<bool>("produceDigis")),
00057   produceRaw_(params.getParameter<bool>("produceRaw")),
00058   inputRawCollection_(params.getParameter<InputTag>("inputRawCollection")),
00059   mergeRaw_(params.getParameter<bool>("mergeRaw")),
00060   ignoreTriggerType_(params.getParameter<bool>("ignoreTriggerType")),
00061   matacq_(0, 0),
00062   inFile_(0),
00063   data_(bufferSize),
00064   openedFileRunNumber_(0),
00065   lastOrb_(0),
00066   fastRetrievalThresh_(0),
00067   orbitOffsetFile_(params.getUntrackedParameter<std::string>("orbitOffsetFile",
00068                                                              "")),
00069   inFileName_(""),
00070   stats_(stats_init),
00071   logFileName_(params.getUntrackedParameter<std::string>("logFileName",
00072                                                          "matacqProducer.log")){
00073   if(verbosity_>=4) cout << "[Matacq] in MatacqProducer ctor"  << endl;
00074   
00075   posEstim_.verbosity(verbosity_);
00076 
00077   logFile_.open(logFileName_.c_str(), ios::app | ios::out);
00078   
00079   if(logFile_.bad()){
00080     throw cms::Exception("FileOpen") << "Failed to open file "
00081                                      << logFileName_ << " for logging.\n";
00082   }
00083 
00084   if(produceDigis_){
00085     if(verbosity_>0) cout << "[Matacq] registering new "
00086                        "EcalMatacqDigiCollection product with instance name '"
00087                           << digiInstanceName_ << "'\n";
00088     produces<EcalMatacqDigiCollection>(digiInstanceName_);
00089   }
00090   
00091   if(produceRaw_){
00092     if(verbosity_>0) cout << "[Matacq] registering new FEDRawDataCollection "
00093                        "product with instance name '"
00094                           << rawInstanceName_ << "'\n";
00095     produces<FEDRawDataCollection>(rawInstanceName_);
00096   }
00097   
00098   startTime_.tv_sec = startTime_.tv_usec = 0;
00099   if(orbitOffsetFile_.size()>0){
00100     doOrbitOffset_ = true;
00101     loadOrbitOffset();
00102   } else{
00103     doOrbitOffset_ = false;
00104   }
00105   if(verbosity_>=4) cout << "[Matacq] exiting MatacqProducer ctor"  << endl;
00106 }
00107 
00108 
00109 void
00110 MatacqProducer::produce(edm::Event& event, const edm::EventSetup& eventSetup){
00111   if(verbosity_>=4) cout << "[Matacq] in MatacqProducer::produce"  << endl;
00112   if(startTime_.tv_sec==0) gettimeofday(&startTime_, 0);
00113   ++stats_.nEvents;  
00114   if(disabled_) return;
00115   addMatacqData(event);
00116 }
00117 
00118 void
00119 MatacqProducer::addMatacqData(edm::Event& event){
00120   edm::Handle<FEDRawDataCollection> sourceColl;
00121   if(inputRawCollection_.label().size() == 0
00122      && inputRawCollection_.instance().size() == 0){
00123     event.getByType(sourceColl);
00124   } else{
00125     event.getByLabel(inputRawCollection_, sourceColl);
00126   }
00127   
00128   std::auto_ptr<FEDRawDataCollection> rawColl;
00129   if(produceRaw_){
00130     if(mergeRaw_){
00131       rawColl = auto_ptr<FEDRawDataCollection>(new FEDRawDataCollection(*sourceColl));
00132     } else{
00133       rawColl = auto_ptr<FEDRawDataCollection>(new FEDRawDataCollection());
00134     }
00135   }
00136   
00137   std::auto_ptr<EcalMatacqDigiCollection>
00138     digiColl(new EcalMatacqDigiCollection());
00139 
00140   if(sourceColl->FEDData(matacqFedId_).size()>4 && !produceRaw_){
00141     //input raw data collection already contains matacqData
00142     formatter_.interpretRawData(sourceColl->FEDData(matacqFedId_),
00143                                 *digiColl);             
00144   } else{
00145     bool isLaserEvent = (getCalibTriggerType(event) == laserType);
00146     if(isLaserEvent || ignoreTriggerType_){
00147 
00148       const uint32_t runNumber = getRunNumber(event);
00149       const uint32_t orbitId   = getOrbitId(event);
00150 
00151       LogInfo("Matacq") << "Run " << runNumber << "\t Orbit " << orbitId << "\n";
00152     
00153       bool fileChange;
00154       uint32_t offset = 0;
00155       if(doOrbitOffset_){
00156         map<uint32_t,uint32_t>::iterator it = orbitOffset_.find(runNumber);
00157         if(it == orbitOffset_.end()){
00158           LogWarning("IncorrectLaserEvent") << "Orbit offset not found for run "
00159                                << runNumber
00160                                << ". No orbit correction will be applied.";
00161         } else{
00162           offset = it->second;
00163         }
00164       }    
00165       
00166       if(getMatacqFile(runNumber, orbitId, &fileChange)){
00167         //matacq file retrieval succeeded
00168         LogInfo("Matacq") << "Matacq data file found for "
00169                           << "run " << runNumber << " orbit " << orbitId;
00170         if(getMatacqEvent(runNumber, orbitId, fileChange)){
00171           if(produceDigis_){
00172             formatter_.interpretRawData(matacq_, *digiColl);
00173           }
00174           if(produceRaw_){
00175             uint32_t dataLen64 = matacq_.getParsedLen();
00176             if(dataLen64 > bufferSize*8 || matacq_.getDccLen()!= dataLen64){
00177               LogWarning("IncorrectLaserEvent") << " Error in Matacq event fragment length! "
00178                                    << "DCC len: " << matacq_.getDccLen()
00179                                    << "*8 Bytes, Parsed len: "
00180                                    << matacq_.getParsedLen() << "*8 Bytes.  "
00181                                    << "Matacq data will not be included for this event.\n";
00182             } else{
00183               rawColl->FEDData(matacqFedId_).resize(dataLen64*8);
00184               copy(data_.begin(), data_.begin() + dataLen64*8,
00185                    rawColl->FEDData(matacqFedId_).data());
00186             }
00187           }
00188           LogInfo("Matacq") << "Associating matacq data with orbit id "
00189                             << matacq_.getOrbitId()
00190                             << " to dcc event with orbit id "
00191                             << orbitId << std::endl;
00192           if(isLaserEvent){
00193             ++stats_.nLaserEventsWithMatacq;
00194           } else{
00195             ++stats_.nNonLaserEventsWithMatacq;
00196           }
00197         } else{
00198           LogWarning("IncorrectLaserEvent") << "No matacq data found for "
00199                                << "run " << runNumber << " orbit " << orbitId;
00200         }
00201       } else{
00202         LogWarning("IncorrectLaserEvent") << "No matacq file found for event "
00203                              << event.id();
00204       }
00205     }
00206   }
00207   
00208   if(produceRaw_){
00209     if(verbosity_>1) cout << "[Matacq] "
00210                           << "Adding FEDRawDataCollection collection "
00211                           << " to event.\n";
00212     event.put(rawColl, rawInstanceName_);
00213   }
00214 
00215   if(produceDigis_){
00216     if(verbosity_>1) cout << "[Matacq] "
00217                           << "Adding EcalMatacqDigiCollection collection "
00218                           << " to event.\n";
00219     event.put(digiColl, digiInstanceName_);
00220   }
00221 }
00222 
00223 // #if 0
00224 // bool
00225 // MatacqProducer::getMatacqEvent(std::ifstream& f,
00226 //                             uint32_t runNumber,
00227 //                             uint32_t orbitId,
00228 //                             bool doWrap,
00229 //                             std::streamoff maxPos){
00230 //   bool found = false;
00231 //   streampos startPos = f.tellg();
00232 
00233 //   while(!f.eof()
00234 //      && !found
00235 //      && (maxPos<0 || f.tellg()<=maxPos)){
00236 //     const streamsize headerSize = 8*8;
00237 //     f.read((char*)&data_[0], headerSize);
00238 //     if(f.eof()) break;
00239 //     int32_t orb = MatacqRawEvent::getOrbitId(&data_[0], headerSize);
00240 //     uint32_t len = MatacqRawEvent::getDccLen(&data_[0], headerSize);
00241 //     uint32_t run = MatacqRawEvent::getRunNum(&data_[0], headerSize);
00242 //     //     cout << "Matacq: orbit = " << orb
00243 //     //        << " len = " << len
00244 //     //        << " run = " << run << endl;
00245 //     if((abs(orb-(int32_t)orbitId) < orbitTolerance_)
00246 //        && (runNumber==0 || runNumber==run)){
00247 //       found = true;
00248 //       //reads the rest of the event:
00249 //       if(data_.size() < len*8){
00250 //      throw cms::Exception("Matacq") << "Buffer overflow";
00251 //       }
00252 //       f.read((char*)&data_[0]+headerSize, len*8-headerSize);
00253 //       matacq_ = MatacqRawEvent((unsigned char*)&data_[0], len*8);
00254 //     } else{
00255 //       //moves to next event:
00256 //       f.seekg(len*8 - headerSize, ios::cur);
00257 //     }
00258 //   }
00259   
00260 //   f.clear(); //clears eof error to allow seekg  
00261 //   if(doWrap && !found){
00262 //     f.seekg(0, ios::beg);
00263 //     found =  getMatacqEvent(f, runNumber, orbitId, false, startPos);
00264 //   }
00265 //   return found;
00266 // }
00267 //#endif
00268 
00269 bool
00270 MatacqProducer::getMatacqEvent(uint32_t runNumber,
00271                                int32_t orbitId,
00272                                bool fileChange){
00273   filepos_t startPos;
00274   if(!mtell(startPos)) return false;
00275   
00276   int32_t startOrb = -1;
00277   const size_t headerSize = 8*8;
00278   if(mread((char*)&data_[0], headerSize, "Reading matacq header", true)){
00279     startOrb = MatacqRawEvent::getOrbitId(&data_[0], headerSize);
00280     if(startOrb<0) startOrb = 0;
00281   } else{
00282     if(verbosity_>2){
00283       cout << "[Matacq] Failed to read matacq header. Moved to start of "
00284         " the file.\n";
00285     }
00286     mrewind();
00287     if(mread((char*)&data_[0], headerSize, "Reading matacq header", true)){
00288       startPos = 0;
00289       startOrb = MatacqRawEvent::getOrbitId(&data_[0], headerSize);
00290     } else{
00291       if(verbosity_>2) cout << "[Matacq] Looks like matacq file is empty"
00292                             << "\n";
00293       return false;
00294     }
00295   }
00296   
00297   if(verbosity_>2) cout << "[Matacq] Last read orbit: " << lastOrb_
00298                         << " looking for orbit " << orbitId
00299                         << ". Current file position: " << startPos
00300                         << " Orbit at current position: " << startOrb << "\n";
00301   
00302   //  f.clear();
00303   bool didCoarseMove = false;
00304   if(!posEstim_.invalid()
00305      && (abs(lastOrb_-orbitId) > fastRetrievalThresh_)){
00306     filepos_t pos = posEstim_.pos(orbitId);
00307 
00308     //    struct stat st;
00309     filepos_t fsize;
00310     //    if(0==stat(inFileName_.c_str(), &st)){
00311     if(msize(fsize)){
00312       //      const int64_t fsize = st.st_size;
00313       if(0!=posEstim_.eventLength() && pos > fsize){
00314         //estimated position is beyong end of file
00315         //-> move to beginning of last event:
00316         int64_t evtSize = posEstim_.eventLength()*sizeof(uint64_t);
00317         pos = ((int64_t)fsize/evtSize-1)*evtSize;
00318         if(verbosity_>2){
00319           cout << "[Matacq] Estimated position was beyond end of file. "
00320             "Changed to " << pos << "\n";
00321         }
00322       }
00323     } else{
00324       LogWarning("IncorrectConfiguration") << "Failed to access file " << inFileName_ << ".";
00325     }
00326     if(pos>=0){
00327       if(verbosity_>2) cout << "[Matacq] jumping to estimated position "
00328                             << pos << "\n";
00329       mseek(pos, SEEK_SET, "Jumping to estimated event position");
00330       if(mread((char*)&data_[0], headerSize, "Reading matacq header", true)){
00331         didCoarseMove = true;
00332       } else{
00333         //estimated position might have been beyond the end of the file,
00334         //try, with original position:
00335         didCoarseMove = false;
00336         if(!mread((char*)&data_[0], headerSize, "Reading event header", true)){
00337           return false;
00338         }
00339       }
00340     } else{
00341       if(verbosity_) cout << "[Matacq] Event orbit outside of orbit range "
00342                        "of matacq data file events\n";
00343       return false;
00344     }
00345   }
00346   
00347   int32_t orb = MatacqRawEvent::getOrbitId(&data_[0], headerSize);
00348 
00349   if(didCoarseMove){
00350     //autoadjustement of threshold for coarse move:
00351     if(abs(orb-orbitId) > fastRetrievalThresh_){
00352       if(verbosity_>2) cout << "[Matacq] Fast retrieval threshold increased from "
00353                             << fastRetrievalThresh_;
00354       fastRetrievalThresh_ = 2*abs(orb-orbitId);
00355       if(verbosity_>2) cout << " to " << fastRetrievalThresh_ << "\n";
00356     }
00357 
00358     //if coarse move did not improve situation, rolls back:
00359     if(startOrb > 0
00360        && (abs(orb-orbitId) > abs(startOrb-orbitId))){
00361       if(verbosity_>2) cout << "[Matacq] Estimation (-> orbit " << orb << ") "
00362                          "was worst than original position (-> orbit "
00363                             << startOrb
00364                             << "). Restoring position (" << startPos << ").\n";
00365       mseek(startPos, SEEK_SET);
00366       mread((char*)&data_[0], headerSize, "Reading event header", true);
00367       orb = MatacqRawEvent::getOrbitId(&data_[0], headerSize);
00368     }
00369   }
00370   
00371   bool searchBackward = (orb>orbitId)?true:false;
00372   //BEWARE: len must be signed, because we are using latter in the code (-len)
00373   //expression
00374   int len = (int)MatacqRawEvent::getDccLen(&data_[0], headerSize);
00375 
00376   if(len==0){
00377     cout << "[Matacq] read DCC length is null! Cancels matacq event search "
00378          << " and move matacq file pointer to beginning of the file. "
00379          << "(" << __FILE__ << ":" << __LINE__ << ")."
00380          << "\n";
00381     //rewind(f);
00382     mrewind();
00383     return false;
00384   }
00385   
00386   enum state_t { searching, found, failed } state = searching;
00387   
00388   while(state == searching){
00389     orb = MatacqRawEvent::getOrbitId(&data_[0], headerSize);
00390     len = (int)MatacqRawEvent::getDccLen(&data_[0], headerSize);
00391     uint32_t run = MatacqRawEvent::getRunNum(&data_[0], headerSize);
00392     if(verbosity_>3){
00393       filepos_t pos;
00394       mtell(pos);
00395       cout << "[Matacq] Header read at file position "
00396            << pos
00397            << ":  orbit = " << orb
00398            << " len = " << len << "x8 Byte"
00399            << " run = " << run << "\n";
00400     }
00401     if((abs(orb-orbitId) < orbitTolerance_)
00402        && (runNumber==0 || runNumber==run)){
00403       state = found;
00404       lastOrb_ = orb;
00405       //reads the rest of the event:
00406       if((int)data_.size() < len*8){
00407         throw cms::Exception("Matacq") << "Buffer overflow";
00408       }
00409       if(verbosity_>2) cout << "[Matacq] Event found. Reading "
00410                          " matacq event." << "\n";
00411       if(!mread((char*)&data_[0], len*8, "Reading matacq event")){
00412         if(verbosity_>2) cout << "[Matacq] Failed to read matacq event."
00413                               << "\n";
00414         state = failed;
00415       }
00416       matacq_ = MatacqRawEvent((unsigned char*)&data_[0], len*8);
00417     } else {
00418       if((searchBackward && (orb < orbitId))
00419          || (!searchBackward && orb > orbitId)){ //search ended
00420         lastOrb_ = orb;      
00421         state = failed;
00422         if(verbosity_) cout << "[Matacq] Event search failed." << "\n";
00423       } else{
00424         off_t offset = (searchBackward?-len:len)*8;
00425         lastOrb_ = orb; 
00426         if(verbosity_>3){
00427           cout << "[Matacq] In matacq file, moving "
00428                << abs(offset) << " byte " << (offset>0?"forward":"backward")
00429                << ".\n";
00430         }       
00431 
00432         if(mseek(offset, SEEK_CUR,
00433                  (searchBackward?"Moving to previous event":
00434                   "Moving to next event"))
00435            && mread((char*)&data_[0], headerSize, "Reading event header",
00436                     true)){
00437         } else{
00438           if(!searchBackward) mseek(-len*8, SEEK_CUR,
00439                                     "Moving to start of last complete event");
00440           state = failed;
00441         }
00442       }
00443     }
00444   }
00445   
00446   if(state==found){
00447     filepos_t pos;
00448     filepos_t fsize;
00449     mtell(pos);
00450     msize(fsize);
00451     if(pos==fsize-1){ //last byte.
00452       if(verbosity_>2){
00453         cout << "[Matacq] Event found was at the end of the file. Moving "
00454           "stream position to beginning of this event."
00455              << "\n";
00456       }
00457       mseek(-(int)len*8-1, SEEK_CUR,
00458             "Moving to beginning of last matacq event");
00459     }
00460   }
00461   return (state==found);
00462 }
00463 
00464 
00465 bool
00466 MatacqProducer::getMatacqFile(uint32_t runNumber, uint32_t orbitId,
00467                               bool* fileChange){
00468   if(openedFileRunNumber_!=0
00469      && openedFileRunNumber_==runNumber){
00470     if(fileChange!=0) *fileChange = false;
00471     return misOpened();
00472   }
00473 
00474   if(fileNames_.size()==0) return 0;
00475 
00476   const string runNumberFormat = "%08d";
00477   string sRunNumber = str(boost::format(runNumberFormat) % runNumber);
00478   //cout << "Run number string: " << sRunNumber << "\n";
00479   bool found = false;
00480   string fname;
00481   for(unsigned i=0; i < fileNames_.size() && !found; ++i){
00482     fname = fileNames_[i];
00483     boost::algorithm::replace_all(fname, "%run_subdir%",
00484                                   runSubDir(runNumber));
00485     boost::algorithm::replace_all(fname, "%run_number%", sRunNumber);
00486 
00487     if(verbosity_) cout << "[Matacq] Looking for a file with path "
00488                         << fname << "\n";
00489     
00490     if(mcheck(fname)){
00491       LogInfo("Matacq") << "Uses matacq data file: '" << fname << "'\n";
00492       found = true;
00493     }
00494   }
00495   if(!found){
00496     openedFileRunNumber_ = 0;
00497     if(fileChange!=0) *fileChange = false;
00498     return 0;
00499   }
00500   
00501   if(!mopen(fname)){
00502     LogWarning("IncorrectConfiguration") << "Failed to open file " << fname << "\n";
00503     openedFileRunNumber_ = 0;
00504     if(fileChange!=0) *fileChange = false;
00505     return false;
00506   } else{
00507     openedFileRunNumber_ = runNumber;
00508     lastOrb_ = 0;
00509     posEstim_.init(this);
00510     if(fileChange!=0) *fileChange = true;
00511     return true;
00512   }
00513 }
00514  
00515 
00516 uint32_t MatacqProducer::getRunNumber(edm::Event& ev) const{
00517   return ev.run();
00518 }
00519 
00520 uint32_t MatacqProducer::getOrbitId(edm::Event& ev) const{
00521   //on CVS HEAD (June 4, 08), class Event has a method orbitNumber()
00522   //we could use here. The code would be shorten to:
00523   //return ev.orbitNumber();
00524   //we have to deal with what we have in current CMSSW releases:
00525   edm::Handle<FEDRawDataCollection> rawdata;
00526   if(!(ev.getByType(rawdata) && rawdata.isValid())){
00527     throw cms::Exception("NotFound")
00528       << "No FED raw data collection found. ECAL raw data are "
00529       "required to retrieve the orbit ID";
00530   }
00531   
00532   int orbit = 0;
00533   for(int id=601; id<=654; ++id){
00534     if(!FEDNumbering::inRange(id)) continue;
00535     const FEDRawData& data = rawdata->FEDData(id);
00536     const int orbitIdOffset64 = 3;
00537     if(data.size()>=8*(orbitIdOffset64+1)){//orbit id is in 4th 64-bit word
00538       const unsigned char* pOrbit = data.data() + orbitIdOffset64*8;
00539       int thisOrbit = pOrbit[0]
00540         | (pOrbit[1] <<8)
00541         | (pOrbit[2] <<16)
00542         | (pOrbit[3] <<24);
00543       if(orbit!=0 && thisOrbit!=0 && abs(orbit-thisOrbit)>orbitTolerance_){
00544         //throw cms::Exception("EventCorruption")
00545         //  << "Orbit ID inconsitency in DCC headers";
00546         LogWarning("IncorrectEvent")
00547           << "Orbit ID inconsitency in DCC headers";
00548         orbit = 0;
00549         break;
00550       }
00551       if(thisOrbit!=0) orbit = thisOrbit;
00552     }
00553   }
00554   
00555   if(orbit==0){
00556     //    throw cms::Exception("NotFound")
00557     //  << "Failed to retrieve orbit ID of event "<< ev.id();
00558     LogWarning("IncorrectEvent") << "Failed to retrieve orbit ID of event "
00559                                 << ev.id();
00560   }
00561   return orbit;
00562 }
00563  
00564 int MatacqProducer::getCalibTriggerType(edm::Event& ev) const{  
00565   edm::Handle<FEDRawDataCollection> rawdata;
00566   if(!(ev.getByType(rawdata) && rawdata.isValid())){
00567     throw cms::Exception("NotFound")
00568       << "No FED raw data collection found. ECAL raw data are "
00569       "required to retrieve the trigger type";
00570   }
00571   
00572   Majority<int> stat;
00573   for(int id=601; id<=654; ++id){
00574     if(!FEDNumbering::inRange(id)) continue;
00575     const FEDRawData& data = rawdata->FEDData(id);
00576     const int detailedTrigger32 = 5;
00577     if(data.size()>=4*(detailedTrigger32+1)){
00578       const unsigned char* pTType = data.data() + detailedTrigger32*4;
00579       int tType = pTType[1] & 0x7;
00580       stat.add(tType);
00581     }
00582   }
00583   double p;
00584   int tType = stat.result(&p);
00585   if(p<0){
00586     //throw cms::Exception("NotFound") << "No ECAL DCC data found\n";
00587     LogWarning("IncorrectEvent")  << "No ECAL DCC data found\n";
00588     tType = -1;
00589   }
00590   if(p<.8){
00591     //throw cms::Exception("EventCorruption") << "Inconsitency in detailed trigger type indicated in ECAL DCC data headers\n";
00592     LogWarning("IncorrectEvent") << "Inconsitency in detailed trigger type indicated in ECAL DCC data headers\n";
00593     tType = -1;
00594   }
00595   return tType;
00596 }
00597   
00598 void MatacqProducer::PosEstimator::init(MatacqProducer* mp){
00599   mp->mrewind();
00600 
00601   const size_t headerSize = 8*8;
00602   unsigned char data[headerSize];
00603   if(!mp->mread((char*)data, headerSize)){
00604     if(verbosity_) cout << "[Matacq] reached end of file!\n"; 
00605     firstOrbit_ = eventLength_ = orbitStepMean_ = 0;
00606     return;
00607   } else{
00608     firstOrbit_ = MatacqRawEvent::getOrbitId(data, headerSize);
00609     eventLength_ = MatacqRawEvent::getDccLen(data, headerSize);
00610     if(verbosity_>1) cout << "[Matacq] First event orbit: " << firstOrbit_
00611                           << " event length: " << eventLength_
00612                           << "*8 byte\n";
00613   }
00614 
00615   mp->mrewind();
00616   
00617   if(eventLength_==0){    
00618     if(verbosity_) cout << "[Matacq] event length is null!" << endl; 
00619     return;
00620   }
00621 
00622   filepos_t s;
00623   mp->msize(s);
00624 
00625   //number of complete events:
00626   const unsigned nEvents = s/eventLength_/8;
00627 
00628   if(nEvents==0){
00629     if(verbosity_) cout << "[Matacq] File is empty!" << endl;
00630     orbitStepMean_ = 0;
00631     return;
00632   }
00633 
00634   if(verbosity_>1) cout << "[Matacq] File size: " << s
00635                         << " Number of events: " << nEvents << endl;
00636   
00637   //position of last complete events:
00638   off_t last = (nEvents-1)*(off_t)eventLength_*8;
00639   mp->mseek(last, SEEK_SET, "Moving to beginning of last complete "
00640             "matacq event");
00641   if(!mp->mread((char*) data, headerSize, "Reading matacq header", true)){
00642     LogWarning("IncorrectLaserEvent") << "Fast matacq event retrieval failure. "
00643       "Falling back to safe retrieval mode.";
00644     orbitStepMean_ = 0;
00645   }
00646   
00647   int32_t lastOrb = MatacqRawEvent::getOrbitId(data, headerSize);
00648   int32_t lastLen = MatacqRawEvent::getDccLen(data, headerSize);
00649 
00650   if(verbosity_>1) cout << "[Matacq] Last event orbit: " << lastOrb
00651                         << " last event length: " << lastLen << endl;
00652   
00653   //some consistency check
00654   if(lastLen!=eventLength_){
00655     LogWarning("IncorrectLaserEvent")
00656       << "Fast matacq event retrieval failure: it looks like "
00657       "the matacq file contains events of different sizes. Falling back to "
00658       "safe retrieval mode.";
00659     invalid_ = true;
00660     orbitStepMean_ = 0;
00661     return;
00662   }
00663 
00664   orbitStepMean_ = (lastOrb - firstOrbit_)/nEvents;
00665   
00666   if(verbosity_>1) cout << "[Matacq] Orbit step mean: " << orbitStepMean_
00667                         << "\n";
00668 
00669   invalid_ = false;
00670 }
00671 
00672 int64_t MatacqProducer::PosEstimator::pos(int orb) const{
00673   if(orb<firstOrbit_) return -1;
00674   uint64_t r = orbitStepMean_!=0?
00675     (((uint64_t)(orb-firstOrbit_))/orbitStepMean_)*eventLength_*8
00676     :0;
00677   if(verbosity_>2) cout << "[Matacq] Estimated Position for orbit  " << orb
00678                         << ": " << r << endl;
00679   return r;
00680 }
00681 
00682 MatacqProducer::~MatacqProducer(){
00683   mclose();
00684   timeval t;
00685   gettimeofday(&t, 0);
00686   if(timing_ && startTime_.tv_sec!=0){
00687     //not using logger, to allow timing with different logging options
00688     cout << "[Matacq] Time elapsed between first event and "
00689       "destruction of MatacqProducer: "
00690          << ((t.tv_sec-startTime_.tv_sec)*1.
00691              + (t.tv_usec-startTime_.tv_usec)*1.e-6) << "s\n";
00692   }
00693   logFile_ << "Event count: "
00694            << "total: " << stats_.nEvents << ", "
00695            << "Laser event with Matacq data: "
00696            << stats_.nLaserEventsWithMatacq << ", "
00697            << "Non laser event (according to DCC header) with Matacq data: "
00698            << stats_.nNonLaserEventsWithMatacq << "\n";
00699 }
00700 
00701 void MatacqProducer::loadOrbitOffset(){
00702   ifstream f(orbitOffsetFile_.c_str());
00703   if(f.bad()){
00704     throw cms::Exception("Matacq")
00705       << "Failed to open orbit ID correction file '"
00706       << orbitOffsetFile_ << "'\n";
00707   }
00708 
00709   cout << "[Matacq] "
00710        << "Offset to substract to Matacq events Orbit ID: \n"
00711        << "#Run Number\t Offset\n";
00712 
00713   int iline = 0;
00714   string s;
00715   stringstream buf;
00716   while(f.eof()){
00717     getline(f, s);
00718     ++iline;
00719     if(s[0]=='#'){//comment
00720       //skip line:
00721       f.ignore(numeric_limits<streamsize>::max(), '\n');
00722       continue;
00723     }
00724     buf.str("");
00725     buf << s;
00726     int run;
00727     int orbit;
00728     buf >> run;
00729     buf >> orbit;
00730     if(buf.bad()){
00731       throw cms::Exception("Matacq")
00732         << "Syntax error in Orbit offset file '"
00733         << orbitOffsetFile_ << "'";
00734     }
00735     cout << run << "\t" << orbit << "\n";
00736     orbitOffset_.insert(pair<int, int>(run, orbit));
00737   }
00738 }
00739 
00740 #ifdef USE_STORAGE_MANAGER
00741 bool MatacqProducer::mseek(filepos_t offset, int whence, const char* mess){
00742   if(0==inFile_.get()) return false;
00743   try{
00744     Storage::Relative wh;
00745     if(whence==SEEK_SET) wh = Storage::SET;
00746     else if(whence==SEEK_CUR) wh = Storage::CURRENT;
00747     else if(whence==SEEK_END) wh = Storage::END;
00748     else throw cms::Exception("Bug") << "Bug found in "
00749                                      << __FILE__ << ": "<< __LINE__ << "\n";
00750                    
00751     inFile_->position(offset, wh);
00752   } catch(cms::Exception& e){
00753     if(verbosity_){
00754       cout << "[Matacq] ";
00755       if(mess) cout << mess << ". ";
00756       cout << "Random access error on input matacq file. "
00757         "Reopening file. " << e.what() << "\n";
00758       mopen(inFileName_);
00759       return false;
00760     }
00761   }
00762   return true;
00763 }
00764 
00765 bool MatacqProducer::mtell(filepos_t& pos){
00766   if(0==inFile_.get()) return false;
00767   pos = inFile_->position();
00768   return true;
00769 }
00770 
00771 bool MatacqProducer::mread(char* buf, size_t n, const char* mess, bool peek){
00772   if(0==inFile_.get()) return false;
00773   
00774   filepos_t pos;
00775   if(!mtell(pos)) return false;
00776 
00777   bool rc = false;
00778   try{
00779     rc =  (n==inFile_->xread(buf, n));
00780   } catch(cms::Exception& e){
00781     if(verbosity_){
00782       cout << "[Matacq] ";
00783       if(mess) cout << mess << ". ";
00784       cout << "Read failure from input matacq file: "
00785            << e.what() << "\n";
00786     }
00787     //recovering from error:
00788     mopen(inFileName_);
00789     mseek(pos);
00790     return false;
00791   }
00792   if(peek){//asked to restore original file position
00793     mseek(pos);
00794   }
00795   return rc;
00796 }
00797 
00798 bool MatacqProducer::msize(filepos_t& s){
00799   if(inFile_.get()==0) return false;
00800   s = inFile_.get()->size();
00801   return true;
00802 }
00803 
00804 bool MatacqProducer::mrewind(){
00805   Storage* file = inFile_.get();
00806   if(file==0) return false;
00807   try{
00808     file->rewind();
00809   } catch(cms::Exception e){
00810     if(verbosity_) cout << "Exception cautgh while rewinding file "
00811                         << inFileName_ << ": " << e.what() << ". "
00812                         << "File will be reopened.";
00813     return mopen(inFileName_);
00814   }
00815   return true;
00816 }
00817 
00818 bool MatacqProducer::mcheck(const std::string& name){
00819   return StorageFactory::get()->check(name);
00820 }
00821 
00822 bool MatacqProducer::mopen(const std::string& name){
00823   //close already opened file if any:
00824   mclose();
00825   
00826   try{
00827     inFile_
00828       = auto_ptr<Storage>(StorageFactory::get()->open(name,
00829                                                       IOFlags::OpenRead));
00830     inFileName_ = name;
00831   } catch(cms::Exception& e){
00832     LogWarning("IncorrectConfiguration") << e.what();
00833     inFile_.reset();
00834     inFileName_ = "";
00835     return false;
00836   }
00837   return true;
00838 }
00839 
00840 void MatacqProducer::mclose(){
00841   if(inFile_.get()!=0){
00842     inFile_->close();
00843     inFile_.reset();
00844   }
00845 }
00846 
00847 bool MatacqProducer::misOpened(){
00848   return inFile_.get()!=0;
00849 }
00850 
00851 bool MatacqProducer::meof(){
00852   if(inFile_.get()==0) return true;
00853   return inFile_->eof();
00854 }
00855 
00856 #else //USE_STORAGE_MANAGER not defined
00857 bool MatacqProducer::mseek(off_t offset, int whence, const char* mess){
00858   if(0==inFile_) return false;
00859   const int rc = fseeko(inFile_, offset, whence);
00860   if(rc!=0 && verbosity_){
00861     cout << "[Matacq] ";
00862     if(mess) cout << mess << ". ";
00863     cout << "Random access error on input matacq file. "
00864       "Rewind file.\n";
00865     mrewind();
00866   }
00867   return rc==0;
00868 }
00869 
00870 bool MatacqProducer::mtell(filepos_t& pos){
00871   if(0==inFile_) return false;
00872   pos = ftello(inFile_);
00873   return pos != -1;
00874     
00875 }
00876 
00877 bool MatacqProducer::mread(char* buf, size_t n, const char* mess, bool peek){
00878   if(0==inFile_) return false;
00879   off_t pos = ftello(inFile_);
00880   bool rc = (pos!=-1) && (1==fread(buf, n, 1, inFile_));
00881   if(!rc){
00882     if(verbosity_){
00883       cout << "[Matacq] ";
00884       if(mess) cout << mess << ". ";
00885       cout << "Read failure from input matacq file.\n";
00886     }
00887     clearerr(inFile_);
00888   }
00889   if(peek || !rc){//need to restore file position
00890     if(0!=fseeko(inFile_, pos, SEEK_SET)){
00891       if(verbosity_){
00892         cout << "[Matacq] ";
00893         if(mess) cout << mess << ". ";
00894         cout << "Failed to restore file position of "
00895           "before read error. Rewind file.\n";
00896       }
00897       //rewind(inFile_.get());
00898       mrewind();
00899       lastOrb_ = 0;
00900     }
00901   }
00902   return rc;
00903 }
00904 
00905 bool MatacqProducer::msize(filepos_t& s){
00906   if(0==inFile_) return false;
00907   struct stat buf;
00908   if(0!=fstat(fileno(inFile_), &buf)){
00909     s = 0;
00910     return false;
00911   } else{
00912     s = buf.st_size;
00913     return true;
00914   }
00915 }
00916 
00917 bool MatacqProducer::mrewind(){
00918   if(0==inFile_) return false;
00919   clearerr(inFile_);
00920   return fseeko(inFile_, 0, SEEK_SET)!=0; 
00921 }
00922 
00923 bool MatacqProducer::mcheck(const std::string& name){
00924   struct stat dummy;
00925   return 0==stat(name.c_str(), &dummy);
00926 }
00927 
00928 bool MatacqProducer::mopen(const std::string& name){
00929   if(inFile_!=0) mclose();
00930   inFile_ = fopen(name.c_str(), "r");
00931   if(inFile_!=0){
00932     inFileName_ = name;
00933     return true;
00934   } else{
00935     inFileName_ = "";
00936     return false;
00937   }
00938 }
00939 
00940 void MatacqProducer::mclose(){
00941   if(inFile_!=0) fclose(inFile_);
00942   inFile_ = 0;
00943 }
00944 
00945 bool MatacqProducer::misOpened(){
00946   return inFile_!=0;
00947 }
00948 
00949 bool MatacqProducer::meof(){
00950   if(0==inFile_) return true;
00951   return feof(inFile_)==0;
00952 }
00953 
00954 #endif //USE_STORAGE_MANAGER defined
00955 
00956 std::string MatacqProducer::runSubDir(uint32_t runNumber){
00957   int millions = runNumber / (1000*1000);
00958   int thousands = (runNumber-millions*1000*1000) / 1000;
00959   int units = runNumber-millions*1000*1000 - thousands*1000;
00960   return str(boost::format("%03d/%03d/%03d") % millions % thousands % units);
00961 }