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;
00041 TFile *newFile = TFile::Open(m_name.c_str());
00042 if (newFile == 0 || newFile->IsZombie() || !newFile->Get("Events")) {
00043
00044
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
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
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
00099
00100
00101
00102
00103
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
00153
00154
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
00168
00169
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
00212
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
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
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
00273
00274
00275
00276 }
00277
00278 m_file->cd();
00279 m_eventTree->SetEventList(0);
00280
00281
00282
00283
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
00297 previousBranchAddresses.push_back(0);
00298 continue;
00299 }
00300
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
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
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
00375
00376
00377
00378
00379 bool junction_mode = true;
00380 if (selection.find("||")!=std::string::npos)
00381 junction_mode = false;
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
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
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
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 }