CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_0/src/Fireworks/Core/src/FWFileEntry.cc

Go to the documentation of this file.
00001 #include <boost/regex.hpp>
00002 
00003 #include "TFile.h"
00004 #include "TTreeCache.h"
00005 #include "TError.h"
00006 #include "TMath.h"
00007 
00008 #include "Fireworks/Core/interface/FWFileEntry.h"
00009 #include "DataFormats/FWLite/interface/Handle.h"
00010 #include "FWCore/Common/interface/TriggerNames.h"
00011 #include "DataFormats/Common/interface/TriggerResults.h"
00012 #include "DataFormats/Provenance/interface/ProcessConfiguration.h"
00013 #include "DataFormats/Provenance/interface/ReleaseVersion.h"
00014 
00015 #define private public
00016 #include "Fireworks/Core/interface/FWEventItem.h"
00017 #undef private
00018 
00019 #include "Fireworks/Core/interface/FWEventItemsManager.h"
00020 #include "Fireworks/Core/interface/fwLog.h"
00021 #include "Fireworks/Core/interface/fwPaths.h"
00022 
00023 FWFileEntry::FWFileEntry(const std::string& name, bool checkVersion) :
00024    m_name(name), m_file(0), m_eventTree(0), m_event(0),
00025    m_needUpdate(true), m_globalEventList(0)
00026 {
00027    openFile(checkVersion);
00028 }
00029 
00030 FWFileEntry::~FWFileEntry()
00031 {
00032    for(std::list<Filter*>::iterator i = m_filterEntries.begin(); i != m_filterEntries.end(); ++i)
00033       delete (*i)->m_eventList;
00034 
00035    delete m_globalEventList;
00036 }
00037 
00038 void FWFileEntry::openFile(bool checkVersion)
00039 {
00040    gErrorIgnoreLevel = 3000; // suppress warnings about missing dictionaries
00041    TFile *newFile = TFile::Open(m_name.c_str());
00042    if (newFile == 0 || newFile->IsZombie() || !newFile->Get("Events")) {
00043       //  std::cout << "Invalid file. Ignored." << std::endl;
00044       // return false;
00045       throw std::runtime_error("Invalid file. Ignored.");
00046    }
00047    gErrorIgnoreLevel = -1;
00048    m_file = newFile;
00049    m_event = new fwlite::Event(m_file);
00050    m_eventTree = dynamic_cast<TTree*>(m_file->Get("Events"));
00051 
00052    if (m_eventTree == 0)
00053    { 
00054       throw std::runtime_error("Cannot find TTree 'Events' in the data file");
00055    }
00056 
00057    // check CMSSW relese version for compatibility
00058    if (checkVersion) {
00059       typedef std::vector<edm::ProcessConfiguration> provList;
00060   
00061       TTree   *metaData = dynamic_cast<TTree*>(m_file->Get("MetaData"));
00062       TBranch *b = metaData->GetBranch("ProcessConfiguration");
00063       provList *x = 0;
00064       b->SetAddress(&x);
00065       b->GetEntry(0);
00066 
00067       const edm::ProcessConfiguration& dd= x->back();
00068 
00069       fwLog(fwlog::kInfo) << "Checking process history. " << m_name.c_str() << " latest process \""  << dd.processName() << "\", version " << dd.releaseVersion() << std::endl;
00070 
00071       b->SetAddress(0);
00072       TString v = dd.releaseVersion();
00073       if (!fireworks::acceptDataFormatsVersion(v))
00074       {
00075          int* di = (fireworks::supportedDataFormatsVersion());
00076          TString msg = Form("incompatible data: Process version does not mactch major data formats version. File produced with %s. Data formats version \"CMSSW_%d_%d_%d\".\n", 
00077                             dd.releaseVersion().c_str(), di[0], di[1], di[2]);
00078          msg += "Use --no-version-check option if you still want to view the file.\n";
00079          throw std::runtime_error(msg.Data());
00080       }
00081    }
00082 
00083 
00084    // This now set in DataHelper
00085    //TTreeCache::SetLearnEntries(2);
00086    //m_eventTree->SetCacheSize(10*1024*1024);
00087    //TTreeCache *tc = (TTreeCache*) m_file->GetCacheRead();
00088    //tc->AddBranch(m_event->auxBranch_,kTRUE);
00089    //tc->StartLearningPhase();
00090 }
00091 
00092 void FWFileEntry::closeFile()
00093 {
00094    if (m_file) {
00095       printf("Reading %lld bytes in %d transactions.\n",
00096              m_file->GetBytesRead(), m_file->GetReadCalls());
00097       m_file->Close();
00098       delete m_file;
00099    }
00100    if (m_event) delete m_event;
00101 }
00102 
00103 //______________________________________________________________________________
00104 
00105 bool FWFileEntry::isEventSelected(int tree_entry)
00106 {
00107    int idx = m_globalEventList->GetIndex(tree_entry);
00108    return idx >= 0;
00109 }
00110 
00111 bool FWFileEntry::hasSelectedEvents()
00112 {
00113    return m_globalEventList->GetN() > 0;
00114 }
00115 
00116 int FWFileEntry::firstSelectedEvent()
00117 {
00118    if (m_globalEventList->GetN() > 0)
00119    {
00120       return m_globalEventList->GetEntry(0);
00121    }
00122    else
00123    {
00124       return -1;
00125    }
00126 }
00127 
00128 int FWFileEntry::lastSelectedEvent()
00129 {
00130    if (m_globalEventList->GetN() > 0)
00131       return m_globalEventList->GetEntry(m_globalEventList->GetN() - 1);
00132    else
00133       return -1;
00134 }
00135 
00136 int FWFileEntry::nextSelectedEvent(int tree_entry)
00137 {
00138    // Find next selected event after the current one.
00139    // This returns the index in the selected event list.
00140    // If none exists -1 is returned.
00141 
00142    const Long64_t *list = m_globalEventList->GetList();
00143    Long64_t val = tree_entry;
00144    Long64_t idx = TMath::BinarySearch(m_globalEventList->GetN(), list, val);
00145    ++idx;
00146    if (idx >= m_globalEventList->GetN() || idx < 0)
00147       return -1;
00148    return list[idx];
00149 }
00150 
00151 int FWFileEntry::previousSelectedEvent(int tree_entry)
00152 {
00153    // Find first selected event before current one.
00154    // This returns the index in the selected event list.
00155    // If none exists -1 is returned.
00156 
00157    const Long64_t *list = m_globalEventList->GetList();
00158    Long64_t val = tree_entry;
00159    Long64_t idx = TMath::BinarySearch(m_globalEventList->GetN(), list, val);
00160    if (list[idx] == val)
00161       --idx;
00162    if (idx >= 0)
00163       return list[idx];
00164    else
00165       return -1;
00166 }
00167 
00168 //______________________________________________________________________________
00169 bool FWFileEntry::hasActiveFilters()
00170 {
00171    for (std::list<Filter*>::iterator it = m_filterEntries.begin(); it != m_filterEntries.end(); ++it)
00172    {
00173       if ((*it)->m_selector->m_enabled)
00174          return true;
00175    }
00176 
00177    return false;
00178 }
00179 
00180 //______________________________________________________________________________
00181 void FWFileEntry::updateFilters(const FWEventItemsManager* eiMng, bool globalOR)
00182 {
00183    if (!m_needUpdate)
00184       return;
00185    
00186    if (m_globalEventList)
00187       m_globalEventList->Reset();
00188    else
00189       m_globalEventList = new FWTEventList;
00190 
00191    for (std::list<Filter*>::iterator it = m_filterEntries.begin(); it != m_filterEntries.end(); ++it)
00192    {
00193       if ((*it)->m_selector->m_enabled && (*it)->m_needsUpdate)
00194       {
00195          runFilter(*it, eiMng);
00196       }
00197       // Need to re-check if enabled after filtering as it can be set to false
00198       // in runFilter().
00199       if ((*it)->m_selector->m_enabled)
00200       {
00201          if ((*it)->hasSelectedEvents())
00202          {
00203             if (globalOR || m_globalEventList->GetN() == 0)
00204             {
00205                m_globalEventList->Add((*it)->m_eventList);
00206             }
00207             else
00208             {
00209                m_globalEventList->Intersect((*it)->m_eventList);
00210             }
00211          }
00212          else if (!globalOR)
00213          {
00214             m_globalEventList->Reset();
00215             break;
00216          }
00217       }
00218    }
00219    
00220    fwLog(fwlog::kDebug) << "FWFileEntry::updateFilters in [" << m_file->GetName() << "]  global selection [" << m_globalEventList->GetN() << "/" <<  m_eventTree->GetEntries() << "]" << std::endl;
00221 
00222    m_needUpdate = false;
00223 }
00224 
00225 //_____________________________________________________________________________
00226 void FWFileEntry::runFilter(Filter* filter, const FWEventItemsManager* eiMng)
00227 {
00228    if (!filter->m_selector->m_triggerProcess.empty())
00229    {
00230       filterEventsWithCustomParser(filter);
00231       return;
00232    }
00233     
00234    // parse selection for known Fireworks expressions
00235    std::string interpretedSelection = filter->m_selector->m_expression;
00236     
00237    for (FWEventItemsManager::const_iterator i = eiMng->begin(),
00238            end = eiMng->end(); i != end; ++i)
00239    {
00240       FWEventItem *item = *i;
00241       if (item == 0) 
00242          continue;
00243       //FIXME: hack to get full branch name filled
00244       if (item->m_event == 0) 
00245       {
00246          item->m_event = m_event;
00247          item->getPrimaryData();
00248          item->m_event = 0;
00249       }
00250       boost::regex re(std::string("\\$") + (*i)->name());
00251       std::string fullBranchName = m_event->getBranchNameFor(*(item->type()->GetTypeInfo()), 
00252                                                              item->moduleLabel().c_str(), 
00253                                                              item->productInstanceLabel().c_str(),
00254                                                              item->processName().c_str());
00255       
00256       interpretedSelection = boost::regex_replace(interpretedSelection, re,
00257                                                   fullBranchName + ".obj");
00258       // printf("selection after applying s/%s/%s/: %s\n",
00259       //     (std::string("\\$") + (*i)->name()).c_str(),
00260       //     ((*i)->m_fullBranchName + ".obj").c_str(),
00261       //     interpretedSelection.c_str());
00262    }
00263 
00264    m_file->cd();
00265    m_eventTree->SetEventList(0);
00266    
00267    // Since ROOT will leave any TBranches used in the filtering at the last event,
00268    // we need to be able to reset them to what fwlite::Event expects them to be
00269    // we do this by holding onto the old buffers and create temporary new ones.
00270    
00271    TObjArray* branches = m_eventTree->GetListOfBranches();
00272    std::vector<void*> previousBranchAddresses;
00273    previousBranchAddresses.reserve(branches->GetEntriesFast());
00274    {
00275       std::auto_ptr<TIterator> pIt( branches->MakeIterator());
00276       while(TObject* branchObj = pIt->Next()) {
00277          TBranch* b = dynamic_cast<TBranch*> (branchObj);
00278          if(0!=b) {
00279             const char * name = b->GetName();
00280             unsigned int length = strlen(name);
00281             if(length > 1 && name[length-1]!='.') {
00282                //this is not a data branch so we should ignore it
00283                previousBranchAddresses.push_back(0);
00284                continue;
00285             }
00286             //std::cout <<" branch '"<<b->GetName()<<"' "<<static_cast<void*>(b->GetAddress())<<std::endl;
00287             if(0!=b->GetAddress()) {
00288                b->SetAddress(0);
00289             }
00290             previousBranchAddresses.push_back(b->GetAddress());
00291          } else {
00292             previousBranchAddresses.push_back(0);
00293          }
00294       }
00295    }
00296 
00297    FWTEventList *flist = (FWTEventList*) gDirectory->Get("fworks_filter");
00298    if (flist == 0)
00299       flist = new FWTEventList("fworks_filter");
00300 
00301    Int_t result = m_eventTree->Draw(">>fworks_filter", interpretedSelection.c_str());
00302    
00303    if (filter->m_eventList)
00304       filter->m_eventList->Reset();
00305    else
00306       filter->m_eventList = new FWTEventList;
00307 
00308    filter->m_eventList->Add(flist);
00309       
00310    if (result < 0)
00311       fwLog(fwlog::kWarning) << "FWFile::runFilter in file [" << m_file->GetName() << "] filter [" << filter->m_selector->m_expression << "] is invalid." << std::endl;
00312    else      
00313       fwLog(fwlog::kDebug) << "FWFile::runFilter is file [" << m_file->GetName() << "], filter [" << filter->m_selector->m_expression << "] has ["  << flist->GetN() << "] events selected" << std::endl;
00314 
00315    // Set back the old branch buffers.
00316    {
00317       std::auto_ptr<TIterator> pIt( branches->MakeIterator());
00318       std::vector<void*>::const_iterator itAddress = previousBranchAddresses.begin();
00319       while(TObject* branchObj = pIt->Next()) {
00320          TBranch* b = dynamic_cast<TBranch*> (branchObj);
00321          if(0!=b && 0!=*itAddress) {
00322             b->SetAddress(*itAddress);
00323          }
00324          ++itAddress;
00325       }
00326    }
00327 
00328    filter->m_needsUpdate = false;
00329 }
00330 
00331 //______________________________________________________________________________
00332 
00333 bool
00334 FWFileEntry::filterEventsWithCustomParser(Filter* filterEntry)
00335 {
00336    std::string selection(filterEntry->m_selector->m_expression);
00337 
00338    boost::regex re_spaces("\\s+");
00339    selection = boost::regex_replace(selection,re_spaces,"");
00340    if (selection.find("&&") != std::string::npos &&
00341        selection.find("||") != std::string::npos )
00342    {
00343       // Combination of && and || operators not supported.
00344       return false;
00345    }
00346 
00347    fwlite::Handle<edm::TriggerResults> hTriggerResults;
00348    edm::TriggerNames const* triggerNames(0);
00349    try
00350    {
00351       hTriggerResults.getByLabel(*m_event,"TriggerResults","", filterEntry->m_selector->m_triggerProcess.c_str());
00352       triggerNames = &(m_event->triggerNames(*hTriggerResults));
00353    }
00354    catch(...)
00355    {
00356       fwLog(fwlog::kWarning) << " failed to get trigger results with process name "<<  filterEntry->m_selector->m_triggerProcess << std::endl;
00357       return false;
00358    }
00359    
00360    // std::cout << "Number of trigger names: " << triggerNames->size() << std::endl;
00361    // for (unsigned int i=0; i<triggerNames->size(); ++i)
00362    //  std::cout << " " << triggerNames->triggerName(i);
00363    //std::cout << std::endl;
00364    
00365    bool junction_mode = true; // AND
00366    if (selection.find("||")!=std::string::npos)
00367       junction_mode = false; // OR
00368 
00369    boost::regex re("\\&\\&|\\|\\|");
00370 
00371    boost::sregex_token_iterator i(selection.begin(), selection.end(), re, -1);
00372    boost::sregex_token_iterator j;
00373 
00374    // filters and how they enter in the logical expression
00375    std::vector<std::pair<unsigned int,bool> > filters;
00376 
00377    while (i != j)
00378    {
00379       std::string filter = *i++;
00380       bool flag = true;
00381       if (filter[0] == '!')
00382       {
00383          flag = false;
00384          filter.erase(filter.begin());
00385       }
00386       unsigned int index = triggerNames->triggerIndex(filter);
00387       if (index == triggerNames->size()) 
00388       {
00389          // Trigger name not found.
00390          return false;
00391       }
00392       filters.push_back(std::make_pair(index, flag));
00393    }
00394    if (filters.empty())
00395       return false;
00396 
00397    if (filterEntry->m_eventList)
00398       filterEntry->m_eventList->Reset();
00399    else
00400        filterEntry->m_eventList = new FWTEventList();
00401    FWTEventList* list = filterEntry->m_eventList;
00402 
00403    // loop over events
00404    edm::EventID currentEvent = m_event->id();
00405    unsigned int iEvent = 0;
00406 
00407    for (m_event->toBegin(); !m_event->atEnd(); ++(*m_event))
00408    {
00409       hTriggerResults.getByLabel(*m_event,"TriggerResults","", filterEntry->m_selector->m_triggerProcess.c_str());
00410       std::vector<std::pair<unsigned int,bool> >::const_iterator filter = filters.begin();
00411       bool passed = hTriggerResults->accept(filter->first) == filter->second;
00412       while (++filter != filters.end())
00413       {
00414          if (junction_mode)
00415             passed &= hTriggerResults->accept(filter->first) == filter->second;
00416          else
00417             passed |= hTriggerResults->accept(filter->first) == filter->second;
00418       }
00419       if (passed)
00420          list->Enter(iEvent);
00421       ++iEvent;
00422    }
00423    m_event->to(currentEvent);
00424 
00425    filterEntry->m_needsUpdate = false;
00426    
00427    fwLog(fwlog::kDebug) << "FWFile::filterEventsWithCustomParser file [" << m_file->GetName() << "], filter [" << filterEntry->m_selector->m_expression << "], selected [" << list->GetN() << "]"  << std::endl;
00428    
00429    return true;
00430 }