]>
Commit | Line | Data |
---|---|---|
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 | 48 | struct AnalyseAOD |
7e4038b5 | 49 | { |
50 | public: | |
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 |