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