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