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