CMS 3D CMS Logo

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