CMS 3D CMS Logo

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