]> git.uio.no Git - u/mrichter/AliRoot.git/blob - PWGLF/FORWARD/analysis2/OtherData.C
Merge branch 'feature-movesplit'
[u/mrichter/AliRoot.git] / PWGLF / FORWARD / analysis2 / OtherData.C
1 #ifndef __CINT__
2 # include <TFile.h>
3 # include <TString.h>
4 # include <TGraphAsymmErrors.h>
5 # include <TMultiGraph.h>
6 # include <TROOT.h>
7 # include <TError.h>
8 # include <TSystem.h>
9 # include <TH1F.h>
10 # include <TStyle.h>
11 # include <TMath.h>
12 #else 
13 class TFile;
14 class TGraphAsymmErrors;
15 class TMultiGraph;
16 class TGraph;
17 class TH1;
18 #endif 
19
20
21 struct RefData
22 {
23   //____________________________________________________________________
24   /**
25    * Values used 
26    * 
27    * @ingroup pwglf_forward_otherdata 
28    */
29   enum { 
30     UA5, 
31     CMS, 
32     ALICE, 
33     WIP,
34     PYTHIA,
35     INEL, 
36     INELGt0, 
37     NSD
38   };
39   
40   //____________________________________________________________________
41   /** 
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
46    * UPDATE mode.
47    * 
48    * @param path Path to file.
49    * @param rw   If true, open read/write.  
50    * 
51    * @return Pointer to file, or null
52    */
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");
56       
57     TObject* o = gROOT->GetListOfFiles()->FindObject(base);
58     
59     TFile* f  = 0;
60     if (o) {
61       f = static_cast<TFile*>(o);
62       if (!rw) return f;
63       if (!f->IsWritable() && f->ReOpen("UPDATE") < 0) return 0;
64       return f;
65     }
66
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);
72     if (!f) 
73       f = TFile::Open("$ALICE_ROOT/PWGLF/FORWARD/analysis2/other.root",mode);
74     if (!f) 
75       ::Error("", "Failed to open file");
76     return f;
77   }
78   //____________________________________________________________________
79   /** 
80    * Get the collision system name from the identifier (1: pp, 2:
81    * PbPb, 3: pPb)
82    * 
83    * @param sys Collision system identifier 
84    * 
85    * @return String or null
86    */
87   static const char* SysName(UShort_t sys) { 
88     switch (sys) { 
89     case 1: return "pp";
90     case 2: return "PbPb";
91     case 3: return "pPb";
92     }
93     ::Error("", "Unknown system: %d", sys);
94     return 0;
95   }
96   //____________________________________________________________________
97   /** 
98    * Get the zero-padded collision energy name 
99    * 
100    * @param sNN Collision energy (in GeV)
101    * 
102    * @return Zero-padded collision energy
103    */
104   static const char* SNNName(UShort_t sNN) 
105   { 
106     return Form("%05d", sNN);
107   }
108   //____________________________________________________________________
109   /** 
110    * Get the centrality method prefix.  @a trg is a bit mask, of which
111    * bits 4-7 are used here.  The flags are 
112    *
113    * - 0x10 V0M 
114    * - 0x20 V0A
115    * - 0x40 ZNA
116    * - 0X80 ZNC
117    * 
118    * @param trg Bits
119    * 
120    * @return Prefix string or empty string 
121    */
122   static const char* CntName(UShort_t trg) 
123   {
124     switch (trg >> 4) { 
125     case 1: return "V0M_";
126     case 2: return "V0A_";
127     case 4: return "ZNA_";
128     case 8: return "ZNC_";
129     }
130     return "";
131   }
132   //____________________________________________________________________
133   /** 
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.
137    *
138    * The meaning of the bits are 
139    *
140    * - 0x01 INEL
141    * - 0x02 INEL>0
142    * - 0x04 NSD 
143    * - 0xf0 Mask for centrality estimator. 
144    * 
145    * @param trg Trigger mask.  
146    * @param c1  Least centrality @f$ c_1@f$ 
147    * @param c2  Largest centrality @f$ c_2@f$
148    * 
149    * @return Trigger string or null
150    */
151   static const char* TrgName(UShort_t trg, UShort_t c1, UShort_t c2)
152   {
153     if (c2 > c1) return Form("%s%03d_%03d", CntName(trg), c1, c2);
154
155     switch (trg) { 
156     case 1: return "INEL";
157     case 2: return "INELGT0";
158     case 4: return "NSD";
159     }
160     ::Error("", "Unknown trigger: %d", trg);
161     return 0;
162   }
163   //____________________________________________________________________
164   /** 
165    * Get the experiment name.  
166    *
167    * - 0: UA5 
168    * - 1: CMS 
169    * - 2: ALICE (published or pre-print)
170    * - 3: ALICE Work-in-progress 
171    * - 4: PYTHIA (or MC)
172    * 
173    * @param which Experiment identifier 
174    * 
175    * @return Experiment name or null
176    */
177   static const char* ExpName(UShort_t which) 
178   {
179     switch (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";
185     }
186     ::Error("", "Unknown experiment: %d", which); 
187     return 0;
188   }
189   // _________________________________________________________________
190   /** 
191    * Get graphs for selected experiments under @a d.  
192    * 
193    * @param d        Directory to search
194    * @param which    Which experiments to get data from 
195    * @param verbose  Whether to be verbose or not 
196    * 
197    * @return Graph of data, or null
198    */
199   static TMultiGraph* GetExps(TDirectory* d, UShort_t which, Bool_t verbose)
200   {
201     TMultiGraph* ret = 0;
202     for (UShort_t w = UA5; w <= PYTHIA; w++) { 
203       if (!(which & (1 << w))) continue;
204
205       const char* expName = ExpName(w);
206       TDirectory* expDir  = 0;
207       if (!expName || !(expDir = d->GetDirectory(expName))) continue;
208
209       TObject* o = expDir->Get("data");
210       if (o) {
211         if (!ret) ret = new TMultiGraph();
212         TMultiGraph* mg = static_cast<TMultiGraph*>(o);
213         if (w == WIP) { 
214           TIter   next(mg->GetListOfGraphs());
215           TGraph* g = 0;
216           while ((g = static_cast<TGraph*>(next()))) 
217             if (g->GetMarkerColor() == kMagenta+3) {
218               g->SetMarkerColor(kCyan-6);
219               g->SetLineColor(kCyan-6);
220             }
221         }
222         ret->Add(mg);
223       }
224     }
225     if (!ret && verbose)
226       ::Error("GetExps", "Didn't get any data for exp=0x%x in dir %s", 
227               which, d->GetPath());
228     return ret;
229   }
230
231   // _________________________________________________________________
232   /** 
233    * Get data for selected trigger and experiments under @a d.  
234    * 
235    * @param d        Directory to seach 
236    * @param type     Which triggers 
237    * @param which    Which experiments
238    * @param verbose  Whether to be verbose 
239    * 
240    * @return Graph of data, or null
241    */
242   static TMultiGraph* GetTrigs(TDirectory* d, UShort_t type, 
243                                UShort_t which, Bool_t verbose) 
244   {
245     TMultiGraph* ret = 0;
246     for (UShort_t t = INEL; t <= NSD; t++) { 
247       UShort_t trg = (1 << (t-INEL));
248       if (!(type & trg)) {
249         if (verbose) 
250           ::Info("GetTrigs", "Skipping trigger 0x%x (0x%x)", trg, type);
251         continue;
252       }
253
254       const char* trgName = TrgName(trg, 0, 0);
255       TDirectory* trgDir  = 0;
256       if (!trgName || !(trgDir = d->GetDirectory(trgName))) {
257         if (verbose) 
258           ::Warning("GetTrigs", "No directory %s for 0x%x in %s", 
259                     trgName, trg, d->GetPath());
260         continue;
261       }
262
263       TMultiGraph* g = GetExps(trgDir, which, verbose);
264       if (g) { 
265         if (!ret) ret = new TMultiGraph();
266         ret->Add(g);
267       }
268     }
269     if (!ret) 
270       ::Error("GetTrigs", 
271               "Didn't get any data for trigger=0x%x and exp=0x%x in dir %s", 
272               type, which, d->GetPath());
273     return ret;
274   }
275
276   // _________________________________________________________________
277   /** 
278    * Get data for selected centrality range 
279    * 
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 
286    * 
287    * @return Graph of data or null
288    */
289   static TMultiGraph* GetCents(TDirectory* d, UShort_t experiment, 
290                                UShort_t trigger, UShort_t centLow, 
291                                UShort_t centHigh, Bool_t verbose) 
292   {
293     // We need to find the bins we can and check for the
294     // experiments
295     TMultiGraph* ret = 0;
296     TIter    next(d->GetListOfKeys());
297     TObject* obj = 0;
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;
303       UShort_t off = 0;
304       if (cntPre && cntPre[0] != '\0') {
305         if (!n.BeginsWith(cntPre, TString::kIgnoreCase)) continue;
306         off = 4;
307       }
308       if (n.Length() != 7+off) continue;
309       
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();
314       
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());
318         continue;
319       }
320       
321       TDirectory* centDir = d->GetDirectory(obj->GetName());
322       if (!centDir) continue;
323       
324       TMultiGraph* exps = GetExps(centDir, experiment, verbose);
325       if (exps) {
326         if (!ret) ret = new TMultiGraph();
327         ret->Add(exps);
328       }
329     } // experiment (key)
330     if (!ret && verbose) 
331       ::Error("GetCents", "No graphs for centralities %d-%d%% in %s", 
332               centLow, centHigh, d->GetPath());
333     return ret;
334   }
335   //____________________________________________________________________
336   /** 
337    * Get a multi graph of data for a given energy and trigger type 
338    * 
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 
342    *   - 0x01 INEL 
343    *   - 0x02 INEL>0
344    *   - 0x04 NSD 
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 
349    * 
350    * @return A multi graph with the selected data. 
351    * 
352    * @ingroup pwglf_forward_otherdata
353    */
354   static TMultiGraph* GetData(UShort_t sys, 
355                               UShort_t sNN,
356                               UShort_t triggers=0x1, 
357                               UShort_t centLow=0, 
358                               UShort_t centHigh=0, 
359                               UShort_t experiments=0x7)
360   {
361     Bool_t verbose = false;
362     UShort_t trg = (triggers & 0xF7);
363     if (triggers & 0x2000) trg |= 0x4;
364
365     TFile* f = GetFile(0,false);
366     if (!f) return 0;
367
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);
372       return 0;
373     }
374
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);
379       return 0;
380     }
381
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);
388       else {
389         // Look for specific centrality bin 
390         TDirectory* centDir = sNNDir->GetDirectory(TrgName(trg, 
391                                                            centLow,centHigh));
392         if (!centDir) {
393           Warning("", "No directory '%s' (0x%x,%d%d)", 
394                   TrgName(trg, centLow,centHigh), trg, centLow, centHigh);
395           return 0;
396         }
397
398         return GetExps(centDir, experiments, verbose);
399       }
400     } // centHigh > centLow
401     else 
402       ret = GetTrigs(sNNDir, trg, experiments, verbose);
403
404     if (ret) {
405       TString title;
406       FormatTitle(title, sys, sNN, trg, centLow, centHigh);
407       ret->SetTitle(title);
408     }
409     return ret;
410   }
411   //__________________________________________________________________
412   /** 
413    * Format title of a plot
414    * 
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 
419    *   - 0x01 INEL 
420    *   - 0x02 INEL>0
421    *   - 0x04 NSD 
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
426    */
427   static void FormatTitle(TString& title,
428                           UShort_t sys, 
429                           UShort_t sNN,
430                           UShort_t triggers, 
431                           UShort_t centLow, 
432                           UShort_t centHigh,
433                           Bool_t   seenUA5=false)
434   {
435     TString sn(SysName(sys));
436     if (seenUA5) sn.Append("(p#bar{p})");
437
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));
442     TString tn;
443     if (centHigh > centLow) 
444       tn = Form("%d%% - %d%% central", centLow, centHigh);
445     else { 
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("|");
450         switch (t) { 
451         case INEL:    tn.Append("INEL"); break;
452         case INELGt0: tn.Append("INEL>0"); break;
453         case NSD:     tn.Append("NSD"); break;
454         }
455       } // for 
456     }
457     if (!en.IsNull()) en.Prepend(", ");
458     if (!tn.IsNull()) tn.Prepend(", ");
459     title.Form("%s%s%s", sn.Data(), en.Data(), tn.Data());
460   }
461   //=== Importing ====================================================
462   enum { 
463     /** Style used for UA5 data */
464     UA5Style   = 21, 
465     /** Style used for CMS data */
466     CMSStyle   = 29, 
467     /** Style used for ALICE published data */
468     ALICEStyle = 27,
469     /** Color used for ALICE work-in-progress data */
470     WIPStyle = 33,
471     /** Style used for Pythia data */
472     PYTHIAStyle = 28,
473     /** Color used for UA5 data */
474     UA5Color   = kBlue+1,
475     /** Color used for Pytia data */
476     PYTHIAColor = kGray+2,
477     /** Color used for CMS data */
478     CMSColor   = kGreen+1,
479     /** Color used for ALICE data */
480     ALICEColor = kMagenta+1,
481     /** Color used for ALICE work-in-progress data */
482     WIPColor = kCyan+2
483   }; 
484   enum { 
485     /** Marker style INEL data */
486     INELStyle   = 22,
487     /** Marker style INEL>0 data */
488     INELGt0Style= 29,
489     /** Marker style NSD data */
490     NSDStyle    = 23,
491     /** Color used for UA5 data */
492     INELColor   = kBlue+1,
493     /** Color used for CMS data */
494     INELGt0Color = kGreen+1,
495     /** Color used for ALICE data */
496     NSDColor     = kMagenta+1
497   };
498   enum {
499     /** Style offset for mirror data */
500     MirrorOff  = 4
501   };
502   //____________________________________________________________________
503   /** 
504    * Set graph attributes based on trigger type and experiment. 
505    * 
506    * @param g        Graph
507    * @param exp      Experiment 
508    * @param mirror   True if mirrored data 
509    * @param name     Name of graph 
510    * @param title    Title of graph 
511    * 
512    * @ingroup pwglf_forward_otherdata
513    */
514   static void SetGraphAttributes(TGraph* g, 
515                                  Int_t /*trig*/, 
516                                  Int_t exp, 
517                                  bool mirror,
518                                  const Char_t* name, 
519                                  const Char_t* title)
520   {
521     Int_t color = 0;
522     Int_t style = 0;
523     switch (exp) { 
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;
529     }
530     Float_t size = g->GetMarkerSize();
531     switch (style) {
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;
536     }
537     
538     if (mirror) style += MirrorOff;
539
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);
546     g->SetFillColor(0);
547     g->SetFillStyle(0);
548     g->GetHistogram()->SetStats(kFALSE);
549     g->GetHistogram()->SetXTitle("#eta");
550     g->GetHistogram()->SetYTitle("#frac{1}{N} #frac{dN_{ch}}{#eta}");
551   }
552   //__________________________________________________________________
553   /** 
554    * Get the color for a centrality bin
555    * 
556    * @param centLow  Centrality bin 
557    * @param centHigh Centrality bin 
558    * 
559    * @return Color 
560    */
561   static Int_t CentralityColor(UShort_t centLow, 
562                                UShort_t centHigh,
563                                UShort_t /*nBins*/=0)
564   {
565 #if 0
566     if (nBins > 0 && nBins < 6) { 
567       switch (bin) { 
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;
574       }
575     }
576 #endif
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);
583     return col;
584   }
585   /** 
586    * Import a histogram into the data base
587    * 
588    * @param h            Histogram
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 
597    * 
598    * @return true on success
599    */
600   static Bool_t Import(TH1* h, 
601                        const char* title, 
602                        UShort_t experiment,
603                        UShort_t sys, 
604                        UShort_t sNN,
605                        UShort_t trigger, 
606                        UShort_t centLow=0, 
607                        UShort_t centHigh=0,
608                        const char* path=0)
609   {
610     TGraphAsymmErrors* g = new TGraphAsymmErrors();
611     Int_t nx = h->GetNbinsX();
612     Int_t j  = 0;
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);
618       
619       if (TMath::Abs(y) < 1e-6 || ey < 1e-6) continue;
620       
621       g->SetPoint(j, x, y);
622       g->SetPointError(j, ex, ex, ey, ey);
623       j++;
624     }
625     if (j <= 0) return false;
626
627     return Import(g, title, experiment, sys, sNN, trigger, centLow, centHigh, 
628                   path);
629   }
630   /** 
631    * Import a graph into the data base
632    * 
633    * @param g            Graph
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 
642    * 
643    * @return true on success
644    */
645   static Bool_t Import(TGraphAsymmErrors* g,
646                        const char* title, 
647                        UShort_t experiment,
648                        UShort_t sys, 
649                        UShort_t sNN,
650                        UShort_t trigger, 
651                        UShort_t centLow=0, 
652                        UShort_t centHigh=0,
653                        const char* path=0) 
654   {
655     if (!g) return false;
656
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);
663     
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);
670     }
671       
672     TMultiGraph* mg = new TMultiGraph("data","");
673     mg->Add(g);
674
675     return Import(mg, experiment, sys, sNN, trigger, centLow, centHigh, path);
676   }
677   /** 
678    * Import a graph into the data base
679    * 
680    * @param g            Graph
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 
689    * 
690    * @return true on success
691    */
692   static Bool_t Import(TMultiGraph* g,
693                        UShort_t experiment,
694                        UShort_t sys, 
695                        UShort_t sNN,
696                        UShort_t trigger, 
697                        UShort_t centLow=0, 
698                        UShort_t centHigh=0,
699                        const char* path=0)
700   {
701     TFile* file = GetFile(path, true);
702     
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);
707     
708     if (!sysName || !sNNName || !trgName || !expName) return false;
709     
710     TString dirName;
711     dirName = Form("%s/%s/%s/%s", sysName, sNNName, trgName, expName);
712     
713     TDirectory* dir = file->GetDirectory(dirName);
714     if (!dir) dir = file->mkdir(dirName);
715     file->cd(dirName);
716
717     if (dir->Get("data")) { 
718       ::Warning("", "Already have data in %s", dirName.Data());
719       // return false;
720     }
721
722     g->SetName("data");
723     g->Write();
724     
725     file->cd();
726     file->Close();
727
728     return true;
729   }
730 };
731
732 // EOF
733
734
735
736     
737