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
00050
00051
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
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
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
00101
00102
00103
00104
00105
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
00155
00156
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
00170
00171
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
00214
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
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
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
00275
00276
00277
00278 }
00279
00280 m_file->cd();
00281 m_eventTree->SetEventList(0);
00282
00283
00284
00285
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
00299 previousBranchAddresses.push_back(0);
00300 continue;
00301 }
00302
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
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
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
00377
00378
00379
00380
00381 bool junction_mode = true;
00382 if (selection.find("||")!=std::string::npos)
00383 junction_mode = false;
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
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
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
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 }