Leftover from previous commit
[u/mrichter/AliRoot.git] / MUON / AliMUONDigitCalibrator.cxx
CommitLineData
d99769c3 1/**************************************************************************
66cdf5b3 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 **************************************************************************/
d99769c3 15
16// $Id$
17
18#include "AliMUONDigitCalibrator.h"
19
861d6ce8 20#include "AliLog.h"
d99769c3 21#include "AliMUONCalibrationData.h"
fe6ed686 22#include "AliMUONLogger.h"
d1c20d08 23#include "AliMUONPadStatusMaker.h"
24#include "AliMUONPadStatusMapMaker.h"
de487b6e 25#include "AliMUONRecoParam.h"
c795d086 26#include "AliMUONVCalibParam.h"
861d6ce8 27#include "AliMUONVDigit.h"
28#include "AliMUONVDigitStore.h"
29#include "AliMUONVStore.h"
30#include "AliMpBusPatch.h"
de98fdc9 31#include "AliMpConstants.h"
ab167304 32#include "AliMpCDB.h"
de98fdc9 33#include "AliMpDDLStore.h"
861d6ce8 34#include "AliMpDEIterator.h"
35#include "AliMpDetElement.h"
ab167304 36#include "AliMpManuStore.h"
d99769c3 37
3d1463c8 38//-----------------------------------------------------------------------------
7945aae7 39/// \class AliMUONDigitCalibrator
1171bb0a 40/// Class used to calibrate digits (either real or simulated ones).
41///
42/// The calibration consists of subtracting the pedestal
43/// and multiplying by a gain, so that
44/// Signal = (ADC-pedestal)*gain
45///
46/// Please note also that for the moment, if a digit lies on a dead channel
47/// we remove this digit from the list of digits.
48/// FIXME: this has to be revisited. By using the AliMUONDigit::fFlags we
49/// should in principle flag a digit as bad w/o removing it, but this
50/// then requires some changes in the cluster finder to deal with this extra
51/// information correctly (e.g. to set a quality for the cluster if it contains
52/// bad digits).
53///
7945aae7 54/// \author Laurent Aphecetche
3d1463c8 55//-----------------------------------------------------------------------------
7945aae7 56
1171bb0a 57
7945aae7 58/// \cond CLASSIMP
d99769c3 59ClassImp(AliMUONDigitCalibrator)
7945aae7 60/// \endcond
d99769c3 61
de98fdc9 62const Int_t AliMUONDigitCalibrator::fgkNoGain(0);
63const Int_t AliMUONDigitCalibrator::fgkGainConstantCapa(1);
64const Int_t AliMUONDigitCalibrator::fgkGain(2);
66cdf5b3 65const Int_t AliMUONDigitCalibrator::fgkInjectionGain(3);
de98fdc9 66
d99769c3 67//_____________________________________________________________________________
de98fdc9 68AliMUONDigitCalibrator::AliMUONDigitCalibrator(const AliMUONCalibrationData& calib,
ab167304 69 const AliMUONRecoParam* recoParams,
de98fdc9 70 const char* calibMode)
42825ed9 71: TObject(),
3b6f7dce 72fLogger(new AliMUONLogger(20000)),
49e396d9 73fStatusMaker(0x0),
74fStatusMapMaker(0x0),
75fPedestals(0x0),
de98fdc9 76fGains(0x0),
77fApplyGains(0),
de487b6e 78fCapacitances(0x0),
79fNumberOfBadPads(0),
170f4046 80fNumberOfPads(0),
81fChargeSigmaCut(0)
d99769c3 82{
42825ed9 83 /// ctor
de98fdc9 84
de487b6e 85 Ctor(calibMode,calib,recoParams);
86}
87
88//_____________________________________________________________________________
89AliMUONDigitCalibrator::AliMUONDigitCalibrator(const AliMUONCalibrationData& calib,
90 const char* calibMode)
91: TObject(),
92fLogger(new AliMUONLogger(20000)),
93fStatusMaker(0x0),
94fStatusMapMaker(0x0),
95fPedestals(0x0),
96fGains(0x0),
97fApplyGains(0),
98fCapacitances(0x0),
99fNumberOfBadPads(0),
170f4046 100fNumberOfPads(0),
101fChargeSigmaCut(0)
de487b6e 102{
103 /// ctor
104
105 Ctor(calibMode,calib,0x0);
106}
107
108//_____________________________________________________________________________
109void
110AliMUONDigitCalibrator::Ctor(const char* calibMode,
111 const AliMUONCalibrationData& calib,
112 const AliMUONRecoParam* recoParams)
113{
114 /// designated ctor
115
de98fdc9 116 TString cMode(calibMode);
117 cMode.ToUpper();
118
119 if ( cMode == "NOGAIN" )
120 {
121 fApplyGains = fgkNoGain;
122 AliInfo("Will NOT apply gain correction");
123 }
3b6f7dce 124 else if ( cMode == "GAINCONSTANTCAPA" )
de98fdc9 125 {
126 fApplyGains = fgkGainConstantCapa;
127 AliInfo("Will apply gain correction, but with constant capacitance");
128 }
129 else if ( cMode == "GAIN" )
130 {
131 fApplyGains = fgkGain;
132 AliInfo("Will apply gain correction, with measured capacitances");
133 }
66cdf5b3 134 else if ( cMode == "INJECTIONGAIN")
135 {
136 fApplyGains = fgkInjectionGain;
137 AliInfo("Will apply injection gain correction, with EMELEC factory gains");
138 }
de98fdc9 139 else
140 {
141 AliError(Form("Invalid calib mode = %s. Will use NOGAIN instead",calibMode));
142 fApplyGains = fgkNoGain;
143 }
66cdf5b3 144
ab167304 145 // Load mapping manu store
146 if ( ! AliMpCDB::LoadManuStore() ) {
147 AliFatal("Could not access manu store from OCDB !");
148 }
66cdf5b3 149
49e396d9 150 fStatusMaker = new AliMUONPadStatusMaker(calib);
151
170f4046 152 // Set default values, as loose as reasonable
66cdf5b3 153
170f4046 154 fChargeSigmaCut = 3.0;
155
156 Int_t mask(0x8080); // reject pads where ped *or* hv are missing
de487b6e 157
de487b6e 158 if ( recoParams )
159 {
170f4046 160 // if we have reco params, we use limits and cuts from there :
161
de487b6e 162 fStatusMaker->SetHVSt12Limits(recoParams->HVSt12LowLimit(),recoParams->HVSt12HighLimit());
163 fStatusMaker->SetHVSt345Limits(recoParams->HVSt345LowLimit(),recoParams->HVSt345HighLimit());
164 fStatusMaker->SetPedMeanLimits(recoParams->PedMeanLowLimit(),recoParams->PedMeanHighLimit());
165 fStatusMaker->SetPedSigmaLimits(recoParams->PedSigmaLowLimit(),recoParams->PedSigmaHighLimit());
166 fStatusMaker->SetGainA1Limits(recoParams->GainA1LowLimit(),recoParams->GainA1HighLimit());
167 fStatusMaker->SetGainA2Limits(recoParams->GainA2LowLimit(),recoParams->GainA2HighLimit());
168 fStatusMaker->SetGainThresLimits(recoParams->GainThresLowLimit(),recoParams->GainThresHighLimit());
170f4046 169
170 mask = recoParams->PadGoodnessMask();
de487b6e 171 //WARNING : getting this mask wrong is a very effective way of getting
172 //no digits at all out of this class ;-)
170f4046 173
174 fChargeSigmaCut = recoParams->ChargeSigmaCut();
de487b6e 175 }
49e396d9 176
177 Bool_t deferredInitialization = kTRUE;
178
179 fStatusMapMaker = new AliMUONPadStatusMapMaker(*fStatusMaker,mask,deferredInitialization);
180
181 fPedestals = calib.Pedestals();
66cdf5b3 182
de98fdc9 183 fGains = calib.Gains(); // we get gains whatever the calibMode is, in order
184 // to get the saturation value...
66cdf5b3 185
6b31d882 186 if ( fApplyGains == fgkGain || fApplyGains == fgkInjectionGain )
de98fdc9 187 {
188 fCapacitances = calib.Capacitances();
189 }
d99769c3 190}
191
1171bb0a 192//_____________________________________________________________________________
d99769c3 193AliMUONDigitCalibrator::~AliMUONDigitCalibrator()
194{
d1c20d08 195 /// dtor.
49e396d9 196 delete fStatusMaker;
197 delete fStatusMapMaker;
fe6ed686 198
199 AliInfo("Summary of messages:");
200 fLogger->Print();
66cdf5b3 201
de487b6e 202 AliInfo(Form("We have seen %g pads, and rejected %g (%7.2f %%)",
203 fNumberOfPads,fNumberOfBadPads,
204 ( fNumberOfPads > 0 ) ? fNumberOfBadPads*100.0/fNumberOfPads : 0 ));
205
fe6ed686 206 delete fLogger;
d99769c3 207}
208
209//_____________________________________________________________________________
210void
42825ed9 211AliMUONDigitCalibrator::Calibrate(AliMUONVDigitStore& digitStore)
d99769c3 212{
42825ed9 213 /// Calibrate the digits contained in digitStore
214 TIter next(digitStore.CreateTrackerIterator());
215 AliMUONVDigit* digit;
66cdf5b3 216
0045b488 217 fStatusMapMaker->RefreshRejectProbabilities(); // this will do something only for simulations
218 // (and only for those simulations where the reject list contain probabilities which are
219 // different from zero or one)
861d6ce8 220
221 AliDebug(1,Form("# of digits = %d",digitStore.GetSize()));
c795d086 222
42825ed9 223 while ( ( digit = static_cast<AliMUONVDigit*>(next() ) ) )
d99769c3 224 {
de487b6e 225 if ( digit->IsCalibrated() )
226 {
227 fLogger->Log("ERROR : trying to calibrate a digit twice");
228 return;
229 }
230
231 digit->Calibrated(kTRUE);
232
de487b6e 233 Float_t charge(0.0);
234 Int_t statusMap;
235 Bool_t isSaturated(kFALSE);
66cdf5b3 236
8bf22fd6 237 ++fNumberOfPads;
66cdf5b3 238
de487b6e 239 Bool_t ok = IsValidDigit(digit->DetElemId(),digit->ManuId(),digit->ManuChannel(),&statusMap);
66cdf5b3 240
de487b6e 241 digit->SetStatusMap(statusMap);
242
243 if (ok)
244 {
de487b6e 245 charge = CalibrateDigit(digit->DetElemId(),digit->ManuId(),digit->ManuChannel(),
0045b488 246 digit->ADC(),fChargeSigmaCut,&isSaturated);
de487b6e 247 }
248 else
249 {
0045b488 250 AliDebug(3,Form("Rejecting the pad DE %4d MANU %4d CH %2d ADC %6d STATUSMAP %x STATUS %s",
251 digit->DetElemId(),digit->ManuId(),digit->ManuChannel(),
252 digit->ADC(),statusMap,
253 fStatusMaker->AsString(fStatusMaker->PadStatus(digit->DetElemId(),digit->ManuId(),digit->ManuChannel())).Data()));
66cdf5b3 254
de487b6e 255 ++fNumberOfBadPads;
0045b488 256
de487b6e 257 }
258
259 digit->SetCharge(charge);
260 digit->Saturated(isSaturated);
42825ed9 261 }
262}
263
264//_____________________________________________________________________________
de487b6e 265Float_t
266AliMUONDigitCalibrator::CalibrateDigit(Int_t detElemId, Int_t manuId, Int_t manuChannel,
267 Float_t adc, Float_t nsigmas,
268 Bool_t* isSaturated) const
269
42825ed9 270{
271 /// Calibrate one digit
272
cf27231a 273
de487b6e 274 AliMUONVCalibParam* pedestal = static_cast<AliMUONVCalibParam*>
275 (fPedestals->FindObject(detElemId,manuId));
49e396d9 276
de487b6e 277 if (!pedestal)
42825ed9 278 {
de487b6e 279 // no pedestal -> no charge
280 fLogger->Log(Form("Got a null pedestal object for DE,manu=%d,%d",detElemId,manuId));
281 return 0.0;
42825ed9 282 }
de487b6e 283
284
285 AliMUONVCalibParam* gain = static_cast<AliMUONVCalibParam*>
286 (fGains->FindObject(detElemId,manuId));
287
288 if (!gain)
42825ed9 289 {
de487b6e 290 if ( fApplyGains != fgkNoGain )
d99769c3 291 {
de487b6e 292 // no gain -> no charge
293 fLogger->Log(Form("Got a null gain object for DE,manu=%d,%d",
294 detElemId,manuId));
295 return 0.0;
42825ed9 296 }
de487b6e 297 }
298
299 Float_t padc = adc-pedestal->ValueAsFloat(manuChannel,0);
de487b6e 300
66cdf5b3 301 // Gain (mV/fC) = 1/(a0*capa) with a0~1.25 and capa~0.2
302 Float_t charge(0);
303 Float_t capa(0.2); // capa = 0.2 and a0 = 1.25
304 Float_t a0(1.25); // is equivalent to gain = 4 mV/fC
305 Float_t a1(0);
306 Float_t adc2mv(0.61); // 1 ADC channel = 0.61 mV
307 Float_t injGain(4); // By default the gain is set to 4 mV/fC
308
309 if ( fApplyGains == fgkGain || fApplyGains == fgkInjectionGain )
de487b6e 310 {
ab167304 311 Int_t serialNumber
66cdf5b3 312 = AliMpManuStore::Instance()->GetManuSerial(detElemId, manuId);
3b6f7dce 313
de487b6e 314 AliMUONVCalibParam* param = static_cast<AliMUONVCalibParam*>(fCapacitances->FindObject(serialNumber));
315
316 if ( param )
42825ed9 317 {
66cdf5b3 318 capa = param->ValueAsFloat(manuChannel,0);
319 injGain = param->ValueAsFloat(manuChannel,1);
42825ed9 320 }
de487b6e 321 else
de98fdc9 322 {
66cdf5b3 323 // If capa not found in the OCDB we use default value
324 fLogger->Log(Form("No capa (injGain) found for serialNumber=%d",serialNumber));
325 return 0.0;
de98fdc9 326 }
de487b6e 327 }
328
329 if ( padc > nsigmas*pedestal->ValueAsFloat(manuChannel,1) )
330 {
66cdf5b3 331 if ( fApplyGains == fgkGain || fApplyGains == fgkGainConstantCapa )
de98fdc9 332 {
66cdf5b3 333 a0 = gain->ValueAsFloat(manuChannel,0);
334 a1 = gain->ValueAsFloat(manuChannel,1);
de487b6e 335 Int_t thres = gain->ValueAsInt(manuChannel,2);
336 if ( padc < thres )
3b6f7dce 337 {
de487b6e 338 charge = a0*padc;
3b6f7dce 339 }
340 else
341 {
de487b6e 342 charge = a0*thres + a0*(padc-thres) + a1*(padc-thres)*(padc-thres);
3b6f7dce 343 }
66cdf5b3 344 charge *= capa*adc2mv;
de98fdc9 345 }
66cdf5b3 346 else if ( fApplyGains == fgkInjectionGain )
42825ed9 347 {
66cdf5b3 348
349 charge = padc*adc2mv/injGain;
42825ed9 350 }
66cdf5b3 351 else
352 {
353 charge = a0*padc*capa*adc2mv;
354 }
de487b6e 355 }
356
de487b6e 357 if ( isSaturated )
358 {
3b6f7dce 359 Int_t saturation(3000);
66cdf5b3 360
6b191dea 361 if ( gain && ( fApplyGains != fgkNoGain ) )
3b6f7dce 362 {
363 saturation = gain->ValueAsInt(manuChannel,4);
364 }
66cdf5b3 365
de98fdc9 366 if ( padc >= saturation )
42825ed9 367 {
de487b6e 368 *isSaturated = kTRUE;
369 }
370 else
371 {
ada26c2d 372 *isSaturated = kFALSE;
d99769c3 373 }
374 }
de487b6e 375
376 return charge;
d99769c3 377}
de487b6e 378
379//_____________________________________________________________________________
380Bool_t
381AliMUONDigitCalibrator::IsValidDigit(Int_t detElemId, Int_t manuId, Int_t manuChannel,
382 Int_t* statusMap) const
383
384{
385 /// Check if a given pad is ok or not.
386
387 // First a protection against bad input parameters
388 AliMpDetElement* de = AliMpDDLStore::Instance()->GetDetElement(detElemId);
389 if (!de) return kFALSE; // not existing DE
390 if (!de->IsExistingChannel(manuId,manuChannel))
391 {
392 // non-existing (might happen when we get parity errors in read-out
393 // that spoils the manuId
394 return kFALSE;
395 }
396 if (!de->IsConnectedChannel(manuId,manuChannel))
397 {
398 // existing (in read-out), but not connected channel
399 return kFALSE;
400 }
401
402 // ok, now we have a valid channel number, so let's see if that pad
403 // behaves or not ;-)
404
405 Int_t sm = fStatusMapMaker->StatusMap(detElemId,manuId,manuChannel);
406
407 if (statusMap) *statusMap = sm;
408
409 if ( ( sm & AliMUONPadStatusMapMaker::SelfDeadMask() ) != 0 )
410 {
411 // pad itself is bad (not testing its neighbours at this stage)
412 return kFALSE;
413 }
414
415 return kTRUE;
416}
417
418//_____________________________________________________________________________
419Int_t
420AliMUONDigitCalibrator::PadStatus(Int_t detElemId, Int_t manuId, Int_t manuChannel) const
421{
422 /// Return the status of the given pad
423 return fStatusMaker->PadStatus(detElemId,manuId,manuChannel);
424}
425
426//_____________________________________________________________________________
427Int_t
428AliMUONDigitCalibrator::StatusMap(Int_t detElemId, Int_t manuId, Int_t manuChannel) const
429{
430 /// Return the status map of the given pad
431 return fStatusMapMaker->StatusMap(detElemId,manuId,manuChannel);
432
433}
434