]>
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" | |
c795d086 | 25 | #include "AliMUONVCalibParam.h" |
861d6ce8 | 26 | #include "AliMUONVDigit.h" |
27 | #include "AliMUONVDigitStore.h" | |
28 | #include "AliMUONVStore.h" | |
29 | #include "AliMpBusPatch.h" | |
de98fdc9 | 30 | #include "AliMpConstants.h" |
de98fdc9 | 31 | #include "AliMpDDLStore.h" |
861d6ce8 | 32 | #include "AliMpDEIterator.h" |
33 | #include "AliMpDetElement.h" | |
d99769c3 | 34 | |
3d1463c8 | 35 | //----------------------------------------------------------------------------- |
7945aae7 | 36 | /// \class AliMUONDigitCalibrator |
1171bb0a | 37 | /// Class used to calibrate digits (either real or simulated ones). |
38 | /// | |
39 | /// The calibration consists of subtracting the pedestal | |
40 | /// and multiplying by a gain, so that | |
41 | /// Signal = (ADC-pedestal)*gain | |
42 | /// | |
43 | /// Please note also that for the moment, if a digit lies on a dead channel | |
44 | /// we remove this digit from the list of digits. | |
45 | /// FIXME: this has to be revisited. By using the AliMUONDigit::fFlags we | |
46 | /// should in principle flag a digit as bad w/o removing it, but this | |
47 | /// then requires some changes in the cluster finder to deal with this extra | |
48 | /// information correctly (e.g. to set a quality for the cluster if it contains | |
49 | /// bad digits). | |
50 | /// | |
7945aae7 | 51 | /// \author Laurent Aphecetche |
3d1463c8 | 52 | //----------------------------------------------------------------------------- |
7945aae7 | 53 | |
1171bb0a | 54 | |
7945aae7 | 55 | /// \cond CLASSIMP |
d99769c3 | 56 | ClassImp(AliMUONDigitCalibrator) |
7945aae7 | 57 | /// \endcond |
d99769c3 | 58 | |
de98fdc9 | 59 | const Int_t AliMUONDigitCalibrator::fgkNoGain(0); |
60 | const Int_t AliMUONDigitCalibrator::fgkGainConstantCapa(1); | |
61 | const Int_t AliMUONDigitCalibrator::fgkGain(2); | |
62 | ||
d99769c3 | 63 | //_____________________________________________________________________________ |
de98fdc9 | 64 | AliMUONDigitCalibrator::AliMUONDigitCalibrator(const AliMUONCalibrationData& calib, |
65 | const char* calibMode) | |
42825ed9 | 66 | : TObject(), |
3b6f7dce | 67 | fLogger(new AliMUONLogger(20000)), |
49e396d9 | 68 | fStatusMaker(0x0), |
69 | fStatusMapMaker(0x0), | |
70 | fPedestals(0x0), | |
de98fdc9 | 71 | fGains(0x0), |
72 | fApplyGains(0), | |
861d6ce8 | 73 | fCapacitances(0x0), |
74 | fNofChannelsPerDE(new TExMap) | |
d99769c3 | 75 | { |
42825ed9 | 76 | /// ctor |
de98fdc9 | 77 | |
78 | TString cMode(calibMode); | |
79 | cMode.ToUpper(); | |
80 | ||
81 | if ( cMode == "NOGAIN" ) | |
82 | { | |
83 | fApplyGains = fgkNoGain; | |
84 | AliInfo("Will NOT apply gain correction"); | |
85 | } | |
3b6f7dce | 86 | else if ( cMode == "GAINCONSTANTCAPA" ) |
de98fdc9 | 87 | { |
88 | fApplyGains = fgkGainConstantCapa; | |
89 | AliInfo("Will apply gain correction, but with constant capacitance"); | |
90 | } | |
91 | else if ( cMode == "GAIN" ) | |
92 | { | |
93 | fApplyGains = fgkGain; | |
94 | AliInfo("Will apply gain correction, with measured capacitances"); | |
95 | } | |
96 | else | |
97 | { | |
98 | AliError(Form("Invalid calib mode = %s. Will use NOGAIN instead",calibMode)); | |
99 | fApplyGains = fgkNoGain; | |
100 | } | |
101 | ||
49e396d9 | 102 | fStatusMaker = new AliMUONPadStatusMaker(calib); |
103 | ||
104 | // this is here that we decide on our "goodness" policy, i.e. | |
105 | // what do we call an invalid pad (a pad maybe bad because its HV | |
106 | // was too low, or its pedestals too high, etc..) | |
107 | // FIXME: find a way not to hard-code the goodness policy (i.e. the limits) | |
108 | // here... | |
109 | fStatusMaker->SetHVSt12Limits(1300,1600); | |
110 | fStatusMaker->SetHVSt345Limits(1500,2000); | |
111 | fStatusMaker->SetPedMeanLimits(50,200); | |
112 | fStatusMaker->SetPedSigmaLimits(0.1,3); | |
113 | ||
114 | Int_t mask(0x8080); | |
115 | //FIXME: kind of fake one for the moment, we consider dead only | |
116 | // if ped and/or hv value missing. | |
117 | //WARNING : getting this mask wrong is a very effective way of getting | |
118 | //no digits at all out of this class ;-) | |
119 | ||
120 | Bool_t deferredInitialization = kTRUE; | |
121 | ||
122 | fStatusMapMaker = new AliMUONPadStatusMapMaker(*fStatusMaker,mask,deferredInitialization); | |
123 | ||
124 | fPedestals = calib.Pedestals(); | |
de98fdc9 | 125 | |
126 | fGains = calib.Gains(); // we get gains whatever the calibMode is, in order | |
127 | // to get the saturation value... | |
128 | ||
129 | if ( fApplyGains == fgkGain ) | |
130 | { | |
131 | fCapacitances = calib.Capacitances(); | |
132 | } | |
861d6ce8 | 133 | |
134 | // FIXME: get the nof of channels per de directly within AliMpDetElement ? | |
135 | // or use the AliMUONTrackerData class for that ? | |
136 | ||
137 | AliMpDEIterator it; | |
138 | ||
139 | it.First(); | |
140 | ||
141 | while ( !it.IsDone() ) | |
142 | { | |
143 | ||
144 | AliMpDetElement* det = it.CurrentDE(); | |
145 | Int_t detElemId = det->GetId(); | |
146 | Int_t nchannels(0); | |
147 | ||
148 | for ( Int_t i = 0; i < det->GetNofBusPatches(); ++i ) | |
149 | { | |
150 | Int_t busPatchId = det->GetBusPatchId(i); | |
151 | AliMpBusPatch* bp = AliMpDDLStore::Instance()->GetBusPatch(busPatchId); | |
152 | for ( Int_t j = 0; j < bp->GetNofManus(); ++j ) | |
153 | { | |
154 | Int_t manuId = bp->GetManuId(j); | |
155 | nchannels += det->NofChannelsInManu(manuId); | |
156 | } | |
157 | } | |
158 | ||
159 | it.Next(); | |
160 | ||
161 | fNofChannelsPerDE->Add((Long_t)detElemId,(Long_t)nchannels); | |
162 | } | |
d99769c3 | 163 | } |
164 | ||
165 | //_____________________________________________________________________________ | |
166 | AliMUONDigitCalibrator::~AliMUONDigitCalibrator() | |
167 | { | |
d1c20d08 | 168 | /// dtor. |
49e396d9 | 169 | delete fStatusMaker; |
170 | delete fStatusMapMaker; | |
fe6ed686 | 171 | |
172 | AliInfo("Summary of messages:"); | |
173 | fLogger->Print(); | |
174 | ||
175 | delete fLogger; | |
861d6ce8 | 176 | delete fNofChannelsPerDE; |
d99769c3 | 177 | } |
178 | ||
179 | //_____________________________________________________________________________ | |
180 | void | |
42825ed9 | 181 | AliMUONDigitCalibrator::Calibrate(AliMUONVDigitStore& digitStore) |
d99769c3 | 182 | { |
42825ed9 | 183 | /// Calibrate the digits contained in digitStore |
184 | TIter next(digitStore.CreateTrackerIterator()); | |
185 | AliMUONVDigit* digit; | |
861d6ce8 | 186 | Int_t detElemId(-1); |
187 | Double_t nsigmas(3.0); | |
188 | ||
189 | AliDebug(1,Form("# of digits = %d",digitStore.GetSize())); | |
c795d086 | 190 | |
42825ed9 | 191 | while ( ( digit = static_cast<AliMUONVDigit*>(next() ) ) ) |
d99769c3 | 192 | { |
861d6ce8 | 193 | if ( digit->DetElemId() != detElemId ) |
194 | { | |
195 | // Find out occupancy of that DE | |
196 | detElemId = digit->DetElemId(); | |
197 | Double_t nchannels = fNofChannelsPerDE->GetValue(detElemId); | |
198 | Double_t occ = digitStore.GetSize(detElemId)/nchannels; | |
199 | if ( occ > 0.05 ) | |
200 | { | |
201 | nsigmas = 10.0; // enlarge (a lot) sigma cut if occupancy is high | |
202 | // (which probably means zero suppression was not exactly OK). | |
203 | fLogger->Log(Form("Will use %5.0f*sigma cut for DE %04d " | |
204 | "due to high occupancy",nsigmas,detElemId)); | |
205 | } | |
206 | else | |
207 | { | |
208 | nsigmas = 3.0; | |
209 | } | |
210 | } | |
211 | ||
212 | CalibrateDigit(*digit,nsigmas); | |
42825ed9 | 213 | } |
214 | } | |
215 | ||
216 | //_____________________________________________________________________________ | |
217 | void | |
861d6ce8 | 218 | AliMUONDigitCalibrator::CalibrateDigit(AliMUONVDigit& digit, Double_t nsigmas) |
42825ed9 | 219 | { |
220 | /// Calibrate one digit | |
221 | ||
cf27231a | 222 | if ( digit.IsCalibrated() ) |
223 | { | |
224 | fLogger->Log("ERROR : trying to calibrate a digit twice"); | |
225 | return; | |
226 | } | |
227 | ||
49e396d9 | 228 | Int_t statusMap = fStatusMapMaker->StatusMap(digit.DetElemId(), |
229 | digit.ManuId(), | |
230 | digit.ManuChannel()); | |
231 | ||
42825ed9 | 232 | digit.SetStatusMap(statusMap); |
233 | digit.Calibrated(kTRUE); | |
49e396d9 | 234 | |
42825ed9 | 235 | if ( ( statusMap & AliMUONPadStatusMapMaker::SelfDeadMask() ) != 0 ) |
236 | { | |
237 | // pad itself is bad (not testing its neighbours at this stage) | |
238 | digit.SetCharge(0); | |
239 | fLogger->Log(Form("%s:%d:Channel detElemId %d manuId %d " | |
240 | "manuChannel %d is bad %x",__FILE__,__LINE__, | |
241 | digit.DetElemId(),digit.ManuId(), | |
242 | digit.ManuChannel(),digit.StatusMap())); | |
243 | } | |
244 | else | |
245 | { | |
246 | // If the channel is good, go on with the calibration itself. | |
247 | ||
248 | AliMUONVCalibParam* pedestal = static_cast<AliMUONVCalibParam*> | |
49e396d9 | 249 | (fPedestals->FindObject(digit.DetElemId(),digit.ManuId())); |
3b6f7dce | 250 | |
42825ed9 | 251 | if (!pedestal) |
d99769c3 | 252 | { |
3b6f7dce | 253 | // no pedestal -> no charge |
254 | digit.SetCharge(0); | |
c795d086 | 255 | |
3b6f7dce | 256 | fLogger->Log(Form("Got a null pedestal object for DE,manu=%d,%d", |
257 | digit.DetElemId(),digit.ManuId())); | |
258 | return; | |
42825ed9 | 259 | } |
3b6f7dce | 260 | |
261 | ||
de98fdc9 | 262 | AliMUONVCalibParam* gain = static_cast<AliMUONVCalibParam*> |
263 | (fGains->FindObject(digit.DetElemId(),digit.ManuId())); | |
264 | ||
42825ed9 | 265 | if (!gain) |
266 | { | |
3b6f7dce | 267 | if ( fApplyGains != fgkNoGain ) |
268 | { | |
269 | // no gain -> no charge | |
270 | digit.SetCharge(0); | |
271 | ||
272 | fLogger->Log(Form("Got a null gain object for DE,manu=%d,%d", | |
273 | digit.DetElemId(),digit.ManuId())); | |
274 | return; | |
275 | } | |
42825ed9 | 276 | } |
3b6f7dce | 277 | |
42825ed9 | 278 | Int_t manuChannel = digit.ManuChannel(); |
279 | Float_t adc = digit.ADC(); | |
280 | Float_t padc = adc-pedestal->ValueAsFloat(manuChannel,0); | |
cf27231a | 281 | Float_t charge(0); |
de98fdc9 | 282 | Float_t capa(1.0); |
283 | ||
284 | if ( fApplyGains == fgkGainConstantCapa ) | |
285 | { | |
286 | capa = 0.2; // pF | |
287 | } | |
288 | else if ( fApplyGains == fgkGain ) | |
289 | { | |
290 | AliMpDetElement* de = AliMpDDLStore::Instance()->GetDetElement(digit.DetElemId()); | |
291 | ||
292 | Int_t serialNumber = de->GetManuSerialFromId(digit.ManuId()); | |
293 | ||
294 | AliMUONVCalibParam* param = static_cast<AliMUONVCalibParam*>(fCapacitances->FindObject(serialNumber)); | |
295 | ||
3b6f7dce | 296 | if ( param ) |
297 | { | |
298 | capa = param->ValueAsFloat(digit.ManuChannel()); | |
299 | } | |
300 | else | |
301 | { | |
302 | fLogger->Log(Form("No capa found for serialNumber=%d",serialNumber)); | |
303 | capa = 0.0; | |
304 | } | |
de98fdc9 | 305 | } |
306 | ||
861d6ce8 | 307 | if ( padc > nsigmas*pedestal->ValueAsFloat(manuChannel,1) ) |
42825ed9 | 308 | { |
de98fdc9 | 309 | if ( fApplyGains != fgkNoGain ) |
cf27231a | 310 | { |
de98fdc9 | 311 | Float_t a0 = gain->ValueAsFloat(manuChannel,0); |
312 | Float_t a1 = gain->ValueAsFloat(manuChannel,1); | |
313 | Int_t thres = gain->ValueAsInt(manuChannel,2); | |
314 | if ( padc < thres ) | |
315 | { | |
316 | charge = a0*padc; | |
317 | } | |
318 | else | |
319 | { | |
320 | charge = a0*thres + a0*(padc-thres) + a1*(padc-thres)*(padc-thres); | |
321 | } | |
cf27231a | 322 | } |
323 | else | |
324 | { | |
de98fdc9 | 325 | charge = padc; |
cf27231a | 326 | } |
42825ed9 | 327 | } |
3b6f7dce | 328 | |
de98fdc9 | 329 | charge *= capa; |
42825ed9 | 330 | digit.SetCharge(charge); |
3b6f7dce | 331 | |
332 | Int_t saturation(3000); | |
333 | ||
334 | if ( gain ) | |
335 | { | |
336 | saturation = gain->ValueAsInt(manuChannel,4); | |
337 | } | |
338 | ||
de98fdc9 | 339 | if ( padc >= saturation ) |
42825ed9 | 340 | { |
341 | digit.Saturated(kTRUE); | |
d99769c3 | 342 | } |
343 | } | |
344 | } |