LCOV - code coverage report
Current view: top level - FMD/FMDrec - AliFMDEncodedEdx.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 23 31 74.2 %
Date: 2016-06-14 17:26:59 Functions: 7 7 100.0 %

          Line data    Source code
       1             : #ifndef ALIFMDENCODEDEDX_H
       2             : #define ALIFMDENCODEDEDX_H
       3             : /**
       4             :  * @file   AliFMDEncodedEdx.C
       5             :  * @author Christian Holm Christensen <cholm@nbi.dk>
       6             :  * @date   Thu Oct 10 11:50:59 2013
       7             :  * 
       8             :  * @brief  Class to encode the energy loss @f$d\Delta@f$ and path length
       9             :  * @f$dx@f$ of a particle into track reference bits.
      10             :  */
      11             : #ifndef __CINT__
      12             : # include <TMath.h>
      13             : # include <TArrayD.h>
      14             : # include <TH1D.h>
      15             : # include <TH2D.h>
      16             : #else
      17             : class TArrayD;
      18             : class TH1;
      19             : class TH2;
      20             : #endif
      21             : 
      22             : /**
      23             :  * Class to encode the energy loss @f$d\Delta@f$ and path length
      24             :  * @f$dx@f$ of a particle into track reference bits.  A total of 13
      25             :  * bits are available.  Of these 8 are used for @f$d\Delta@f$ and 5
      26             :  * for @f$dx@f$.
      27             :  *
      28             :  * The encoding is done by binning.  That is, for a given value of
      29             :  * @f$d\Delta@f$ or @f$dx@f$ we calculate a bin number and store that.
      30             :  * The reverse decoding is done by looking up the bin center of the
      31             :  * bin number stored.  Note, that the bin numbers go from 0 to 255
      32             :  * (for @f$d\Delta@f$) and 31 (for @f$dx@f$).
      33             :  *
      34             :  * The bins become progressively wider.  That is, we define 3 regions. 
      35             :  * 
      36             :  * - Lower region which spans the lower 10% of the distribution has
      37             :  *   75% of all avaible bins.
      38             :  * - Middle region which spans from the 10% to 20% of the distribtion
      39             :  *    and has 20% of the available bins.
      40             :  * - Upper region which covers the rest of the distribtion in 5% of
      41             :  *   the available bins
      42             :  *
      43             :  *  | Type          | N bins | Range | bin | value | bin | value |
      44             :  *  | ------------- | ------ | ----- | --- | ----- | --- | ----- |
      45             :  *  | @f$d\Delta@f$ |  256   | 0-11  | 192 |  1.1  | 243 |  2.2  |
      46             :  *  | @f$dx@f$      |   32   | 0-0.7 |  24 |  0.07 |  30 |  1.4  |
      47             :  *      
      48             :  * Currently there's no support of other schemas 
      49             :  * 
      50             :  * 
      51             :  */
      52             : class AliFMDEncodedEdx
      53             : {
      54             : public:
      55             :   /**
      56             :    * Specification of the bins 
      57             :    * 
      58             :    */
      59             :   struct Spec {
      60             :     UShort_t nBins;     // Total number of bins
      61             :     Double_t min;       // Least value 
      62             :     Double_t max;       // Largest value 
      63             :     UShort_t cutBin1;   // Last bin (plus one) of lower region
      64             :     Double_t cutVal1;   // Upper cut on lower region
      65             :     UShort_t cutBin2;   // Last bin (plus one) of middle region
      66             :     Double_t cutVal2;   // Upper cut on middle region         
      67             :     /** 
      68             :      * Constructor 
      69             :      * 
      70             :      * @param nb Total number of bins 
      71             :      * @param l  Lower value 
      72             :      * @param h  Upper value 
      73             :      */
      74             :     Spec(UShort_t nb, Double_t l, Double_t h)
      75           4 :       : nBins(nb), min(l), max(h), 
      76           2 :         cutBin1(UShort_t(nb * 0.75 + .5)), 
      77           2 :         cutVal1((max-min) / 10 + min),
      78           2 :         cutBin2(UShort_t(nb * 0.95 + .5)),
      79           2 :         cutVal2((max-min) / 5  + min)
      80           6 :     {}
      81             :     /** 
      82             :      * Encode a value 
      83             :      * 
      84             :      * @param v Value to encode 
      85             :      * 
      86             :      * @return Encoded (bin number) value 
      87             :      */
      88             :     UInt_t Encode(Double_t v) const
      89             :     {
      90             :       UInt_t   off  = 0;
      91         440 :       UInt_t   n    = cutBin1;
      92         220 :       Double_t low  = min;
      93         220 :       Double_t high = cutVal1;
      94         220 :       if (v > cutVal2) { 
      95             :         // Upper part of the plot
      96           0 :         off  = cutBin2;
      97           0 :         n    = nBins - cutBin2;
      98             :         low  = cutVal2;
      99           0 :         high = max;
     100           0 :       }
     101         220 :       else if (v > cutVal1) {
     102             :         // Middle part 
     103             :         off  = cutBin1;
     104           0 :         n    = cutBin2 - cutBin1;
     105             :         low  = cutVal1;
     106             :         high = cutVal2;
     107           0 :       }
     108         220 :       return off + UInt_t(n*(v-low)/(high-low));
     109             :     }
     110             :     /** 
     111             :      * Decode a bin into a value 
     112             :      * 
     113             :      * @param b Encoded (bin number) value 
     114             :      * @param w On return, the width of the bin
     115             :      * 
     116             :      * @return Decoded value (center of bin)
     117             :      */
     118             :     Double_t Decode(UInt_t b, Double_t& w) const
     119             :     {
     120             :       Double_t off  = min;
     121             :       UInt_t   n    = cutBin1;
     122             :       Double_t high = cutVal1;
     123             :       if (b >= cutBin2) {
     124             :         // Upper part
     125             :         off  = cutVal2;
     126             :         n    = nBins - cutBin2;
     127             :         high = max;
     128             :         b    -= cutBin2;
     129             :       }
     130             :       else if (b >= cutBin1) {
     131             :         // Middle part
     132             :         off  = cutVal1;
     133             :         n    = cutBin2 - cutBin1;
     134             :         high = cutVal2;
     135             :         b    -= cutBin1;
     136             :       }
     137             :       w = (high-off)/n;
     138             :       return off + w * (b+.5);
     139             :     }
     140             :     /** 
     141             :      * Decode a bin into a value 
     142             :      * 
     143             :      * @param b Encoded (bin number) value 
     144             :      * 
     145             :      * @return Decoded value (center of bin)
     146             :      */
     147             :     Double_t Decode(UInt_t b) const 
     148             :     {
     149             :       Double_t w;
     150             :       return Decode(b, w);
     151             :     }
     152             :     /** 
     153             :      * Fill an array with values appropriate for defining a histogram 
     154             :      * axis with the _natural_ binning of the encoding 
     155             :      * 
     156             :      * @param a On return, the modified bin-border array 
     157             :      */
     158             :     void FillBinArray(TArrayD& a) const
     159             :     {
     160             :       a.Set(nBins+1);
     161             :       a[0] = min;
     162             :       Double_t w0 = (cutVal1 - min)     / cutBin1;
     163             :       Double_t w1 = (cutVal2 - cutVal1) / (cutBin2 - cutBin1);
     164             :       Double_t w2 = (max     - cutVal2) / (nBins   - cutBin2);
     165             :       for (UInt_t i = 1;         i <= cutBin1; i++) a[i] = a[i-1] + w0;
     166             :       for (UInt_t i = cutBin1+1; i <= cutBin2; i++) a[i] = a[i-1] + w1;
     167             :       for (UInt_t i = cutBin2+1; i <= nBins;   i++) a[i] = a[i-1] + w2;
     168             :     }
     169             :     /** 
     170             :      * Print information.
     171             :      * 
     172             :      * @param opt If this starts with `T' also run a test 
     173             :      */
     174             :     void Print(Option_t* opt="") const 
     175             :     {
     176             :       Printf("Spec: [%8.4f,%8.4f] in %3d bins, cuts %8.4f (%3d) %8.4f (%3d)",
     177             :              min, max, nBins, cutVal1, cutBin1, cutVal2, cutBin2);
     178             :       if (opt[0] == 'T' || opt[0] == 't') {
     179             :         for (Int_t i = 0; i < nBins; i++) { 
     180             :           Double_t w = 0;
     181             :           Double_t x = Decode(i,w );
     182             :           UInt_t   j = Encode(x);
     183             :           Printf("%3d -> %8.4f (%7.4f) -> %3d", i, x, w, j);
     184             :         }
     185             :       }
     186             :     }
     187             :     /** 
     188             :      * Run a test 
     189             :      * 
     190             :      */
     191             :     static void Test() 
     192             :     {
     193             :       Spec s(125, 0, 125);
     194             :       s.Print("T");
     195             :     }
     196             :   };
     197             :   /**
     198             :    * How the 13 bits are distributed 
     199             :    */
     200             :   enum { 
     201             :     kNEBits = 8, 
     202             :     kNLBits = 5,
     203             :     kEMask  = 0xFF, // (1 << kNEBits) - 1
     204             :     kLMask  = 0x1F  // (1 << kNLBits) - 1
     205             :   };
     206             :   /** 
     207             :    * Constructor - a no-op
     208             :    */
     209             :   AliFMDEncodedEdx() {}
     210             :   /** 
     211             :    * Destructor - a no-op 
     212             :    */
     213             :   virtual ~AliFMDEncodedEdx() {}
     214             :   /** 
     215             :    * Get the @f$d\Delta@f$ bin specification. If not initialized
     216             :    * already, do so .
     217             :    * 
     218             :    * @return Constant reference to @f$d\Delta@f$ bin specification
     219             :    */
     220             :   static const Spec& GetdEAxis() 
     221             :   { 
     222             :     static Spec* dEAxis = 0;
     223         222 :     if (!dEAxis) dEAxis = new Spec((1<<kNEBits), 0 /*0.0000025*/, 11);
     224         110 :     return *dEAxis;
     225           0 :   }
     226             :   /** 
     227             :    * Get the @f$dx@f$ bin specification. If not initialized
     228             :    * already, do so .
     229             :    * 
     230             :    * @return Constant reference to @f$dx@f$ bin specification
     231             :    */
     232             :   static const Spec& GetdLAxis() 
     233             :   { 
     234             :     static Spec* dLAxis = 0;
     235         222 :     if (!dLAxis) dLAxis = new Spec((1<<kNLBits), 0 /*0.00014*/,   0.7);
     236         110 :     return *dLAxis;
     237           0 :   }
     238             :   /** 
     239             :    * Encode @f$d\Delta@f$ and @f$dx@f$ into a 13bit number.  
     240             :    * 
     241             :    * @param edep   @f$d\Delta@f$
     242             :    * @param length @f$dx@f$ 
     243             :    * 
     244             :    * @return 13-bit (lower) encoded value 
     245             :    */
     246             :   static UInt_t Encode(Double_t edep, Double_t length)
     247             :   {
     248         220 :     UInt_t uE = EncodeOne(edep,   GetdEAxis());
     249         110 :     UInt_t uL = EncodeOne(length, GetdLAxis());
     250         110 :     return (((uE & kEMask) << 0) | ((uL & kLMask) << kNEBits));
     251             :   }
     252             :   /** 
     253             :    * Decode the lower 13-bit of the input into @f$d\Delta@f$ and @f$dx@f$ 
     254             :    * 
     255             :    * @param bits   Encoded 13-bit word (lower 13 bit)
     256             :    * @param edep   On return, the @f$d\Delta@f$
     257             :    * @param length On return, the @f$dx@f$ 
     258             :    */
     259             :   static void Decode(UInt_t bits, Double_t& edep, Double_t& length)
     260             :   {
     261             :     edep   = DecodeOne((bits >> 0)       & kEMask, GetdEAxis());
     262             :     length = DecodeOne((bits >> kNEBits) & kLMask, GetdLAxis());
     263             :   }
     264             :   /** 
     265             :    * Decode the lower 13-bit of the input into @f$d\Delta@f$ and @f$dx@f$ 
     266             :    * 
     267             :    * @param bits    Encoded 13-bit word (lower 13 bit)
     268             :    * @param edep    On return, the @f$d\Delta@f$
     269             :    * @param length  On return, the @f$dx@f$ 
     270             :    * @param wEdep   On return, the width of the corresponding @f$d\Delta@f$ bin
     271             :    * @param wLength On return, the width of the corresponding @f$dx@f$ bin
     272             :    */
     273             :   static void Decode(UInt_t bits, Double_t& edep, Double_t& length, 
     274             :                      Double_t& wEdep, Double_t& wLength)
     275             :   {
     276             :     edep   = DecodeOne((bits >> 0)       & kEMask, wEdep,   GetdEAxis());
     277             :     length = DecodeOne((bits >> kNEBits) & kLMask, wLength, GetdLAxis());
     278             :   }    
     279             :   /** 
     280             :    * Make a 1-dimension histogram with the natural binning for the
     281             :    * encoding for either @f$d\Delta@f$ or @f$dx@f$
     282             :    * 
     283             :    * @param name   Name of produced histogram
     284             :    * @param title  Title of produced histogram 
     285             :    * @param mode   If 0, make histogram for @f$d\Delta@f$. If 1
     286             :    * for @f$dx@f$, if 2 for @f$d\Delta/dx@f$
     287             :    * 
     288             :    * @return Newly allocated histogram
     289             :    */
     290             :   static TH1* Make1D(const char* name, const char* title, UShort_t mode=true)
     291             :   {
     292             :     const Spec& a = (mode==0 || mode==2 ? GetdEAxis() : GetdLAxis());
     293             :     TArrayD     aa; a.FillBinArray(aa);
     294             : 
     295             :     if (mode == 2) 
     296             :       // In case we need to do dE/dx, extend the range by a factor 100
     297             :       for (Int_t i = 0; i < aa.GetSize(); i++) aa[i] *= 100;
     298             : 
     299             :     // Make the histogram 
     300             :     TH1* h = new TH1D(name, title, aa.GetSize()-1, aa.GetArray());
     301             :     h->SetXTitle(mode == 0 ? "d#Delta [MeV]" : 
     302             :                  mode == 1 ? "dx [cm]" : 
     303             :                  mode == 2 ? "d#Delta/dx [MeV/cm]" : "?");
     304             :     h->SetFillStyle(3001);
     305             :     h->SetMarkerStyle(20);
     306             :     h->Sumw2();
     307             :     
     308             :     return h;
     309             :   }
     310             :   /** 
     311             :    * Make a 2-dimension histogram with the natural binning for the
     312             :    * encoding of @f$d\Delta@f$ versus @f$dx@f$ (or vice versa)
     313             :    * 
     314             :    * @param name   Name of produced histogram
     315             :    * @param title  Title of produced histogram 
     316             :    * @param xedep  If true, put @f$d\Delta@f$ on the X-axis, otherwise
     317             :    * for @f$dx@f$
     318             :    * 
     319             :    * @return Newly allocated histogram
     320             :    */
     321             :   static TH2* Make2D(const char* name, const char* title, Bool_t xedep=true)
     322             :   {
     323             :     const Spec& a1 = (xedep ? GetdEAxis() : GetdLAxis());
     324             :     const Spec& a2 = (xedep ? GetdLAxis() : GetdEAxis());
     325             :     TArrayD     aa1; a1.FillBinArray(aa1);
     326             :     TArrayD     aa2; a2.FillBinArray(aa2);
     327             :     TH2* h = new TH2D(name, title, 
     328             :                       aa1.GetSize()-1, aa1.GetArray(),
     329             :                       aa2.GetSize()-1, aa2.GetArray());
     330             :     h->SetXTitle(xedep ? "d#Delta [MeV]" : "dx [cm]");
     331             :     h->SetYTitle(xedep ? "dx [cm]"       : "d#Delta [MeV]");
     332             :     return h;
     333             :   }
     334             :   /** 
     335             :    * Check if the encoded @f$d\Delta@f$ and @f$dx@f$ are available in
     336             :    * the upper 13 bits of the unique ID field of track references.
     337             :    * 
     338             :    * @param alirootRev AliROOT revision of the code that _produced_
     339             :    * the track references.  Note, it cannot be the revision of AliROOT
     340             :    * running, since that can be much newer (or older) than the code
     341             :    * that made the track references.  One should get this information
     342             :    * from the object stored in the ESD tree's user objects.
     343             :    * 
     344             :    * @return true if @a alirootRev is larger than some fixed number
     345             :    * set when this class was committed to SVN.
     346             :    */
     347             :   static Bool_t IsAvailable(UInt_t alirootRev) 
     348             :   {
     349             :     const UInt_t target = 64491;
     350             :     return alirootRev >= target;
     351             :   }
     352             : private:
     353             :   /** 
     354             :    * Encode one value 
     355             :    * 
     356             :    * @param v  Value 
     357             :    * @param a  Bin specification
     358             :    * 
     359             :    * @return Encoded value 
     360             :    */
     361             :   static UInt_t EncodeOne(Double_t v, const Spec& a) 
     362             :   {
     363         440 :     if (v < a.min) return 0;
     364         220 :     if (v > a.max) return a.nBins;
     365         220 :     return a.Encode(v);
     366         220 :   }
     367             :   /** 
     368             :    * Decode a value 
     369             :    * 
     370             :    * @param b   Encoded value 
     371             :    * @param a   Bin specification
     372             :    * 
     373             :    * @return Decoded value 
     374             :    */  
     375             :   static Double_t DecodeOne(UInt_t b, const Spec& a) 
     376             :   {
     377             :     if (b >= a.nBins) b = a.nBins-1;
     378             :     return a.Decode(b);
     379             :   }
     380             :   /** 
     381             :    * Decode a value 
     382             :    * 
     383             :    * @param b   Encoded value 
     384             :    * @param a   Bin specification
     385             :    * @param w   On return, the bin width 
     386             :    *
     387             :    * @return Decoded value 
     388             :    */  
     389             :   static Double_t DecodeOne(UInt_t b, Double_t& w, const Spec& a) 
     390             :   {
     391             :     if (b >= a.nBins) b = a.nBins-1;
     392             :     return a.Decode(b, w);
     393             :   }
     394             : 
     395             :   ClassDef(AliFMDEncodedEdx,1); // En-/Decode dE/dx for/from track references
     396             : };
     397             : #endif
     398             : // Local Variables:
     399             : //  mode: C++
     400             : // End:

Generated by: LCOV version 1.11