CMS 3D CMS Logo

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