Adding comment lines to class description needed for Root documentation,
[u/mrichter/AliRoot.git] / MUON / AliMUONDigitCalibrator.cxx
1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3 *                                                                        *
4 * Author: The ALICE Off-line Project.                                    *
5 * Contributors are mentioned in the code where appropriate.              *
6 *                                                                        *
7 * Permission to use, copy, modify and distribute this software and its   *
8 * documentation strictly for non-commercial purposes is hereby granted   *
9 * without fee, provided that the above copyright notice appears in all   *
10 * copies and that both the copyright notice and this permission notice   *
11 * appear in the supporting documentation. The authors make no claims     *
12 * about the suitability of this software for any purpose. It is          *
13 * provided "as is" without express or implied warranty.                  *
14 **************************************************************************/
15
16 // $Id$
17
18 #include "AliMUONDigitCalibrator.h"
19
20 #include "AliLog.h"
21 #include "AliMpConstants.h"
22 #include "AliMUONCalibrationData.h"
23 #include "AliMUONVDigit.h"
24 #include "AliMUONVDigitStore.h"
25 #include "AliMUONLogger.h"
26 #include "AliMUONPadStatusMaker.h"
27 #include "AliMUONPadStatusMapMaker.h"
28 #include "AliMUONVStore.h"
29 #include "AliMUONVCalibParam.h"
30
31 //-----------------------------------------------------------------------------
32 /// \class AliMUONDigitCalibrator
33 /// Class used to calibrate digits (either real or simulated ones).
34 ///
35 /// The calibration consists of subtracting the pedestal
36 /// and multiplying by a gain, so that
37 /// Signal = (ADC-pedestal)*gain
38 ///
39 /// Please note also that for the moment, if a digit lies on a dead channel
40 /// we remove this digit from the list of digits.
41 /// FIXME: this has to be revisited. By using the AliMUONDigit::fFlags we
42 /// should in principle flag a digit as bad w/o removing it, but this 
43 /// then requires some changes in the cluster finder to deal with this extra
44 /// information correctly (e.g. to set a quality for the cluster if it contains
45 /// bad digits).
46 ///
47 /// \author Laurent Aphecetche
48 //-----------------------------------------------------------------------------
49
50
51 /// \cond CLASSIMP
52 ClassImp(AliMUONDigitCalibrator)
53 /// \endcond
54
55 //_____________________________________________________________________________
56 AliMUONDigitCalibrator::AliMUONDigitCalibrator(const AliMUONCalibrationData& calib,
57                                                Bool_t createAndUseStatusMap)
58 : TObject(),
59 fCalibrationData(calib),
60 fStatusMap(0x0),
61 fLogger(new AliMUONLogger(1000))
62 {
63   /// ctor
64   if (createAndUseStatusMap) 
65   {
66     AliMUONPadStatusMaker maker(fCalibrationData);
67     
68     // this is here that we decide on our "goodness" policy, i.e.
69     // what do we call an invalid pad (a pad maybe bad because its HV
70     // was too low, or its pedestals too high, etc..)
71     // FIXME: find a way not to hard-code the goodness policy (i.e. the limits)
72     // here...
73     maker.SetHVSt12Limits(1300,1600);
74     maker.SetHVSt345Limits(1500,2000);
75     maker.SetPedMeanLimits(50,200);
76     maker.SetPedSigmaLimits(0.1,3);
77     
78     // From this set of limits, compute the status of all tracker pads.
79     AliMUONVStore* status = maker.MakeStatus();      
80     // we do not check that status is != 0x0, as this is supposed to be
81     // the responsability of the padStatusMaker.
82     
83     AliMUONPadStatusMapMaker mapMaker(fCalibrationData);
84     
85     Int_t mask(0x8080); 
86     //FIXME: kind of fake one for the moment, we consider dead only 
87     // if ped and/or hv value missing.
88     //WARNING : getting this mask wrong is a very effective way of getting
89     //no digits at all out of this class ;-)
90     
91     fStatusMap = mapMaker.MakePadStatusMap(*status,mask);
92     
93     delete status;
94     }
95   else
96   {
97     // make a fake (empty) status map
98     fStatusMap = AliMUONPadStatusMapMaker::MakeEmptyPadStatusMap();
99   }
100 }
101
102 //_____________________________________________________________________________
103 AliMUONDigitCalibrator::~AliMUONDigitCalibrator()
104 {
105   /// dtor.
106   delete fStatusMap;
107   
108   AliInfo("Summary of messages:");
109   fLogger->Print();
110
111   delete fLogger;
112 }
113
114 //_____________________________________________________________________________
115 void
116 AliMUONDigitCalibrator::Calibrate(AliMUONVDigitStore& digitStore)
117 {
118   /// Calibrate the digits contained in digitStore  
119   TIter next(digitStore.CreateTrackerIterator());
120   AliMUONVDigit* digit;
121   
122   while ( ( digit = static_cast<AliMUONVDigit*>(next() ) ) )
123   {
124     CalibrateDigit(*digit);
125   }
126 }
127
128 //_____________________________________________________________________________
129 void
130 AliMUONDigitCalibrator::CalibrateDigit(AliMUONVDigit& digit)
131 {
132   /// Calibrate one digit
133   
134   if ( digit.IsCalibrated() ) 
135   {
136     fLogger->Log("ERROR : trying to calibrate a digit twice");
137     return;
138   }
139   
140   AliMUONVCalibParam* deadmap = static_cast<AliMUONVCalibParam*>
141   (fStatusMap->FindObject(digit.DetElemId(),digit.ManuId()));
142   Int_t statusMap = deadmap->ValueAsInt(digit.ManuChannel());
143   digit.SetStatusMap(statusMap);
144   digit.Calibrated(kTRUE);
145   if ( ( statusMap & AliMUONPadStatusMapMaker::SelfDeadMask() ) != 0 ) 
146   {
147     // pad itself is bad (not testing its neighbours at this stage)
148     digit.SetCharge(0);
149     fLogger->Log(Form("%s:%d:Channel detElemId %d manuId %d "
150                     "manuChannel %d is bad %x",__FILE__,__LINE__,
151                     digit.DetElemId(),digit.ManuId(),
152                     digit.ManuChannel(),digit.StatusMap()));
153   }
154   else
155   {
156     // If the channel is good, go on with the calibration itself.
157
158     AliMUONVCalibParam* pedestal = static_cast<AliMUONVCalibParam*>
159     (fCalibrationData.Pedestals(digit.DetElemId(),digit.ManuId()));
160     
161     AliMUONVCalibParam* gain = static_cast<AliMUONVCalibParam*>
162       (fCalibrationData.Gains(digit.DetElemId(),digit.ManuId()));
163     
164     if (!pedestal)
165     {
166       AliFatal(Form("Got a null ped object for DE,manu=%d,%d",
167                     digit.DetElemId(),digit.ManuId()));
168       
169     }
170     if (!gain)
171     {
172       AliFatal(Form("Got a null gain object for DE,manu=%d,%d",
173                     digit.DetElemId(),digit.ManuId()));        
174     }
175     
176     Int_t manuChannel = digit.ManuChannel();
177     Float_t adc = digit.ADC();
178     Float_t padc = adc-pedestal->ValueAsFloat(manuChannel,0);
179     Float_t charge(0);
180     if ( padc > 3.0*pedestal->ValueAsFloat(manuChannel,1) ) 
181     {
182       Float_t a0 = gain->ValueAsFloat(manuChannel,0);
183       Float_t a1 = gain->ValueAsFloat(manuChannel,1);
184       Int_t thres = gain->ValueAsInt(manuChannel,2);
185       if ( padc < thres ) 
186       {
187         charge = a0*padc;
188       }
189       else
190       {
191         charge = a0*thres + a0*(padc-thres) + a1*(padc-thres)*(padc-thres);
192       }
193     }
194     digit.SetCharge(charge);
195     Int_t saturation = gain->ValueAsInt(manuChannel,4);
196     if ( charge >= saturation )
197     {
198       digit.Saturated(kTRUE);
199     }
200   }
201 }