CMS 3D CMS Logo

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