ROOT logo
/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

// Draw histograms/graphs with same name located in different directories
// author: Eulogio Serradilla <eulogio.serradilla@cern.ch>

#if !defined(__CINT__) || defined(__MAKECINT__)
#include <TFile.h>
#include <TString.h>
#include <TMath.h>
#include <TCanvas.h>
#include <TPad.h>
#include <TLegend.h>
#include <TH1.h>
#include <TGraphErrors.h>
#include <TKey.h>
#include <TLine.h>
#include <TStyle.h>
#endif

TGraphErrors* Divide(const TGraphErrors* grX1, const TGraphErrors* grX2, const TString& name);

void DrawDir(const TString& inputFile,
             const TString& graphName,
             const TString& refdir="",
             Double_t xmin = 0,
             Double_t xmax = 3.5,
             Double_t ymin = 0,
             Double_t ymax = 1.,
             const TString& xtitle = "",
             const TString& ytitle = "",
             Int_t option = 1,
             const TString& canvasName = "c0",
             const TString& canvasTitle = "DrawDir")
{
//
// draw histograms/graphs with same name located in different directories
// if option = 0 no comparison,
// if option = 1 draw a bottom pad with the comparison, and
// if option = 2 draw the comparison in a different canvas
//
	const Int_t kMax = 10; // maximum number of subdirectories
	
	const Int_t kColor[kMax]  = { kRed, kBlue, kOrange+1, kGreen-2, kGreen+2, kAzure, kViolet+10, kAzure+2, kOrange+2, kSpring-7 };
	
	const Int_t kMarker[kMax] = { kFullCircle, kFullTriangleUp, kFullSquare, kFullTriangleDown, kOpenCircle, kOpenSquare, kOpenTriangleUp, kOpenDiamond, kOpenCross, kFullStar };
	
	TFile* finput = new TFile(inputFile.Data());
	if (finput->IsZombie()) exit(1);
	
	// iterate over the list of keys
	
	TObject* obj[kMax];
	TString* subdir[kMax];
	obj[0] = 0; // reference object
	Int_t nDir = 0;
	if(option>0) nDir = 1;
	
	TIter next(finput->GetListOfKeys());
	TKey* key = 0;
	while( (key = (TKey*)next()) && (nDir < kMax) )
	{
		TString classname = key->GetClassName();
		if(classname == "TDirectoryFile")
		{
			TObject* i = 0;
			finput->GetObject(Form("%s/%s;1", key->GetName(), graphName.Data()),i);
			if(i == 0)
			{
				finput->Error("GetObject","%s/%s not found", key->GetName(), graphName.Data());
				exit(1);
			}
			else if(i->InheritsFrom("TH1") || i->InheritsFrom("TGraph"))
			{
				Int_t j = 0;
				
				if(option==0) j = nDir++;
				else if(TString(key->GetName()) != refdir) j = nDir++;
				
				obj[j] = i;
				(dynamic_cast<TAttLine*>(i))->SetLineColor(kColor[j]);
				(dynamic_cast<TAttMarker*>(i))->SetMarkerColor(kColor[j]);
				(dynamic_cast<TAttMarker*>(i))->SetMarkerStyle(kMarker[j]);
				subdir[j] = new TString(key->GetName());
			}
			else
			{
				finput->Warning("GetObject", "%s does not contain %s", key->GetName(), graphName.Data());
			}
		}
	}
	
	// compare w.r.t. reference data
	
	TGraphErrors* grDiv[kMax];
	
	if(option > 0)
	{
		if(obj[0] == 0)
		{
			finput->Error("GetObject", "reference directory %s not found", refdir.Data());
			for(Int_t i=0; i < nDir; ++i) delete subdir[i];
			exit(1);
		}
		
		TGraphErrors* grY = 0;
		
		if(obj[0]->InheritsFrom("TH1"))
		{
			grY = new TGraphErrors(dynamic_cast<TH1*>(obj[0]));
		}
		else if(obj[0]->InheritsFrom("TGraph"))
		{
			grY = new TGraphErrors(*dynamic_cast<TGraphErrors*>(obj[0]));
		}
		
		TGraphErrors* grX = 0;
		
		for(Int_t i=1; i < nDir; ++i)
		{
			if(obj[i]->InheritsFrom("TH1"))
			{
				grX = new TGraphErrors(dynamic_cast<TH1*>(obj[i]));
			}
			else if(obj[i]->InheritsFrom("TGraph"))
			{
				grX = new TGraphErrors(*dynamic_cast<TGraphErrors*>(obj[i]));
			}
			
			grDiv[i] = Divide(grX, grY, Form("%s_%s_Ratio", subdir[i]->Data(), obj[i]->GetName()));
			
			grDiv[i]->SetLineColor(kColor[i]);
			grDiv[i]->SetMarkerColor(kColor[i]);
			grDiv[i]->SetMarkerStyle(kMarker[i]);
			
			delete grX;
		}
		
		delete grY;
	}
	
	// draw
	
	gStyle->SetPadTickX(1);
	gStyle->SetPadTickY(1);
	gStyle->SetOptTitle(0);
	gStyle->SetOptStat(0);
	
	TCanvas* c0 = new TCanvas(canvasName.Data(), canvasTitle.Data());
	
	if(option == 1) // create a top pad
	{
		TPad* top = new TPad("top", "Variable", 0, 0.25, 1, 1, 0, 0, 0);
		
		top->SetBottomMargin(0.);
		top->Draw();
		
		top->cd();
		
		TH1F* frm = top->DrawFrame(xmin, ymin , xmax, ymax);
		frm->GetYaxis()->SetTitle(ytitle);
	}
	else // only draw the frame
	{
		TH1F* frm = c0->DrawFrame(xmin, ymin , xmax, ymax);
		frm->GetXaxis()->SetTitle(xtitle);
		frm->GetYaxis()->SetTitle(ytitle);
	}
	
	// draw objects in current pad
	for(Int_t i=0; i < nDir; ++i)
	{
		if(obj[i]->InheritsFrom("TH1"))
		{
			obj[i]->Draw("same");
		}
		else if(obj[i]->InheritsFrom("TGraph"))
		{
			obj[i]->Draw("zP");
		}
	}
	
	// build a legend
	TLegend* legend = new TLegend(0.5718391,0.6991525,0.8390805,0.8368644,0,"brNDC");
	legend->SetTextSize(0.03);
	legend->SetFillColor(0);
	legend->SetBorderSize(0);
	
	for(Int_t i=0; i < nDir; ++i)
	{
		legend->AddEntry(obj[i], subdir[i]->Data(), "lp");
	}
	
	legend->Draw();
	
	if(option == 1) // create a bottom pad
	{
		c0->cd();
		
		TPad* bottom = new TPad("bottom", "ratio", 0, 0, 1, 0.25, 0, 0, 0);
		
		bottom->SetBottomMargin(0.3);
		bottom->SetTopMargin(0.);
		bottom->Draw();
		
		bottom->cd();
		
		TH1F* frm = bottom->DrawFrame(xmin, 0.7 , xmax, 1.3);
		
		frm->GetXaxis()->SetLabelSize(0.13);
		frm->GetXaxis()->SetTitle(xtitle);
		frm->GetXaxis()->SetTitleSize(0.13);
		frm->GetYaxis()->SetTitle("Ratio");
		frm->GetYaxis()->SetLabelSize(0.1);
		frm->GetYaxis()->SetTitleSize(0.12);
		frm->GetYaxis()->SetTitleOffset(0.3);
	}
	else if(option == 2) // create a new canvas
	{
		TCanvas* c1 = new TCanvas(Form("%s.Ratio",canvasName.Data()), Form("%s ratio",canvasTitle.Data()));
		
		TH1F* frm = c1->DrawFrame(xmin, 0.5 ,xmax, 1.5);
		frm->GetXaxis()->SetTitle(xtitle);
		frm->GetYaxis()->SetTitle("Ratio");
		frm->GetYaxis()->SetTitleOffset(1.20);
	}
	
	// draw comparison
	if(nDir>0 && option > 0)
	{
		// draw a red line for the reference
		TLine* ref = new TLine(xmin,1,xmax,1);
		ref->SetLineWidth(1);
		ref->SetLineColor(kColor[0]);
		ref->SetLineStyle(2);
		ref->Draw();
		
		for(Int_t i=1; i<nDir; ++i)
		{
			grDiv[i]->Draw("zP");
		}
		
		if(option == 2)
		{
			TLegend* legendRatio = new TLegend(0.5718391,0.6991525,0.8390805,0.8368644,0,"brNDC");
			legendRatio->SetTextSize(0.03);
			legendRatio->SetFillColor(0);
			legendRatio->SetBorderSize(0);
			
			legendRatio->AddEntry(ref, subdir[0]->Data(), "l");
			for(Int_t i=1; i < nDir; ++i)
			{
				legendRatio->AddEntry(grDiv[i], subdir[i]->Data(), "lp");
			}
			
			legendRatio->SetTextFont(42);
			legendRatio->Draw();
		}
	}
	
	// release memory
}

