]> git.uio.no Git - u/mrichter/AliRoot.git/blob - PWGLF/FORWARD/analysis2/AliForwardUtil.h
Renamed some member functions for more logical names
[u/mrichter/AliRoot.git] / PWGLF / FORWARD / analysis2 / AliForwardUtil.h
1 // 
2 // Utilities used in the forward multiplcity analysis 
3 // 
4 //
5 #ifndef ALIFORWARDUTIL_H
6 #define ALIFORWARDUTIL_H
7 /**
8  * @file   AliForwardUtil.h
9  * @author Christian Holm Christensen <cholm@dalsgaard.hehi.nbi.dk>
10  * @date   Wed Mar 23 14:06:54 2011
11  * 
12  * @brief  
13  * 
14  * 
15  * @ingroup pwglf_forward 
16  */
17 #include <TObject.h>
18 #include <TString.h>
19 #include <TObjArray.h>
20 class TH2D;
21 class TH1I;
22 class TH1;
23 class TF1;
24 class TAxis;
25 class AliESDEvent;
26 class AliAODEvent;
27 class AliAnalysisTaskSE;
28
29 /** 
30  * Utilities used in the forward multiplcity analysis 
31  * 
32  * @ingroup pwglf_forward 
33  */
34 class AliForwardUtil : public TObject
35 {
36 public:
37   /** 
38    * Get the standard color for a ring  
39    *
40    * @param d Detector
41    * @param r Ring 
42    * 
43    * @return 
44    */
45   static Color_t RingColor(UShort_t d, Char_t r)
46   { 
47     return ((d == 1 ? kRed : (d == 2 ? kGreen : kBlue))
48             + ((r == 'I' || r == 'i') ? 2 : -3));
49   }
50   //==================================================================
51   /** 
52    * @{ 
53    * @name Collision/run parameters 
54    */
55   /**                                           
56    * Defined collision types 
57    */
58   enum ECollisionSystem {
59     kUnknown, 
60     kPP, 
61     kPbPb,
62     kPPb
63   };
64   //__________________________________________________________________
65   /** 
66    * Calculate the beam rapidity. 
67    *
68    * @b Note: The beam energy is given in GeV/charge
69    * 
70    * @param beam Beam energy in GeV/charge 
71    * @param z    Charge number of projectile
72    * @param a    Mass number of projectile 
73    * 
74    * @return The rapidity of the beam
75    */
76   static Float_t BeamRapidity(Float_t beam, UShort_t z, UShort_t a);
77   /** 
78    * Calculate the center of mass energy from the beam energy per
79    * charge and the nucleus numbers.
80    * 
81    * @param beam Beam energy in GeV/charge 
82    * @param z1   Charge number of projectile
83    * @param a1   Mass number of projectile
84    * @param z2   Charge number of projectile
85    * @param a2   Mass number of projectile  
86    * 
87    * @return The center of mass energy in GeV/nucleon
88    */
89   static Float_t CenterOfMassEnergy(Float_t beam, UShort_t z1, UShort_t a1, 
90                                     Short_t z2=-1, Short_t a2=-1);
91   /** 
92    * Calculate the center of mass rapidity (shift)
93    * 
94    * @param z1 Charge number of projectile
95    * @param a1 Mass number of projectile  
96    * @param z2 Charge number of projectile
97    * @param a2 Mass number of projectile  
98    * x
99    * @return Rapidity of the center of mass 
100    */
101   static Float_t CenterOfMassRapidity(UShort_t z1, UShort_t a1, 
102                                       Short_t z2=-1, Short_t a2=-1);
103   /** 
104    * Parse a collision system spec given in a string.   Known values are 
105    * 
106    *  - "pp", "p-p" which returns kPP 
107    *  - "PbPb", "Pb-Pb", "A-A", which returns kPbPb
108    *  - "pPb", "p-Pb", "pA", p-A" which returns kPPb
109    *  - Everything else gives kUnknown 
110    * 
111    * @param sys Collision system spec 
112    * 
113    * @return Collision system id 
114    */
115   static UShort_t ParseCollisionSystem(const char* sys);
116   /** 
117    * Get a string representation of the collision system 
118    * 
119    * @param sys  Collision system 
120    * - kPP -> "pp"
121    * - kPbPb -> "PbPb" 
122    * - kPPb -> "pPb"
123    * - anything else gives "unknown"
124    * 
125    * @return String representation of the collision system 
126    */
127   static const char* CollisionSystemString(UShort_t sys);
128   //__________________________________________________________________
129   /** 
130    * Parse the center of mass energy given as a float and return known 
131    * values as a unsigned integer
132    * 
133    * @param sys  Collision system (needed for AA)
134    * @param cms  Center of mass energy * total charge 
135    * 
136    * @return Center of mass energy per nucleon
137    */
138   static UShort_t ParseCenterOfMassEnergy(UShort_t sys, Float_t cms);
139   /** 
140    * Get a string representation of the center of mass energy per nuclean
141    * 
142    * @param cms  Center of mass energy per nucleon
143    * 
144    * @return String representation of the center of mass energy per nuclean
145    */
146   static const char* CenterOfMassEnergyString(UShort_t cms);
147   //__________________________________________________________________
148   /** 
149    * Parse the magnetic field (in kG) as given by a floating point number
150    * 
151    * @param field  Magnetic field in kG 
152    * 
153    * @return Short integer value of magnetic field in kG 
154    */
155   static Short_t ParseMagneticField(Float_t field);
156   /** 
157    * Get the radius of a strip. 
158    * 
159    * @param ring  Ring identifier 'I' or 'O'
160    * @param strip Strip number 
161    * 
162    * @return Radial distance from beam of the strip 
163    */
164   static Double_t GetStripR(Char_t ring, UShort_t strip);
165   /** 
166    * Get eta from strip
167    * 
168    * @param det, ring, sec, strip, zvtx
169    * 
170    * @return eta
171    */
172   static Double_t GetEtaFromStrip(UShort_t det, Char_t ring, 
173                                   UShort_t sec, UShort_t strip, Double_t zvtx);
174   /** 
175    * Get the azimuthal angle of a strip
176    * 
177    * @param ring  Ring identifier 'I' or 'O'
178    * @param strip Strip number 
179    * @param phi   Straight forward strip phi
180    * @param xvtx  Ip X coordinate 
181    * @param yvtx  Ip Y coordinate 
182    * 
183    * @return The phi angle correctef for (X,Y) off set. 
184    */  
185   static Double_t GetPhiFromStrip(Char_t ring, UShort_t strip, 
186                                   Double_t phi, Double_t xvtx, Double_t yvtx);
187   /** 
188    * Get a string representation of the magnetic field
189    * 
190    * @param field Magnetic field in kG
191    * 
192    * @return String representation of the magnetic field
193    */
194    static const char* MagneticFieldString(Short_t field);
195   /* @} */
196
197   //__________________________________________________________________
198   /** 
199    * Get the AOD event - either from the input (AOD analysis) or the
200    * output (ESD analysis)
201    * 
202    * @param task Task to do the investigation for
203    * 
204    * @return Found AOD event or null
205    */
206   static AliAODEvent* GetAODEvent(AliAnalysisTaskSE* task);
207   /** 
208    * Check if we have something that will provide and AOD event 
209    * 
210    * @return 0 if there's nothing that provide an AOD event, 1 if it
211    * is provided on the input (AOD analysis) or 2 if it is provided on
212    * the output (ESD analysis)
213    */
214   static UShort_t CheckForAOD();
215   /** 
216    * Check if we have a particular (kind) of task in our train
217    * 
218    * @param clsOrName  Class name or name of task 
219    * @param cls If true, look for a task of a particular class -
220    * otherwise search for a speficially name task
221    * 
222    * @return true if the needed task was found 
223    */
224   static Bool_t CheckForTask(const char* clsOrName, Bool_t cls=true);
225
226   //__________________________________________________________________
227   /** 
228    * @{ 
229    * @name Member functions to store and retrieve analysis parameters 
230    */
231   static TObject* MakeParameter(const char* name, UShort_t value);
232   static TObject* MakeParameter(const char* name, Int_t value);
233   static TObject* MakeParameter(const char* name, Double_t value);
234   static TObject* MakeParameter(const char* name, Bool_t value);
235   static void GetParameter(TObject* o, UShort_t& value);
236   static void GetParameter(TObject* o, Int_t& value);
237   static void GetParameter(TObject* o, Double_t& value);
238   static void GetParameter(TObject* o, Bool_t& value);
239   /* @} */
240
241   /** 
242    * @{ 
243    * @name Energy stragling functions 
244    */
245   //__________________________________________________________________
246   /**
247    * Number of steps to do in the Landau, Gaussiam convolution 
248    */
249   static Int_t fgConvolutionSteps; // Number of convolution steps
250   //------------------------------------------------------------------
251   /** 
252    * How many sigma's of the Gaussian in the Landau, Gaussian
253    * convolution to integrate over
254    */
255   static Double_t fgConvolutionNSigma; // Number of convolution sigmas 
256   //------------------------------------------------------------------
257   /** 
258    * Calculate the shifted Landau
259    * @f[
260    *    f'_{L}(x;\Delta,\xi) = f_L(x;\Delta+0.22278298\xi)
261    * @f]
262    *
263    * where @f$ f_{L}@f$ is the ROOT implementation of the Landau
264    * distribution (known to have @f$ \Delta_{p}=-0.22278298@f$ for
265    * @f$\Delta=0,\xi=1@f$. 
266    *
267    * @param x      Where to evaluate @f$ f'_{L}@f$ 
268    * @param delta  Most probable value 
269    * @param xi     The 'width' of the distribution 
270    *
271    * @return @f$ f'_{L}(x;\Delta,\xi) @f$
272    */
273   static Double_t Landau(Double_t x, Double_t delta, Double_t xi);
274   
275   //------------------------------------------------------------------
276   /** 
277    * Calculate the value of a Landau convolved with a Gaussian 
278    * 
279    * @f[ 
280    * f(x;\Delta,\xi,\sigma') = \frac{1}{\sigma' \sqrt{2 \pi}}
281    *    \int_{-\infty}^{+\infty} d\Delta' f'_{L}(x;\Delta',\xi)
282    *    \exp{-\frac{(\Delta-\Delta')^2}{2\sigma'^2}}
283    * @f]
284    * 
285    * where @f$ f'_{L}@f$ is the Landau distribution, @f$ \Delta@f$ the
286    * energy loss, @f$ \xi@f$ the width of the Landau, and 
287    * @f$ \sigma'^2=\sigma^2-\sigma_n^2 @f$.  Here, @f$\sigma@f$ is the
288    * variance of the Gaussian, and @f$\sigma_n@f$ is a parameter modelling 
289    * noise in the detector.  
290    *
291    * Note that this function uses the constants fgConvolutionSteps and
292    * fgConvolutionNSigma
293    * 
294    * References: 
295    *  - <a href="http://dx.doi.org/10.1016/0168-583X(84)90472-5">Nucl.Instrum.Meth.B1:16</a>
296    *  - <a href="http://dx.doi.org/10.1103/PhysRevA.28.615">Phys.Rev.A28:615</a>
297    *  - <a href="http://root.cern.ch/root/htmldoc/tutorials/fit/langaus.C.html">ROOT implementation</a>
298    * 
299    * @param x         where to evaluate @f$ f@f$
300    * @param delta     @f$ \Delta@f$ of @f$ f(x;\Delta,\xi,\sigma')@f$
301    * @param xi        @f$ \xi@f$ of @f$ f(x;\Delta,\xi,\sigma')@f$
302    * @param sigma     @f$ \sigma@f$ of @f$\sigma'^2=\sigma^2-\sigma_n^2 @f$
303    * @param sigma_n   @f$ \sigma_n@f$ of @f$\sigma'^2=\sigma^2-\sigma_n^2 @f$
304    * 
305    * @return @f$ f@f$ evaluated at @f$ x@f$.  
306    */
307   static Double_t LandauGaus(Double_t x, Double_t delta, Double_t xi, 
308                              Double_t sigma, Double_t sigma_n);
309
310   //------------------------------------------------------------------
311   /** 
312    * Evaluate 
313    * @f[ 
314    *    f_i(x;\Delta,\xi,\sigma') = f(x;\Delta_i,\xi_i,\sigma_i')
315    * @f] 
316    * corresponding to @f$ i@f$ particles i.e., with the substitutions 
317    * @f{eqnarray*}{ 
318    *    \Delta    \rightarrow \Delta_i    &=& i(\Delta + \xi\log(i))\\
319    *    \xi       \rightarrow \xi_i       &=& i \xi\\
320    *    \sigma    \rightarrow \sigma_i    &=& \sqrt{i}\sigma\\
321    *    \sigma'^2 \rightarrow \sigma_i'^2 &=& \sigma_n^2 + \sigma_i^2
322    * @f} 
323    * 
324    * @param x        Where to evaluate 
325    * @param delta    @f$ \Delta@f$ 
326    * @param xi       @f$ \xi@f$ 
327    * @param sigma    @f$ \sigma@f$ 
328    * @param sigma_n  @f$ \sigma_n@f$
329    * @param i        @f$ i @f$
330    * 
331    * @return @f$ f_i @f$ evaluated
332    */  
333   static Double_t ILandauGaus(Double_t x, Double_t delta, Double_t xi, 
334                               Double_t sigma, Double_t sigma_n, Int_t i);
335
336   //------------------------------------------------------------------
337   /** 
338    * Numerically evaluate 
339    * @f[ 
340    *    \left.\frac{\partial f_i}{\partial p_i}\right|_{x}
341    * @f] 
342    * where @f$ p_i@f$ is the @f$ i^{\mbox{th}}@f$ parameter.  The mapping 
343    * of the parameters is given by 
344    *
345    * - 0: @f$\Delta@f$ 
346    * - 1: @f$\xi@f$ 
347    * - 2: @f$\sigma@f$ 
348    * - 3: @f$\sigma_n@f$ 
349    *
350    * This is the partial derivative with respect to the parameter of
351    * the response function corresponding to @f$ i@f$ particles i.e.,
352    * with the substitutions
353    * @f[ 
354    *    \Delta    \rightarrow \Delta_i    = i(\Delta + \xi\log(i))\\
355    *    \xi       \rightarrow \xi_i       = i \xi\\
356    *    \sigma    \rightarrow \sigma_i    = \sqrt{i}\sigma\\
357    *    \sigma'^2 \rightarrow \sigma_i'^2 = \sigma_n^2 + \sigma_i^2
358    * @f] 
359    * 
360    * @param x        Where to evaluate 
361    * @param ipar     Parameter number 
362    * @param dp       @f$ \epsilon\delta p_i@f$ for some value of @f$\epsilon@f$
363    * @param delta    @f$ \Delta@f$ 
364    * @param xi       @f$ \xi@f$ 
365    * @param sigma    @f$ \sigma@f$ 
366    * @param sigma_n  @f$ \sigma_n@f$
367    * @param i        @f$ i@f$
368    * 
369    * @return @f$ f_i@f$ evaluated
370    */  
371   static Double_t IdLandauGausdPar(Double_t x, UShort_t ipar, Double_t dp,
372                                    Double_t delta, Double_t xi, 
373                                    Double_t sigma, Double_t sigma_n, Int_t i);
374
375   //------------------------------------------------------------------
376   /** 
377    * Evaluate 
378    * @f[ 
379    *   f_N(x;\Delta,\xi,\sigma') = \sum_{i=1}^N a_i f_i(x;\Delta,\xi,\sigma'a)
380    * @f] 
381    * 
382    * where @f$ f(x;\Delta,\xi,\sigma')@f$ is the convolution of a
383    * Landau with a Gaussian (see LandauGaus).  Note that 
384    * @f$ a_1 = 1@f$, @f$\Delta_i = i(\Delta_1 + \xi\log(i))@f$, 
385    * @f$\xi_i=i\xi_1@f$, and @f$\sigma_i'^2 = \sigma_n^2 + i\sigma_1^2@f$. 
386    *  
387    * References: 
388    *  - <a href="http://dx.doi.org/10.1016/0168-583X(84)90472-5">Nucl.Instrum.Meth.B1:16</a>
389    *  - <a href="http://dx.doi.org/10.1103/PhysRevA.28.615">Phys.Rev.A28:615</a>
390    *  - <a href="http://root.cern.ch/root/htmldoc/tutorials/fit/langaus.C.html">ROOT implementation</a>
391    * 
392    * @param x        Where to evaluate @f$ f_N@f$
393    * @param delta    @f$ \Delta_1@f$ 
394    * @param xi       @f$ \xi_1@f$
395    * @param sigma    @f$ \sigma_1@f$ 
396    * @param sigma_n  @f$ \sigma_n@f$ 
397    * @param n        @f$ N@f$ in the sum above.
398    * @param a        Array of size @f$ N-1@f$ of the weights @f$ a_i@f$ for 
399    *                 @f$ i > 1@f$ 
400    * 
401    * @return @f$ f_N(x;\Delta,\xi,\sigma')@f$ 
402    */
403   static Double_t NLandauGaus(Double_t x, Double_t delta, Double_t xi, 
404                               Double_t sigma, Double_t sigma_n, Int_t n, 
405                               const Double_t* a);
406   /** 
407    * Generate a TF1 object of @f$ f_I@f$ 
408    * 
409    * @param c        Constant
410    * @param delta    @f$ \Delta@f$ 
411    * @param xi       @f$ \xi_1@f$              
412    * @param sigma    @f$ \sigma_1@f$           
413    * @param sigma_n  @f$ \sigma_n@f$           
414    * @param i        @f$ i@f$ - the number of particles
415    * @param xmin     Least value of range
416    * @param xmax     Largest value of range
417    * 
418    * @return Newly allocated TF1 object
419    */
420   static TF1* MakeILandauGaus(Double_t c, 
421                               Double_t delta, Double_t xi, 
422                               Double_t sigma, Double_t sigma_n,
423                               Int_t    i, 
424                               Double_t xmin,  Double_t  xmax);
425   /** 
426    * Generate a TF1 object of @f$ f_N@f$ 
427    * 
428    * @param c         Constant                         
429    * @param delta     @f$ \Delta@f$                    
430    * @param xi        @f$ \xi_1@f$                     
431    * @param sigma     @f$ \sigma_1@f$                  
432    * @param sigma_n   @f$ \sigma_n@f$                  
433    * @param n         @f$ N@f$ - how many particles to sum to
434    * @param a         Array of size @f$ N-1@f$ of the weights @f$ a_i@f$ for 
435    *                  @f$ i > 1@f$ 
436    * @param xmin      Least value of range  
437    * @param xmax      Largest value of range
438    * 
439    * @return Newly allocated TF1 object
440    */
441   static TF1* MakeNLandauGaus(Double_t c, 
442                               Double_t delta, Double_t  xi, 
443                               Double_t sigma, Double_t  sigma_n,
444                               Int_t    n,     const Double_t* a, 
445                               Double_t xmin,  Double_t  xmax);
446                                                     
447   //__________________________________________________________________
448   /** 
449    * Structure to do fits to the energy loss spectrum 
450    * 
451    * @ingroup pwglf_forward 
452    */
453   struct ELossFitter 
454   {
455     enum { 
456       kC     = 0,
457       kDelta, 
458       kXi, 
459       kSigma, 
460       kSigmaN, 
461       kN, 
462       kA
463     };
464     /** 
465      * Constructor 
466      * 
467      * @param lowCut     Lower cut of spectrum - data below this cuts is ignored
468      * @param maxRange   Maximum range to fit to 
469      * @param minusBins  The number of bins below maximum to use 
470      */
471     ELossFitter(Double_t lowCut, Double_t maxRange, UShort_t minusBins); 
472     /** 
473      * Destructor
474      * 
475      */
476     virtual ~ELossFitter();
477     /** 
478      * Clear internal arrays 
479      * 
480      */
481     void Clear();
482     /** 
483      * Fit a 1-particle signal to the passed energy loss distribution 
484      * 
485      * Note that this function clears the internal arrays first 
486      *
487      * @param dist    Data to fit the function to 
488      * @param sigman If larger than zero, the initial guess of the
489      *               detector induced noise. If zero or less, then this 
490      *               parameter is ignored in the fit (fixed at 0)
491      * 
492      * @return The function fitted to the data 
493      */
494     TF1* Fit1Particle(TH1* dist, Double_t sigman=-1);
495     /** 
496      * Fit a N-particle signal to the passed energy loss distribution 
497      *
498      * If there's no 1-particle fit present, it does that first 
499      *
500      * @param dist   Data to fit the function to 
501      * @param n      Number of particle signals to fit 
502      * @param sigman If larger than zero, the initial guess of the
503      *               detector induced noise. If zero or less, then this 
504      *               parameter is ignored in the fit (fixed at 0)
505      * 
506      * @return The function fitted to the data 
507      */
508     TF1* FitNParticle(TH1* dist, UShort_t n, Double_t sigman=-1);
509     /**
510      * Get Lower cut on data 
511      *
512      * @return Lower cut on data 
513      */
514     Double_t GetLowCut() const { return fLowCut; }
515     /**
516      * Get Maximum range to fit 
517      *
518      * @return Maximum range to fit 
519      */
520     Double_t GetMaxRange() const { return fMaxRange; }
521     /**
522      * Get Number of bins from maximum to fit 1st peak
523      *
524      * @return Number of bins from maximum to fit 1st peak
525      */
526     UShort_t GetMinusBins() const { return fMinusBins; }
527     /**
528      * Get Array of fit results 
529      *
530      * @return Array of fit results 
531      */
532     const TObjArray& GetFitResults() const { return fFitResults; }
533     /** 
534      * Get Array of fit results  
535      *
536      * @return Array of fit results 
537      */
538     TObjArray& GetFitResults() { return fFitResults; }
539     /**
540      * Get Array of functions 
541      *
542      * @return Array of functions 
543      */
544     const TObjArray& GetFunctions() const { return fFunctions; }
545     /** 
546      * Get Array of functions  
547      *
548      * @return Array of functions 
549      */
550     TObjArray& GetFunctions() { return fFunctions; }
551   private:
552     const Double_t fLowCut;     // Lower cut on data 
553     const Double_t fMaxRange;   // Maximum range to fit 
554     const UShort_t fMinusBins;  // Number of bins from maximum to fit 1st peak
555     TObjArray fFitResults;      // Array of fit results 
556     TObjArray fFunctions;       // Array of functions 
557   };
558   /* @} */
559       
560
561   //==================================================================
562   /** 
563    * @{
564    * @name Convenience containers 
565    */
566   /** 
567    * Structure to hold histograms 
568    *
569    * @ingroup pwglf_forward 
570    */
571   struct Histos : public TObject
572   {     
573     /** 
574      * Constructor 
575      * 
576      * 
577      */
578     Histos() : fFMD1i(0), fFMD2i(0), fFMD2o(0), fFMD3i(0), fFMD3o(0) {}
579     /** 
580      * Copy constructor 
581      * 
582      * @param o Object to copy from 
583      */
584     Histos(const Histos& o) 
585       : TObject(o), 
586         fFMD1i(o.fFMD1i), 
587         fFMD2i(o.fFMD2i), 
588         fFMD2o(o.fFMD2o), 
589         fFMD3i(o.fFMD3i), 
590         fFMD3o(o.fFMD3o)
591     {}
592     /** 
593      * Assignement operator 
594      * 
595      * @return Reference to this 
596      */
597     Histos& operator=(const Histos&) { return *this;}
598     /** 
599      * Destructor.  This does not delete the interally allocated
600      * memory.  Use the member function Delete for that.
601      */
602     ~Histos();
603     /** 
604      * Clear internal memory.  Note, if the internal histograms are
605      * added to an output container, then we must not free this
606      * memory.
607      */
608     void Delete(Option_t* opt="");
609     /** 
610      * Initialize the object 
611      * 
612      * @param etaAxis Eta axis to use 
613      */
614     void Init(const TAxis& etaAxis);
615     /** 
616      * Make a histogram 
617      * 
618      * @param d        Detector
619      * @param r        Ring 
620      * @param etaAxis  Eta axis to use
621      * 
622      * @return Newly allocated histogram 
623      */
624     TH2D* Make(UShort_t d, Char_t r, const TAxis& etaAxis) const;
625     /** 
626      * Clear data 
627      * 
628      * @param option Not used 
629      */
630     void  Clear(Option_t* option="");
631     // const TH2D* Get(UShort_t d, Char_t r) const;
632     /** 
633      * Get the histogram for a particular detector,ring
634      * 
635      * @param d Detector 
636      * @param r Ring 
637      * 
638      * @return Histogram for detector,ring or nul 
639      */
640     TH2D* Get(UShort_t d, Char_t r) const;
641     TH2D* fFMD1i; // Histogram for FMD1i
642     TH2D* fFMD2i; // Histogram for FMD2i
643     TH2D* fFMD2o; // Histogram for FMD2o
644     TH2D* fFMD3i; // Histogram for FMD3i
645     TH2D* fFMD3o; // Histogram for FMD3o
646
647     ClassDef(Histos,2) 
648   };
649
650   //__________________________________________________________________
651   /**
652    * Base class for structure holding ring specific histograms
653    * 
654    * @ingroup pwglf_forward 
655    */
656   struct RingHistos : public TObject
657   {
658     /** 
659      * Constructor
660      * 
661      */
662     RingHistos() : fDet(0), fRing('\0'), fName("") {}
663     /** 
664      * 
665      * 
666      * @param d Detector
667      * @param r Ring 
668      */
669     RingHistos(UShort_t d, Char_t r) 
670       : fDet(d), fRing(r), fName(TString::Format("FMD%d%c", d, r)) 
671     {}
672     /** 
673      * Copy constructor
674      * 
675      * @param o Object to copy from 
676      */
677     RingHistos(const RingHistos& o) 
678       : TObject(o), fDet(o.fDet), fRing(o.fRing), fName(o.fName)
679     {}
680     /** 
681      * 
682      */
683     virtual ~RingHistos() {}
684     /** 
685      * Assignement operator
686      * 
687      * @param o Object to assign from
688      * 
689      * @return Reference to this
690      */
691     RingHistos& operator=(const RingHistos& o) 
692     {
693       if (&o == this) return *this;
694       TObject::operator=(o);
695       fDet  = o.fDet;
696       fRing = o.fRing;
697       fName = o.fName;
698       return *this;
699     }
700     /** 
701      * Define the outout list in @a d
702      * 
703      * @param d Where to put the output list
704      * 
705      * @return Newly allocated TList object or null
706      */
707     TList* DefineOutputList(TList* d) const;
708     /** 
709      * Get our output list from the container @a d
710      * 
711      * @param d where to get the output list from 
712      * 
713      * @return The found TList or null
714      */
715     TList* GetOutputList(const TList* d) const;
716     /** 
717      * Find a specific histogram in the source list @a d
718      * 
719      * @param d     (top)-container 
720      * @param name  Name of histogram
721      * 
722      * @return Found histogram or null
723      */
724     TH1* GetOutputHist(const TList* d, const char* name) const;
725     /** 
726      * 
727      * 
728      * 
729      * @return 
730      */
731     Color_t Color() const 
732     { 
733       return AliForwardUtil::RingColor(fDet, fRing);
734     }
735     /** 
736      * The name of this ring 
737      * 
738      * @return Name of this ring 
739      */
740     const char* GetName() const { return fName.Data(); } 
741     UShort_t fDet;   // Detector
742     Char_t   fRing;  // Ring
743     TString  fName;  // Name
744
745     ClassDef(RingHistos,1) 
746   };
747   /* @} */
748
749   //__________________________________________________________________
750   /**
751    * A guard idom for producing debug output 
752    * 
753    */
754   struct DebugGuard 
755   {
756     /** 
757      * Constructor 
758      * 
759      * @param lvl       Current level
760      * @param msgLvl    Target level 
761      * @param format    @c printf -like format
762      * 
763      * @return 
764      */
765     DebugGuard(Int_t lvl, Int_t msgLvl, const char* format, ...);
766     /** 
767      * Destructor
768      */
769     ~DebugGuard();
770     /** 
771      * Make a message 
772      * 
773      * @param lvl    Current level
774      * @param msgLvl Target level 
775      * @param format @c printf -like format
776      */
777     static void Message(Int_t lvl, Int_t msgLvl, const char* format, ...);
778   private:
779     /** 
780      * Output the message 
781      * 
782      * @param in    Direction
783      * @param msg   Message 
784      */
785     static void Output(int in, TString& msg);
786     /** 
787      * Format a message 
788      * 
789      * @param out     Output is stored here
790      * @param format  @c printf -like format
791      * @param ap      List of arguments
792      */
793     static void Format(TString& out, const char* format, va_list ap);
794     TString fMsg;
795   };
796 private:
797   /** 
798    * Constructor 
799    */
800   AliForwardUtil() {}
801   /** 
802    * Copy constructor 
803    * 
804    * @param o Object to copy from 
805    */
806   AliForwardUtil(const AliForwardUtil& o) : TObject(o) {}
807   /** 
808    * Assingment operator 
809    * 
810    * 
811    * @return Reference to this object 
812    */
813   AliForwardUtil& operator=(const AliForwardUtil&) { return *this; }
814   /** 
815    * Destructor
816    */
817   ~AliForwardUtil() {}
818   
819
820   ClassDef(AliForwardUtil,1) // Utilities - do not make object
821 };
822
823 // #ifdef LOG_NO_DEBUG
824 // # define DGUARD(L,N,F,...) do {} while(false) 
825 // #else
826 /** 
827  * Macro to declare a DebugGuard
828  * 
829  * @param L Current debug level
830  * @param N Target debug level
831  * @param F @c printf -like Format 
832  */
833 # define DGUARD(L,N,F,...)                                      \
834   AliForwardUtil::DebugGuard _GUARD(L,N,F, ## __VA_ARGS__)
835 /** 
836  * Macro to make a debug message, using DebugGuard::Message
837  * 
838  * @param L Current debug level
839  * @param N Target debug level
840  * @param F @c printf -like Format 
841  */
842 # define DMSG(L,N,F,...)                                        \
843   AliForwardUtil::DebugGuard::Message(L,N,F, ## __VA_ARGS__)
844 // #endif
845 #endif
846 // Local Variables:
847 //  mode: C++
848 // End:
849