1 |
anderson |
1.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 |
anderson |
1.3 |
root -b -l -q "plotHistogramsTogether.C(\"fileA.root\",\"fileB.root\",\"Signal\",\"Background\",10,2,1)"
|
11 |
anderson |
1.1 |
|
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 |
anderson |
1.3 |
Float_t scale1, scale2;
|
29 |
|
|
bool showStatsBoxes;
|
30 |
anderson |
1.1 |
|
31 |
|
|
// *******************************************
|
32 |
|
|
// Variables
|
33 |
|
|
TString imageType = "gif";
|
34 |
|
|
int outputWidth = 480;
|
35 |
|
|
int outputHeight = 360;
|
36 |
anderson |
1.3 |
bool yAxisLogScale = false;
|
37 |
anderson |
1.1 |
// End of Variables
|
38 |
|
|
// *******************************************
|
39 |
|
|
|
40 |
|
|
|
41 |
|
|
void plotHistogramsTogether(TString fileName1,
|
42 |
|
|
TString fileName2,
|
43 |
|
|
TString fileLabel1 = "",
|
44 |
anderson |
1.3 |
TString fileLabel2 = "",
|
45 |
|
|
Float_t fileScale1 = 1.0,
|
46 |
|
|
Float_t fileScale2 = 1.0,
|
47 |
|
|
bool showStats = false) {
|
48 |
anderson |
1.1 |
|
49 |
anderson |
1.3 |
// If file labels were not given as argument,
|
50 |
|
|
// use the filename as a label
|
51 |
anderson |
1.1 |
if (fileLabel1 == "") {
|
52 |
|
|
fileLabel1 = fileName1;
|
53 |
|
|
fileLabel2 = fileName2;
|
54 |
|
|
fileLabel1.ReplaceAll(".root","");
|
55 |
|
|
fileLabel1.ReplaceAll(".root","");
|
56 |
|
|
}
|
57 |
anderson |
1.3 |
label1 = fileLabel1;
|
58 |
anderson |
1.1 |
label2 = fileLabel2;
|
59 |
|
|
|
60 |
anderson |
1.3 |
// 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 |
anderson |
1.1 |
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 |
anderson |
1.3 |
// This function will plot all histograms from
|
78 |
|
|
// file1 against matching histogram from file2
|
79 |
anderson |
1.1 |
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 |
anderson |
1.2 |
if (path != "") {
|
116 |
|
|
sourceFile2->GetObject(path+"/"+histName, htemp2);
|
117 |
|
|
} else {
|
118 |
|
|
sourceFile2->GetObject(histName, htemp2);
|
119 |
|
|
}
|
120 |
anderson |
1.1 |
|
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 |
anderson |
1.3 |
//TString title = htemp1->GetName();
|
142 |
|
|
TString title = htemp1->GetTitle();
|
143 |
|
|
|
144 |
anderson |
1.5 |
// Make sure histograms exist
|
145 |
|
|
if ( !htemp2 ) {
|
146 |
|
|
cout << "Histogram missing from 2nd file: " << htemp1->GetName() << endl;
|
147 |
|
|
return;
|
148 |
|
|
}
|
149 |
|
|
|
150 |
anderson |
1.3 |
// Scale by given factor.
|
151 |
|
|
// If given factor is negative, area normalize
|
152 |
|
|
if (scale1 > 0.0) {
|
153 |
|
|
htemp1->Scale(scale1);
|
154 |
|
|
} else {
|
155 |
|
|
Double_t integral = htemp1->Integral();
|
156 |
|
|
if (integral>0.0) htemp1->Scale(1/integral);
|
157 |
|
|
}
|
158 |
|
|
if (scale2 > 0.0) {
|
159 |
|
|
htemp2->Scale(scale2);
|
160 |
|
|
} else {
|
161 |
|
|
Double_t integral = htemp2->Integral();
|
162 |
|
|
if (integral>0.0) htemp2->Scale(1/integral);
|
163 |
|
|
}
|
164 |
anderson |
1.1 |
|
165 |
|
|
// Set the histogram colors & lines
|
166 |
|
|
htemp1->SetLineColor(kRed);
|
167 |
|
|
htemp2->SetLineColor(kBlue);
|
168 |
|
|
htemp1->SetLineWidth(1);
|
169 |
|
|
htemp2->SetLineWidth(2);
|
170 |
|
|
|
171 |
anderson |
1.3 |
// Turn off stats
|
172 |
|
|
if (!showStatsBoxes) {
|
173 |
|
|
gStyle->SetOptStat(0);
|
174 |
|
|
}
|
175 |
anderson |
1.1 |
|
176 |
|
|
// Create TStack but we will draw without stacking
|
177 |
|
|
THStack *tempStack = new THStack();
|
178 |
anderson |
1.4 |
tempStack->Add(htemp1,"sames");
|
179 |
|
|
tempStack->Add(htemp2,"sames");
|
180 |
anderson |
1.1 |
|
181 |
|
|
// Draw the histogram and titles
|
182 |
anderson |
1.3 |
tempStack->Draw("hist nostack");
|
183 |
anderson |
1.1 |
tempStack->SetTitle(title);
|
184 |
|
|
//tempStack->GetXaxis()->SetTitle(titleX);
|
185 |
|
|
|
186 |
|
|
// Draw the legend
|
187 |
anderson |
1.3 |
TLegend *infoBox = new TLegend(0.75, 0.83, 0.99, 0.99, "");
|
188 |
anderson |
1.1 |
infoBox->AddEntry(htemp1,label1,"L");
|
189 |
|
|
infoBox->AddEntry(htemp2,label2,"L");
|
190 |
anderson |
1.5 |
infoBox->SetShadowColor(0); // 0 = transparent
|
191 |
|
|
infoBox->SetFillColor(kWhite);
|
192 |
anderson |
1.1 |
infoBox->Draw();
|
193 |
|
|
|
194 |
anderson |
1.3 |
// Place the stats boxes to be non-overlapping
|
195 |
|
|
if (showStatsBoxes) {
|
196 |
|
|
canvasDefault->SetRightMargin(0.2);
|
197 |
|
|
canvasDefault->Update();
|
198 |
|
|
TPaveStats *st1 = (TPaveStats*)htemp1->GetListOfFunctions()->FindObject("stats");
|
199 |
|
|
TPaveStats *st2 = (TPaveStats*)htemp2->GetListOfFunctions()->FindObject("stats");
|
200 |
|
|
st1->SetX1NDC(.79); st1->SetX2NDC(.99);
|
201 |
|
|
st1->SetY1NDC(.6); st1->SetY2NDC(.8);
|
202 |
|
|
st2->SetX1NDC(.79); st2->SetX2NDC(.99);
|
203 |
|
|
st2->SetY1NDC(.38); st2->SetY2NDC(.58);
|
204 |
|
|
canvasDefault->Modified();
|
205 |
|
|
}
|
206 |
|
|
|
207 |
|
|
// Set log y axis
|
208 |
|
|
if (yAxisLogScale) canvasDefault->SetLogy(1);
|
209 |
anderson |
1.1 |
// Save the canvas
|
210 |
|
|
canvasDefault->SaveAs(filename);
|
211 |
|
|
|
212 |
|
|
}
|
213 |
|
|
|