]>
Commit | Line | Data |
---|---|---|
be6e4497 | 1 | #ifndef __TREND_C_ |
2 | #define __TREND_C_ | |
3 | #include "SummaryDrawer.C" | |
4 | #include <TH1.h> | |
5 | #include <THStack.h> | |
6 | #include <TMultiGraph.h> | |
7 | #include <TGraphAsymmErrors.h> | |
8 | #include <TTree.h> | |
9 | #include <TList.h> | |
10 | #include <TLegend.h> | |
11 | ||
12 | /** | |
13 | * Structure to make trendind plots from cut scans | |
14 | * | |
15 | */ | |
16 | struct Trend : public SummaryDrawer | |
17 | { | |
18 | //__________________________________________________________________ | |
19 | /** | |
20 | * Constructor | |
21 | */ | |
22 | Trend() | |
23 | { | |
24 | fSLCuts.SetName("sl"); | |
25 | fSHCuts.SetName("sh"); | |
26 | fDCCuts.SetName("dc"); | |
27 | fOrder[0] = &fSLCuts; | |
28 | fOrder[1] = &fSHCuts; | |
29 | fOrder[2] = &fDCCuts; | |
30 | } | |
31 | //=== Customization member function ================================ | |
32 | /** | |
33 | * Add a sharing filter low cut | |
34 | * | |
35 | * @param name Name of the cut type (fix,mpv,sig,xi,prob) | |
36 | * @param values Space-separated cut parameters | |
37 | */ | |
38 | void AddSLCut(const TString& name, const TString& values) | |
39 | { | |
40 | fSLCuts.Add(new TNamed(name, values)); | |
41 | } | |
42 | //__________________________________________________________________ | |
43 | /** | |
44 | * Add a sharing filter high cut | |
45 | * | |
46 | * @param name Name of the cut type (fix,mpv,sig,xi,prob) | |
47 | * @param values Space-separated cut parameters | |
48 | */ | |
49 | void AddSHCut(const TString& name, const TString& values) | |
50 | { | |
51 | fSHCuts.Add(new TNamed(name, values)); | |
52 | } | |
53 | //__________________________________________________________________ | |
54 | /** | |
55 | * Add a density calculator threshold | |
56 | * | |
57 | * @param name Name of the cut type (fix,mpv,sig,xi,prob) | |
58 | * @param values Space-separated cut parameters | |
59 | */ | |
60 | void AddDCCut(const TString& name, const TString& values) | |
61 | { | |
62 | fDCCuts.Add(new TNamed(name, values)); | |
63 | } | |
64 | //__________________________________________________________________ | |
65 | /** | |
66 | * Add a run to analyse | |
67 | * | |
68 | * @param name Run number | |
69 | */ | |
70 | void AddRun(const TString& name) | |
71 | { | |
72 | fRuns.Add(new TNamed(name, name)); | |
73 | } | |
74 | //__________________________________________________________________ | |
75 | /** | |
76 | * Add a centrality bin to analyse | |
77 | * | |
78 | * @param l Lower bound | |
79 | * @param h Upper bound | |
80 | */ | |
81 | void AddCentrality(UShort_t l, UShort_t h) | |
82 | { | |
83 | TObjString* n = 0; | |
84 | if (l <= 0 && h >= 100) n = new TObjString("all"); | |
85 | else n = new TObjString(Form("cent%03d_%03d", l, h)); | |
86 | n->SetUniqueID((h & 0xFFFF) << 16 | (l & 0xFFFF)); | |
87 | fCents.Add(n); | |
88 | } | |
89 | //__________________________________________________________________ | |
90 | /** | |
91 | * Set the order in which to do the comparison. Most important | |
92 | * should be last. | |
93 | * | |
94 | * @param order Permutation of sl, sh, and dc, space separated | |
95 | */ | |
96 | void SetOrder(const TString& order) | |
97 | { | |
98 | TObjArray* a = order.Tokenize(" "); | |
99 | if (a->GetEntries() < 3) { | |
100 | Error("SetOrder", "Order must contain a pertubation of " | |
101 | "\"sl\", \"sh\", and \"dc\", separated by spaces"); | |
102 | fOrder[0] = fOrder[1] = fOrder[2] = 0; | |
103 | return; | |
104 | } | |
105 | for (Int_t i = 0; i < 3; i++) { | |
106 | const TString& n = static_cast<TObjString*>(a->At(i))->String(); | |
107 | TList* l = 0; | |
108 | if (n.EqualTo("sl", TString::kIgnoreCase)) l = &fSLCuts; | |
109 | else if (n.EqualTo("sh", TString::kIgnoreCase)) l = &fSHCuts; | |
110 | else if (n.EqualTo("dc", TString::kIgnoreCase)) l = &fDCCuts; | |
111 | if (!l) { | |
112 | Error("SetOrder", "Unknown cut \"%s\"", n.Data()); | |
113 | fOrder[0] = fOrder[1] = fOrder[2] = 0; | |
114 | return; | |
115 | } | |
116 | fOrder[i] = l; | |
117 | } | |
118 | a->Delete(); | |
119 | } | |
120 | //=== Processing member functions ================================== | |
121 | /** | |
122 | * Run it | |
123 | * | |
124 | * @param sys | |
125 | * @param sNN | |
126 | * @param trg | |
127 | */ | |
128 | void Run(const char* output="trending.root", | |
129 | UShort_t sys=2, | |
130 | UShort_t sNN=2760, | |
131 | UShort_t trg=1) | |
132 | { | |
133 | TString outName(output); | |
134 | outName.ReplaceAll(".pdf", ".root"); | |
135 | if (!outName.EndsWith(".root")) outName.Append(".root"); | |
136 | TString pdfName(outName); | |
137 | pdfName.ReplaceAll(".root", ".pdf"); | |
138 | ||
139 | CreateCanvas(pdfName, true); | |
140 | ||
141 | TFile* out = TFile::Open(outName, "RECREATE"); | |
142 | TDirectory* refDir = out->mkdir("reference"); | |
143 | ||
144 | TIter iCent(&fCents); | |
145 | TObject* pCent = 0; | |
146 | while ((pCent = iCent())) { | |
147 | UShort_t low = (pCent->GetUniqueID() & 0xFFFF); | |
148 | UShort_t high = (pCent->GetUniqueID() >> 16) & 0xFFFF; | |
149 | TGraph* graph = GetOther(sys, sNN, trg, low, high); | |
150 | if (!graph) break; | |
151 | ||
152 | TString name(graph->GetName()); | |
153 | name.Append(Form("_%s", pCent->GetName())); | |
154 | graph->SetName(name); | |
155 | ||
156 | fOthers.Add(graph); | |
157 | refDir->Add(graph); | |
158 | } | |
159 | ||
160 | TIter iRun(&fRuns); | |
161 | TObject* pRun = 0; | |
162 | while ((pRun = iRun())) { | |
163 | TString sRun = pRun->GetName(); | |
164 | TDirectory* dRun = out->mkdir(sRun); | |
165 | ||
166 | MakeChapter(sRun); | |
167 | ||
168 | for (Int_t i = 0; i < 1/*2*/; i++) { | |
169 | TString three(Form("%dstrip", i+2)); | |
170 | TDirectory* dStrip = dRun->mkdir(three); | |
171 | ||
172 | MakeChapter(Form("_%s", three.Data())); | |
173 | ||
174 | three.Append("_slX_shX_dcX"); | |
175 | ||
176 | LoopCuts(sRun, three, fOrder[0], fOrder[1], fOrder[2], dStrip); | |
177 | } | |
178 | } | |
179 | out->Write(); | |
180 | out->Close(); | |
181 | CloseCanvas(); | |
182 | } | |
183 | //__________________________________________________________________ | |
184 | /** | |
185 | * Loop over cuts. Recursively calls self. | |
186 | * | |
187 | * @param run Run number | |
188 | * @param cur Current path | |
189 | * @param cuts1 Cuts | |
190 | * @param cuts2 Cuts (or null) | |
191 | * @param cuts3 Cuts (or null) | |
192 | * @param out Output diretory | |
193 | * @param upBin Parents bin number | |
194 | * @param upMean Parents mean | |
195 | * @param upRatios Parents ratios | |
196 | */ | |
197 | void LoopCuts(const TString& run, | |
198 | const TString& cur, | |
199 | const TList* cuts1, | |
200 | const TList* cuts2, | |
201 | const TList* cuts3, | |
202 | TDirectory* out, | |
203 | Int_t upBin=0, | |
204 | THStack* upMean=0, | |
205 | THStack* upRatios=0) | |
206 | { | |
207 | TString pre(Form("%s%s",(cuts3 ? "" : "_"), (cuts2 ? "" : "_"))); | |
208 | Printf("%s%s", pre.Data(), cur.Data()); | |
209 | ||
210 | TDirectory* dCut = out->mkdir(cuts1->GetName()); | |
211 | TIter iCut(cuts1); | |
212 | TObject* pCut = 0; | |
213 | dCut->cd(); | |
214 | while ((pCut = iCut())) { | |
215 | TString sMethod = pCut->GetName(); | |
216 | TDirectory* dMethod = dCut->mkdir(sMethod); | |
217 | TString sValues = pCut->GetTitle(); | |
218 | TObjArray* aValues = sValues.Tokenize(" "); | |
219 | TIter iValue(aValues); | |
220 | TObjString* pValue = 0; | |
221 | TString templ(Form("%s%s", cuts1->GetName(), sMethod.Data())); | |
222 | TString base(cur); | |
223 | base.ReplaceAll(Form("%sX", cuts1->GetName()), templ); | |
224 | aValues->SetName(cuts1->GetName()); | |
225 | ||
226 | THStack* mean = 0; | |
227 | THStack* ratios = 0; | |
228 | dMethod->cd(); | |
229 | MakeStacks(base, aValues, mean, ratios); | |
230 | dMethod->Add(mean); | |
231 | dMethod->Add(ratios); | |
232 | ||
233 | Int_t xbin = 1; | |
234 | while ((pValue = static_cast<TObjString*>(iValue()))) { | |
235 | TString sValue(Form("%05.2f", pValue->String().Atof())); | |
236 | sValue.ReplaceAll(".", "d"); | |
237 | TDirectory* dValue = dMethod->mkdir(sValue); | |
238 | TString now(base); | |
239 | TString sub(Form("%s%s", templ.Data(), sValue.Data())); | |
240 | now.ReplaceAll(templ.Data(), sub.Data()); | |
241 | // now.Append(sValue); | |
242 | dValue->cd(); | |
243 | ||
244 | if (cuts2) { | |
245 | // Loop over sub-cut. | |
246 | LoopCuts(run, now, cuts2, cuts3, 0, | |
247 | dValue, xbin, mean, ratios); | |
248 | } | |
249 | else { | |
250 | // Process for a given cut with the current value of that cut. | |
251 | if (!NextFile(run, now, dValue, xbin, | |
252 | mean, ratios)) { | |
253 | // xbin++; | |
254 | dMethod->cd(); | |
255 | continue; | |
256 | } | |
257 | // After this, we have points for the current cut value | |
258 | // stored in the stacks mean and wSpread, and added ratios | |
259 | // for the current cut to the stack ratios. Since we're not | |
260 | // done with the cut values just yet, we should wait to | |
261 | // update the parent stacks. | |
262 | } | |
263 | ||
264 | if (upMean /*&& upWSpread*/) { | |
265 | // For each centrality extract | |
266 | // - mean of mean of ... | |
267 | // - var of var of ... | |
268 | // - spread of spread of ... | |
269 | TIter iCent(&fCents); | |
270 | TObject* pCent = 0; | |
271 | Int_t jCent = 0; | |
272 | while ((pCent = iCent())) { | |
273 | TH1* h = static_cast<TH1*>(mean->GetHists()->At(jCent)); | |
274 | // Info("", "Updating parent %s with %s @ %d", | |
275 | // upMean->GetTitle(), h->GetTitle(),upBin); | |
276 | UpdateStacks(h, jCent, upBin, upMean); | |
277 | jCent++; | |
278 | } | |
279 | } // if ups | |
280 | ||
281 | xbin++; | |
282 | dMethod->cd(); | |
283 | } // for values | |
284 | ||
285 | if (upRatios) { | |
286 | TIter nextHist(ratios->GetHists()); | |
287 | TH1* hist = 0; | |
288 | while ((hist = static_cast<TH1*>(nextHist()))) | |
289 | upRatios->Add(hist); | |
290 | } | |
291 | dCut->cd(); | |
292 | ||
293 | FixMinMax(ratios); | |
294 | FixMinMax(mean); | |
295 | ||
296 | if (mean && mean->GetHists()->GetEntries() > 0 && | |
297 | ratios && ratios->GetHists() && | |
298 | ratios->GetHists()->GetEntries() > 0) { | |
299 | fBody->Divide(2,1); | |
300 | DrawStacks(fBody->GetPad(1), mean, kNorth|kWest); | |
301 | DrawStacks(fBody->GetPad(2), ratios, kNorth|kCenter, kSouth|kCenter); | |
302 | PrintCanvas(Form("%s_%s", pre.Data(), base.Data()), 0.5); | |
303 | } | |
304 | } // for methods | |
305 | out->cd(); | |
306 | } | |
307 | //__________________________________________________________________ | |
308 | /** | |
309 | * Process the next file | |
310 | * | |
311 | * @param dir Directory | |
312 | * @param filename File name | |
313 | * @param out Output directory | |
314 | * @param binx Bin number | |
315 | * @param mean Graphs of mean +/- variance | |
316 | * @param wspread Graphs of mean +/- max/min | |
317 | * @param ratios Ratios stack | |
318 | * | |
319 | * @return true on success | |
320 | */ | |
321 | Bool_t NextFile(const TString& run, const TString& now, | |
322 | TDirectory* out, Int_t binx, | |
323 | THStack* mean, THStack* ratios) | |
324 | { | |
325 | TString dir(Form("%s_dndeta_%s", run.Data(), now.Data())); | |
326 | TString path(Form("%s/forward_dndeta.root", dir.Data())); | |
327 | if (gSystem->AccessPathName(path.Data())) { | |
328 | Warning("NextFile", "%s not found", path.Data()); | |
329 | return false; | |
330 | } | |
331 | TFile* file = TFile::Open(path, "READ"); | |
332 | if (!file) { | |
333 | Warning("NextFile", "Failed to open %s", path.Data()); | |
334 | return false; | |
335 | } | |
336 | // Info("NextFile", "Opened %s", path.Data()); | |
337 | ||
338 | TCollection* results = GetCollection(file, "ForwarddNdetaResults"); | |
339 | if (!results) return false; | |
340 | ||
0ccdab7b | 341 | TCollection* mcResults = GetCollection(file, "MCTruthdNdetaResults"); |
342 | ||
be6e4497 | 343 | THStack* all = new THStack("all", "All"); |
344 | THStack* rat = new THStack("ratios", "Ratios"); | |
345 | ||
346 | TIter iCent(&fCents); | |
347 | TObject* pCent = 0; | |
348 | Int_t jCent = 0; | |
349 | while ((pCent = iCent())) { | |
be6e4497 | 350 | TString folderName(pCent->GetName()); |
351 | TCollection* centFolder = GetCollection(results, folderName); | |
0ccdab7b | 352 | if (!centFolder) { |
353 | Warning("", "Didn't get the centrality %s folder from %s", | |
354 | folderName.Data(), results->GetName()); | |
355 | // results->ls(); | |
356 | break; | |
357 | } | |
be6e4497 | 358 | |
0ccdab7b | 359 | TCollection* mcCentFolder = 0; |
360 | if (mcResults) mcCentFolder = GetCollection(mcResults, folderName); | |
361 | ||
be6e4497 | 362 | TH1* dNdeta = GetH1(centFolder, Form("dndetaForward%s", |
363 | fRebinned ? "_rebin05" : "")); | |
364 | if (!dNdeta) { | |
365 | Warning("", "Didn't get histogram for jCent=%d in %s", | |
366 | jCent, path.Data()); | |
0ccdab7b | 367 | // results->ls(); |
be6e4497 | 368 | break; |
369 | } | |
370 | dNdeta->SetDirectory(out); | |
371 | dNdeta->SetName(folderName); | |
372 | dNdeta->SetMarkerColor(jCent+1); | |
373 | dNdeta->SetLineColor(jCent+1); | |
374 | ||
0ccdab7b | 375 | TH1* other = 0; |
376 | if (mcCentFolder) | |
377 | other = GetH1(mcCentFolder, Form("dndetaMCTruth%s", | |
378 | fRebinned ? "_rebin05" : "")); | |
379 | if (!other) { | |
380 | TGraph* graph = static_cast<TGraph*>(fOthers.At(jCent)); | |
381 | if (!graph) break; | |
382 | ||
383 | other = G2H(graph, *(dNdeta->GetXaxis())); | |
384 | } | |
385 | ||
386 | if (!other) { | |
387 | Warning("", "No other data found for %s", path.Data()); | |
388 | break; | |
389 | } | |
390 | ||
be6e4497 | 391 | other->SetMarkerColor(dNdeta->GetMarkerColor()); |
392 | other->SetMarkerSize(dNdeta->GetMarkerSize()); | |
393 | other->SetLineColor(dNdeta->GetLineColor()); | |
394 | other->SetDirectory(out); | |
395 | folderName.ReplaceAll("cent", "other"); | |
396 | folderName.ReplaceAll("all", "other"); | |
397 | other->SetName(folderName); | |
398 | ||
399 | all->Add(other); | |
400 | all->Add(dNdeta); | |
401 | ||
402 | folderName.ReplaceAll("other", "ratio"); | |
403 | TH1* ratio = static_cast<TH1*>(dNdeta->Clone(folderName)); | |
404 | ratio->SetTitle(Form("%s %s", dir.Data(), pCent->GetName())); | |
405 | ratio->SetDirectory(out); | |
406 | ratio->Divide(other); | |
407 | ratio->SetMarkerStyle(20+binx-1); | |
408 | ratio->SetMarkerColor(jCent+1); | |
409 | ratio->SetLineColor(kGray); | |
410 | ratio->SetLineWidth(0); | |
411 | ratios->Add(ratio); | |
412 | ||
413 | rat->Add(ratio); | |
414 | ||
415 | UpdateStacks(ratio, jCent, binx, mean); | |
416 | jCent++; | |
417 | } | |
418 | out->Add(all); | |
419 | out->Add(rat); | |
420 | ||
421 | FixMinMax(all); | |
422 | FixMinMax(rat); | |
423 | ||
424 | fBody->Divide(1,2,0,0); | |
425 | DrawStacks(fBody->GetPad(1), all/*, 21*/); | |
426 | DrawStacks(fBody->GetPad(2), rat, kNorth|kCenter); | |
427 | PrintCanvas(Form("____%s", now.Data()), .4); | |
428 | ||
429 | file->Close(); | |
430 | if (jCent <= 0) return false; | |
431 | ||
432 | return true; | |
433 | } | |
434 | //=== Stack functions ============================================== | |
435 | /** | |
436 | * Make stacks | |
437 | * | |
438 | * @param run Run number | |
439 | * @param values Cut parameters | |
440 | * @param mean Stack of means | |
441 | * @param ratios Stack of ratios | |
442 | */ | |
443 | void MakeStacks(const TString& run, | |
444 | const TObjArray* values, | |
445 | THStack*& mean, | |
446 | THStack*& ratios) | |
447 | { | |
448 | mean = new THStack("mean", run); | |
449 | ratios = new THStack("ratios", run); | |
450 | ||
451 | // --- Create histograms and graphs ------------------------ | |
452 | Int_t nValues = values->GetEntriesFast(); | |
453 | TIter nextCent(&fCents); | |
454 | TObject* pcent = 0; | |
455 | Int_t col = 1; | |
456 | while ((pcent = nextCent())) { | |
457 | UShort_t low = (pcent->GetUniqueID() & 0xFFFF); | |
458 | UShort_t high = (pcent->GetUniqueID() >> 16) & 0xFFFF; | |
459 | ||
460 | TH1* hMean = new TH1D(pcent->GetName(), | |
461 | Form("%s %d%%-%d%% central", run.Data(), | |
462 | low, high), | |
463 | nValues, .5, nValues+.5); | |
464 | hMean->SetMarkerColor(col); | |
465 | hMean->SetMarkerStyle(20); | |
466 | hMean->SetLineColor(col); | |
467 | hMean->SetXTitle(Form("Cut parameter X_{%s}", values->GetName())); | |
468 | hMean->SetYTitle("Average, spread, and min/max of ratio"); | |
469 | hMean->SetDirectory(0); | |
470 | TIter nextV(values); | |
471 | TObjString* pvalue = 0; | |
472 | Int_t xbin = 1; | |
473 | while ((pvalue = static_cast<TObjString*>(nextV()))) { | |
474 | TString& value = pvalue->String(); | |
475 | hMean->GetXaxis()->SetBinLabel(xbin, value); | |
476 | xbin++; | |
477 | } | |
478 | ||
479 | TGraphAsymmErrors* gWSpread = new TGraphAsymmErrors(nValues); | |
480 | gWSpread->SetName("minmax"); | |
481 | gWSpread->SetTitle(hMean->GetTitle()); | |
482 | gWSpread->SetMarkerColor(col); | |
483 | gWSpread->SetLineColor(col); | |
484 | gWSpread->SetFillColor(0); | |
485 | gWSpread->SetFillStyle(0); | |
486 | ||
487 | hMean->GetListOfFunctions()->Add(gWSpread, "[]pl same"); | |
488 | mean->Add(hMean, "x0 e1"); | |
489 | col++; | |
490 | } | |
491 | } | |
492 | //__________________________________________________________________ | |
493 | /** | |
494 | * Update stacks | |
495 | * | |
496 | * @param h Histogram | |
497 | * @param i Index | |
498 | * @param binx Bin number | |
499 | * @param stack Stack to update | |
500 | */ | |
501 | void UpdateStacks(TH1* h, | |
502 | Int_t i, | |
503 | Int_t binx, | |
504 | THStack* stack) | |
505 | { | |
506 | Double_t avg = 0; | |
507 | Double_t var = 0; | |
508 | Double_t min = +100000; | |
509 | Double_t max = -100000; | |
510 | HistStatistics(h, avg, var, min, max); | |
511 | h->SetMinimum(0.95*min); | |
512 | h->SetMaximum(1.1*max); | |
513 | ||
514 | TH1* hMean = static_cast<TH1*>(stack->GetHists()->At(i)); | |
515 | hMean->SetBinContent(binx, avg); | |
516 | hMean->SetBinError(binx,var); | |
517 | ||
518 | TObject* pG = hMean->GetListOfFunctions()->FindObject("minmax"); | |
519 | if (!pG) { | |
520 | hMean->GetListOfFunctions()->ls(); | |
521 | return; | |
522 | } | |
523 | TGraphAsymmErrors* gWSpread = static_cast<TGraphAsymmErrors*>(pG); | |
524 | gWSpread->SetPoint(binx-1, binx, avg); | |
525 | gWSpread->SetPointError(binx-1,0, 0, /*0.5,0.5,*/ | |
526 | TMath::Abs(avg-min), TMath::Abs(max-avg)); | |
527 | } | |
528 | //=== Graphics member functions ==================================== | |
529 | //__________________________________________________________________ | |
530 | /** | |
531 | * Build a centrality legend | |
532 | * | |
533 | * @param p Pad | |
534 | * @param where See above | |
535 | * @param stack Stack to make legend for | |
536 | */ | |
537 | void BuildCentLegend(TVirtualPad* p, UInt_t where, THStack* stack=0) | |
538 | { | |
539 | TLegend* l = MakeLegend(p, where, false); | |
540 | TIter iCent(&fCents); | |
541 | TObject* pCent = 0; | |
542 | Int_t col = 1; | |
543 | while ((pCent = iCent())) { | |
544 | UShort_t low = (pCent->GetUniqueID() & 0xFFFF); | |
545 | UShort_t high = (pCent->GetUniqueID() >> 16) & 0xFFFF; | |
546 | ||
547 | TLegendEntry* e = l->AddEntry("dummy", | |
548 | Form("%2d%% - %2d%% central", low, high), | |
549 | "pl"); | |
550 | e->SetFillColor(col); | |
551 | e->SetMarkerColor(col); | |
552 | e->SetLineColor(col); | |
553 | e->SetMarkerStyle(20); | |
554 | col++; | |
555 | } | |
556 | if (stack && stack->GetHistogram()) { | |
557 | stack->GetHistogram()->GetListOfFunctions()->Add(l); | |
558 | } | |
559 | else | |
560 | l->Draw(); | |
561 | ||
562 | } | |
563 | //__________________________________________________________________ | |
564 | /** | |
565 | * Make a cut legend. | |
566 | * | |
567 | * @param p Pad | |
568 | * @param where See above | |
569 | * @param stack Stack to make legend for | |
570 | */ | |
571 | void BuildCutLegend(TVirtualPad* p, UInt_t where, THStack* stack) | |
572 | { | |
573 | TLegend* l = MakeLegend(p, where, false); | |
574 | l->SetX1(p->GetLeftMargin()); | |
575 | l->SetX2(1-p->GetRightMargin()); | |
576 | // l->SetBorderSize(1); | |
577 | l->SetNColumns(1); | |
578 | ||
579 | TList seen; | |
580 | TIter iHist(stack->GetHists()); | |
581 | TH1* pHist = 0; | |
582 | while ((pHist = static_cast<TH1*>(iHist()))) { | |
583 | TString title(pHist->GetTitle()); | |
584 | ||
585 | Int_t idx = title.Index(" cent"); | |
586 | if (idx != kNPOS) title.Remove(idx, 5+3+3+1); | |
587 | ||
588 | idx = title.Index("_dndeta"); | |
589 | if (idx != kNPOS) title.Remove(0, idx+6+1+1); | |
590 | ||
591 | TObject* before = seen.FindObject(title); | |
592 | if (before) continue; | |
593 | ||
594 | seen.Add(new TObjString(title)); | |
595 | ||
596 | TLegendEntry* e = l->AddEntry("dummy", title, "p"); | |
597 | e->SetMarkerColor(kBlack); | |
598 | e->SetMarkerStyle(pHist->GetMarkerStyle()); | |
599 | } | |
600 | seen.IsOwner(); | |
601 | if (stack->GetHistogram()) { | |
602 | stack->GetHistogram()->GetListOfFunctions()->Add(l); | |
603 | } | |
604 | else | |
605 | l->Draw(); | |
606 | ||
607 | } | |
608 | //__________________________________________________________________ | |
609 | /** | |
610 | * Draw stacks | |
611 | * | |
612 | * @param p Pad | |
613 | * @param stack Stacks | |
614 | * @param cent Centrality legend location | |
615 | * @param cuts Cut legend location | |
616 | */ | |
617 | void DrawStacks(TVirtualPad* p, | |
618 | THStack* stack, | |
619 | UInt_t cent=0, | |
620 | UInt_t cuts=0) | |
621 | { | |
622 | if (!stack) { | |
623 | Warning("DrawStacks", "Stack is missing!"); | |
624 | return; | |
625 | } | |
0ccdab7b | 626 | if (!stack->GetHists() || stack->GetHists()->GetEntries() <= 0) { |
627 | Warning("DrawStacks", "Stack is empty"); | |
628 | return; | |
629 | } | |
be6e4497 | 630 | TH1* first = static_cast<TH1*>(stack->GetHists()->At(0)); |
631 | TString xT = first->GetXaxis()->GetTitle(); | |
632 | ||
633 | p->cd(); | |
634 | stack->Draw("nostack"); | |
635 | // DrawInPad(p, 0, stack, "nostack", flags); | |
636 | stack->GetXaxis()->SetTitle(xT); | |
637 | FixMinMax(stack); | |
638 | ||
639 | if (cent > 0) BuildCentLegend(p, cent, stack); | |
640 | if (cuts > 0) BuildCutLegend(p, cuts, stack); | |
641 | ||
642 | p->Modified(); | |
643 | p->Update(); | |
644 | p->cd(); | |
645 | } | |
646 | //=== Utility static member functions ============================== | |
647 | /** | |
648 | * Update statistics | |
649 | * | |
650 | * @param y Current observation | |
651 | * @param cnt On entry, last count, on return current count | |
652 | * @param mean On entry, last mean, on return current mean | |
653 | * @param var On entry, last variance, on return current variance | |
654 | */ | |
655 | static void Statistics(Double_t y, | |
656 | Int_t& cnt, | |
657 | Double_t& mean, | |
658 | Double_t& var) | |
659 | { | |
660 | cnt += 1; | |
661 | mean += (y - mean) / cnt; | |
662 | var += (cnt > 1 ? (TMath::Power(y-mean,2)/(cnt-1)-var/cnt) : 0); | |
663 | } | |
664 | //__________________________________________________________________ | |
665 | /** | |
666 | * Calculate histogram statistics | |
667 | * | |
668 | * @param h Histogram | |
669 | * @param mean On return, the Y-mean | |
670 | * @param var On return, the Y variance | |
671 | * @param min On return, the least Y | |
672 | * @param max On return, the largest Y | |
673 | */ | |
674 | static void HistStatistics(const TH1* h, | |
675 | Double_t& mean, | |
676 | Double_t& var, | |
677 | Double_t& min, | |
678 | Double_t& max) | |
679 | { | |
680 | mean = 0; | |
681 | var = 0; | |
682 | min = +100000; | |
683 | max = -100000; | |
684 | Int_t cnt = 0; | |
685 | for (Int_t i = 1; i <= h->GetNbinsX(); i++) { | |
686 | Double_t y = h->GetBinContent(i); | |
687 | if (TMath::Abs(y) <= 1e-9) continue; | |
688 | min = TMath::Min(min, y); | |
689 | max = TMath::Max(max, y); | |
690 | Statistics(y, cnt, mean, var); | |
691 | } | |
692 | // Info("", "Stats for %s: mean=%f +/- %f [%f,%f]", | |
693 | // h->GetTitle(), mean, var, min, max); | |
694 | } | |
695 | //__________________________________________________________________ | |
696 | /** | |
697 | * Fix the min/max of a stack | |
698 | * | |
699 | * @param stack | |
700 | */ | |
701 | static void FixMinMax(THStack* stack) | |
702 | { | |
703 | TIter iHist(stack->GetHists()); | |
704 | TH1* pHist = 0; | |
705 | Double_t m1 = 10000000; | |
706 | Double_t m2 = -10000000; | |
707 | while((pHist = static_cast<TH1*>(iHist()))) { | |
708 | m1 = TMath::Min(m1, pHist->GetMinimum(1e-6)); | |
709 | m2 = TMath::Max(m2, pHist->GetMaximum()); | |
710 | } | |
711 | // Double_t m1 = stack->GetMinimum("nostack e"); | |
712 | // Double_t m2 = stack->GetMaximum("nostack e"); | |
713 | // Printf("Stack %s minimum: %f", stack->GetTitle(), m1); | |
714 | stack->SetMinimum((m1 < 0 ? 1.05 : 0.95) * m1); | |
715 | stack->SetMaximum((m2 > 0 ? 1.05 : 0.95) * m2); | |
716 | } | |
717 | //__________________________________________________________________ | |
718 | /** | |
719 | * Turn a graph into a histogram | |
720 | * | |
721 | * @param g Graph | |
722 | * @param axis Axis to use | |
723 | * | |
724 | * @return Newly allocated histogram | |
725 | */ | |
726 | static TH1* G2H(const TGraph* g, const TAxis& axis) | |
727 | { | |
728 | TH1* h = 0; | |
729 | if (axis.GetXbins()->GetArray()) | |
730 | h = new TH1D(g->GetName(), g->GetTitle(), | |
731 | axis.GetNbins(), axis.GetXbins()->GetArray()); | |
732 | else | |
733 | h = new TH1D(g->GetName(), g->GetTitle(), | |
734 | axis.GetNbins(), axis.GetXmin(), axis.GetXmax()); | |
735 | h->SetMarkerColor(g->GetMarkerColor()); | |
736 | h->SetMarkerStyle(g->GetMarkerStyle()); | |
737 | h->SetMarkerSize(g->GetMarkerSize()); | |
738 | h->SetLineColor(g->GetLineColor()); | |
739 | h->SetLineStyle(g->GetLineStyle()); | |
740 | h->SetLineWidth(g->GetLineWidth()); | |
741 | h->SetFillColor(g->GetFillColor()); | |
742 | h->SetFillStyle(g->GetFillStyle()); | |
743 | h->SetDirectory(0); | |
744 | ||
745 | for (Int_t i = 1; i <= h->GetNbinsX(); i++) { | |
746 | Double_t x = h->GetXaxis()->GetBinCenter(i); | |
747 | Double_t y = g->Eval(x); // , 0, "S"); | |
748 | h->SetBinContent(i, y); | |
749 | } | |
750 | return h; | |
751 | } | |
752 | //__________________________________________________________________ | |
753 | /** | |
754 | * Get other data | |
755 | * | |
756 | * @param sys Collision system | |
757 | * @param sNN Collision energy | |
758 | * @param trg Trigger | |
759 | * @param lowC Low centrality | |
760 | * @param highC High centrality | |
761 | * | |
762 | * @return Newly allocated histogram | |
763 | */ | |
764 | static TGraph* GetOther(UShort_t sys, | |
765 | UShort_t sNN, | |
766 | UShort_t trg, | |
767 | UShort_t lowC, | |
768 | UShort_t highC) | |
769 | { | |
770 | // --- Set the macro pathand load other data script -------------- | |
771 | // Always recompile | |
772 | if (!gROOT->GetClass("RefData")) { | |
773 | TString savPath(gROOT->GetMacroPath()); | |
774 | gROOT->SetMacroPath(Form("%s:$(ALICE_ROOT)/PWGLF/FORWARD/analysis2", | |
775 | gROOT->GetMacroPath())); | |
776 | gROOT->LoadMacro("OtherData.C++"); | |
777 | gROOT->SetMacroPath(savPath); | |
778 | } | |
779 | Long_t ret = gROOT->ProcessLine(Form("RefData::GetData(%d,%d,%d,%d,%d,0x4)", | |
780 | sys, sNN, trg, lowC, highC)); | |
781 | if (!ret) { | |
782 | Warning("GetOther", "No other data for %d %d %d %d%%-%d%% central", | |
783 | sys, sNN, trg, lowC, highC); | |
784 | return 0; | |
785 | } | |
786 | TMultiGraph* others = reinterpret_cast<TMultiGraph*>(ret); | |
787 | TGraph* other =static_cast<TGraph*>(others->GetListOfGraphs()->At(0)); | |
788 | if (!other) { | |
789 | Warning("GetOther", "No ALICE data for %d %d %d %d%%-%d%% central", | |
790 | sys, sNN, trg, lowC, highC); | |
791 | return 0; | |
792 | } | |
793 | ||
794 | // Info("", "Got graph %s/%s", other->GetName(), other->GetTitle()); | |
795 | ||
796 | return other; | |
797 | } | |
798 | ||
799 | //__________________________________________________________________ | |
800 | TList fSLCuts; | |
801 | TList fSHCuts; | |
802 | TList fDCCuts; | |
803 | TList fRuns; | |
804 | TList fCents; | |
805 | TList fOthers; | |
806 | TList* fOrder[3]; | |
807 | Bool_t fRebinned; | |
808 | }; | |
809 | ||
810 | #endif |