]> git.uio.no Git - u/mrichter/AliRoot.git/blame - PWG2/FORWARD/analysis2/AnalyseAOD.C
Fix up some drawing stuff
[u/mrichter/AliRoot.git] / PWG2 / FORWARD / analysis2 / AnalyseAOD.C
CommitLineData
7dacdf84 1
7c1a1f1d 2/**
3 * @file
4 *
5 * @ingroup pwg2_forward_scripts
6 */
7e4038b5 7#include <TH1D.h>
8#include <TH2D.h>
9#include <TCanvas.h>
10#include <TPad.h>
11#include <TFile.h>
12#include <TTree.h>
95985fc4 13#include <TChain.h>
7e4038b5 14#include <TError.h>
95985fc4 15#include <TSystemDirectory.h>
16#include <TROOT.h>
7e4038b5 17#include <TStyle.h>
18#include <THStack.h>
19#include <TLegend.h>
20#include <TMath.h>
21#include <TMultiGraph.h>
22#include <TGraph.h>
23#include <TGraphErrors.h>
24#include <TLatex.h>
65a1e0cd 25#include <TSystem.h>
7e4038b5 26#include "AliAODForwardMult.h"
27#include "OtherData.C"
7dacdf84 28#include <ctime>
7e4038b5 29
30/**
31 * Draw the data stored in the AOD
32 *
33 * To use this, do
34 *
35 * @code
36 * Root> .L $ALICE_ROOT/PWG2/FORWARD/analysis2/Compile.C
270764db 37 * Root> Compile("$ALICE_ROOT/PWG2/FORWARD/analysis2/AnalyseAOD.C")
38 * Root> AnalyseAOD dr
7e4038b5 39 * Root> dr.Run("AliAODs.root",-10,10,5,AliAODForwardMult::kInel,900)
40 * @endcode
41 *
42 * The output is stored in a ROOT file
43 *
44 * See also the script Pass2.C
45 *
7c1a1f1d 46 * @ingroup pwg2_forward_scripts
7e4038b5 47 */
270764db 48struct AnalyseAOD
7e4038b5 49{
50public:
51 /** AOD tree */
52 TTree* fTree;
53 /** AOD object */
54 AliAODForwardMult* fAOD;
270764db 55 /** AOD object */
56 AliAODForwardMult* fMCAOD;
7e4038b5 57 /** Output file */
58 TFile* fOut;
59 /** Summed histogram */
60 TH2D* fSum;
270764db 61 /** Summed histogram */
62 TH2D* fMCSum;
4cbdf467 63 /** Primary information */
64 TH2D* fPrimary;
65 /** Sum primary information */
66 TH2D* fSumPrimary;
3a08cca0 67 /** Central region */
68 TH2D* fCentral;
69 /** Central region */
70 TH2D* fSumCentral;
7e4038b5 71 /** Vertex efficiency */
72 Double_t fVtxEff;
73 /** Title to put on the plot */
74 TString fTitle;
f4494b7a 75 /** Do HHD comparison */
76 Bool_t fDoHHD;
4cbdf467 77 /** Number of events with a trigger */
78 Int_t fNTriggered;
79 /** Number of events with a vertex */
80 Int_t fNWithVertex;
81 /** Number of events accepted */
82 Int_t fNAccepted;
e333578d 83 /** Number of events accepted */
84 Int_t fNAll;
9bff843b 85 /** Number of events accepted */
86 Int_t fNMB;
4543dda1 87 /** Number of B triggers */
88 Int_t fNB;
89 /** Number of A triggers */
90 Int_t fNA;
91 /** Number of C triggers */
92 Int_t fNC;
93 /** Number of E triggers */
94 Int_t fNE;
1174780f 95 /** Min vertex */
96 Double_t fVtxMin;
97 /** Max vertex */
98 Double_t fVtxMax;
9bff843b 99 /** Whether to cut edges in the rebinning */
100 Bool_t fCutEdges;
e333578d 101
7e4038b5 102 //__________________________________________________________________
103 /**
104 * Constructor
105 *
106 */
270764db 107 AnalyseAOD()
7e4038b5 108 : fTree(0),
109 fAOD(0),
270764db 110 fMCAOD(0),
7e4038b5 111 fOut(0),
112 fSum(0),
270764db 113 fMCSum(0),
4cbdf467 114 fPrimary(0),
115 fSumPrimary(0),
3a08cca0 116 fCentral(0),
117 fSumCentral(0),
7e4038b5 118 fVtxEff(0),
f4494b7a 119 fTitle(""),
4543dda1 120 fDoHHD(kTRUE),
121 fNTriggered(0),
122 fNWithVertex(0),
123 fNAccepted(0),
124 fNAll(0),
9bff843b 125 fNMB(0),
4543dda1 126 fNB(0),
127 fNA(0),
128 fNC(0),
129 fNE(0),
130 fVtxMin(0),
9bff843b 131 fVtxMax(0),
132 fCutEdges(false)
7e4038b5 133 {}
134 //__________________________________________________________________
135 /**
136 * Reset internal structures
137 *
138 */
139 void Clear(Option_t* )
140 {
141 if (fTree && fTree->GetCurrentFile()) {
142 fTree->GetCurrentFile()->Close();
143 delete fTree;
144 }
145 if (fOut) {
146 fOut->Close();
147 delete fOut;
148 }
4cbdf467 149 if (fSum) delete fSum;
150 if (fMCSum) delete fMCSum;
151 if (fSumPrimary) delete fSumPrimary;
3a08cca0 152 if (fCentral) delete fCentral;
153 if (fSumCentral) delete fSumCentral;
4cbdf467 154 fTree = 0;
155 fOut = 0;
156 fSum = 0;
157 fMCSum = 0;
3a08cca0 158 fPrimary = 0;
4cbdf467 159 fSumPrimary = 0;
3a08cca0 160 fCentral = 0;
161 fSumCentral = 0;
4cbdf467 162 fVtxEff = 0;
4543dda1 163 fNTriggered = 0;
164 fNWithVertex= 0;
165 fNAccepted = 0;
166 fNAll = 0;
9bff843b 167 fNMB = 0;
4543dda1 168 fNB = 0;
169 fNA = 0;
170 fNC = 0;
171 fNE = 0;
172 // fVtxMin = 0;
173 // fVtxMax = 0;
7e4038b5 174
175 }
176 //__________________________________________________________________
177 /**
178 * Run
179 *
95985fc4 180 * @param file Input path for files with AOD trees
7e4038b5 181 * @param vzMin Minimum interaction point z coordinate
182 * @param vzMax Maximum interaction point z coordinate
183 * @param rebin How many times to re-bin the @f$ dN_{ch}/d\eta@f$
184 * @param mask Trigger mask
185 * @param energy Collision energy @f$ \sqrt{s}@f$ or @f$\sqrt{s_{NN}}@f$
186 * @param title Title to put on the plot
c389303e 187 * @param doHHD Whether to do HHD comparison
188 * @param doComp Whether to do comparisons
7e4038b5 189 *
190 * @return True on success, false otherwise
191 */
95985fc4 192 Bool_t Run(const char* file=".",
7e4038b5 193 Double_t vzMin=-10, Double_t vzMax=10, Int_t rebin=1,
194 Int_t mask=AliAODForwardMult::kInel, Int_t energy=900,
f4494b7a 195 const char* title="", Bool_t doHHD=false, Bool_t doComp=false)
7e4038b5 196 {
197 TString trgName;
198 if (mask & AliAODForwardMult::kInel) trgName.Append("inel-");
199 if (mask & AliAODForwardMult::kInelGt0) trgName.Append("inelgt0-");
200 if (mask & AliAODForwardMult::kNSD) trgName.Append("nsd-");
201 if (trgName.EndsWith("-")) trgName.Remove(trgName.Length()-1);
202 if (trgName.IsNull()) trgName = "unknown";
203 TString outName =
204 TString::Format("dndeta_%04dGeV_%c%02d-%c%02dcm_rb%02d_%s.root",
205 energy,
206 vzMin < 0 ? 'm' : 'p', Int_t(TMath::Abs(vzMin)+.5),
207 vzMax < 0 ? 'm' : 'p', Int_t(TMath::Abs(vzMax)+.5),
208 rebin, trgName.Data());
1174780f 209 fTitle = title;
210 fVtxMin = vzMin;
211 fVtxMax = vzMax;
7e4038b5 212 if (!Open(file, outName)) return kFALSE;
1174780f 213 if (!Process(mask)) return kFALSE;
f4494b7a 214 if (!Finish(rebin, mask, energy,doHHD,doComp)) return kFALSE;
7e4038b5 215
216 return kTRUE;
217 }
95985fc4 218 //__________________________________________________________________
219 /**
220 * Scan directory @a dir for AODs
221 *
222 * @param dir Directory to scan
223 * @param chain Chain to add to
224 * @param recursive Whether to scan recusively
225 */
226 void ScanDirectory(TSystemDirectory* dir, TChain* chain, bool recursive)
227 {
cc83fca2 228 // gROOT->IndentLevel();
229 // printf("Scanning %s ...\n", dir->GetName());
230 // gROOT->IncreaseDirLevel();
95985fc4 231
232 // Get list of files, and go back to old working directory
233 TString oldDir(gSystem->WorkingDirectory());
234 TList* files = dir->GetListOfFiles();
235 gSystem->ChangeDirectory(oldDir);
236
237 // Sort list of files and check if we should add it
238 files->Sort();
239 TIter next(files);
240 TSystemFile* file = 0;
241 while ((file = static_cast<TSystemFile*>(next()))) {
242 TString name(file->GetName());
243
244 // Ignore special links
245 if (name == "." || name == "..") continue;
246
247 // Check if this is a directory
248 if (file->IsDirectory()) {
249 if (recursive)
250 ScanDirectory(static_cast<TSystemDirectory*>(file),chain,recursive);
251 continue;
252 }
253
254 // If this is not a root file, ignore
255 if (!name.EndsWith(".root")) continue;
256
257 // If this file does not contain AliESDs, ignore
258 if (!name.Contains("AliAOD")) continue;
259
260 // Get the path
261 TString aod(Form("%s/%s", file->GetTitle(), name.Data()));
262
263 // Print and add
cc83fca2 264 // gROOT->IndentLevel();
265 // printf("adding %s\n", aod.Data());
95985fc4 266 chain->Add(aod);
267
268 }
cc83fca2 269 // gROOT->DecreaseDirLevel();
95985fc4 270 }
271
272 //__________________________________________________________________
273 /**
274 * Make a chain of AOD files
275 *
276 * @param aoddir Directory so search
277 * @param recursive Whether to scan recusively
278 *
279 * @return The new chain
280 */
281 TChain*
282 MakeChain(const char* aoddir, bool recursive=false)
283 {
284 // --- Our data chain ----------------------------------------------
285 TChain* chain = new TChain("aodTree");
286
287 // --- Get list of AODs --------------------------------------------
288 // Open source directory, and make sure we go back to were we were
289 TString oldDir(gSystem->WorkingDirectory());
290 TSystemDirectory d(aoddir, aoddir);
291 ScanDirectory(&d, chain, recursive);
292
293 chain->GetListOfFiles()->ls();
294 if (chain->GetListOfFiles()->GetEntries() <= 0) {
295 delete chain;
296 chain = 0;
297 }
298 return chain;
299 }
300
301 //__________________________________________________________________
302 /**
303 * Open data. Make a chain of all AOD files in the given path
304 * and below.
305 *
306 * @param path Path to search
307 * @param outname Output name
308 *
309 * @return
310 */
311 Bool_t Open(const char* path, const char* outname)
312 {
313 Clear("");
314
315 // Get the AOD tree
316 fTree = MakeChain(path, true);
317 if (!fTree) {
318 Error("Init", "Couldn't get the tree");
319 return kFALSE;
320 }
321
322 // Set the branch pointer
323 fTree->SetBranchAddress("Forward", &fAOD);
324
325 // Set the branch pointer
cc83fca2 326 if (fTree->GetBranch("ForwardMC"))
327 fTree->SetBranchAddress("ForwardMC", &fMCAOD);
95985fc4 328
329 // Set the branch pointer
cc83fca2 330 if (fTree->GetBranch("primary"))
331 fTree->SetBranchAddress("primary", &fPrimary);
3a08cca0 332
333 // Set branch pointer
334 if (fTree->GetBranch("Central"))
335 fTree->SetBranchAddress("Central", &fCentral);
95985fc4 336
337 fOut = TFile::Open(outname, "RECREATE");
338 if (!fOut) {
339 Error("Open", "Couldn't open %s", outname);
340 return kFALSE;
341 }
342 return kTRUE;
343
344 }
345
95985fc4 346
7e4038b5 347 //__________________________________________________________________
348 /**
349 * Process the events
350 *
351 * @param vzMin Minimum interaction point z coordinate
352 * @param vzMax Maximum interaction point z coordinate
353 * @param mask Trigger mask
354 *
355 * @return true on success, false otherwise
356 */
1174780f 357 Bool_t Process(Int_t mask)
7e4038b5 358 {
4cbdf467 359 fNTriggered = 0; // # of triggered ev.
360 fNWithVertex = 0; // # of ev. w/vertex
361 fNAccepted = 0; // # of ev. used
fa4236ed 362 Int_t nAvailable = fTree->GetEntries(); // How many entries
7dacdf84 363 Int_t start = time(NULL);
7e4038b5 364
365 for (int i = 0; i < nAvailable; i++) {
366 fTree->GetEntry(i);
65a1e0cd 367 if (((i+1) % 100) == 0) {
7dacdf84 368 Int_t now = time(NULL);
369 double t = difftime(now,start);
370 double full = t / (i+1) * nAvailable;
371 int rem = full-t;
372 Int_t ss = rem % 60;
373 Int_t mm = (rem / 60) % 60;
374 Int_t hh = (rem / 60 / 60);
375 fprintf(stdout,"Event # %9d of %9d, %9d accepted so far "
376 "ETA %02d:%02d:%02d\r", i+1, nAvailable, fNAccepted,
377 hh, mm, ss);
65a1e0cd 378 fflush(stdout);
379 }
7e4038b5 380
381 // Create sum histogram on first event - to match binning to input
9bff843b 382 if (!fSum)
7e4038b5 383 fSum = static_cast<TH2D*>(fAOD->GetHistogram().Clone("d2ndetadphi"));
9bff843b 384 if (!fMCSum && fTree->GetBranch("ForwardMC"))
270764db 385 fMCSum =
386 static_cast<TH2D*>(fMCAOD->GetHistogram().Clone("d2ndetadphiMC"));
9bff843b 387 if (!fSumPrimary && fTree->GetBranch("primary"))
388 fSumPrimary = static_cast<TH2D*>(fPrimary->Clone("primarySum"));
389 if (!fSumCentral && fTree->GetBranch("Central"))
390 fSumCentral = static_cast<TH2D*>(fCentral->Clone("centralSum"));
e333578d 391
392 // Add contribution from this event
393 if (fSumPrimary) fSumPrimary->Add(fPrimary);
394
395 fNAll++;
4543dda1 396 if (fAOD->IsTriggerBits(AliAODForwardMult::kB)) fNB++;
397 if (fAOD->IsTriggerBits(AliAODForwardMult::kA)) fNA++;
398 if (fAOD->IsTriggerBits(AliAODForwardMult::kC)) fNC++;
399 if (fAOD->IsTriggerBits(AliAODForwardMult::kE)) fNE++;
e333578d 400
9bff843b 401 // Other trigger/event requirements could be defined
402 if (fAOD->IsTriggerBits(AliAODForwardMult::kInel)) fNMB++;
403
7e4038b5 404 // fAOD->Print();
405 // Other trigger/event requirements could be defined
406 if (!fAOD->IsTriggerBits(mask)) continue;
4cbdf467 407 fNTriggered++;
fa4236ed 408
409 // Check if there's a vertex
410 if (!fAOD->HasIpZ()) continue;
4cbdf467 411 fNWithVertex++;
fa4236ed 412
7e4038b5 413 // Select vertex range (in centimeters)
1174780f 414 if (!fAOD->InRange(fVtxMin, fVtxMax)) continue;
4cbdf467 415 fNAccepted++;
7e4038b5 416
417 // Add contribution from this event
418 fSum->Add(&(fAOD->GetHistogram()));
270764db 419
420 // Add contribution from this event
421 if (fMCSum) fMCSum->Add(&(fMCAOD->GetHistogram()));
4cbdf467 422
3a08cca0 423 // Add contribution from this event
424 if (fSumCentral) fSumCentral->Add(fCentral);
7e4038b5 425 }
7dacdf84 426 Int_t now = time(NULL);
427 Int_t t = Int_t(difftime(now,start));
428 Int_t ss = t % 60;
429 Int_t mm = (t / 60) % 60;
430 Int_t hh = (t / 60 / 60);
431 fprintf(stdout,"%9d events processed in %02d:%02d:%02d%33s\n",
432 nAvailable, hh, mm, ss, " ");
433 fflush(stdout);
434
4543dda1 435 // fVtxEff = Double_t(fNWithVertex)/fNTriggered;
3c5497d0 436 Int_t nGood = (fNB-fNA-fNC+2*fNE);
9bff843b 437 fVtxEff = (Double_t(fNMB) / fNTriggered) *
438 (nGood > 0 ? Double_t(fNAccepted) / nGood : 0);
3c5497d0 439
fa4236ed 440 Info("Process", "Total of %9d events\n"
9bff843b 441 " of these %9d are minimum bias\n"
3c5497d0 442 " of these %9d has a trigger\n"
443 " of these %9d has a vertex\n"
444 " of these %9d was used\n"
445 " Triggers by type:\n"
446 " B = %9d\n"
447 " A|C = %9d (%9d+%-9d)\n"
448 " E = %9d\n"
449 " Implies %9d good triggers\n"
450 " Vertex efficiency: %f",
9bff843b 451 nAvailable, fNMB, fNTriggered, fNWithVertex, fNAccepted,
3c5497d0 452 fNB, fNA+fNC, fNA, fNC, fNE, nGood, fVtxEff);
7e4038b5 453
454 return kTRUE;
455 }
456 //__________________________________________________________________
457 /**
458 * Finish the stuff and draw
459 *
460 * @param rebin How many times to rebin
461 * @param energy Collision energy
462 * @param mask Trigger mask
c389303e 463 * @param doHHD Whether to do HHD comparison
464 * @param doComp Whether to do comparisons
7e4038b5 465 *
466 * @return true on success, false otherwise
467 */
f4494b7a 468 Bool_t Finish(Int_t rebin, Int_t mask, Int_t energy,
469 Bool_t doHHD, Bool_t doComp)
7e4038b5 470 {
471 fOut->cd();
472
473 // Get acceptance normalisation from underflow bins
474 TH1D* norm = fSum->ProjectionX("norm", 0, 1, "");
475 // Project onto eta axis - _ignoring_underflow_bins_!
476 TH1D* dndeta = fSum->ProjectionX("dndeta", 1, -1, "e");
270764db 477 dndeta->SetTitle("ALICE Forward");
7e4038b5 478 // Normalize to the acceptance
479 dndeta->Divide(norm);
480 // Scale by the vertex efficiency
481 dndeta->Scale(fVtxEff, "width");
482 dndeta->SetMarkerColor(kRed+1);
483 dndeta->SetMarkerStyle(20);
484 dndeta->SetMarkerSize(1);
485 dndeta->SetFillStyle(0);
82fc512a 486 Rebin(dndeta, rebin);
270764db 487
488 TH1D* dndetaMC = 0;
489 if (fMCSum) {
490 // Get acceptance normalisation from underflow bins
491 norm = fMCSum->ProjectionX("norm", 0, 1, "");
492 // Project onto eta axis - _ignoring_underflow_bins_!
493 dndetaMC = fMCSum->ProjectionX("dndetaMC", 1, -1, "e");
494 dndetaMC->SetTitle("ALICE Forward (MC)");
495 // Normalize to the acceptance
496 dndetaMC->Divide(norm);
497 // Scale by the vertex efficiency
498 dndetaMC->Scale(fVtxEff, "width");
499 dndetaMC->SetMarkerColor(kRed+3);
500 dndetaMC->SetMarkerStyle(21);
501 dndetaMC->SetMarkerSize(1);
502 dndetaMC->SetFillStyle(0);
503 Rebin(dndetaMC, rebin);
504 }
505
4cbdf467 506 TH1D* dndetaTruth = 0;
507 if (fSumPrimary) {
508 dndetaTruth = fSumPrimary->ProjectionX("dndetaTruth", -1, -1, "e");
e333578d 509 //dndetaTruth->Scale(1./fNTriggered, "width");
510 dndetaTruth->Scale(1./fNAll, "width");
4cbdf467 511 dndetaTruth->SetMarkerColor(kGray+3);
512 dndetaTruth->SetMarkerStyle(22);
513 dndetaTruth->SetMarkerSize(1);
514 dndetaTruth->SetFillStyle(0);
515 Rebin(dndetaTruth, rebin);
516 }
3a08cca0 517 TH1D* dndetaCentral = 0;
518 if (fSumCentral) {
519 dndetaCentral = fSumCentral->ProjectionX("dndetaCentral", -1, -1, "e");
9bff843b 520 dndetaCentral->SetTitle("ALICE Central - track(let)s");
19abe41d 521 // dndetaCentral->Scale(1./fNTriggered, "width");
522 dndetaCentral->Scale(1./(fNB-fNA-fNC+2*fNE), "width");
3a08cca0 523 dndetaCentral->SetMarkerColor(kGray+3);
524 dndetaCentral->SetMarkerStyle(22);
525 dndetaCentral->SetMarkerSize(1);
526 dndetaCentral->SetFillStyle(0);
19abe41d 527 dndetaCentral->GetXaxis()->SetRangeUser(-1,1);
3a08cca0 528 Rebin(dndetaCentral, rebin <= 1 ? 1 : 2*(rebin/2));
529 // 1 -> 1
530 // 2 -> 2*2/2 -> 2*1 -> 2
531 // 3 -> 2*3/2 -> 2*1 -> 2
532 // 4 -> 2*4/2 -> 2*2 -> 4
533 // 5 -> 2*5/2 -> 2*2 -> 4
534 // 6 -> 2*6/2 -> 2*3 -> 6
535 }
4cbdf467 536
3a08cca0 537 DrawIt(dndeta, dndetaMC, dndetaTruth, dndetaCentral,
538 mask, energy, doHHD, doComp);
7e4038b5 539
82fc512a 540 return kTRUE;
541 }
542 //__________________________________________________________________
543 /**
544 */
3a08cca0 545 void DrawIt(TH1* dndeta, TH1* dndetaMC, TH1* dndetaTruth, TH1* dndetaCentral,
4cbdf467 546 Int_t mask, Int_t energy, Bool_t doHHD,
e333578d 547 Bool_t doComp)
82fc512a 548 {
549 // --- 1st part - prepare data -----------------------------------
e333578d 550 TH1* dndetaSym = Symmetrice(dndeta);
7e4038b5 551
270764db 552 Double_t max = dndeta->GetMaximum();
553
554 // Make our histogram stack
7e4038b5 555 THStack* stack = new THStack("results", "Results");
270764db 556
e333578d 557 TH1* dndetaTruthSym = 0;
558 if (dndetaTruth) {
559 dndetaTruth->SetFillColor(kGray);
560 dndetaTruth->SetFillStyle(3001);
561 dndetaTruthSym = Symmetrice(dndetaTruth);
8329a584 562 stack->Add(dndetaTruthSym, "e5 p");
563 stack->Add(dndetaTruth, "e5 p");
4cbdf467 564 Info("DrawIt", "Maximum of MC dndeta (truth): %f, was %f",
e333578d 565 dndetaTruth->GetMaximum(),dndeta->GetMaximum());
566 max = TMath::Max(dndetaTruth->GetMaximum(),max);
4cbdf467 567 }
7e4038b5 568
82fc512a 569 // Get the data from HHD's analysis - if available
e333578d 570 TH1* dndetaHHD = 0;
571 TH1* dndetaHHDSym = 0;
8329a584 572 // Info("DrawIt", "Will %sdraw HHD results", (doHHD ? "" : "not "));
f4494b7a 573 if (doHHD) {
574 TString hhdName(fOut->GetName());
575 hhdName.ReplaceAll("dndeta", "hhd");
e333578d 576 dndetaHHD = GetHHD(hhdName.Data(), mask & AliAODForwardMult::kNSD);
577 dndetaHHDSym = 0;
578 if (dndetaHHD) {
f4494b7a 579 // Symmetrice and add to stack
e333578d 580 dndetaHHD->SetTitle("ALICE Forward (HHD)");
581 dndetaHHDSym = Symmetrice(dndetaHHD);
582 stack->Add(dndetaHHDSym);
583 stack->Add(dndetaHHD);
584 max = TMath::Max(dndetaHHD->GetMaximum(),max);
f4494b7a 585 }
586 else
587 Warning("DrawIt", "No HHD data found");
270764db 588 fOut->cd();
7e4038b5 589 }
590
270764db 591 // If we have MC analysed data, plot it
592 if (dndetaMC) {
e333578d 593 TH1* dndetaMCSym = Symmetrice(dndetaMC);
594 stack->Add(dndetaMCSym);
270764db 595 stack->Add(dndetaMC);
270764db 596 max = TMath::Max(dndetaMC->GetMaximum(),max);
597 }
598
599 // Add the analysis results to the list
e333578d 600 stack->Add(dndetaSym);
270764db 601 stack->Add(dndeta);
270764db 602
3a08cca0 603 // If we have central region data, add that
604 if (dndetaCentral) {
605 stack->Add(dndetaCentral);
606 max = TMath::Max(dndetaCentral->GetMaximum(),max);
607 }
608
609
82fc512a 610 // Get graph of 'other' data - e.g., UA5, CMS, ... - and check if
611 // there's any graphs. Set the pad division based on that.
8329a584 612 // Info("DrawIt", "Will %sdraw other results", (doComp ? "" : "not "));
f4494b7a 613 TMultiGraph* other = (doComp ? GetData(energy, mask) : 0);
e333578d 614 THStack* ratios = MakeRatios(dndeta, dndetaSym,
615 dndetaHHD, dndetaHHDSym,
616 dndetaTruth, dndetaTruthSym,
9bff843b 617 dndetaCentral,
e333578d 618 other);
7e4038b5 619
82fc512a 620 // Check if we have ratios
621
622 // --- 2nd part - Draw in canvas ---------------------------------
623 // Make a canvas
7e4038b5 624 gStyle->SetOptTitle(0);
f4494b7a 625 gStyle->SetTitleFont(132, "xyz");
626 gStyle->SetLabelFont(132, "xyz");
7e4038b5 627 TCanvas* c = new TCanvas("c", "C", 900, 800);
628 c->SetFillColor(0);
629 c->SetBorderMode(0);
630 c->SetBorderSize(0);
631 c->cd();
632
82fc512a 633 Double_t yd = (ratios ? 0.3 : 0);
634
635 // Make a sub-pad for the result itself
7e4038b5 636 TPad* p1 = new TPad("p1", "p1", 0, yd, 1.0, 1.0, 0, 0);
637 p1->SetTopMargin(0.05);
82fc512a 638 p1->SetBottomMargin(ratios ? 0.001 : 0.1);
7e4038b5 639 p1->SetRightMargin(0.05);
640 p1->SetGridx();
641 p1->SetTicks(1,1);
642 p1->Draw();
643 p1->cd();
82fc512a 644
645 // Fix the apperance of the stack and redraw.
270764db 646 if (other) {
647 TGraphAsymmErrors* o = 0;
648 TIter nextG(other->GetListOfGraphs());
649 while ((o = static_cast<TGraphAsymmErrors*>(nextG()))) {
650 Double_t gmax = TMath::MaxElement(o->GetN(), o->GetY());
8329a584 651 //Info("DrawIt", "Maximum of %s is %f, was %f", o->GetName(),gmax,max);
270764db 652 max = TMath::Max(max, gmax);
653 }
654 }
655 max *= 1.1;
8329a584 656 // Info("DrawIt", "Setting maximum to %f", max);
82fc512a 657 stack->SetMinimum(ratios ? -0.1 : 0);
270764db 658 stack->SetMaximum(max);
1174780f 659 FixAxis(stack, 1/(1-yd)/1.5,
660 "#frac{1}{#it{N}} #frac{#it{dN}_{ch}}{#it{d#eta}}");
7e4038b5 661 p1->Clear();
662 stack->DrawClone("nostack e1");
9bff843b 663 if (dndetaCentral)
664 dndetaCentral->GetXaxis()->SetRangeUser(-1,1);
665
82fc512a 666 // Draw other data
667 if (other) {
668 TGraphAsymmErrors* o = 0;
669 TIter nextG(other->GetListOfGraphs());
270764db 670 while ((o = static_cast<TGraphAsymmErrors*>(nextG())))
82fc512a 671 o->Draw("same p");
fa4236ed 672 }
673
82fc512a 674 // Make a legend in the main result pad
7e4038b5 675 TString trigs(AliAODForwardMult::GetTriggerString(mask));
65a1e0cd 676 TLegend* l = p1->BuildLegend(.15,p1->GetBottomMargin()+.01,.90,.35);
677 l->SetNColumns(2);
7e4038b5 678 l->SetFillColor(0);
679 l->SetFillStyle(0);
680 l->SetBorderSize(0);
f4494b7a 681 l->SetTextFont(132);
7e4038b5 682 p1->cd();
65a1e0cd 683
82fc512a 684 // Put a title on top
685 TLatex* tit = new TLatex(0.10, 0.95, fTitle.Data());
686 tit->SetNDC();
f4494b7a 687 tit->SetTextFont(132);
82fc512a 688 tit->SetTextSize(0.05);
689 tit->Draw();
690
691 // Put a nice label in the plot
1174780f 692 TString eS;
693 if (energy > 1000) eS = Form("%4.2fTeV", float(energy)/1000);
694 else eS = Form("%3dGeV", energy);
f4494b7a 695 TLatex* tt = new TLatex(.93, .93,
1174780f 696 Form("#sqrt{s}=%s, %s", eS.Data(),
65a1e0cd 697 AliAODForwardMult::GetTriggerString(mask)));
698 tt->SetNDC();
f4494b7a 699 tt->SetTextFont(132);
700 tt->SetTextAlign(33);
65a1e0cd 701 tt->Draw();
702
1174780f 703 // Put number of accepted events on the plot
704 TLatex* et = new TLatex(.93, .83, Form("%d events", fNAccepted));
705 et->SetNDC();
706 et->SetTextFont(132);
707 et->SetTextAlign(33);
708 et->Draw();
709
710 // Put number of accepted events on the plot
711 TLatex* vt = new TLatex(.93, .88,
9bff843b 712 Form("v_{z}#in[%+5.1f,%+5.1f]cm",fVtxMin,fVtxMax));
1174780f 713 vt->SetNDC();
714 vt->SetTextFont(132);
715 vt->SetTextAlign(33);
716 vt->Draw();
717
718 // Mark the plot as preliminary
719 TLatex* pt = new TLatex(.12, .93, "Preliminary");
65a1e0cd 720 pt->SetNDC();
f4494b7a 721 pt->SetTextFont(22);
65a1e0cd 722 pt->SetTextSize(0.07);
723 pt->SetTextColor(kRed+1);
1174780f 724 pt->SetTextAlign(13);
65a1e0cd 725 pt->Draw();
7e4038b5 726 c->cd();
727
82fc512a 728 // If we do not have the ratios, fix up the display
729 // p1->SetPad(0, 0, 1, 1);
730 // p1->SetBottomMargin(0.1);
731 // l->SetY1(0.11);
732 // stack->SetMinimum(0);
733 // FixAxis(stack, (1-yd)/1, "#frac{1}{N} #frac{dN_{ch}}{#eta}",10,false);
734 if (ratios) {
735 // If we do have the ratios, then make a new pad and draw the
736 // ratios there
7e4038b5 737 c->cd();
7e4038b5 738 TPad* p2 = new TPad("p2", "p2", 0, 0.0, 1.0, yd, 0, 0);
739 p2->SetTopMargin(0.001);
740 p2->SetRightMargin(0.05);
741 p2->SetBottomMargin(1/yd * 0.07);
742 p2->SetGridx();
743 p2->SetTicks(1,1);
744 p2->Draw();
745 p2->cd();
82fc512a 746
747 // Fix up axis
65a1e0cd 748 FixAxis(ratios, 1/yd/1.5, "Ratios", 5);
82fc512a 749
750 // Fix up y range and redraw
65a1e0cd 751 ratios->SetMinimum(.58);
752 ratios->SetMaximum(1.22);
7e4038b5 753 p2->Clear();
754 ratios->DrawClone("nostack e1");
755
82fc512a 756 // Make a legend
65a1e0cd 757 TLegend* l2 = p2->BuildLegend(.15,p2->GetBottomMargin()+.01,.9,.6);
758 l2->SetNColumns(2);
7e4038b5 759 l2->SetFillColor(0);
760 l2->SetFillStyle(0);
761 l2->SetBorderSize(0);
f4494b7a 762 l2->SetTextFont(132);
763
82fc512a 764 // Make a nice band from 0.9 to 1.1
7e4038b5 765 TGraphErrors* band = new TGraphErrors(2);
e333578d 766 band->SetPoint(0, dndetaSym->GetXaxis()->GetXmin(), 1);
7e4038b5 767 band->SetPoint(1, dndeta->GetXaxis()->GetXmax(), 1);
768 band->SetPointError(0, 0, .1);
769 band->SetPointError(1, 0, .1);
770 band->SetFillColor(kYellow+2);
771 band->SetFillStyle(3002);
9bff843b 772 band->SetLineStyle(2);
773 band->SetLineWidth(1);
7e4038b5 774 band->Draw("3 same");
9bff843b 775 band->DrawClone("X L same");
82fc512a 776
777 // Replot the ratios on top
7e4038b5 778 ratios->DrawClone("nostack e1 same");
779
780 c->cd();
781 }
7e4038b5 782
82fc512a 783 // Plot to disk
7e4038b5 784 TString imgName(fOut->GetName());
785 imgName.ReplaceAll(".root", ".png");
786 c->SaveAs(imgName.Data());
f4494b7a 787 imgName.ReplaceAll(".png", ".C");
788 c->SaveAs(imgName.Data());
270764db 789
790 fOut->cd();
7e4038b5 791 stack->Write();
82fc512a 792 if (other) other->Write();
793 if (ratios) ratios->Write();
7e4038b5 794
82fc512a 795 // Close our file
7e4038b5 796 fOut->Close();
7e4038b5 797 }
798 //__________________________________________________________________
799 /**
800 * Get the result from previous analysis code
801 *
c389303e 802 * @param fn File to open
803 * @param nsd Whether this is NSD
7e4038b5 804 *
805 * @return null or result of previous analysis code
806 */
807 TH1* GetHHD(const char* fn="fmd_dNdeta_mult.root", bool nsd=false)
808 {
809 TDirectory* savdir = gDirectory;
65a1e0cd 810 if (gSystem->AccessPathName(fn)) {
811 Warning("GetHHD", "Output of HHD analysis (%s) not available", fn);
812 return 0;
813 }
7e4038b5 814 TFile* file = TFile::Open(fn, "READ");
815 if (!file) {
816 Warning("GetHHD", "couldn't open HHD file %s", fn);
817 savdir->cd();
818 return 0;
819 }
820 TString hist(Form("dNdeta_dNdeta%s", (nsd ? "NSD" : "")));
821 TH1* h = static_cast<TH1*>(file->Get(hist.Data()));
822 if (!h) {
823 Warning("GetHHD", "Couldn't find HHD histogram %s in %s",
824 hist.Data(), fn);
7e4038b5 825 file->Close();
826 savdir->cd();
827 return 0;
828 }
829 TH1* r = static_cast<TH1*>(h->Clone("dndeta_hhd"));
830 r->SetTitle("1/N dN_{ch}/d#eta (HHD)");
831 r->SetFillStyle(0);
832 r->SetFillColor(0);
833 r->SetMarkerStyle(21);
834 r->SetMarkerColor(kPink+1);
835 r->SetDirectory(savdir);
836
837 file->Close();
838 savdir->cd();
839 return r;
840 }
82fc512a 841 //__________________________________________________________________
842 /**
843 */
9bff843b 844 THStack* MakeRatios(const TH1* dndeta, const TH1* dndetaSym,
845 const TH1* hhd, const TH1* hhdSym,
846 const TH1* mc, const TH1* mcSym,
847 const TH1* central,
82fc512a 848 TMultiGraph* other) const
849 {
850 // If we have 'other' data, then do the ratio of the results to that
851 Bool_t hasOther = (other && other->GetListOfGraphs() &&
852 other->GetListOfGraphs()->GetEntries() > 0);
9bff843b 853 Bool_t hasHhd = (hhd && hhdSym);
854 if (!hasOther && !hasHhd && !mc && !mcSym) return 0;
82fc512a 855
856 THStack* ratios = new THStack("ratios", "Ratios");
857 if (hasOther) {
9bff843b 858 TGraphAsymmErrors* ua5 = 0;
859 TGraphAsymmErrors* alice = 0;
860 TGraphAsymmErrors* cms = 0;
82fc512a 861 TGraphAsymmErrors* o = 0;
862 TIter nextG(other->GetListOfGraphs());
863 while ((o = static_cast<TGraphAsymmErrors*>(nextG()))) {
9bff843b 864 ratios->Add(Ratio(dndeta, o));
865 ratios->Add(Ratio(dndetaSym, o));
866 ratios->Add(Ratio(hhd, o));
867 ratios->Add(Ratio(hhdSym, o));
868 ratios->Add(Ratio(central, o));
869 TString oName(o->GetName());
870 oName.ToLower();
871 if (oName.Contains("ua5")) ua5 = o;
872 if (oName.Contains("alice")) alice = o;
873 if (oName.Contains("cms")) cms = o;
82fc512a 874 }
9bff843b 875 if (ua5 && alice)
876 ratios->Add(Ratio(alice, ua5));
877 if (cms && alice)
878 ratios->Add(Ratio(alice, cms));
82fc512a 879 }
9bff843b 880
82fc512a 881
882 // If we have data from HHD's analysis, then do the ratio of
883 // our result to that data.
884 if (hasHhd) {
9bff843b 885 ratios->Add(Ratio(dndeta, hhd));
886 ratios->Add(Ratio(dndetaSym, hhdSym));
270764db 887 }
888
889 // Do comparison to MC
890 if (mc) {
9bff843b 891 ratios->Add(Ratio(dndeta, mc));
892 ratios->Add(Ratio(dndetaSym, mcSym));
82fc512a 893 }
894
895 // Check if we have ratios
896 Bool_t hasRatios = (ratios->GetHists() &&
897 (ratios->GetHists()->GetEntries() > 0));
8329a584 898#if 0
82fc512a 899 Info("MakeRatios", "Got a total of %d ratios", !hasRatios ? 0 :
900 ratios->GetHists()->GetEntries());
8329a584 901#endif
82fc512a 902
903 if (!hasRatios) { delete ratios; ratios = 0; }
904 return ratios;
905 }
906
7e4038b5 907 //__________________________________________________________________
908 /**
909 * Fix the apperance of the axis in a stack
910 *
911 * @param stack stack of histogram
912 * @param s Scaling factor
913 * @param ytitle Y axis title
914 * @param force Whether to draw the stack first or not
c389303e 915 * @param ynDiv Divisions on Y axis
7e4038b5 916 */
917 void FixAxis(THStack* stack, Double_t s, const char* ytitle,
9bff843b 918 Int_t ynDiv=210, Bool_t force=true)
7e4038b5 919 {
920 if (force) stack->Draw("nostack e1");
921
922 TH1* h = stack->GetHistogram();
923 if (!h) return;
924
925 h->SetXTitle("#eta");
926 h->SetYTitle(ytitle);
927 TAxis* xa = h->GetXaxis();
928 TAxis* ya = h->GetYaxis();
929 if (xa) {
930 xa->SetTitle("#eta");
931 // xa->SetTicks("+-");
932 xa->SetTitleSize(s*xa->GetTitleSize());
933 xa->SetLabelSize(s*xa->GetLabelSize());
934 xa->SetTickLength(s*xa->GetTickLength());
935 }
936 if (ya) {
937 ya->SetTitle(ytitle);
65a1e0cd 938 ya->SetDecimals();
7e4038b5 939 // ya->SetTicks("+-");
65a1e0cd 940 ya->SetNdivisions(ynDiv);
7e4038b5 941 ya->SetTitleSize(s*ya->GetTitleSize());
942 ya->SetLabelSize(s*ya->GetLabelSize());
943 }
944 }
945 //__________________________________________________________________
946 /**
947 * Compute the ratio of @a h to @a g. @a g is evaluated at the bin
948 * centers of @a h
949 *
950 * @param h Numerator
951 * @param g Divisor
952 *
953 * @return h/g
954 */
955 TH1* Ratio(const TH1* h, const TGraph* g) const
956 {
957 if (!h || !g) return 0;
958
959 TH1* ret = static_cast<TH1*>(h->Clone("tmp"));
960 ret->SetName(Form("%s_over_%s", h->GetName(), g->GetName()));
961 ret->SetTitle(Form("%s / %s", h->GetTitle(), g->GetTitle()));
962 ret->Reset();
9bff843b 963 ret->SetMarkerStyle(g->GetMarkerStyle());
964 ret->SetMarkerColor(h->GetMarkerColor());
65a1e0cd 965 ret->SetMarkerSize(0.9*g->GetMarkerSize());
7e4038b5 966 Double_t xlow = g->GetX()[0];
967 Double_t xhigh = g->GetX()[g->GetN()-1];
968 if (xlow > xhigh) { Double_t t = xhigh; xhigh = xlow; xlow = t; }
969
970 for (Int_t i = 1; i <= h->GetNbinsX(); i++) {
971 Double_t c = h->GetBinContent(i);
972 if (c <= 0) continue;
973
974 Double_t x = h->GetBinCenter(i);
975 if (x < xlow || x > xhigh) continue;
976
977 Double_t f = g->Eval(x);
978 if (f <= 0) continue;
979
980 ret->SetBinContent(i, c / f);
981 ret->SetBinError(i, h->GetBinError(i) / f);
982 }
983 if (ret->GetEntries() <= 0) { delete ret; ret = 0; }
984 return ret;
985 }
9bff843b 986 //__________________________________________________________________
987 /**
988 * Make the ratio of h1 to h2
989 *
990 * @param h1 First histogram (numerator)
991 * @param h2 Second histogram (denominator)
992 *
993 * @return h1 / h2
994 */
995 TH1* Ratio(const TH1* h1, const TH1* h2) const
996 {
997 TH1* t1 = static_cast<TH1*>(h1->Clone(Form("%s_%s",
998 h1->GetName(),
999 h2->GetName())));
1000 t1->SetTitle(Form("%s / %s", h1->GetTitle(), h2->GetTitle()));
1001 t1->Divide(h2);
1002 t1->SetMarkerColor(h1->GetMarkerColor());
1003 t1->SetMarkerStyle(h2->GetMarkerStyle());
1004 return t1;
1005 }
1006 //__________________________________________________________________
1007 /**
1008 * Calculate the ratio of two graphs - g1 / g2
1009 *
1010 * @param g1 Numerator
1011 * @param g2 Denominator
1012 *
1013 * @return g1 / g2 in a histogram
1014 */
1015 TH1* Ratio(const TGraphAsymmErrors* g1, const TGraphAsymmErrors* g2) const
1016 {
1017 Int_t nBins = g1->GetN();
1018 TArrayF bins(nBins+1);
1019 Double_t dx = 0;
1020 for (Int_t i = 0; i < nBins; i++) {
1021 Double_t x = g1->GetX()[i];
1022 Double_t exl = g1->GetEXlow()[i];
1023 Double_t exh = g1->GetEXhigh()[i];
1024 bins.fArray[i] = x-exl;
1025 bins.fArray[i+1] = x+exh;
1026 Double_t dxi = exh+exl;
1027 if (i == 0) dx = dxi;
1028 else if (dxi != dx) dx = 0;
1029 }
1030 TString name(Form("%s_%s", g1->GetName(), g2->GetName()));
1031 TString title(Form("%s / %s", g1->GetTitle(), g2->GetTitle()));
1032 TH1* h = 0;
1033 if (dx != 0) {
1034 h = new TH1F(name.Data(), title.Data(), nBins, bins[0], bins[nBins]);
1035 }
1036 else {
1037 h = new TH1F(name.Data(), title.Data(), nBins, bins.fArray);
1038 }
1039 h->SetMarkerStyle(g2->GetMarkerStyle());
1040 h->SetMarkerColor(g1->GetMarkerColor());
1041 h->SetMarkerSize(0.9*g2->GetMarkerSize());
1042
1043 for (Int_t i = 0; i < nBins; i++) {
1044 Double_t x = g1->GetX()[i];
1045 Double_t c1 = g1->GetY()[i];
1046 Double_t e1 = g1->GetErrorY(i);
1047 Double_t c2 = g2->Eval(x);
1048
1049 h->SetBinContent(i+1, c1 / c2);
1050 h->SetBinError(i+1, e1 / c2);
1051 }
1052 return h;
1053 }
7e4038b5 1054 //__________________________________________________________________
1055 /**
1056 * Make an extension of @a h to make it symmetric about 0
1057 *
1058 * @param h Histogram to symmertrice
1059 *
1060 * @return Symmetric extension of @a h
1061 */
1062 TH1* Symmetrice(const TH1* h) const
1063 {
270764db 1064 fOut->cd();
1065
7e4038b5 1066 Int_t nBins = h->GetNbinsX();
1067 TH1* s = new TH1D(Form("%s_mirror", h->GetName()),
1068 Form("%s (mirrored)", h->GetTitle()),
1069 nBins,
1070 -h->GetXaxis()->GetXmax(),
1071 -h->GetXaxis()->GetXmin());
1072 s->SetMarkerColor(h->GetMarkerColor());
1073 s->SetMarkerSize(h->GetMarkerSize());
1074 s->SetMarkerStyle(h->GetMarkerStyle()+4);
1075 s->SetFillColor(h->GetFillColor());
1076 s->SetFillStyle(h->GetFillStyle());
270764db 1077 // s->SetDirectory(0);
7e4038b5 1078
1079 // Find the first and last bin with data
1080 Int_t first = nBins+1;
1081 Int_t last = 0;
1082 for (Int_t i = 1; i <= nBins; i++) {
1083 if (h->GetBinContent(i) <= 0) continue;
1084 first = TMath::Min(first, i);
1085 last = TMath::Max(last, i);
1086 }
1087
1088 Double_t xfirst = h->GetBinCenter(first-1);
1089 Int_t f1 = h->GetXaxis()->FindBin(-xfirst);
1090 Int_t l2 = s->GetXaxis()->FindBin(xfirst);
1091 for (Int_t i = f1, j=l2; i <= last; i++,j--) {
1092 s->SetBinContent(j, h->GetBinContent(i));
1093 s->SetBinError(j, h->GetBinError(i));
1094 }
e333578d 1095 // Fill in overlap bin
1096 s->SetBinContent(l2+1, h->GetBinContent(first));
1097 s->SetBinError(l2+1, h->GetBinError(first));
7e4038b5 1098 return s;
1099 }
1100 //__________________________________________________________________
1101 /**
1102 * Rebin a histogram
1103 *
1104 * @param h Histogram to rebin
1105 * @param rebin Rebinning factor
1106 *
1107 * @return
1108 */
1109 virtual void Rebin(TH1* h, Int_t rebin) const
1110 {
1111 if (rebin <= 1) return;
1112
1113 Int_t nBins = h->GetNbinsX();
1114 if(nBins % rebin != 0) {
1115 Warning("Rebin", "Rebin factor %d is not a devisor of current number "
1116 "of bins %d in the histogram %s", rebin, nBins, h->GetName());
1117 return;
1118 }
1119
1120 // Make a copy
1121 TH1* tmp = static_cast<TH1*>(h->Clone("tmp"));
1122 tmp->Rebin(rebin);
1123 tmp->SetDirectory(0);
1124
1125 // The new number of bins
1126 Int_t nBinsNew = nBins / rebin;
1127 for(Int_t i = 1;i<= nBinsNew; i++) {
1128 Double_t content = 0;
1129 Double_t sumw = 0;
1130 Double_t wsum = 0;
1131 Int_t nbins = 0;
1132 for(Int_t j = 1; j<=rebin;j++) {
9bff843b 1133 Int_t bin = (i-1)*rebin + j;
1134 Double_t c = h->GetBinContent(bin);
1135
1136 if (c <= 0) continue;
1137
1138 if (fCutEdges) {
1139 if (h->GetBinContent(bin+1)<=0 ||
1140 h->GetBinContent(bin-1)) {
1141 Warning("Rebin", "removing bin %d=%f of %s (%d=%f,%d=%f)",
1142 bin, c, h->GetName(),
1143 bin+1, h->GetBinContent(bin+1),
1144 bin-1, h->GetBinContent(bin-1));
1145 continue;
1146 }
1147 }
cc83fca2 1148 Double_t e = h->GetBinError(bin);
1149 Double_t w = 1 / (e*e); // 1/c/c
7e4038b5 1150 content += c;
1151 sumw += w;
1152 wsum += w * c;
1153 nbins++;
1154 }
1155
cc83fca2 1156 if(content > 0 && nbins > 0) {
7e4038b5 1157 tmp->SetBinContent(i, wsum / sumw);
cc83fca2 1158 tmp->SetBinError(i,1./TMath::Sqrt(sumw));
7e4038b5 1159 }
1160 }
1161
1162 // Finally, rebin the histogram, and set new content
1163 h->Rebin(rebin);
1c762251 1164 h->Reset();
cc83fca2 1165 for(Int_t i = 1; i<= nBinsNew; i++) {
7e4038b5 1166 h->SetBinContent(i,tmp->GetBinContent(i));
cc83fca2 1167 h->SetBinError(i, tmp->GetBinError(i));
7e4038b5 1168 }
1169
1170 delete tmp;
1171 }
1172};
1173
1174//____________________________________________________________________
1175//
1176// EOF
1177//
1178