Skip to content
Snippets Groups Projects
Commit 9dcd9eb7 authored by Administrator's avatar Administrator
Browse files

Compare leaves of trees in two files

The added macro is meant to compare the data stored in trees of two different
files for identity. The macro generates a list of all relevant leaves of one
of the trees, loops over all these leaves and draws the difference of the data
in the leaves of the two different files. If the data is identical the result
is a histogram with a delta function at 0 which can easily be detected.
The macro returns 0 in case all detected leaves are identical and a non zero
value if this isn't the case.
parent caa3df22
No related branches found
No related tags found
No related merge requests found
std::vector<std::pair<TString,TString>> GetLeafNames(TTree*);
Bool_t CheckHistogram(TH1* compHist, TH1* origHist, TH1* newHist, std::stringstream& outstream, Bool_t& okay);
int TreeCompareAuto(TString fileName1 = "",
TString fileName2 =""
)
{
if (fileName1.IsNull() || fileName2.IsNull() ) {
cout << "Filenames are not defined" << endl;
exit(42);
}
// Get the output tree from the original file
TFile* file1 = TFile::Open(fileName1, "READ");
if (nullptr == file1) return 42;
TTree* tree1 = (TTree*) file1->Get("cbmsim");
// Get the output tree from the file whcih should be compared
TFile* file2 = TFile::Open(fileName2, "READ");
if (nullptr == file2) return 42;
TTree* tree2 = (TTree*) file2->Get("cbmsim");
// Add the output tree from the file to compare as friend to the tree
// of the original file. This allows to access a data member of the
// original file by e.g. StsHit.fX and the data element of the second tree
// by tree2.StsHit.fX
tree1->AddFriend(tree2, "tree2");
// Define pairs of data members to compare. One from each tree.
// This allows to compare them also if names or the structure of
// the classses change.
std::vector<std::pair<TString,TString>> leaves=GetLeafNames(tree1);
/*
for(auto leaf : leaves) {
TString leafName = leaf.first;
TString leafName1 = leaf.second;
cout << leafName << " : " << leafName1 << endl;
}
*/
// exit(1);
TCanvas c1;
std::stringstream outstream;
Bool_t okay{kTRUE};
Int_t numTestedLeaves{0};
Int_t numFailedLeaves{0};
for (auto leaf : leaves) {
TString leafName = leaf.first;
TString leafName1 = leaf.second;
TString command1 = leafName+">>htemp";
tree1->Draw(command1);
// std::cout << command1 << std::endl;
int entries1{0};
float low1{0.};
float high1{0.};
int nBins1{0};
auto htemp = (TH1F*)gPad->GetPrimitive("htemp");
if (htemp) {
entries1 = htemp->GetEntries();
nBins1 = htemp->GetNbinsX();
low1 = htemp->GetXaxis()->GetXmin();
high1 = htemp->GetXaxis()->GetXmax();
}
// std::cout << low1 << ", " << high1 << ", " << nBins1 <<std::endl;
// command1 = leafName1 + ">>hist1(" + nBins +"," + low + "," + high +")";
command1 = leafName1 + ">>hist1";
tree1->Draw(command1);
auto hist1 = (TH1F*)gPad->GetPrimitive("hist1");
int entries2{0};
float low2{0.};
float high2{0.};
int nBins2{0};
if (hist1) {
entries2 = hist1->GetEntries();
nBins2 = hist1->GetNbinsX();
low2 = hist1->GetXaxis()->GetXmin();
high2 = hist1->GetXaxis()->GetXmax();
}
// std::cout << low2 << ", " << high2 << ", " << nBins2 <<std::endl;
if ( ( 0 == entries1 && 0 != entries2 ) ||
( 0 != entries1 && 0 == entries2 ) ) {
std::cout << "One of the distributions is empty" << std::endl;
okay=kFALSE;
}
if ( 0 == entries1 && 0 == entries2 ) {
// outstream << "Both Histograms are empty." << std::endl;
//
hist1->Clear();
htemp->Clear();
continue;
}
// When executing the draw command "Leaf1 - Leaf2" the subtraction is
// executed entry by entry. If the content of the class members are
// identical the result is a histogram with a delta function at 0
// If the content is differnt one gets a distribution which is
// detected.
TString command = leafName + "-" + leafName1 + ">>hist(20, -10.,10.)";
outstream << "Comparing " << leafName << " and " << leafName1 << std::endl;
tree1->Draw(command);
auto hist = (TH1F*)gPad->GetPrimitive("hist");
numTestedLeaves++;
// Check if the entries in the tree are identical
Bool_t leafIsIdentical=CheckHistogram(hist, htemp, hist1, outstream, okay);
// If the entries are not identical check if the histograms are
// identical. This is the case if the entries in the tree are sorted
// differently
if ( ! leafIsIdentical) {
okay=kFALSE;
numFailedLeaves++;
}
outstream << "**********************" << std::endl;
hist1->Clear();
hist->Clear();
htemp->Clear();
}
if (! okay) {
std::cout << outstream.str();
std::cout << "Test failed." << std::endl;
std::cout << numFailedLeaves << " of " << numTestedLeaves
<< " leaves are different." << std::endl;
return 1;
}
std::cout << outstream.str();
std::cout << "Test passed. All leaves of all branches are exactly identical." << std::endl;
return 0;
}
Bool_t CheckHistogram(TH1* compHist, TH1* origHist, TH1* newHist, std::stringstream& outstream, Bool_t& okay)
{
if ( (TMath::Abs(compHist->GetMean())>0.000001 &&
TMath::Abs(compHist->GetRMS())>0.000001) ||
(0 != compHist->GetBinContent(0)) ||
(0 != compHist->GetBinContent(compHist->GetNbinsX()+1)) ) {
if (origHist && newHist) {
outstream << "Comparing histograms" << std::endl;
for (int x=0; x<origHist->GetNbinsX() + 1; ++x) {
if ( origHist->GetBinContent(x) != newHist->GetBinContent(x) ) {
outstream << "Bin content is differnt" << std::endl;
outstream << "**********************" << std::endl;
outstream << "Entries are different." << std::endl;
outstream << "Entries: " << compHist->GetEntries()<< std::endl;
outstream << "Mean: " << compHist->GetMean()<< std::endl;
outstream << "RMS: " << compHist->GetRMS() << std::endl;
outstream << "Underflow: " << compHist->GetBinContent(0) << std::endl;
outstream << "Overflow: " << compHist->GetBinContent(compHist->GetNbinsX()+1) << std::endl;
outstream << "**********************" << std::endl;
return kFALSE;
}
}
outstream << "Histograms are identical." << std::endl;
outstream << "**********************" << std::endl;
return kTRUE;
}
return kFALSE;
} else {
outstream << "Entries are identical." << std::endl;
outstream << "**********************" << std::endl;
return kTRUE;
}
}
std::vector<std::pair<TString,TString>> GetLeafNames(TTree* cbmsim)
{
std::vector<TString> ListOfLeaves;
if (cbmsim) {
TObjArray *bla1=cbmsim->GetListOfLeaves();
TIter myiter1(bla1);
TBranch* branch;
while ( (branch = (TBranch*)myiter1.Next()) ) {
TString mystring = branch->GetName();
// cout << "Branch Name: " << mystring << endl;
// Generate leaf names for transport file
if( mystring.Contains("Point") && !mystring.Contains("MvdPileUpMC") ) {
TObjArray* bla2 = mystring.Tokenize(".");
if ( bla2->GetEntriesFast() == 4) {
TString _branch = ((TObjString*)(bla2->At(2)))->GetString();
TString _leaf = ((TObjString*)(bla2->At(3)))->GetString();
if ( _leaf.EqualTo("fLink") ) {
TString name = _branch + "." + _leaf + ".fLinks";
ListOfLeaves.emplace_back(_branch + "." + _leaf + ".fLinks.fFile");
ListOfLeaves.emplace_back(_branch + "." + _leaf + ".fLinks.fType");
ListOfLeaves.emplace_back(_branch + "." + _leaf + ".fLinks.fEntry");
ListOfLeaves.emplace_back(_branch + "." + _leaf + ".fLinks.fIndex");
ListOfLeaves.emplace_back(_branch + "." + _leaf + ".fLinks.fWeight");
ListOfLeaves.emplace_back(_branch + "." + _leaf + ".fEntryNr.fFile");
ListOfLeaves.emplace_back(_branch + "." + _leaf + ".fEntryNr.fType");
ListOfLeaves.emplace_back(_branch + "." + _leaf + ".fEntryNr.fEntry");
ListOfLeaves.emplace_back(_branch + "." + _leaf + ".fEntryNr.fIndex");
ListOfLeaves.emplace_back(_branch + "." + _leaf + ".fEntryNr.fWeight");
}
else {
ListOfLeaves.emplace_back(_branch + "." + _leaf);
}
}
}
if( mystring.Contains("MCTrack") ) {
TObjArray* bla2 = mystring.Tokenize(".");
if ( bla2->GetEntriesFast() == 4) {
TString _branch = ((TObjString*)(bla2->At(2)))->GetString();
TString _leaf = ((TObjString*)(bla2->At(3)))->GetString();
ListOfLeaves.emplace_back(_branch + "." + _leaf);
}
}
// Generate leaf names for digitization file
if( mystring.Contains("Digi") &&
! ( mystring.Contains("Match") || mystring.Contains("DigiEvent") ) ) {
TObjArray* bla2 = mystring.Tokenize(".");
if ( bla2->GetEntriesFast() == 2) {
TString _branch = ((TObjString*)(bla2->At(0)))->GetString();
TString _leaf = ((TObjString*)(bla2->At(1)))->GetString();
ListOfLeaves.emplace_back(_branch + "." + _leaf);
}
}
// Generate leaf names for reconstruction file
if( mystring.Contains("Hit") &&
!( mystring.Contains("Track") || mystring.Contains("DigiMatch")) ) {
TObjArray* bla2 = mystring.Tokenize(".");
if ( bla2->GetEntriesFast() == 4) {
TString _branch = ((TObjString*)(bla2->At(2)))->GetString();
TString _leaf = ((TObjString*)(bla2->At(3)))->GetString();
if ( _leaf.EqualTo("CbmHit") ) {
TString name = _branch + "." + _leaf + ".fType";
ListOfLeaves.emplace_back(_branch + "." + _leaf + ".fType");
ListOfLeaves.emplace_back(_branch + "." + _leaf + ".fZ");
ListOfLeaves.emplace_back(_branch + "." + _leaf + ".fDz");
ListOfLeaves.emplace_back(_branch + "." + _leaf + ".fRefId");
ListOfLeaves.emplace_back(_branch + "." + _leaf + ".fAddress");
ListOfLeaves.emplace_back(_branch + "." + _leaf + ".fTime");
ListOfLeaves.emplace_back(_branch + "." + _leaf + ".fTimeError");
ListOfLeaves.emplace_back(_branch + "." + _leaf + ".fMatch.fTotalWeight");
ListOfLeaves.emplace_back(_branch + "." + _leaf + ".fMatch.fMatchedIndex");
ListOfLeaves.emplace_back(_branch + "." + _leaf + ".fMatch.fLinks.fFile");
ListOfLeaves.emplace_back(_branch + "." + _leaf + ".fMatch.fLinks.fEntry");
ListOfLeaves.emplace_back(_branch + "." + _leaf + ".fMatch.fLinks.fIndex");
ListOfLeaves.emplace_back(_branch + "." + _leaf + ".fMatch.fLinks.fWeight");
}
else {
ListOfLeaves.emplace_back(_branch + "." + _leaf);
}
}
}
if( mystring.Contains("Cluster") &&
!( mystring.Contains("Track") || mystring.Contains("DigiMatch")) ) {
TObjArray* bla2 = mystring.Tokenize(".");
if ( bla2->GetEntriesFast() == 4) {
TString _branch = ((TObjString*)(bla2->At(2)))->GetString();
TString _leaf = ((TObjString*)(bla2->At(3)))->GetString();
if ( _leaf.EqualTo("fMatch") ) {
TString name = _branch + "." + _leaf + ".fType";
ListOfLeaves.emplace_back(_branch + "." + _leaf + ".fTotalWeight");
ListOfLeaves.emplace_back(_branch + "." + _leaf + ".fMatchedIndex");
ListOfLeaves.emplace_back(_branch + "." + _leaf + ".fLinks.fFile");
ListOfLeaves.emplace_back(_branch + "." + _leaf + ".fLinks.fEntry");
ListOfLeaves.emplace_back(_branch + "." + _leaf + ".fLinks.fIndex");
ListOfLeaves.emplace_back(_branch + "." + _leaf + ".fLinks.fWeight");
}
else {
ListOfLeaves.emplace_back(_branch + "." + _leaf);
}
}
}
if( mystring.Contains("Track") && ! mystring.Contains("PrimaryVertex") ) {
TObjArray* bla2 = mystring.Tokenize(".");
if ( bla2->GetEntriesFast() == 4) {
TString _branch = ((TObjString*)(bla2->At(2)))->GetString();
TString _leaf = ((TObjString*)(bla2->At(3)))->GetString();
if ( _leaf.EqualTo("fMatch") ) {
TString name = _branch + "." + _leaf + ".fType";
ListOfLeaves.emplace_back(_branch + "." + _leaf + ".fTotalWeight");
ListOfLeaves.emplace_back(_branch + "." + _leaf + ".fMatchedIndex");
ListOfLeaves.emplace_back(_branch + "." + _leaf + ".fLinks.fFile");
ListOfLeaves.emplace_back(_branch + "." + _leaf + ".fLinks.fEntry");
ListOfLeaves.emplace_back(_branch + "." + _leaf + ".fLinks.fIndex");
ListOfLeaves.emplace_back(_branch + "." + _leaf + ".fLinks.fWeight");
}
else {
ListOfLeaves.emplace_back(_branch + "." + _leaf);
}
}
}
}
}
std::vector<std::pair<TString,TString>> leaves;
for(auto const element: ListOfLeaves) {
TString nameTree2 = "tree2." + element;
// cout << element << " : " << nameTree2<< endl;
leaves.emplace_back(make_pair(element, nameTree2));
}
return leaves;
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment