1 |
/*************************************************
|
2 |
Automatically plots histograms from two files
|
3 |
onto the same plot and saves them.
|
4 |
It looksfor ALL histograms in the first file
|
5 |
and plots the corresponding histogram in the 2nd
|
6 |
file onto the sample plot.
|
7 |
|
8 |
Can be run from a bash prompt as well:
|
9 |
root -b -l -q "plotHistogramsTogether.C(\"fileA.root\",\"fileB.root\")"
|
10 |
root -b -l -q "plotHistogramsTogether.C(\"fileA.root\",\"fileB.root\",\"Signal\",\"Background\",10,2,1)"
|
11 |
|
12 |
Michael B. Anderson
|
13 |
Sept 5, 2008
|
14 |
*************************************************/
|
15 |
|
16 |
#include <string.h>
|
17 |
#include "TFile.h"
|
18 |
#include "TH1.h"
|
19 |
#include "TKey.h"
|
20 |
#include "Riostream.h"
|
21 |
|
22 |
// Accesable everywhere
|
23 |
TObject *obj;
|
24 |
TFile *sourceFile1, *sourceFile2;
|
25 |
TString label1, label2;
|
26 |
TString outputFolder,outputFilename;
|
27 |
TCanvas *canvasDefault;
|
28 |
Float_t scale1, scale2;
|
29 |
bool showStatsBoxes;
|
30 |
|
31 |
// *******************************************
|
32 |
// Variables
|
33 |
TString imageType = "gif";
|
34 |
int outputWidth = 480;
|
35 |
int outputHeight = 360;
|
36 |
bool yAxisLogScale = false;
|
37 |
// End of Variables
|
38 |
// *******************************************
|
39 |
|
40 |
|
41 |
void plotHistogramsTogether(TString fileName1,
|
42 |
TString fileName2,
|
43 |
TString fileLabel1 = "",
|
44 |
TString fileLabel2 = "",
|
45 |
Float_t fileScale1 = 1.0,
|
46 |
Float_t fileScale2 = 1.0,
|
47 |
bool showStats = false) {
|
48 |
|
49 |
// If file labels were not given as argument,
|
50 |
// use the filename as a label
|
51 |
if (fileLabel1 == "") {
|
52 |
fileLabel1 = fileName1;
|
53 |
fileLabel2 = fileName2;
|
54 |
fileLabel1.ReplaceAll(".root","");
|
55 |
fileLabel1.ReplaceAll(".root","");
|
56 |
}
|
57 |
label1 = fileLabel1;
|
58 |
label2 = fileLabel2;
|
59 |
|
60 |
// Set the scale of the histograms.
|
61 |
// If they are < 0.0, they will be area normalized
|
62 |
scale1 = fileScale1;
|
63 |
scale2 = fileScale2;
|
64 |
showStatsBoxes = showStats;
|
65 |
|
66 |
sourceFile1 = TFile::Open( fileName1 );
|
67 |
sourceFile2 = TFile::Open( fileName2 );
|
68 |
|
69 |
outputFolder = "HistogramsTogether/"; // Blank to use current directory,
|
70 |
// or, for a specific dir type
|
71 |
// something like "images/"
|
72 |
|
73 |
gSystem->MakeDirectory(outputFolder);
|
74 |
|
75 |
canvasDefault = new TCanvas("canvasDefault","testCanvas",outputWidth,outputHeight);
|
76 |
|
77 |
// This function will plot all histograms from
|
78 |
// file1 against matching histogram from file2
|
79 |
recurseOverKeys(sourceFile1);
|
80 |
|
81 |
sourceFile1->Close();
|
82 |
sourceFile2->Close();
|
83 |
|
84 |
TString currentDir = gSystem->pwd();
|
85 |
cout << "Done. See images in:" << endl << currentDir << "/" << outputFolder << endl;
|
86 |
}
|
87 |
|
88 |
void recurseOverKeys( TDirectory *target1 ) {
|
89 |
|
90 |
// Figure out where we are
|
91 |
TString path( (char*)strstr( target1->GetPath(), ":" ) );
|
92 |
path.Remove( 0, 2 );
|
93 |
|
94 |
sourceFile1->cd( path );
|
95 |
|
96 |
TDirectory *current_sourcedir = gDirectory;
|
97 |
|
98 |
TKey *key;
|
99 |
TIter nextkey(current_sourcedir->GetListOfKeys());
|
100 |
|
101 |
while (key = (TKey*)nextkey()) {
|
102 |
|
103 |
obj = key->ReadObj();
|
104 |
|
105 |
// Check if this is a 1D histogram or a directory
|
106 |
if (obj->IsA()->InheritsFrom("TH1F")) {
|
107 |
|
108 |
// **************************
|
109 |
// Plot & Save this Histogram
|
110 |
TH1F *htemp1, *htemp2;
|
111 |
|
112 |
htemp1 = (TH1F*)obj;
|
113 |
TString histName = htemp1->GetName();
|
114 |
|
115 |
if (path != "") {
|
116 |
sourceFile2->GetObject(path+"/"+histName, htemp2);
|
117 |
} else {
|
118 |
sourceFile2->GetObject(histName, htemp2);
|
119 |
}
|
120 |
|
121 |
outputFilename=histName;
|
122 |
plot2Histograms(htemp1, htemp2, outputFolder+path+"/"+outputFilename+"."+imageType);
|
123 |
|
124 |
} else if ( obj->IsA()->InheritsFrom( "TDirectory" ) ) {
|
125 |
// it's a subdirectory
|
126 |
|
127 |
cout << "Found subdirectory " << obj->GetName() << endl;
|
128 |
gSystem->MakeDirectory(outputFolder+path+"/"+obj->GetName());
|
129 |
|
130 |
// obj is now the starting point of another round of merging
|
131 |
// obj still knows its depth within the target file via
|
132 |
// GetPath(), so we can still figure out where we are in the recursion
|
133 |
recurseOverKeys( (TDirectory*)obj );
|
134 |
|
135 |
} // end of IF a TDriectory
|
136 |
}
|
137 |
}
|
138 |
|
139 |
void plot2Histograms(TH1* htemp1, TH1* htemp2, TString filename) {
|
140 |
|
141 |
//TString title = htemp1->GetName();
|
142 |
TString title = htemp1->GetTitle();
|
143 |
|
144 |
// Scale by given factor.
|
145 |
// If given factor is negative, area normalize
|
146 |
if (scale1 > 0.0) {
|
147 |
htemp1->Scale(scale1);
|
148 |
} else {
|
149 |
Double_t integral = htemp1->Integral();
|
150 |
if (integral>0.0) htemp1->Scale(1/integral);
|
151 |
}
|
152 |
if (scale2 > 0.0) {
|
153 |
htemp2->Scale(scale2);
|
154 |
} else {
|
155 |
Double_t integral = htemp2->Integral();
|
156 |
if (integral>0.0) htemp2->Scale(1/integral);
|
157 |
}
|
158 |
|
159 |
// Set the histogram colors & lines
|
160 |
htemp1->SetLineColor(kRed);
|
161 |
htemp2->SetLineColor(kBlue);
|
162 |
htemp1->SetLineWidth(1);
|
163 |
htemp2->SetLineWidth(2);
|
164 |
|
165 |
// Turn off stats
|
166 |
if (!showStatsBoxes) {
|
167 |
gStyle->SetOptStat(0);
|
168 |
}
|
169 |
|
170 |
// Create TStack but we will draw without stacking
|
171 |
THStack *tempStack = new THStack();
|
172 |
tempStack->Add(htemp1,"same");
|
173 |
tempStack->Add(htemp2,"same");
|
174 |
|
175 |
// Draw the histogram and titles
|
176 |
tempStack->Draw("hist nostack");
|
177 |
tempStack->SetTitle(title);
|
178 |
//tempStack->GetXaxis()->SetTitle(titleX);
|
179 |
|
180 |
// Draw the legend
|
181 |
TLegend *infoBox = new TLegend(0.75, 0.83, 0.99, 0.99, "");
|
182 |
infoBox->AddEntry(htemp1,label1,"L");
|
183 |
infoBox->AddEntry(htemp2,label2,"L");
|
184 |
infoBox->Draw();
|
185 |
|
186 |
// Place the stats boxes to be non-overlapping
|
187 |
if (showStatsBoxes) {
|
188 |
canvasDefault->SetRightMargin(0.2);
|
189 |
canvasDefault->Update();
|
190 |
TPaveStats *st1 = (TPaveStats*)htemp1->GetListOfFunctions()->FindObject("stats");
|
191 |
TPaveStats *st2 = (TPaveStats*)htemp2->GetListOfFunctions()->FindObject("stats");
|
192 |
st1->SetX1NDC(.79); st1->SetX2NDC(.99);
|
193 |
st1->SetY1NDC(.6); st1->SetY2NDC(.8);
|
194 |
st2->SetX1NDC(.79); st2->SetX2NDC(.99);
|
195 |
st2->SetY1NDC(.38); st2->SetY2NDC(.58);
|
196 |
canvasDefault->Modified();
|
197 |
}
|
198 |
|
199 |
// Set log y axis
|
200 |
if (yAxisLogScale) canvasDefault->SetLogy(1);
|
201 |
// Save the canvas
|
202 |
canvasDefault->SaveAs(filename);
|
203 |
|
204 |
}
|
205 |
|