All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
diff_spectra.cc
Go to the documentation of this file.
1 #include <cassert>
2 #include <set>
3 #include <iostream>
4 
5 #include "TClass.h"
6 #include "TFile.h"
7 #include "TH1.h"
8 #include "TObject.h"
9 #include "TObjString.h"
10 #include "TPad.h"
11 #include "TTree.h"
12 #include "TVectorD.h"
13 #include "TVector3.h"
14 
15 // Set by command-line switch
16 bool gEnablePdf = true;
17 
18 // Has the output pdf been started?
19 bool gPdfStarted = false;
20 
21 // ----------------------------------------------------------------------------
22 std::string ConcatPath(const std::string& a, const std::string& b)
23 {
24  if(a.empty()) return b;
25  return a+"/"+b;
26 }
27 
28 // ----------------------------------------------------------------------------
29 bool operator==(const TObjString& a, const TObjString& b)
30 {
31  return a.GetString() == b.GetString();
32 }
33 
34 bool operator==(const TVectorD& a, const TVectorD& b)
35 {
36  return (a-b).Norm1() == 0;
37 }
38 
39 bool operator==(const TH1& a, const TH1& b)
40 {
41  if(a.GetNcells() != b.GetNcells()) return false;
42  // TODO - test bin edges
43  for(int i = 0; i <= a.GetNcells(); ++i)
44  if(a.GetBinContent(i) != b.GetBinContent(i))
45  return false;
46 
47  return true;
48 }
49 
50 // ----------------------------------------------------------------------------
51 std::ostream& operator<<(std::ostream& os, const TObjString& a)
52 {
53  return os << "\"" << a.GetString() << "\"";
54 }
55 
56 std::ostream& operator<<(std::ostream& os, const TH1& a)
57 {
58  return os << "integral " << a.Integral(0, -1);
59 }
60 
61 std::ostream& operator<<(std::ostream& os, const TObject& a)
62 {
63  a.Print();
64  return os;
65 }
66 
67 // ----------------------------------------------------------------------------
68 void Plots(const TH1& a, const TH1& b, const std::string& key)
69 {
70  TH1* ac = (TH1*)a.Clone();
71  TH1* bc = (TH1*)b.Clone();
72 
73  ac->SetLineColor(kRed);
74  bc->SetLineColor(kBlue);
75 
76  if(ac->Integral() < bc->Integral()) std::swap(ac, bc);
77 
78  ac->SetTitle(key.c_str());
79 
80  ac->Draw("hist");
81  bc->Draw("hist same");
82 
83  if(!gPdfStarted){
84  gPdfStarted = true;
85  gPad->Print("diff.pdf[");
86  }
87 
88  gPad->Print("diff.pdf");
89 }
90 
91 // ----------------------------------------------------------------------------
92 int gNChecked = 0;
93 template<class T> bool Compare(const T& a, const T& b, const std::string& key)
94 {
95  if(a == b){
96  std::cout << "\rChecked " << ++gNChecked << " keys" << std::flush;
97  return true;
98  }
99 
100  std::cout << "\n'" << key << "' differs: " << a << " vs " << b << std::endl;
101 
102  if constexpr(std::is_same_v<T, TH1>)
103  if(gEnablePdf)
104  Plots(a, b, key);
105 
106  return false;
107 }
108 
109 // ----------------------------------------------------------------------------
110 bool CompareObjects(const TObject& a, const TObject& b, const std::string& key)
111 {
112  if(a.ClassName() != std::string(b.ClassName())){
113  std::cout << key << " is of unlike type: "
114  << a.ClassName() << " vs "
115  << b.ClassName() << std::endl;
116  return false;
117  }
118 
119  if(a.ClassName() == std::string("TObjString")){
120  return Compare((TObjString&)a, (TObjString&)b, key);
121  }
122 
123  if(a.ClassName() == std::string("TVectorT<double>")){
124  return Compare((TVectorD&)a, (TVectorD&)b, key);
125  }
126 
127  if(a.ClassName() == std::string("TVector3")){
128  return Compare((TVector3&)a, (TVector3&)b, key);
129  }
130 
131  if(a.InheritsFrom(TH1::Class()) && b.InheritsFrom(TH1::Class())){
132  return Compare((TH1&)a, (TH1&)b, key);
133  }
134 
135  std::cout << "Don't know how to compare '" << key << "' of type "
136  << a.ClassName() << std::endl;
137  return true; // give them the benefit of the doubt
138 }
139 
140 // ----------------------------------------------------------------------------
141 void ReportUnique(const std::vector<std::string>& only, TDirectory* dir)
142 {
143  if(only.empty()) return;
144 
145  std::cout << "The following keys exist only in " << dir->GetFile()->GetName() << std::endl;
146  for(const std::string& k: only) std::cout << " " << k << std::endl;
147 }
148 
149 // ----------------------------------------------------------------------------
150 bool CheckDirectory(TDirectory* a, TDirectory* b, std::string path = "")
151 {
152  std::set<std::string> keysA, keysB;
153  TIter nextA(a->GetListOfKeys()), nextB(b->GetListOfKeys());
154  while(TObject* x = nextA()) keysA.insert(x->GetName());
155  while(TObject* x = nextB()) keysB.insert(x->GetName());
156 
157  std::vector<std::string> onlyA, onlyB, bothAB;
158  std::set_difference (keysA.begin(), keysA.end(), keysB.begin(), keysB.end(), std::back_inserter(onlyA));
159  std::set_difference (keysB.begin(), keysB.end(), keysA.begin(), keysA.end(), std::back_inserter(onlyB));
160  std::set_intersection(keysA.begin(), keysA.end(), keysB.begin(), keysB.end(), std::back_inserter(bothAB));
161 
162  ReportUnique(onlyA, a);
163  ReportUnique(onlyB, b);
164 
165  bool ok = onlyA.empty() && onlyB.empty();
166 
167  for(const std::string& key: bothAB){
168  TObject* objA = a->Get(key.c_str());
169  TObject* objB = b->Get(key.c_str());
170 
171  TDirectory* dirA = dynamic_cast<TDirectoryFile*>(objA);
172  TDirectory* dirB = dynamic_cast<TDirectoryFile*>(objB);
173  if(dirA && dirB){
174  if(!CheckDirectory(dirA, dirB, ConcatPath(path, key))) ok = false;
175  }
176  else{
177  if(!CompareObjects(*objA, *objB, ConcatPath(path, key))) ok = false;
178  }
179 
180  delete objA;
181  delete objB;
182  } // end for key
183 
184  return ok;
185 }
186 
187 
188 // ----------------------------------------------------------------------------
189 void usage()
190 {
191  std::cout << "Usage: diff_spectra [-np] input1.root input2.root" << std::endl;
192  std::cout << " -np Disable plotting functionality" << std::endl;
193 
194  exit(2);
195 }
196 
197 // ----------------------------------------------------------------------------
198 int main(int argc, char** argv)
199 {
200  if(argc != 3 && argc != 4) usage();
201  if(argc == 4 && argv[1] != std::string("-np")) usage();
202 
203  if(argc == 4){
204  // Must have been -np
205  gEnablePdf = false;
206  // Shift to maintain filenames as [1] and [2]
207  ++argv;
208  }
209 
210  const std::string fnameA = argv[1];
211  const std::string fnameB = argv[2];
212 
213  std::cout << "Comparing " << fnameA << " and " << fnameB << std::endl;
214 
215  if(CheckDirectory(TFile::Open(fnameA.c_str()),
216  TFile::Open(fnameB.c_str()))){
217  std::cout << "\nFiles match!" << std::endl;
218  return 0;
219  }
220  else{
221  if(gPdfStarted) gPad->Print("diff.pdf]");
222 
223  std::cout << "\nFiles do not match" << std::endl;
224  return 1;
225  }
226 }
process_name opflash particleana ie x
bool CheckDirectory(TDirectory *a, TDirectory *b, std::string path="")
int gNChecked
Definition: diff_spectra.cc:92
bool CompareObjects(const TObject &a, const TObject &b, const std::string &key)
usage
Definition: doGit.sh:21
bool Compare(const T &a, const T &b, const std::string &key)
Definition: diff_spectra.cc:93
process_name gaushit a
BEGIN_PROLOG triggeremu_data_config_icarus settings PMTADCthresholds sequence::icarus_stage0_multiTPC_TPC physics sequence::icarus_stage0_EastHits_TPC physics sequence::icarus_stage0_WestHits_TPC physics producers purityana0 caloskimCalorimetryCryoE physics caloskimCalorimetryCryoW physics path
bool gEnablePdf
Definition: diff_spectra.cc:16
std::string ConcatPath(const std::string &a, const std::string &b)
Definition: diff_spectra.cc:22
void ReportUnique(const std::vector< std::string > &only, TDirectory *dir)
tuple dir
Definition: dropbox.py:28
void Plots(const TH1 &a, const TH1 &b, const std::string &key)
Definition: diff_spectra.cc:68
bool gPdfStarted
Definition: diff_spectra.cc:19
pdgs k
Definition: selectors.fcl:22
int main(int argc, char **argv)
std::ostream & operator<<(std::ostream &out, lar::example::CheatTrack const &track)
Definition: CheatTrack.h:153
bool operator==(infinite_endcount_iterator< T > const &, count_iterator< T > const &)
Definition: counter.h:269
BEGIN_PROLOG could also be cout