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