#include #include #include "TString.h" #include "TRegexp.h" #include "TObjArray.h" #include "TObjString.h" #include "TFile.h" #include "TKey.h" #include "Jeep/JParser.hh" #include "JSupport/JMeta.hh" #include "JLang/JPredicate.hh" #include "JCompareHistograms/JTest_t.hh" #include "JCompareHistograms/JTestDictionary.hh" #include "JGizmo/JRootObjectID.hh" namespace { /* * Gets list of ROOT object identifiers in a ROOT TDirectory and stores it in a vector. * Note: Subdirectories are searched recursively. * * \param dir The ROOT directory */ std::vector readDir(TDirectory* dir) { using namespace std; using namespace JPP; vector buffer1; TIter iter(dir->GetListOfKeys()); for (TKey* key; (key = (TKey*) iter.Next()) != NULL; ) { if (key->IsFolder()){ TDirectory *subdir = dir->GetDirectory(key->GetName()); vector buffer2 = readDir(subdir); buffer1.insert(buffer1.end(), buffer2.begin(), buffer2.end()); } else { const string fullName = MAKE_STRING(dir->GetPath() << JRootObjectID::PATHNAME_SEPARATOR << key->GetName()); JRootObjectID objectID(fullName); buffer1.push_back(objectID); } } return buffer1; } } /** * \file * * Program to compare histograms in root files that have same directory structure,\n * and where the histograms have the same names. * The input histograms and the test to be applied for each histogram are specified\n * in an ASCII formatted steering file which is passed by the command line.\n\n * * Each row of the steering file should have multiple columns.\n\n * * Column 1 is the name of the histogram to be compared (including the full path inside the root file)\n * Column 2 is an integer value that indicates the test to be performed. See JTestDictionary()\n * Columns 3..n are reserved for the different parameters of the test.\n\n * * \author rgruiz, bjung */ int main(int argc, char** argv) { using namespace JPP; using namespace std; string steeringFile; string file1; string file2; string output; string ascii; vector keys; bool onlyFailures; int debug; const array_type& listOfKeys = get_keys(JTestSummary().getProperties()); try { const string& keysExplainer = MAKE_STRING("Terminal output:" << endl << listOfKeys); JParser<> zap("\nProgram to compare histograms in root files that have the same directory structure. See the link below this usage for further details.\n"); zap['s'] = make_field(steeringFile , "ASCII steering file with list of histograms and tests"); zap['a'] = make_field(file1 , "input file 1"); zap['b'] = make_field(file2 , "input file 2"); zap['o'] = make_field(output , "output file root") = "zebramantis.root"; zap['t'] = make_field(ascii , "output file txt" ) = "zebramantis.txt"; zap['k'] = make_field(keys , keysExplainer ) = JPARSER::initialised(); zap['w'] = make_field(onlyFailures , "write only failed tests" ); zap['d'] = make_field(debug) = 2; zap(argc,argv); } catch(const exception &error) { ERROR(error.what() << endl); } if (keys.empty()) { keys = listOfKeys; } TFile* f1 = TFile::Open(file1.c_str()); TFile* f2 = TFile::Open(file2.c_str()); TFile out(output.c_str(),"recreate"); ofstream results; results.open (ascii); results << "# " << listOfKeys << endl; const vector objectIDs = readDir(f1); std::ifstream infile(steeringFile); JTestDictionary d; size_t npassed = 0; size_t nfailed = 0; for (string line; getline(infile, line); ) { istringstream iss(line); TString name; int testID; if (!(iss >> name >> testID)) { continue; } DEBUG("Input: " << name << ' ' << testID << endl); const TRegexp regexp(name); for (vector::const_iterator objectID = objectIDs.cbegin() ; objectID != objectIDs.cend() ; ++objectID) { const TString& dirName = objectID->getDirectory(); const TString& fullName = objectID->getFullObjectName(); DEBUG("Key: " << fullName << " match = " << fullName.Contains(regexp) << endl); if ((fullName.Index(regexp) != -1)) { TObject* obj1 = (TObject*)f1->Get(fullName); TObject* obj2 = (TObject*)f2->Get(fullName); if (!obj1 || !obj2) { DEBUG("Could not retrieve " << fullName << endl); continue; } d[testID]->read(iss); d[testID]->test(obj1,obj2); if (dirName.Length() > 0 && !out.GetDirectory(dirName)) { if (dirName[0] == JRootObjectID::PATHNAME_SEPARATOR) { // Remove leading forward slash out.mkdir(TString(dirName(1, dirName.Length() - 1))); } else { out.mkdir(dirName); } } out.cd(dirName); for (vector::iterator r = d[testID]->results.begin() ; r != d[testID]->results.end() ; ++r) { if (onlyFailures && r->passed) { continue; } print(cout, *r, keys.cbegin(), keys.cend(), ' ', false); print(results, *r, listOfKeys.cbegin(), listOfKeys.cend(), ' ', true); r->obj->Write(); } const size_t Npass = count_if(d[testID]->results.cbegin(), d[testID]->results.cend(), make_predicate(&JTestResult::passed, true)); npassed += Npass; nfailed += (d[testID]->results.size() - Npass); d[testID]->clear(); } } } infile.close(); results << WHITE << "# PASSED: " << npassed << " " << " FAILED: " << nfailed << " FAILURE FRACTION: " << float (nfailed)/(nfailed+npassed) << endl; putObject(&out, JMeta(argc, argv)); JMeta::copy(file1.c_str(), out); JMeta::copy(file2.c_str(), out); results.close(); out .Close(); return 0; }