Drift velocity calibration document
[u/mrichter/AliRoot.git] / MUON / AliMUONDigitCalibrator.cxx
CommitLineData
d99769c3 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
d99769c3 20#include "AliMUONCalibrationData.h"
42825ed9 21#include "AliMUONVDigit.h"
22#include "AliMUONVDigitStore.h"
fe6ed686 23#include "AliMUONLogger.h"
d1c20d08 24#include "AliMUONPadStatusMaker.h"
25#include "AliMUONPadStatusMapMaker.h"
42825ed9 26#include "AliMUONVStore.h"
c795d086 27#include "AliMUONVCalibParam.h"
de98fdc9 28#include "AliMpConstants.h"
29#include "AliMpDetElement.h"
30#include "AliMpDDLStore.h"
31#include "AliLog.h"
d99769c3 32
3d1463c8 33//-----------------------------------------------------------------------------
7945aae7 34/// \class AliMUONDigitCalibrator
1171bb0a 35/// Class used to calibrate digits (either real or simulated ones).
36///
37/// The calibration consists of subtracting the pedestal
38/// and multiplying by a gain, so that
39/// Signal = (ADC-pedestal)*gain
40///
41/// Please note also that for the moment, if a digit lies on a dead channel
42/// we remove this digit from the list of digits.
43/// FIXME: this has to be revisited. By using the AliMUONDigit::fFlags we
44/// should in principle flag a digit as bad w/o removing it, but this
45/// then requires some changes in the cluster finder to deal with this extra
46/// information correctly (e.g. to set a quality for the cluster if it contains
47/// bad digits).
48///
7945aae7 49/// \author Laurent Aphecetche
3d1463c8 50//-----------------------------------------------------------------------------
7945aae7 51
1171bb0a 52
7945aae7 53/// \cond CLASSIMP
d99769c3 54ClassImp(AliMUONDigitCalibrator)
7945aae7 55/// \endcond
d99769c3 56
de98fdc9 57const Int_t AliMUONDigitCalibrator::fgkNoGain(0);
58const Int_t AliMUONDigitCalibrator::fgkGainConstantCapa(1);
59const Int_t AliMUONDigitCalibrator::fgkGain(2);
60
d99769c3 61//_____________________________________________________________________________
de98fdc9 62AliMUONDigitCalibrator::AliMUONDigitCalibrator(const AliMUONCalibrationData& calib,
63 const char* calibMode)
42825ed9 64: TObject(),
49e396d9 65fLogger(new AliMUONLogger(1000)),
66fStatusMaker(0x0),
67fStatusMapMaker(0x0),
68fPedestals(0x0),
de98fdc9 69fGains(0x0),
70fApplyGains(0),
71fCapacitances(0x0)
d99769c3 72{
42825ed9 73 /// ctor
de98fdc9 74
75 TString cMode(calibMode);
76 cMode.ToUpper();
77
78 if ( cMode == "NOGAIN" )
79 {
80 fApplyGains = fgkNoGain;
81 AliInfo("Will NOT apply gain correction");
82 }
83 else if ( cMode = "GAINCONSTANTCAPA" )
84 {
85 fApplyGains = fgkGainConstantCapa;
86 AliInfo("Will apply gain correction, but with constant capacitance");
87 }
88 else if ( cMode == "GAIN" )
89 {
90 fApplyGains = fgkGain;
91 AliInfo("Will apply gain correction, with measured capacitances");
92 }
93 else
94 {
95 AliError(Form("Invalid calib mode = %s. Will use NOGAIN instead",calibMode));
96 fApplyGains = fgkNoGain;
97 }
98
49e396d9 99 fStatusMaker = new AliMUONPadStatusMaker(calib);
100
101 // this is here that we decide on our "goodness" policy, i.e.
102 // what do we call an invalid pad (a pad maybe bad because its HV
103 // was too low, or its pedestals too high, etc..)
104 // FIXME: find a way not to hard-code the goodness policy (i.e. the limits)
105 // here...
106 fStatusMaker->SetHVSt12Limits(1300,1600);
107 fStatusMaker->SetHVSt345Limits(1500,2000);
108 fStatusMaker->SetPedMeanLimits(50,200);
109 fStatusMaker->SetPedSigmaLimits(0.1,3);
110
111 Int_t mask(0x8080);
112 //FIXME: kind of fake one for the moment, we consider dead only
113 // if ped and/or hv value missing.
114 //WARNING : getting this mask wrong is a very effective way of getting
115 //no digits at all out of this class ;-)
116
117 Bool_t deferredInitialization = kTRUE;
118
119 fStatusMapMaker = new AliMUONPadStatusMapMaker(*fStatusMaker,mask,deferredInitialization);
120
121 fPedestals = calib.Pedestals();
de98fdc9 122
123 fGains = calib.Gains(); // we get gains whatever the calibMode is, in order
124 // to get the saturation value...
125
126 if ( fApplyGains == fgkGain )
127 {
128 fCapacitances = calib.Capacitances();
129 }
d99769c3 130}
131
1171bb0a 132//_____________________________________________________________________________
d99769c3 133AliMUONDigitCalibrator::~AliMUONDigitCalibrator()
134{
d1c20d08 135 /// dtor.
49e396d9 136 delete fStatusMaker;
137 delete fStatusMapMaker;
fe6ed686 138
139 AliInfo("Summary of messages:");
140 fLogger->Print();
141
142 delete fLogger;
d99769c3 143}
144
145//_____________________________________________________________________________
146void
42825ed9 147AliMUONDigitCalibrator::Calibrate(AliMUONVDigitStore& digitStore)
d99769c3 148{
42825ed9 149 /// Calibrate the digits contained in digitStore
150 TIter next(digitStore.CreateTrackerIterator());
151 AliMUONVDigit* digit;
c795d086 152
42825ed9 153 while ( ( digit = static_cast<AliMUONVDigit*>(next() ) ) )
d99769c3 154 {
42825ed9 155 CalibrateDigit(*digit);
156 }
157}
158
159//_____________________________________________________________________________
160void
161AliMUONDigitCalibrator::CalibrateDigit(AliMUONVDigit& digit)
162{
163 /// Calibrate one digit
164
cf27231a 165 if ( digit.IsCalibrated() )
166 {
167 fLogger->Log("ERROR : trying to calibrate a digit twice");
168 return;
169 }
170
49e396d9 171 Int_t statusMap = fStatusMapMaker->StatusMap(digit.DetElemId(),
172 digit.ManuId(),
173 digit.ManuChannel());
174
42825ed9 175 digit.SetStatusMap(statusMap);
176 digit.Calibrated(kTRUE);
49e396d9 177
42825ed9 178 if ( ( statusMap & AliMUONPadStatusMapMaker::SelfDeadMask() ) != 0 )
179 {
180 // pad itself is bad (not testing its neighbours at this stage)
181 digit.SetCharge(0);
182 fLogger->Log(Form("%s:%d:Channel detElemId %d manuId %d "
183 "manuChannel %d is bad %x",__FILE__,__LINE__,
184 digit.DetElemId(),digit.ManuId(),
185 digit.ManuChannel(),digit.StatusMap()));
186 }
187 else
188 {
189 // If the channel is good, go on with the calibration itself.
190
191 AliMUONVCalibParam* pedestal = static_cast<AliMUONVCalibParam*>
49e396d9 192 (fPedestals->FindObject(digit.DetElemId(),digit.ManuId()));
42825ed9 193
42825ed9 194 if (!pedestal)
d99769c3 195 {
42825ed9 196 AliFatal(Form("Got a null ped object for DE,manu=%d,%d",
197 digit.DetElemId(),digit.ManuId()));
c795d086 198
42825ed9 199 }
de98fdc9 200
201 AliMUONVCalibParam* gain = static_cast<AliMUONVCalibParam*>
202 (fGains->FindObject(digit.DetElemId(),digit.ManuId()));
203
42825ed9 204 if (!gain)
205 {
206 AliFatal(Form("Got a null gain object for DE,manu=%d,%d",
207 digit.DetElemId(),digit.ManuId()));
208 }
209
210 Int_t manuChannel = digit.ManuChannel();
211 Float_t adc = digit.ADC();
212 Float_t padc = adc-pedestal->ValueAsFloat(manuChannel,0);
cf27231a 213 Float_t charge(0);
de98fdc9 214 Float_t capa(1.0);
215
216 if ( fApplyGains == fgkGainConstantCapa )
217 {
218 capa = 0.2; // pF
219 }
220 else if ( fApplyGains == fgkGain )
221 {
222 AliMpDetElement* de = AliMpDDLStore::Instance()->GetDetElement(digit.DetElemId());
223
224 Int_t serialNumber = de->GetManuSerialFromId(digit.ManuId());
225
226 AliMUONVCalibParam* param = static_cast<AliMUONVCalibParam*>(fCapacitances->FindObject(serialNumber));
227
228 capa = param->ValueAsFloat(digit.ManuChannel());
229 }
230
cf27231a 231 if ( padc > 3.0*pedestal->ValueAsFloat(manuChannel,1) )
42825ed9 232 {
de98fdc9 233 if ( fApplyGains != fgkNoGain )
cf27231a 234 {
de98fdc9 235 Float_t a0 = gain->ValueAsFloat(manuChannel,0);
236 Float_t a1 = gain->ValueAsFloat(manuChannel,1);
237 Int_t thres = gain->ValueAsInt(manuChannel,2);
238 if ( padc < thres )
239 {
240 charge = a0*padc;
241 }
242 else
243 {
244 charge = a0*thres + a0*(padc-thres) + a1*(padc-thres)*(padc-thres);
245 }
cf27231a 246 }
247 else
248 {
de98fdc9 249 charge = padc;
cf27231a 250 }
42825ed9 251 }
de98fdc9 252 charge *= capa;
42825ed9 253 digit.SetCharge(charge);
cf27231a 254 Int_t saturation = gain->ValueAsInt(manuChannel,4);
de98fdc9 255 if ( padc >= saturation )
42825ed9 256 {
257 digit.Saturated(kTRUE);
d99769c3 258 }
259 }
260}