CMS 3D CMS Logo

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