Removing a useless dynamic_cast
[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
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);
65
d99769c3 66//_____________________________________________________________________________
de98fdc9 67AliMUONDigitCalibrator::AliMUONDigitCalibrator(const AliMUONCalibrationData& calib,
ab167304 68 const AliMUONRecoParam* recoParams,
de98fdc9 69 const char* calibMode)
42825ed9 70: TObject(),
3b6f7dce 71fLogger(new AliMUONLogger(20000)),
49e396d9 72fStatusMaker(0x0),
73fStatusMapMaker(0x0),
74fPedestals(0x0),
de98fdc9 75fGains(0x0),
76fApplyGains(0),
de487b6e 77fCapacitances(0x0),
78fNumberOfBadPads(0),
170f4046 79fNumberOfPads(0),
80fChargeSigmaCut(0)
d99769c3 81{
42825ed9 82 /// ctor
de98fdc9 83
de487b6e 84 Ctor(calibMode,calib,recoParams);
85}
86
87//_____________________________________________________________________________
88AliMUONDigitCalibrator::AliMUONDigitCalibrator(const AliMUONCalibrationData& calib,
89 const char* calibMode)
90: TObject(),
91fLogger(new AliMUONLogger(20000)),
92fStatusMaker(0x0),
93fStatusMapMaker(0x0),
94fPedestals(0x0),
95fGains(0x0),
96fApplyGains(0),
97fCapacitances(0x0),
98fNumberOfBadPads(0),
170f4046 99fNumberOfPads(0),
100fChargeSigmaCut(0)
de487b6e 101{
102 /// ctor
103
104 Ctor(calibMode,calib,0x0);
105}
106
107//_____________________________________________________________________________
108void
109AliMUONDigitCalibrator::Ctor(const char* calibMode,
110 const AliMUONCalibrationData& calib,
111 const AliMUONRecoParam* recoParams)
112{
113 /// designated ctor
114
de98fdc9 115 TString cMode(calibMode);
116 cMode.ToUpper();
117
118 if ( cMode == "NOGAIN" )
119 {
120 fApplyGains = fgkNoGain;
121 AliInfo("Will NOT apply gain correction");
122 }
3b6f7dce 123 else if ( cMode == "GAINCONSTANTCAPA" )
de98fdc9 124 {
125 fApplyGains = fgkGainConstantCapa;
126 AliInfo("Will apply gain correction, but with constant capacitance");
127 }
128 else if ( cMode == "GAIN" )
129 {
130 fApplyGains = fgkGain;
131 AliInfo("Will apply gain correction, with measured capacitances");
132 }
133 else
134 {
135 AliError(Form("Invalid calib mode = %s. Will use NOGAIN instead",calibMode));
136 fApplyGains = fgkNoGain;
137 }
138
ab167304 139 // Load mapping manu store
140 if ( ! AliMpCDB::LoadManuStore() ) {
141 AliFatal("Could not access manu store from OCDB !");
142 }
143
49e396d9 144 fStatusMaker = new AliMUONPadStatusMaker(calib);
145
170f4046 146 // Set default values, as loose as reasonable
147
148 fChargeSigmaCut = 3.0;
149
150 Int_t mask(0x8080); // reject pads where ped *or* hv are missing
de487b6e 151
de487b6e 152 if ( recoParams )
153 {
170f4046 154 // if we have reco params, we use limits and cuts from there :
155
de487b6e 156 fStatusMaker->SetHVSt12Limits(recoParams->HVSt12LowLimit(),recoParams->HVSt12HighLimit());
157 fStatusMaker->SetHVSt345Limits(recoParams->HVSt345LowLimit(),recoParams->HVSt345HighLimit());
158 fStatusMaker->SetPedMeanLimits(recoParams->PedMeanLowLimit(),recoParams->PedMeanHighLimit());
159 fStatusMaker->SetPedSigmaLimits(recoParams->PedSigmaLowLimit(),recoParams->PedSigmaHighLimit());
160 fStatusMaker->SetGainA1Limits(recoParams->GainA1LowLimit(),recoParams->GainA1HighLimit());
161 fStatusMaker->SetGainA2Limits(recoParams->GainA2LowLimit(),recoParams->GainA2HighLimit());
162 fStatusMaker->SetGainThresLimits(recoParams->GainThresLowLimit(),recoParams->GainThresHighLimit());
170f4046 163
164 mask = recoParams->PadGoodnessMask();
de487b6e 165 //WARNING : getting this mask wrong is a very effective way of getting
166 //no digits at all out of this class ;-)
170f4046 167
168 fChargeSigmaCut = recoParams->ChargeSigmaCut();
de487b6e 169 }
49e396d9 170
171 Bool_t deferredInitialization = kTRUE;
172
173 fStatusMapMaker = new AliMUONPadStatusMapMaker(*fStatusMaker,mask,deferredInitialization);
174
175 fPedestals = calib.Pedestals();
de98fdc9 176
177 fGains = calib.Gains(); // we get gains whatever the calibMode is, in order
178 // to get the saturation value...
179
180 if ( fApplyGains == fgkGain )
181 {
182 fCapacitances = calib.Capacitances();
183 }
d99769c3 184}
185
1171bb0a 186//_____________________________________________________________________________
d99769c3 187AliMUONDigitCalibrator::~AliMUONDigitCalibrator()
188{
d1c20d08 189 /// dtor.
49e396d9 190 delete fStatusMaker;
191 delete fStatusMapMaker;
fe6ed686 192
193 AliInfo("Summary of messages:");
194 fLogger->Print();
195
de487b6e 196 AliInfo(Form("We have seen %g pads, and rejected %g (%7.2f %%)",
197 fNumberOfPads,fNumberOfBadPads,
198 ( fNumberOfPads > 0 ) ? fNumberOfBadPads*100.0/fNumberOfPads : 0 ));
199
fe6ed686 200 delete fLogger;
d99769c3 201}
202
203//_____________________________________________________________________________
204void
42825ed9 205AliMUONDigitCalibrator::Calibrate(AliMUONVDigitStore& digitStore)
d99769c3 206{
42825ed9 207 /// Calibrate the digits contained in digitStore
208 TIter next(digitStore.CreateTrackerIterator());
209 AliMUONVDigit* digit;
861d6ce8 210 Int_t detElemId(-1);
170f4046 211 Double_t nsigmas = fChargeSigmaCut;
861d6ce8 212
213 AliDebug(1,Form("# of digits = %d",digitStore.GetSize()));
c795d086 214
42825ed9 215 while ( ( digit = static_cast<AliMUONVDigit*>(next() ) ) )
d99769c3 216 {
de487b6e 217 if ( digit->IsCalibrated() )
218 {
219 fLogger->Log("ERROR : trying to calibrate a digit twice");
220 return;
221 }
222
223 digit->Calibrated(kTRUE);
224
861d6ce8 225 if ( digit->DetElemId() != detElemId )
226 {
227 // Find out occupancy of that DE
228 detElemId = digit->DetElemId();
630711ed 229 AliMpDetElement* de = AliMpDDLStore::Instance()->GetDetElement(detElemId);
230 Double_t nchannels = de->NofChannels();
861d6ce8 231 Double_t occ = digitStore.GetSize(detElemId)/nchannels;
232 if ( occ > 0.05 )
233 {
234 nsigmas = 10.0; // enlarge (a lot) sigma cut if occupancy is high
235 // (which probably means zero suppression was not exactly OK).
236 fLogger->Log(Form("Will use %5.0f*sigma cut for DE %04d "
237 "due to high occupancy",nsigmas,detElemId));
238 }
239 else
240 {
170f4046 241 nsigmas = fChargeSigmaCut;
861d6ce8 242 }
243 }
244
de487b6e 245 Float_t charge(0.0);
246 Int_t statusMap;
247 Bool_t isSaturated(kFALSE);
8bf22fd6 248
249 ++fNumberOfPads;
250
de487b6e 251 Bool_t ok = IsValidDigit(digit->DetElemId(),digit->ManuId(),digit->ManuChannel(),&statusMap);
252
253 digit->SetStatusMap(statusMap);
254
255 if (ok)
256 {
de487b6e 257 charge = CalibrateDigit(digit->DetElemId(),digit->ManuId(),digit->ManuChannel(),
258 digit->ADC(),nsigmas,&isSaturated);
259 }
260 else
261 {
262 ++fNumberOfBadPads;
263 }
264
265 digit->SetCharge(charge);
266 digit->Saturated(isSaturated);
42825ed9 267 }
268}
269
270//_____________________________________________________________________________
de487b6e 271Float_t
272AliMUONDigitCalibrator::CalibrateDigit(Int_t detElemId, Int_t manuId, Int_t manuChannel,
273 Float_t adc, Float_t nsigmas,
274 Bool_t* isSaturated) const
275
42825ed9 276{
277 /// Calibrate one digit
278
cf27231a 279
de487b6e 280 AliMUONVCalibParam* pedestal = static_cast<AliMUONVCalibParam*>
281 (fPedestals->FindObject(detElemId,manuId));
49e396d9 282
de487b6e 283 if (!pedestal)
42825ed9 284 {
de487b6e 285 // no pedestal -> no charge
286 fLogger->Log(Form("Got a null pedestal object for DE,manu=%d,%d",detElemId,manuId));
287 return 0.0;
42825ed9 288 }
de487b6e 289
290
291 AliMUONVCalibParam* gain = static_cast<AliMUONVCalibParam*>
292 (fGains->FindObject(detElemId,manuId));
293
294 if (!gain)
42825ed9 295 {
de487b6e 296 if ( fApplyGains != fgkNoGain )
d99769c3 297 {
de487b6e 298 // no gain -> no charge
299 fLogger->Log(Form("Got a null gain object for DE,manu=%d,%d",
300 detElemId,manuId));
301 return 0.0;
42825ed9 302 }
de487b6e 303 }
304
305 Float_t padc = adc-pedestal->ValueAsFloat(manuChannel,0);
306 Float_t charge(0);
307 Float_t capa(1.0);
308
309 if ( fApplyGains == fgkGainConstantCapa )
310 {
311 capa = 0.2; // pF
312 }
313 else if ( fApplyGains == fgkGain )
314 {
3b6f7dce 315
ab167304 316
317 Int_t serialNumber
318 = AliMpManuStore::Instance()->GetManuSerial(detElemId, manuId);
3b6f7dce 319
de487b6e 320 AliMUONVCalibParam* param = static_cast<AliMUONVCalibParam*>(fCapacitances->FindObject(serialNumber));
321
322 if ( param )
42825ed9 323 {
de487b6e 324 capa = param->ValueAsFloat(manuChannel);
42825ed9 325 }
de487b6e 326 else
de98fdc9 327 {
de487b6e 328 fLogger->Log(Form("No capa found for serialNumber=%d",serialNumber));
329 capa = 0.0;
de98fdc9 330 }
de487b6e 331 }
332
333 if ( padc > nsigmas*pedestal->ValueAsFloat(manuChannel,1) )
334 {
335 if ( fApplyGains != fgkNoGain )
de98fdc9 336 {
de487b6e 337 Float_t a0 = gain->ValueAsFloat(manuChannel,0);
338 Float_t a1 = gain->ValueAsFloat(manuChannel,1);
339 Int_t thres = gain->ValueAsInt(manuChannel,2);
340 if ( padc < thres )
3b6f7dce 341 {
de487b6e 342 charge = a0*padc;
3b6f7dce 343 }
344 else
345 {
de487b6e 346 charge = a0*thres + a0*(padc-thres) + a1*(padc-thres)*(padc-thres);
3b6f7dce 347 }
de98fdc9 348 }
de487b6e 349 else
42825ed9 350 {
de487b6e 351 charge = padc;
42825ed9 352 }
de487b6e 353 }
354
355 charge *= capa;
356
357 if ( isSaturated )
358 {
3b6f7dce 359 Int_t saturation(3000);
de487b6e 360
6b191dea 361 if ( gain && ( fApplyGains != fgkNoGain ) )
3b6f7dce 362 {
363 saturation = gain->ValueAsInt(manuChannel,4);
364 }
de487b6e 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