HtmlCosmicCompare.C
Go to the documentation of this file.
1 /// Macro to export histogram content of a ROOT file to an html page
2 /// Based on $ROOTSYS/bin/hadd.C
3 /// The script takes the file names of the two releases to be compared
4 /// Raphael Schroeter, May 2011
5 
6 // C/C++ includes
7 #include <iostream>
8 #include <string.h>
9 
10 // ROOT includes
11 #include "Riostream.h"
12 #include "TCanvas.h"
13 #include "TChain.h"
14 #include "TFile.h"
15 #include "TH1.h"
16 #include "TH2.h"
17 #include "TH3.h"
18 #include "TImage.h"
19 #include "TKey.h"
20 #include "TString.h"
21 #include "TSystem.h"
22 
23 TString htmlpath; ///< Path to html page and local location of saved images
24 TString subDir; ///< Name of current subdirectory
25 
26 ofstream *histhtml; ///< Stream to send html code/text/commands to html file
27 
28 double NormPOTPrevious, NormPOTCurrent; ///< Amount of POT used to generate input files
29 
30 /// Write the initial portion of the html file and set up top level directory
31 void InitializeHtml(char* fileNew, char* fileOld);
32 
33 /// Set up subdirectory structure of html file and local area
34 void WriteDirectoryStruct(TString inPath, TList* sourceList);
35 
36 /// Get the amount of POT from both input files
37 void GetPOTInfo(TString inPath, TList* sourceList);
38 
39 /// Recursively compare each histogram in the inPath directory
40 void CompareRootfile(TString inPath, TList* sourceList);
41 
42 /// Write the final lines of the html file
43 void Finalize();
44 
45 //.............................................................................
46 void HtmlCosmicCompare(char* fileNew, char* fileOld)
47 {
48  TList* fileList; // List of input files
49  TString topPath = "/"; // Path to top directory of histogram locations/subdirectories
50 
51  // Open the files, add them to the TList
52  fileList = new TList();
53  fileList->Add(TFile::Open(fileNew));
54  fileList->Add(TFile::Open(fileOld));
55 
56  // Get the base file names
57  std::string baseFileNew(fileNew);
58  std::string baseFileOld(fileOld);
59  baseFileNew.erase(0, baseFileNew.rfind("/"));
60  baseFileOld.erase(0, baseFileOld.rfind("/"));
61 
62  InitializeHtml((char*)baseFileNew.c_str(), (char*)baseFileOld.c_str());
63  WriteDirectoryStruct(topPath, fileList);
64  GetPOTInfo("cosmicana", fileList);
65  CompareRootfile(topPath, fileList);
66  Finalize();
67 
68  return;
69 }
70 
71 //.............................................................................
72 void InitializeHtml(char* fileNew, char* fileOld)
73 {
74  // Set up html files for ease of image viewing
75  gSystem->Exec("mkdir html_out/");
76 
77  char commandHelper[256];
78  sprintf(commandHelper, "mkdir html_out/%s_comp/", fileNew);
79  gSystem->Exec(commandHelper);
80 
81  sprintf(commandHelper, "html_out/%s_comp/", fileNew);
82  htmlpath = commandHelper;
83  histhtml = new ofstream(htmlpath + "index.html", ios::out);
84 
85  *histhtml << "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n"
86  << "<html>\n <head>\n"
87  << "<title>" << fileNew << "</title>\n"
88  << "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\">\n"
89  << "</head>\n<body>\n" << std::endl;
90 
91  *histhtml << "<a name=\"pagetop\" ></a>\n"
92  << "<h1>" << fileNew << "</h1>\n" << std::endl;
93 
94  *histhtml << "<table>" << std::endl;
95  *histhtml << "<tr>" << std::endl;
96  *histhtml << "<td>" << std::endl;
97  *histhtml << "<h2>"<< fileNew <<"</font></h2>\n" << std::endl;
98  *histhtml << "</td>"<< std::endl;
99  *histhtml << "<td>" << std::endl;
100  *histhtml << "<h2><font color=\"#FF0000\">"<< fileOld <<"</font></h2>\n" << std::endl;
101  *histhtml << "</td>"<< std::endl;
102  *histhtml << "</tr>" << std::endl;
103  *histhtml << "</table>" << std::endl;
104 
105  *histhtml << "Skip to:\n" << std::endl;
106 
107  return;
108 }
109 
110 //.............................................................................
111 void WriteDirectoryStruct(TString inPath, TList* sourceList)
112 {
113  TFile* firstSource = (TFile*)sourceList->First();
114  firstSource->cd(inPath);
115  TDirectory* currentSourceDir = gDirectory;
116 
117  // Loop over all keys in this directory and write the subdirectory index on the html file
118  TIter nextkey(currentSourceDir->GetListOfKeys());
119  TKey* key;
120  TKey* oldkey = 0;
121 
122  while((key = (TKey*)nextkey())) {
123  // Keep only the highest cycle number for each key
124  if(oldkey && !strcmp(oldkey->GetName(), key->GetName())) { continue; }
125 
126  // Read object from first source file
127  firstSource->cd(inPath);
128  TObject* obj = key->ReadObj();
129 
130  if(obj->IsA()->InheritsFrom(TDirectory::Class())) { // It's a subdirectory
131  subDir = obj->GetName();
132  *histhtml << "<li><a href=\"#" << subDir << "\">" << subDir << "</a></li>\n" << std::endl;
133  }
134 
135  delete obj;
136  } // end of while loop over TKeys
137 
138  return;
139 }
140 
141 //.............................................................................
142 void GetPOTInfo(TString inPath, TList* sourceList)
143 {
144  // Name of the histogram to get POT information from
145  std::string histPOT = "fSampleTime";
146 
147  TFile* firstSource = (TFile*)sourceList->First();
148 
149  if(firstSource->cd(inPath)) {
150  TKey* keyPOTNew = (TKey*)gDirectory->GetListOfKeys()->FindObject(histPOT.c_str());
151 
152  if(keyPOTNew) {
153  TH1* hPOTNew = (TH1*)keyPOTNew->ReadObj();
154  NormPOTCurrent = hPOTNew->Integral();
155  std::cout << "Total sample time in current release " << NormPOTCurrent << std::endl;
156  }
157  else {
158  NormPOTCurrent = 1.;
159  }
160 
161  TFile* nextSource = (TFile*)sourceList->After(firstSource);
162  nextSource->cd(inPath);
163  TKey* keyPOTOld = (TKey*)gDirectory->GetListOfKeys()->FindObject(histPOT.c_str());
164  if(keyPOTOld) {
165  TH1* hPOTOld = (TH1*)keyPOTOld->ReadObj();
166  NormPOTPrevious = hPOTOld->Integral();
167  std::cout << "Total sample time in previous release " << NormPOTPrevious << std::endl;
168  }
169  else {
170  NormPOTPrevious = 1.;
171  }
172  }
173  else {
174  std::cout << "POT info not available!" << std::endl;
175  NormPOTPrevious = 1.;
176  NormPOTCurrent = 1.;
177  }
178 
179  return;
180 }
181 
182 //.............................................................................
183 void CompareRootfile(TString inPath, TList* sourceList)
184 {
185  TFile* firstSource = (TFile*)sourceList->First();
186  firstSource->cd(inPath);
187  TDirectory* currentSourceDir = gDirectory;
188  TString saveName;
189 
190  // Loop over all keys in this directory and save all histos found as PNG images
191  TIter nextkey(currentSourceDir->GetListOfKeys());
192  TKey* key;
193  TKey* oldkey = 0;
194 
195  while((key = (TKey*)nextkey())) {
196  // Keep only the highest cycle number for each key
197  if(oldkey && !strcmp(oldkey->GetName(), key->GetName())) { continue; }
198 
199  // Read object from first source file
200  firstSource->cd(inPath);
201  TObject* obj = key->ReadObj();
202 
203  if(obj->IsA()->InheritsFrom(TH1::Class())) { // Could be TH1, TH2, or TH3
204  std::cout << "Compare and export histograms " << obj->GetName() << std::endl;
205  TH1* hNew = (TH1*)obj;
206 
207  // Loop over all source files and compare histograms
208  TFile* nextSource = (TFile*)sourceList->After(firstSource);
209  while(nextSource) {
210  // Make sure we are at the correct directory level
211  nextSource->cd(inPath);
212 
213  // Get the object of the same name in the second file
214  TKey* key2 = (TKey*)gDirectory->GetListOfKeys()->FindObject(hNew->GetName());
215 
216  if(key2) {
217  TH1* hOld = (TH1*)key2->ReadObj();
218 
219  TCanvas* c = new TCanvas("c", "c", 700, 500);
220  saveName = subDir + "/";
221 
222  TImage* img = TImage::Create();
223 
224  // If TH1, normalize by POT, draw both histograms in the same canvas and get ratio
225  if(!(obj->IsA()->InheritsFrom(TH2::Class()) ||
226  obj->IsA()->InheritsFrom(TH3::Class()))) {
227  if(NormPOTPrevious > 0. && !strstr(hNew->GetName(), "Subrun")) {
228  hOld->Scale(NormPOTCurrent/NormPOTPrevious);
229  }
230 
231  // Normalize neutrino energy histograms by POT
232  if(strstr(hNew->GetName(), "Enu")) {
233  char yAxisLabel[256];
234  sprintf(yAxisLabel, "Events / %.2E POT", NormPOTCurrent);
235  hNew->GetYaxis()->SetTitle(yAxisLabel);
236  hOld->GetYaxis()->SetTitle(yAxisLabel);
237  }
238 
239  // When drawing, make sure both plots will be totally visible
240  if(hOld->GetMaximum() > hNew->GetMaximum()) {
241  hNew->SetMaximum(1.1*hOld->GetMaximum());
242  }
243 
244  hNew->Sumw2();
245  hOld->Sumw2();
246 
247  hNew->Draw("HIST");
248  hOld->SetLineColor(2);
249  hOld->Draw("HIST same");
250 
251  img->FromPad(c);
252  img->WriteImage(htmlpath + saveName + obj->GetName() + ".png");
253 
254  TH1* hRatio = (TH1*)hNew->Clone("hRatio");
255  hRatio->Divide(hOld);
256  hRatio->SetMinimum(0.);
257  hRatio->SetMaximum(5.);
258  hRatio->GetYaxis()->SetTitle("");
259  hRatio->Draw();
260 
261  img->FromPad(c);
262  img->WriteImage(htmlpath + saveName + obj->GetName() + "_Ratio.png");
263 
264  *histhtml << "<p>" << subDir << "-"<< obj->GetName() << std::endl;
265  *histhtml << "<table>" << std::endl;
266  *histhtml << "<tr>" << std::endl;
267  *histhtml << "<td>" << std::endl;
268  *histhtml << "<p><p><img src=\"" << saveName + obj->GetName() << ".png\">" << std::endl;
269  *histhtml << "</td>"<< std::endl;
270  *histhtml << "<td>" << std::endl;
271  *histhtml << "<p><p><img src=\"" << saveName + obj->GetName() << "_Ratio.png\">" << std::endl;
272  *histhtml << "</td>"<< std::endl;
273  *histhtml << "</tr>" << std::endl;
274  *histhtml << "</table>" << std::endl;
275  *histhtml << "<a href=\"#pagetop\" >Back to top</a>\n" << std::endl;
276  } // End of condition if TObject is a TH1 and not TH2 or TH3
277  else { // If TH2 or TH3, don't overlay histograms
278  if(obj->IsA()->InheritsFrom(TH2::Class())) {
279  hNew->Draw("colz");
280  }
281  else {
282  hNew->Draw();
283  }
284 
285  img->FromPad(c);
286  img->WriteImage(htmlpath + saveName + obj->GetName() + ".png");
287 
288  *histhtml << "<p>" << subDir << "-"<< obj->GetName() << std::endl;
289  *histhtml << "<table>" << std::endl;
290  *histhtml << "<tr>" << std::endl;
291  *histhtml << "<td>" << std::endl;
292  *histhtml << "<p><p><img src=\"" << saveName + obj->GetName() << ".png\">" << std::endl;
293  *histhtml << "</td>"<< std::endl;
294 
295  hOld->SetMarkerColor(2);
296  if(obj->IsA()->InheritsFrom(TH2::Class())) {
297  hOld->Draw("colz");
298  }
299  else {
300  hOld->Draw();
301  }
302 
303  img->FromPad(c);
304  img->WriteImage(htmlpath + saveName + obj->GetName() + "Previous.png");
305 
306  *histhtml << "<td>" << std::endl;
307  *histhtml << "<p><p><img src=\"" << saveName + obj->GetName() << "Previous.png\">" << std::endl;
308  *histhtml << "</td>"<< std::endl;
309  *histhtml << "</tr>" << std::endl;
310  *histhtml << "</table>" << std::endl;
311 
312  *histhtml << "<a href=\"#pagetop\" >Back to top</a>\n" << std::endl;
313  } // end of conditional if object is TH1 and (TH2 or TH3)
314 
315  delete c;
316  delete img;
317  } // end of conditional if key was found in "old file" by the same name as that found in "new file"
318  else {
319  std::cout << "Could not find " << hNew->GetName() << " in previous release." << std::endl;
320  }
321 
322  // This should terminate the while loop if there are only two files in the TList
323  nextSource = (TFile*)sourceList->After(nextSource);
324  } // end of while loop on valid nextSource
325  } // end of conditonal if object is TH1
326  else if(obj->IsA()->InheritsFrom(TDirectory::Class())) { // It's a subdirectory
327  subDir = obj->GetName();
328  std::cout << "Found subdirectory " << subDir << std::endl;
329 
330  // Make local directories for the images
331  gSystem->Exec("mkdir " + htmlpath + subDir);
332 
333  *histhtml << "<a name=\"" << subDir << "\">\n"
334  << "<h2>" << subDir << "</h2>\n" << std::endl;
335 
336  // Create a new subdirectory
337  TString newDir = obj->GetName();
338 
339  CompareRootfile(newDir, sourceList);
340  } // end of conditional if object is a TDirectory
341  else { // Object is of no type that this macro can handle
342  std::cout << "Unknown object type, name: " << obj->GetName()
343  << " title: " << obj->GetTitle() << std::endl;
344  }
345 
346  delete obj;
347  } // end of while loop over TKeys
348 
349  return;
350 }
351 
352 //.............................................................................
353 void Finalize()
354 {
355  *histhtml << "</body></html>" << std::endl;
356  histhtml->close();
357 
358  return;
359 }
void GetPOTInfo(TString inPath, TList *sourceList)
Get the amount of POT from both input files.
double NormPOTCurrent
Amount of POT used to generate input files.
void InitializeHtml(char *fileNew, char *fileOld)
Write the initial portion of the html file and set up top level directory.
void HtmlCosmicCompare(char *fileNew, char *fileOld)
TString htmlpath
Path to html page and local location of saved images.
list fileList
Definition: cafExposure.py:30
ofstream * histhtml
Stream to send html code/text/commands to html file.
void CompareRootfile(TString inPath, TList *sourceList)
Recursively compare each histogram in the inPath directory.
def img(path, mouseover="")
Definition: HTMLTools.py:36
void WriteDirectoryStruct(TString inPath, TList *sourceList)
Set up subdirectory structure of html file and local area.
OStream cout
Definition: OStream.cxx:6
TString subDir
Name of current subdirectory.
double NormPOTPrevious
void Finalize()
Write the final lines of the html file.
enum BeamMode string