CMS 3D CMS Logo

/data/doxygen/doxygen-1.7.3/gen/CMSSW_4_2_8/src/DataFormats/FWLite/src/MultiChainEvent.cc

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 // Package:     FWLite
00004 // Class  :     MultiChainEvent
00005 // 
00006 // Implementation:
00007 //     <Notes on implementation>
00008 //
00009 // Original Author:  Salvatore Rappoccio
00010 //         Created:  Thu Jul  9 22:05:56 CDT 2009
00011 //
00012 
00013 // system include files
00014 
00015 // user include files
00016 #include "DataFormats/FWLite/interface/MultiChainEvent.h"
00017 #include "DataFormats/Common/interface/EDProductGetter.h"
00018 #include "DataFormats/FWLite/interface/Handle.h"
00019 #include "DataFormats/Common/interface/TriggerResults.h"
00020 #include "DataFormats/Provenance/interface/ProcessHistory.h"
00021 #include "FWCore/Common/interface/TriggerResultsByName.h"
00022 
00023 namespace fwlite {
00024 
00025   namespace internal {
00026     
00027     class MultiProductGetter : public edm::EDProductGetter {
00028 public:
00029       MultiProductGetter(MultiChainEvent const * iEvent) : event_(iEvent) {}
00030       
00031       virtual edm::EDProduct const*
00032       getIt(edm::ProductID const& iID) const {
00033 
00034         return event_->getByProductID( iID );
00035       }
00036 private:
00037       MultiChainEvent const * event_;
00038       
00039     };
00040   }
00041 
00042 
00043 //
00044 // constants, enums and typedefs
00045 //
00046 
00047 //
00048 // static data member definitions
00049 //
00050 
00051 //
00052 // constructors and destructor
00053 //
00054   MultiChainEvent::MultiChainEvent(const std::vector<std::string>& iFileNames1,
00055                                    const std::vector<std::string>& iFileNames2,
00056                                    bool useSecFileMapSorted)
00057 {
00058   event1_ = boost::shared_ptr<ChainEvent> ( new ChainEvent( iFileNames1 ) );
00059   event2_ = boost::shared_ptr<ChainEvent> ( new ChainEvent( iFileNames2 ) );
00060 
00061   getter_ = boost::shared_ptr<internal::MultiProductGetter>( new internal::MultiProductGetter( this) );
00062 
00063   event1_->setGetter( getter_ );
00064   event2_->setGetter( getter_ );
00065 
00066   useSecFileMapSorted_ = useSecFileMapSorted;
00067 
00068   if ( !useSecFileMapSorted_ ) {
00069     std::cout << "------------------------------------------------------------------------" << std::endl;
00070     std::cout << "WARNING! What you are about to do may be very slow." << std::endl;
00071     std::cout << "The 2-file solution in FWLite works with very simple assumptions." << std::endl;
00072     std::cout << "It will linearly search through the files in the secondary file list for Products." << std::endl;
00073     std::cout << "There are speed improvements available to make this run faster." << std::endl;
00074     std::cout << "***If your secondary files are sorted with a run-range within a file, (almost always the case) " << std::endl;
00075     std::cout << "***please use the option useSecFileMapSorted=true in this constructor. " << std::endl;
00076     std::cout << "    > usage: MultiChainEvent( primaryFiles, secondaryFiles, true);" << std::endl;
00077     std::cout << "------------------------------------------------------------------------" << std::endl;    
00078     
00079   }
00080 
00081   if ( useSecFileMapSorted_ ) {
00082 
00083     std::cout << "------------------------------------------------------------------------" << std::endl;    
00084     std::cout << "This MultiChainEvent is now creating a (run_range)_2 ---> file_index_2 map" << std::endl;
00085     std::cout << "for the 2-file solution. " << std::endl;
00086     std::cout << "This is assuming the files you are giving me are sorted by run,event pairs within each secondary file." << std::endl;
00087     std::cout << "If this is not true (rarely the case), set this option to false." << std::endl;
00088     std::cout << "    > usage: MultiChainEvent( primaryFiles, secondaryFiles, false);" << std::endl;
00089     std::cout << "------------------------------------------------------------------------" << std::endl;    
00090     // speed up secondary file access with a (run,event)_1 ---> index_2 map
00091     
00092 
00093     // Loop over events, when a new file is encountered, store the first run number from this file,
00094     // and the last run number from the last file. 
00095     TFile * lastFile = 0;
00096     std::pair<event_id_range,Long64_t> eventRange;
00097     bool firstFile = true;
00098 
00099     bool foundAny = false;
00100 
00101     for( event2_->toBegin();
00102          ! event2_->atEnd();
00103          ++(*event2_)) {
00104       // if we have a new file, cache the "first"
00105       if ( lastFile != event2_->getTFile() ) {
00106 
00107         // if this is not the first file, we have an entry.
00108         // Add it to the list.
00109         if ( !firstFile ) {
00110           foundAny = true;
00111           event_id_range toAdd = eventRange.first;
00112           secFileMapSorted_[ toAdd ] = eventRange.second;
00113         }
00114         // always add the "first" event id to the cached event range
00115         eventRange.first.first = event2_->event()->id();
00116         lastFile = event2_->getTFile();
00117       }
00118       // otherwise, cache the "second" event id in the cached event range.
00119       // Upon the discovery of a new file, this will be used as the
00120       // "last" event id in the cached event range. 
00121       else {
00122         eventRange.first.second = event2_->event()->id();
00123         eventRange.second = event2_->eventIndex();
00124       }
00125       firstFile = false;
00126     }
00127     // due to the invailability of a "look ahead" operation, we have one additional "put" to make
00128     // after the loop (which puts the "last" event, not "this" event.
00129     if ( foundAny ) {
00130       event_id_range toAdd = eventRange.first;
00131       secFileMapSorted_[ toAdd ] = eventRange.second;
00132     }
00133 //     std::cout << "Dumping run range to event id list:" << std::endl;
00134 //     for ( sec_file_range_index_map::const_iterator mBegin = secFileMapSorted_.begin(),
00135 //          mEnd = secFileMapSorted_.end(),
00136 //          mit = mBegin;
00137 //        mit != mEnd; ++mit ) {
00138 //       char buff[1000];
00139 //       event2_->to( mit->second );
00140 //       sprintf(buff, "[%10d,%10d - %10d,%10d] ---> %10d",
00141 //            mit->first.first.run(),
00142 //            mit->first.first.event(),
00143 //            mit->first.second.run(),
00144 //            mit->first.second.event(),
00145 //            mit->second );
00146 //       std::cout << buff << std::endl;
00147 //     }
00148   }
00149 
00150 }
00151 
00152 // MultiChainEvent::MultiChainEvent(const MultiChainEvent& rhs)
00153 // {
00154 //    // do actual copying here;
00155 // }
00156 
00157 MultiChainEvent::~MultiChainEvent()
00158 {
00159 }
00160 
00161 //
00162 // assignment operators
00163 //
00164 // const MultiChainEvent& MultiChainEvent::operator=(const MultiChainEvent& rhs)
00165 // {
00166 //   //An exception safe implementation is
00167 //   MultiChainEvent temp(rhs);
00168 //   swap(rhs);
00169 //
00170 //   return *this;
00171 // }
00172 
00173 //
00174 // member functions
00175 //
00176 
00177 const MultiChainEvent& 
00178 MultiChainEvent::operator++()
00179 {
00180    event1_->operator++();
00181    return *this;
00182 }
00183 
00185 bool
00186 MultiChainEvent::to(Long64_t iIndex) 
00187 {
00188   return event1_->to( iIndex );
00189 }
00190 
00191 
00193 bool
00194 MultiChainEvent::to(edm::EventID id) 
00195 {
00196   return to(id.run(), id.luminosityBlock(), id.event());
00197 }
00198 
00200 bool
00201 MultiChainEvent::to(edm::RunNumber_t run, edm::LuminosityBlockNumber_t lumi, edm::EventNumber_t event) 
00202 {
00203    return event1_->to( run, lumi, event );
00204 }
00205 
00207 bool
00208 MultiChainEvent::to(edm::RunNumber_t run, edm::EventNumber_t event) 
00209 {
00210    return to( run, 0U, event );
00211 }
00212 
00213 
00215 bool
00216 MultiChainEvent::toSec(Long64_t iIndex) 
00217 {
00218    return event2_->to( iIndex );
00219 }
00220 
00221 // Go to event with event id "id"
00222 bool
00223 MultiChainEvent::toSec (const edm::EventID &id) 
00224 {
00225    // First try this file.
00226    if ( event2_->event_->to( id ) ) 
00227    {
00228       // Found it, return. 
00229       return true;
00230    }
00231    // Second, assume that the secondary files are each in run/event
00232    // order.  So, let's loop over all files and see if we can figure
00233    // out where the event ought to be.
00234    for ( sec_file_range_index_map::const_iterator mBegin = 
00235             secFileMapSorted_.begin(),
00236             mEnd = secFileMapSorted_.end(),
00237             mit = mBegin;
00238          mit != mEnd; 
00239          ++mit ) 
00240    {
00241       if ( id < mit->first.first || id > mit->first.second ) 
00242       {
00243          // We don't expect this event to be in this file, so don't
00244          // bother checking it right now.
00245          continue;
00246       }
00247       // If we're here, then we have a reasonable belief that this
00248       // event is in this secondary file.  This part is
00249       // expensive. switchToFile does memory allocations and opens the
00250       // files which becomes very time consuming. This should be done
00251       // as infrequently as possible.
00252       event2_->switchToFile( mit->second );
00253       // Is it here?
00254       if (event2_->to( id ))
00255       {
00256          // Yes!
00257          return true;
00258       }
00259       // if we assumed that the secondary files were not each in
00260       // order, but were non-overlapping, we could break here.  But at
00261       // this point, we might as well keep going.
00262    } // for loop over files
00263 
00264    // if we are still here, then we did not find the id in question,
00265    // do it the old fashioned way.  This will open up each secondary
00266    // file and explicitly check to see if the event is there.
00267    if (event2_->to(id))
00268    {
00269       return true;
00270    }
00271    // if we're still here, then there really is no matching event in
00272    // the secondary files.  Throw.
00273    throw cms::Exception("ProductNotFound") << "Cannot find id " 
00274                                            << id.run() << ", " 
00275                                            << id.event() 
00276                                            << " in secondary list. Exiting." 
00277                                            << std::endl;
00278    // to make the compiler happy
00279    return false;
00280 }
00281   
00283 bool 
00284 MultiChainEvent::toSec(edm::RunNumber_t run, edm::LuminosityBlockNumber_t lumi, edm::EventNumber_t event) 
00285 {
00286   return toSec( edm::EventID( run, lumi, event) );
00287 }
00288 
00289 // Go to the very first Event
00291 bool 
00292 MultiChainEvent::toSec(edm::RunNumber_t run, edm::EventNumber_t event) 
00293 {
00294   return toSec( edm::EventID( run, 0U, event) );
00295 }
00296 
00297 // Go to the very first Event
00298 const MultiChainEvent& 
00299 MultiChainEvent::toBegin() 
00300 {
00301    event1_->toBegin();
00302    return *this;
00303 }
00304 
00305 //
00306 // const member functions
00307 //
00308 const std::string 
00309 MultiChainEvent::getBranchNameFor(const std::type_info& iType, 
00310                              const char* iModule, 
00311                              const char* iInstance, 
00312                              const char* iProcess) const
00313 {
00314   return event1_->getBranchNameFor(iType,iModule,iInstance,iProcess);
00315 }
00316 
00317 const std::vector<edm::BranchDescription>&
00318 MultiChainEvent::getBranchDescriptions() const
00319 {
00320   return event1_->getBranchDescriptions();
00321 }
00322 
00323 const std::vector<std::string>&
00324 MultiChainEvent::getProcessHistory() const
00325 {
00326   return event1_->getProcessHistory();
00327 }
00328 
00329 edm::ProcessHistory const&
00330 MultiChainEvent::processHistory() const
00331 {
00332   return event1_->processHistory();
00333 }
00334 
00335 edm::EventAuxiliary const&
00336 MultiChainEvent::eventAuxiliary() const
00337 {
00338    return event1_->eventAuxiliary();
00339 }
00340    
00341 bool 
00342 MultiChainEvent::getByLabel(const std::type_info& iType, 
00343                        const char* iModule, 
00344                        const char* iInstance, 
00345                        const char* iProcess, 
00346                        void* iValue) const
00347 {
00348   bool ret1 = event1_->getByLabel(iType,iModule,iInstance,iProcess,iValue);
00349   if ( !ret1 ) {
00350     (const_cast<MultiChainEvent*>(this))->toSec(event1_->id());
00351     bool ret2 = event2_->getByLabel(iType,iModule,iInstance,iProcess,iValue);
00352     if ( !ret2 ) return false;
00353   }
00354   return true;
00355 }
00356 
00357 edm::EDProduct const* MultiChainEvent::getByProductID(edm::ProductID const&iID) const 
00358 {
00359   // First try the first file
00360   edm::EDProduct const * prod = event1_->getByProductID(iID);
00361   // Did not find the product, try secondary file
00362   if ( 0 == prod ) {
00363     (const_cast<MultiChainEvent*>(this))->toSec(event1_->id());
00364     prod = event2_->getByProductID(iID);
00365     if ( 0 == prod ) {
00366       throw cms::Exception("ProductNotFound") << "Cannot find product " << iID;
00367     }
00368   }
00369   return prod;
00370 }
00371 
00372 
00373 bool 
00374 MultiChainEvent::isValid() const
00375 {
00376   return event1_->isValid();
00377 }
00378 MultiChainEvent::operator bool() const
00379 {
00380   return *event1_;
00381 }
00382 
00383 bool 
00384 MultiChainEvent::atEnd() const 
00385 {
00386   return event1_->atEnd();
00387 }
00388 
00389 Long64_t 
00390 MultiChainEvent::size() const
00391 {
00392   return event1_->size();
00393 }
00394 
00395 edm::TriggerNames const&
00396 MultiChainEvent::triggerNames(edm::TriggerResults const& triggerResults) const
00397 {
00398   edm::TriggerNames const* names = triggerNames_(triggerResults);
00399   if (names != 0) return *names;
00400 
00401   event1_->fillParameterSetRegistry();
00402   names = triggerNames_(triggerResults);
00403   if (names != 0) return *names;
00404 
00405   // If we cannot find it in the primary file, this probably will
00406   // not help but try anyway
00407   event2_->to( event1_->id() );
00408   event2_->fillParameterSetRegistry();
00409   names = triggerNames_(triggerResults);
00410   if (names != 0) return *names;
00411 
00412   throw cms::Exception("TriggerNamesNotFound")
00413     << "TriggerNames not found in ParameterSet registry";
00414   return *names;
00415 }
00416 
00417 edm::TriggerResultsByName
00418 MultiChainEvent::triggerResultsByName(std::string const& process) const {
00419 
00420   fwlite::Handle<edm::TriggerResults> hTriggerResults;
00421   hTriggerResults.getByLabel(*this,"TriggerResults","",process.c_str());
00422   if ( !hTriggerResults.isValid()) {
00423     return edm::TriggerResultsByName(0,0);
00424   }
00425 
00426   edm::TriggerNames const* names = triggerNames_(*hTriggerResults);
00427 
00428   if (names == 0) {
00429     event1_->fillParameterSetRegistry();
00430     names = triggerNames_(*hTriggerResults);
00431   }
00432 
00433   if (names == 0) {
00434     event2_->to( event1_->id() );
00435     event2_->fillParameterSetRegistry();
00436     names = triggerNames_(*hTriggerResults);
00437   }
00438 
00439   return edm::TriggerResultsByName(hTriggerResults.product(), names);
00440 }
00441 
00442 //
00443 // static member functions
00444 //
00445 void 
00446 MultiChainEvent::throwProductNotFoundException(const std::type_info& iType, 
00447                                           const char* iModule,
00448                                           const char* iInstance,
00449                                           const char* iProcess) {
00450   ChainEvent::throwProductNotFoundException(iType,iModule,iInstance,iProcess);
00451 }
00452 }