Double_t GuessErrorY(const TGraphErrors* gr, Double_t x0)
{
//
// estimate error of gr(x0) with the closest point to x0
//
	for(Int_t i=0; i<gr->GetN(); ++i)
	{
		Double_t x, y;
		gr->GetPoint(i, x, y);
		if(x >= x0) return gr->GetErrorY(i);
	}
	
	return 0;
}

TGraphErrors* Divide(const TGraphErrors* grX1, const TGraphErrors* grX2, const TString& name)
{
//
// grX1/grX2 using grX2 as reference
//
	TGraphErrors* grQ = new TGraphErrors();
	grQ->SetName(name.Data());
	
	Double_t xmin = 0;
	Double_t xmax = 0;
	Double_t y1   = 0;
	grX1->GetPoint(0, xmin, y1);
	grX1->GetPoint(grX1->GetN()-1, xmax, y1);
	
	for(Int_t i=0, j=0; i < grX2->GetN(); ++i)
	{
		Double_t x2, y2;
		grX2->GetPoint(i, x2, y2);
		
		if(x2 < xmin) continue;
		if(x2 > xmax) break;
		
		y1 = grX1->Eval(x2);
		
		if(y1 == 0 || y2 == 0) continue;
		
		Double_t r = y1/y2;
		
		Double_t erry1 = GuessErrorY(grX1, x2);
		Double_t erry2 = grX2->GetErrorY(i);
		Double_t err = r*TMath::Sqrt(TMath::Power(erry1/y1,2)+TMath::Power(erry2/y2,2));
		
		grQ->SetPoint(j, x2, r);
		grQ->SetPointError(j++, grX2->GetErrorX(i), err);
	}
	
	return grQ;
}
 DrawDir.C:1
 DrawDir.C:2
 DrawDir.C:3
 DrawDir.C:4
 DrawDir.C:5
 DrawDir.C:6
 DrawDir.C:7
 DrawDir.C:8
 DrawDir.C:9
 DrawDir.C:10
 DrawDir.C:11
 DrawDir.C:12
 DrawDir.C:13
 DrawDir.C:14
 DrawDir.C:15
 DrawDir.C:16
 DrawDir.C:17
 DrawDir.C:18
 DrawDir.C:19
 DrawDir.C:20
 DrawDir.C:21
 DrawDir.C:22
 DrawDir.C:23
 DrawDir.C:24
 DrawDir.C:25
 DrawDir.C:26
 DrawDir.C:27
 DrawDir.C:28
 DrawDir.C:29
 DrawDir.C:30
 DrawDir.C:31
 DrawDir.C:32
 DrawDir.C:33
 DrawDir.C:34
 DrawDir.C:35
 DrawDir.C:36
 DrawDir.C:37
 DrawDir.C:38
 DrawDir.C:39
 DrawDir.C:40
 DrawDir.C:41
 DrawDir.C:42
 DrawDir.C:43
 DrawDir.C:44
 DrawDir.C:45
 DrawDir.C:46
 DrawDir.C:47
 DrawDir.C:48
 DrawDir.C:49
 DrawDir.C:50
 DrawDir.C:51
 DrawDir.C:52
 DrawDir.C:53
 DrawDir.C:54
 DrawDir.C:55
 DrawDir.C:56
 DrawDir.C:57
 DrawDir.C:58
 DrawDir.C:59
 DrawDir.C:60
 DrawDir.C:61
 DrawDir.C:62
 DrawDir.C:63
 DrawDir.C:64
 DrawDir.C:65
 DrawDir.C:66
 DrawDir.C:67
 DrawDir.C:68
 DrawDir.C:69
 DrawDir.C:70
 DrawDir.C:71
 DrawDir.C:72
 DrawDir.C:73
 DrawDir.C:74
 DrawDir.C:75
 DrawDir.C:76
 DrawDir.C:77
 DrawDir.C:78
 DrawDir.C:79
 DrawDir.C:80
 DrawDir.C:81
 DrawDir.C:82
 DrawDir.C:83
 DrawDir.C:84
 DrawDir.C:85
 DrawDir.C:86
 DrawDir.C:87
 DrawDir.C:88
 DrawDir.C:89
 DrawDir.C:90
 DrawDir.C:91
 DrawDir.C:92
 DrawDir.C:93
 DrawDir.C:94
 DrawDir.C:95
 DrawDir.C:96
 DrawDir.C:97
 DrawDir.C:98
 DrawDir.C:99
 DrawDir.C:100
 DrawDir.C:101
 DrawDir.C:102
 DrawDir.C:103
 DrawDir.C:104
 DrawDir.C:105
 DrawDir.C:106
 DrawDir.C:107
 DrawDir.C:108
 DrawDir.C:109
 DrawDir.C:110
 DrawDir.C:111
 DrawDir.C:112
 DrawDir.C:113
 DrawDir.C:114
 DrawDir.C:115
 DrawDir.C:116
 DrawDir.C:117
 DrawDir.C:118
 DrawDir.C:119
 DrawDir.C:120
 DrawDir.C:121
 DrawDir.C:122
 DrawDir.C:123
 DrawDir.C:124
 DrawDir.C:125
 DrawDir.C:126
 DrawDir.C:127
 DrawDir.C:128
 DrawDir.C:129
 DrawDir.C:130
 DrawDir.C:131
 DrawDir.C:132
 DrawDir.C:133
 DrawDir.C:134
 DrawDir.C:135
 DrawDir.C:136
 DrawDir.C:137
 DrawDir.C:138
 DrawDir.C:139
 DrawDir.C:140
 DrawDir.C:141
 DrawDir.C:142
 DrawDir.C:143
 DrawDir.C:144
 DrawDir.C:145
 DrawDir.C:146
 DrawDir.C:147
 DrawDir.C:148
 DrawDir.C:149
 DrawDir.C:150
 DrawDir.C:151
 DrawDir.C:152
 DrawDir.C:153
 DrawDir.C:154
 DrawDir.C:155
 DrawDir.C:156
 DrawDir.C:157
 DrawDir.C:158
 DrawDir.C:159
 DrawDir.C:160
 DrawDir.C:161
 DrawDir.C:162
 DrawDir.C:163
 DrawDir.C:164
 DrawDir.C:165
 DrawDir.C:166
 DrawDir.C:167
 DrawDir.C:168
 DrawDir.C:169
 DrawDir.C:170
 DrawDir.C:171
 DrawDir.C:172
 DrawDir.C:173
 DrawDir.C:174
 DrawDir.C:175
 DrawDir.C:176
 DrawDir.C:177
 DrawDir.C:178
 DrawDir.C:179
 DrawDir.C:180
 DrawDir.C:181
 DrawDir.C:182
 DrawDir.C:183
 DrawDir.C:184
 DrawDir.C:185
 DrawDir.C:186
 DrawDir.C:187
 DrawDir.C:188
 DrawDir.C:189
 DrawDir.C:190
 DrawDir.C:191
 DrawDir.C:192
 DrawDir.C:193
 DrawDir.C:194
 DrawDir.C:195
 DrawDir.C:196
 DrawDir.C:197
 DrawDir.C:198
 DrawDir.C:199
 DrawDir.C:200
 DrawDir.C:201
 DrawDir.C:202
 DrawDir.C:203
 DrawDir.C:204
 DrawDir.C:205
 DrawDir.C:206
 DrawDir.C:207
 DrawDir.C:208
 DrawDir.C:209
 DrawDir.C:210
 DrawDir.C:211
 DrawDir.C:212
 DrawDir.C:213
 DrawDir.C:214
 DrawDir.C:215
 DrawDir.C:216
 DrawDir.C:217
 DrawDir.C:218
 DrawDir.C:219
 DrawDir.C:220
 DrawDir.C:221
 DrawDir.C:222
 DrawDir.C:223
 DrawDir.C:224
 DrawDir.C:225
 DrawDir.C:226
 DrawDir.C:227
 DrawDir.C:228
 DrawDir.C:229
 DrawDir.C:230
 DrawDir.C:231
 DrawDir.C:232
 DrawDir.C:233
 DrawDir.C:234
 DrawDir.C:235
 DrawDir.C:236
 DrawDir.C:237
 DrawDir.C:238
 DrawDir.C:239
 DrawDir.C:240
 DrawDir.C:241
 DrawDir.C:242
 DrawDir.C:243
 DrawDir.C:244
 DrawDir.C:245
 DrawDir.C:246
 DrawDir.C:247
 DrawDir.C:248
 DrawDir.C:249
 DrawDir.C:250
 DrawDir.C:251
 DrawDir.C:252
 DrawDir.C:253
 DrawDir.C:254
 DrawDir.C:255
 DrawDir.C:256
 DrawDir.C:257
 DrawDir.C:258
 DrawDir.C:259
 DrawDir.C:260
 DrawDir.C:261
 DrawDir.C:262
 DrawDir.C:263
 DrawDir.C:264
 DrawDir.C:265
 DrawDir.C:266
 DrawDir.C:267
 DrawDir.C:268
 DrawDir.C:269
 DrawDir.C:270
 DrawDir.C:271
 DrawDir.C:272
 DrawDir.C:273
 DrawDir.C:274
 DrawDir.C:275
 DrawDir.C:276
 DrawDir.C:277
 DrawDir.C:278
 DrawDir.C:279
 DrawDir.C:280
 DrawDir.C:281
 DrawDir.C:282
 DrawDir.C:283
 DrawDir.C:284
 DrawDir.C:285
 DrawDir.C:286
 DrawDir.C:287
 DrawDir.C:288
 DrawDir.C:289
 DrawDir.C:290
 DrawDir.C:291
 DrawDir.C:292
 DrawDir.C:293
 DrawDir.C:294
 DrawDir.C:295
 DrawDir.C:296
 DrawDir.C:297
 DrawDir.C:298
 DrawDir.C:299
 DrawDir.C:300
 DrawDir.C:301
 DrawDir.C:302
 DrawDir.C:303
 DrawDir.C:304
 DrawDir.C:305
 DrawDir.C:306
 DrawDir.C:307
 DrawDir.C:308
 DrawDir.C:309
 DrawDir.C:310
 DrawDir.C:311
 DrawDir.C:312
 DrawDir.C:313
 DrawDir.C:314
 DrawDir.C:315
 DrawDir.C:316
 DrawDir.C:317
 DrawDir.C:318
 DrawDir.C:319
 DrawDir.C:320
 DrawDir.C:321
 DrawDir.C:322
 DrawDir.C:323
 DrawDir.C:324
 DrawDir.C:325
 DrawDir.C:326
 DrawDir.C:327
 DrawDir.C:328
 DrawDir.C:329