4 # include <TGraphAsymmErrors.h>
5 # include <TMultiGraph.h>
14 class TGraphAsymmErrors;
23 //____________________________________________________________________
27 * @ingroup pwglf_forward_otherdata
40 //____________________________________________________________________
42 * Get a pointer to our data file. @a path is the path to the file
43 * containing the data. If it is null, then first search the
44 * current directory, and if not found there, search in specific
45 * AliROOT directory. If @a rw is try the file is (re-)opened in
48 * @param path Path to file.
49 * @param rw If true, open read/write.
51 * @return Pointer to file, or null
53 static TFile* GetFile(const char* path=0, Bool_t rw=false) {
54 TString base = ((path && path[0] != '\0') ?
55 gSystem->BaseName(path) : "other.root");
57 TObject* o = gROOT->GetListOfFiles()->FindObject(base);
61 f = static_cast<TFile*>(o);
63 if (!f->IsWritable() && f->ReOpen("UPDATE") < 0) return 0;
67 const char* mode = (rw ? "UPDATE" : "READ");
68 if (path && path[0] != '\0' && !gSystem->AccessPathName(path))
69 f = TFile::Open(path, mode);
70 if (!f && !gSystem->AccessPathName("other.root"))
71 f = TFile::Open("other.root", mode);
73 f = TFile::Open("$ALICE_ROOT/PWGLF/FORWARD/analysis2/other.root",mode);
75 ::Error("", "Failed to open file");
78 //____________________________________________________________________
80 * Get the collision system name from the identifier (1: pp, 2:
83 * @param sys Collision system identifier
85 * @return String or null
87 static const char* SysName(UShort_t sys) {
90 case 2: return "PbPb";
93 ::Error("", "Unknown system: %d", sys);
96 //____________________________________________________________________
98 * Get the zero-padded collision energy name
100 * @param sNN Collision energy (in GeV)
102 * @return Zero-padded collision energy
104 static const char* SNNName(UShort_t sNN)
106 return Form("%05d", sNN);
108 //____________________________________________________________________
110 * Get the centrality method prefix. @a trg is a bit mask, of which
111 * bits 4-7 are used here. The flags are
120 * @return Prefix string or empty string
122 static const char* CntName(UShort_t trg)
125 case 1: return "V0M_";
126 case 2: return "V0A_";
127 case 4: return "ZNA_";
128 case 8: return "ZNC_";
132 //____________________________________________________________________
134 * Get the trigger name. If @f$ c_2 > c_1@f$ then the bits of @a
135 * trg are ignored, save for the bits 4-7 which are interpreted
136 * according to CntName.
138 * The meaning of the bits are
143 * - 0xf0 Mask for centrality estimator.
145 * @param trg Trigger mask.
146 * @param c1 Least centrality @f$ c_1@f$
147 * @param c2 Largest centrality @f$ c_2@f$
149 * @return Trigger string or null
151 static const char* TrgName(UShort_t trg, UShort_t c1, UShort_t c2)
153 if (c2 > c1) return Form("%s%03d_%03d", CntName(trg), c1, c2);
156 case 1: return "INEL";
157 case 2: return "INELGT0";
158 case 4: return "NSD";
160 ::Error("", "Unknown trigger: %d", trg);
163 //____________________________________________________________________
165 * Get the experiment name.
169 * - 2: ALICE (published or pre-print)
170 * - 3: ALICE Work-in-progress
171 * - 4: PYTHIA (or MC)
173 * @param which Experiment identifier
175 * @return Experiment name or null
177 static const char* ExpName(UShort_t which)
180 case 0: return "UA5";
181 case 1: return "CMS";
182 case 2: return "ALICE";
183 case 3: return "WIP";
184 case 4: return "PYTHIA";
186 ::Error("", "Unknown experiment: %d", which);
189 // _________________________________________________________________
191 * Get graphs for selected experiments under @a d.
193 * @param d Directory to search
194 * @param which Which experiments to get data from
195 * @param verbose Whether to be verbose or not
197 * @return Graph of data, or null
199 static TMultiGraph* GetExps(TDirectory* d, UShort_t which, Bool_t verbose)
201 TMultiGraph* ret = 0;
202 for (UShort_t w = UA5; w <= PYTHIA; w++) {
203 if (!(which & (1 << w))) continue;
205 const char* expName = ExpName(w);
206 TDirectory* expDir = 0;
207 if (!expName || !(expDir = d->GetDirectory(expName))) continue;
209 TObject* o = expDir->Get("data");
211 if (!ret) ret = new TMultiGraph();
212 TMultiGraph* mg = static_cast<TMultiGraph*>(o);
214 TIter next(mg->GetListOfGraphs());
216 while ((g = static_cast<TGraph*>(next())))
217 if (g->GetMarkerColor() == kMagenta+3) {
218 g->SetMarkerColor(kCyan-6);
219 g->SetLineColor(kCyan-6);
226 ::Error("GetExps", "Didn't get any data for exp=0x%x in dir %s",
227 which, d->GetPath());
231 // _________________________________________________________________
233 * Get data for selected trigger and experiments under @a d.
235 * @param d Directory to seach
236 * @param type Which triggers
237 * @param which Which experiments
238 * @param verbose Whether to be verbose
240 * @return Graph of data, or null
242 static TMultiGraph* GetTrigs(TDirectory* d, UShort_t type,
243 UShort_t which, Bool_t verbose)
245 TMultiGraph* ret = 0;
246 for (UShort_t t = INEL; t <= NSD; t++) {
247 UShort_t trg = (1 << (t-INEL));
250 ::Info("GetTrigs", "Skipping trigger 0x%x (0x%x)", trg, type);
254 const char* trgName = TrgName(trg, 0, 0);
255 TDirectory* trgDir = 0;
256 if (!trgName || !(trgDir = d->GetDirectory(trgName))) {
258 ::Warning("GetTrigs", "No directory %s for 0x%x in %s",
259 trgName, trg, d->GetPath());
263 TMultiGraph* g = GetExps(trgDir, which, verbose);
265 if (!ret) ret = new TMultiGraph();
271 "Didn't get any data for trigger=0x%x and exp=0x%x in dir %s",
272 type, which, d->GetPath());
276 // _________________________________________________________________
278 * Get data for selected centrality range
280 * @param d Directory to search
281 * @param experiment Which experiment
282 * @param trigger Which centrality estimator (possibly 0)
283 * @param centLow Least centrality
284 * @param centHigh Largetst centrality
285 * @param verbose Whether to be verbose
287 * @return Graph of data or null
289 static TMultiGraph* GetCents(TDirectory* d, UShort_t experiment,
290 UShort_t trigger, UShort_t centLow,
291 UShort_t centHigh, Bool_t verbose)
293 // We need to find the bins we can and check for the
295 TMultiGraph* ret = 0;
296 TIter next(d->GetListOfKeys());
298 const char* cntPre = CntName(trigger);
299 // Info("", "trigger=0x%x pre=%s", trigger, cntPre);
300 while ((obj = next())) {
301 TString n(obj->GetName());
302 if (n.EqualTo("all")) continue;
304 if (cntPre && cntPre[0] != '\0') {
305 if (!n.BeginsWith(cntPre, TString::kIgnoreCase)) continue;
308 if (n.Length() != 7+off) continue;
310 TString l1(n(off, 3)); TString l2 = l1.Strip(TString::kLeading, '0');
311 TString h1(n(off+4,3)); TString h2 = h1.Strip(TString::kLeading, '0');
312 UShort_t c1 = l2.Atoi();
313 UShort_t c2 = h2.Atoi();
315 // Info("", "n=%s off=%d c1=%d c2=%d", n.Data(), off, c1, c2);
316 if (c1 < centLow || c2 > centHigh) {
317 if (verbose) ::Info("", "Skipping %s in %s", n.Data(),d->GetPath());
321 TDirectory* centDir = d->GetDirectory(obj->GetName());
322 if (!centDir) continue;
324 TMultiGraph* exps = GetExps(centDir, experiment, verbose);
326 if (!ret) ret = new TMultiGraph();
329 } // experiment (key)
331 ::Error("GetCents", "No graphs for centralities %d-%d%% in %s",
332 centLow, centHigh, d->GetPath());
335 //____________________________________________________________________
337 * Get a multi graph of data for a given energy and trigger type
339 * @param sys Collision system (1: pp, 2: PbPb, 3: pPb)
340 * @param energy Energy in GeV (900, 2360, 2760, 7000, 8000)
341 * @param triggers Bit pattern of trigger type
345 * - 0xF0 Mask for centrality estimator
346 * @param centLow Low centrality cut (not pp)
347 * @param centHigh High centrality cut (not pp)
348 * @param experiments From which experiments
350 * @return A multi graph with the selected data.
352 * @ingroup pwglf_forward_otherdata
354 static TMultiGraph* GetData(UShort_t sys,
356 UShort_t triggers=0x1,
359 UShort_t experiments=0x7)
361 Bool_t verbose = false;
362 UShort_t trg = (triggers & 0xF7);
363 if (triggers & 0x2000) trg |= 0x4;
365 TFile* f = GetFile(0,false);
368 TDirectory* sysDir = 0;
369 const char* sysName = SysName(sys);
370 if (!sysName || !(sysDir = f->GetDirectory(sysName))) {
371 ::Error("", "Invalid system %d (%s)", sys, sysName);
375 TDirectory* sNNDir = 0;
376 const char* sNNName = SNNName(sNN);
377 if (!sNNName || !(sNNDir = sysDir->GetDirectory(sNNName))) {
378 ::Error("", "Invalid CMS energy %d (%s)", sNN, sNNName);
382 TMultiGraph* ret = 0;
383 // If we have a centrality request
384 if (centHigh > centLow) {
385 if (centLow == 0 && centHigh >= 100)
386 ret = GetCents(sNNDir, experiments, trg,
387 centLow, centHigh, verbose);
389 // Look for specific centrality bin
390 TDirectory* centDir = sNNDir->GetDirectory(TrgName(trg,
393 Warning("", "No directory '%s' (0x%x,%d%d)",
394 TrgName(trg, centLow,centHigh), trg, centLow, centHigh);
398 return GetExps(centDir, experiments, verbose);
400 } // centHigh > centLow
402 ret = GetTrigs(sNNDir, trg, experiments, verbose);
406 FormatTitle(title, sys, sNN, trg, centLow, centHigh);
407 ret->SetTitle(title);
411 //__________________________________________________________________
413 * Format title of a plot
415 * @param title On return, the title
416 * @param sys Collision system (1: pp, 2: PbPb, 3: pPb)
417 * @param energy Energy in GeV (900, 2360, 2760, 7000, 8000)
418 * @param triggers Bit pattern of trigger type
422 * - 0xF0 Mask for centrality estimator
423 * @param centLow Low centrality cut (not pp)
424 * @param centHigh High centrality cut (not pp)
425 * @param seenUA5 If true and sys=1, then put in p-pbar
427 static void FormatTitle(TString& title,
433 Bool_t seenUA5=false)
435 TString sn(SysName(sys));
436 if (seenUA5) sn.Append("(p#bar{p})");
438 TString en(Form("#sqrt{s%s}=", (sys==1 ? "" : "_{NN}")));
439 if (sNN < 1000) en.Append(Form("%dGeV", sNN));
440 else if ((sNN % 1000) == 0) en.Append(Form("%dTeV", (sNN/1000)));
441 else en.Append(Form("%.2fTeV", Float_t(sNN)/1000));
443 if (centHigh > centLow)
444 tn = Form("%d%% - %d%% central", centLow, centHigh);
446 for (UShort_t t = INEL; t <= NSD; t++) {
447 UShort_t trg = (1 << (t-INEL));
448 if (!(triggers & trg)) continue;
449 if (!tn.IsNull()) tn.Append("|");
451 case INEL: tn.Append("INEL"); break;
452 case INELGt0: tn.Append("INEL>0"); break;
453 case NSD: tn.Append("NSD"); break;
457 if (!en.IsNull()) en.Prepend(", ");
458 if (!tn.IsNull()) tn.Prepend(", ");
459 title.Form("%s%s%s", sn.Data(), en.Data(), tn.Data());
461 //=== Importing ====================================================
463 /** Style used for UA5 data */
465 /** Style used for CMS data */
467 /** Style used for ALICE published data */
469 /** Color used for ALICE work-in-progress data */
471 /** Style used for Pythia data */
473 /** Color used for UA5 data */
475 /** Color used for Pytia data */
476 PYTHIAColor = kGray+2,
477 /** Color used for CMS data */
479 /** Color used for ALICE data */
480 ALICEColor = kMagenta+1,
481 /** Color used for ALICE work-in-progress data */
485 /** Marker style INEL data */
487 /** Marker style INEL>0 data */
489 /** Marker style NSD data */
491 /** Color used for UA5 data */
493 /** Color used for CMS data */
494 INELGt0Color = kGreen+1,
495 /** Color used for ALICE data */
496 NSDColor = kMagenta+1
499 /** Style offset for mirror data */
502 //____________________________________________________________________
504 * Set graph attributes based on trigger type and experiment.
507 * @param exp Experiment
508 * @param mirror True if mirrored data
509 * @param name Name of graph
510 * @param title Title of graph
512 * @ingroup pwglf_forward_otherdata
514 static void SetGraphAttributes(TGraph* g,
524 case UA5: color = UA5Color; style = UA5Style; break;
525 case CMS: color = CMSColor; style = CMSStyle; break;
526 case ALICE: color = ALICEColor; style = ALICEStyle; break;
527 case WIP: color = WIPColor; style = WIPStyle; break;
528 case PYTHIA: color = PYTHIAColor; style = PYTHIAStyle; break;
530 Float_t size = g->GetMarkerSize();
532 case 21: // fall-through
533 case 25: size *= 0.8; break;
534 case 27: size *= 1.4; break;
535 case 33: size *= 1.4; break;
538 if (mirror) style += MirrorOff;
540 if (name) g->SetName(name);
541 if (title) g->SetTitle(title);
542 g->SetMarkerStyle(style);
543 g->SetMarkerSize(size);
544 g->SetMarkerColor(color);
545 g->SetLineColor(color);
548 g->GetHistogram()->SetStats(kFALSE);
549 g->GetHistogram()->SetXTitle("#eta");
550 g->GetHistogram()->SetYTitle("#frac{1}{N} #frac{dN_{ch}}{#eta}");
552 //__________________________________________________________________
554 * Get the color for a centrality bin
556 * @param centLow Centrality bin
557 * @param centHigh Centrality bin
561 static Int_t CentralityColor(UShort_t centLow,
563 UShort_t /*nBins*/=0)
566 if (nBins > 0 && nBins < 6) {
568 case 1: return kRed+2;
569 case 2: return kGreen+2;
570 case 3: return kBlue+1;
571 case 4: return kCyan+1;
572 case 5: return kMagenta+1;
573 case 6: return kYellow+2;
577 gStyle->SetPalette(1);
578 Float_t fc = (centLow+double(centHigh-centLow)/2) / 100;
579 Int_t nCol = gStyle->GetNumberOfColors();
580 Int_t icol = TMath::Min(nCol-1,int(fc * nCol + .5));
581 Int_t col = gStyle->GetColorPalette(icol);
582 //Info("GetCentralityColor","%3d: %3d-%3d -> %3d",bin,centLow,centHigh,col);
586 * Import a histogram into the data base
589 * @param title Title on plot
590 * @param experiment Which experiement
591 * @param sys Collision system
592 * @param sNN Collision energy (in GeV)
593 * @param trigger Trigger type
594 * @param centLow Lease centrality
595 * @param centHigh Largest centrality
596 * @param path Possible path to database
598 * @return true on success
600 static Bool_t Import(TH1* h,
610 TGraphAsymmErrors* g = new TGraphAsymmErrors();
611 Int_t nx = h->GetNbinsX();
613 for (Int_t i = 1; i <= nx; i++) {
614 Double_t x = h->GetXaxis()->GetBinCenter(i);
615 Double_t ex = h->GetXaxis()->GetBinWidth(i)/2;
616 Double_t y = h->GetBinContent(i);
617 Double_t ey = h->GetBinError(i);
619 if (TMath::Abs(y) < 1e-6 || ey < 1e-6) continue;
621 g->SetPoint(j, x, y);
622 g->SetPointError(j, ex, ex, ey, ey);
625 if (j <= 0) return false;
627 return Import(g, title, experiment, sys, sNN, trigger, centLow, centHigh,
631 * Import a graph into the data base
634 * @param title Title on plot
635 * @param experiment Which experiement
636 * @param sys Collision system
637 * @param sNN Collision energy (in GeV)
638 * @param trigger Trigger type
639 * @param centLow Lease centrality
640 * @param centHigh Largest centrality
641 * @param path Possible path to database
643 * @return true on success
645 static Bool_t Import(TGraphAsymmErrors* g,
655 if (!g) return false;
657 TString expName = ExpName(experiment); expName.ToLower();
658 const char* sNNName = SNNName(sNN);
659 const char* sysName = SysName(sys);
660 const char* trgName = TrgName(trigger,centLow,centHigh);
661 TString name = Form("%s%s%s%s",
662 expName.Data(), sysName, sNNName, trgName);
664 SetGraphAttributes(g, trigger, experiment, false, name, title);
665 if (centLow < centHigh) {
666 Int_t col = CentralityColor(centLow, centHigh);
667 g->SetMarkerColor(col);
668 g->SetLineColor(col);
669 g->SetFillColor(col);
672 TMultiGraph* mg = new TMultiGraph("data","");
675 return Import(mg, experiment, sys, sNN, trigger, centLow, centHigh, path);
678 * Import a graph into the data base
681 * @param title Title on plot
682 * @param experiment Which experiement
683 * @param sys Collision system
684 * @param sNN Collision energy (in GeV)
685 * @param trigger Trigger type
686 * @param centLow Lease centrality
687 * @param centHigh Largest centrality
688 * @param path Possible path to database
690 * @return true on success
692 static Bool_t Import(TMultiGraph* g,
701 TFile* file = GetFile(path, true);
703 const char* sysName = SysName(sys);
704 const char* sNNName = SNNName(sNN);
705 const char* trgName = TrgName(trigger, centLow, centHigh);
706 const char* expName = ExpName(experiment);
708 if (!sysName || !sNNName || !trgName || !expName) return false;
711 dirName = Form("%s/%s/%s/%s", sysName, sNNName, trgName, expName);
713 TDirectory* dir = file->GetDirectory(dirName);
714 if (!dir) dir = file->mkdir(dirName);
717 if (dir->Get("data")) {
718 ::Warning("", "Already have data in %s", dirName.Data());