Line data Source code
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 constant 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
62 18 : ClassImp(AliMUONDigitCalibrator)
63 : /// \endcond
64 :
65 : //_____________________________________________________________________________
66 : AliMUONDigitCalibrator::AliMUONDigitCalibrator(Int_t runNumber)
67 0 : : TObject(),
68 0 : fLogger(new AliMUONLogger(20000)),
69 0 : fStatusMaker(0x0),
70 0 : fStatusMapMaker(0x0),
71 0 : fPedestals(0x0),
72 0 : fNumberOfBadPads(0),
73 0 : fNumberOfPads(0),
74 0 : fChargeSigmaCut(0),
75 0 : fMask(0)
76 0 : {
77 : /// ctor
78 :
79 : AliMUONRecoParam* recoParam(0x0);
80 :
81 0 : AliCDBEntry* e = AliCDBManager::Instance()->Get("MUON/Calib/RecoParam",runNumber);
82 0 : if (e)
83 : {
84 0 : TObject* o = e->GetObject();
85 0 : if ( o->IsA() == TObjArray::Class() )
86 : {
87 0 : TObjArray* a = static_cast<TObjArray*>(o);
88 : // a->SetOwner(kTRUE); // FIXME: this should be done but somehow makes the reco crash at the end at cleaning stage... investigate why ?
89 0 : TIter next(a);
90 : AliMUONRecoParam* p;
91 0 : while ( ( p = static_cast<AliMUONRecoParam*>(next()) ))
92 : {
93 0 : if ( p->IsDefault()) recoParam = p;
94 : }
95 0 : }
96 : else
97 : {
98 0 : recoParam = static_cast<AliMUONRecoParam*>(o);
99 : }
100 0 : }
101 0 : if (!recoParam)
102 : {
103 0 : AliError("Cannot get the recoParam. Failing");
104 0 : return;
105 : }
106 :
107 : // OK. Now get all we need and work...
108 :
109 0 : AliMUONCalibrationData calib(runNumber);
110 :
111 0 : Ctor(calib,recoParam,kFALSE);
112 0 : }
113 :
114 : //_____________________________________________________________________________
115 : AliMUONDigitCalibrator::AliMUONDigitCalibrator(const AliMUONCalibrationData& calib,
116 : const AliMUONRecoParam* recoParams)
117 2 : : TObject(),
118 6 : fLogger(new AliMUONLogger(20000)),
119 2 : fStatusMaker(0x0),
120 2 : fStatusMapMaker(0x0),
121 2 : fPedestals(0x0),
122 2 : fNumberOfBadPads(0),
123 2 : fNumberOfPads(0),
124 2 : fChargeSigmaCut(0),
125 2 : fMask(0)
126 10 : {
127 : /// ctor
128 :
129 2 : Ctor(calib,recoParams);
130 4 : }
131 :
132 : //_____________________________________________________________________________
133 : AliMUONDigitCalibrator::AliMUONDigitCalibrator(const AliMUONCalibrationData& calib, int /*b*/)
134 0 : : TObject(),
135 0 : fLogger(new AliMUONLogger(20000)),
136 0 : fStatusMaker(0x0),
137 0 : fStatusMapMaker(0x0),
138 0 : fPedestals(0x0),
139 0 : fNumberOfBadPads(0),
140 0 : fNumberOfPads(0),
141 0 : fChargeSigmaCut(0),
142 0 : fMask(0)
143 0 : {
144 : /// ctor
145 :
146 0 : Ctor(calib,0x0);
147 0 : }
148 :
149 : //_____________________________________________________________________________
150 : void
151 : AliMUONDigitCalibrator::Ctor(const AliMUONCalibrationData& calib,
152 : const AliMUONRecoParam* recoParams,
153 : Bool_t deferredInitialization)
154 : {
155 : /// designated ctor
156 :
157 : // Load mapping manu store
158 2 : if ( ! AliMpCDB::LoadManuStore() ) {
159 0 : AliFatal("Could not access manu store from OCDB !");
160 0 : }
161 :
162 4 : fStatusMaker = new AliMUONPadStatusMaker(calib);
163 :
164 : // Set default values, as loose as reasonable
165 :
166 2 : fChargeSigmaCut = 3.0;
167 :
168 2 : fMask = 0x8080; // reject pads where ped *or* hv are missing
169 :
170 2 : if ( recoParams )
171 : {
172 : // if we have reco params, we use limits and cuts from there :
173 :
174 2 : fStatusMaker->SetLimits(*recoParams);
175 :
176 2 : fMask = recoParams->PadGoodnessMask();
177 : //WARNING : getting this mask wrong is a very effective way of getting
178 : //no digits at all out of this class ;-)
179 :
180 2 : fChargeSigmaCut = recoParams->ChargeSigmaCut();
181 2 : }
182 : else
183 : {
184 0 : fLogger->Log("No RecoParam available");
185 0 : fLogger->Log(Form("SigmaCut=%e",fChargeSigmaCut));
186 : }
187 :
188 4 : fStatusMapMaker = new AliMUONPadStatusMapMaker(*fStatusMaker,fMask,deferredInitialization);
189 :
190 2 : fPedestals = calib.Pedestals();
191 2 : }
192 :
193 : //_____________________________________________________________________________
194 : AliMUONDigitCalibrator::~AliMUONDigitCalibrator()
195 12 : {
196 : /// dtor.
197 :
198 2 : if ( fNumberOfPads > 0 )
199 : {
200 2 : if ( fStatusMaker )
201 : {
202 2 : fStatusMaker->Report(fMask);
203 : }
204 :
205 4 : AliInfo("Summary of messages:");
206 :
207 2 : fLogger->Print();
208 :
209 10 : AliInfo(Form("We have seen %g pads, and rejected %g (%7.2f %%)",
210 : fNumberOfPads,fNumberOfBadPads,
211 : ( fNumberOfPads > 0 ) ? fNumberOfBadPads*100.0/fNumberOfPads : 0 ));
212 : }
213 :
214 4 : delete fStatusMaker;
215 4 : delete fStatusMapMaker;
216 4 : delete fLogger;
217 6 : }
218 :
219 : //_____________________________________________________________________________
220 : void
221 : AliMUONDigitCalibrator::Calibrate(AliMUONVDigitStore& digitStore)
222 : {
223 : /// Calibrate the digits contained in digitStore
224 16 : TIter next(digitStore.CreateTrackerIterator());
225 : AliMUONVDigit* digit;
226 :
227 8 : fStatusMapMaker->RefreshRejectProbabilities(); // this will do something only for simulations
228 : // (and only for those simulations where the reject list contain probabilities which are
229 : // different from zero or one)
230 :
231 40 : AliDebug(1,Form("# of digits = %d",digitStore.GetSize()));
232 :
233 4264 : while ( ( digit = static_cast<AliMUONVDigit*>(next() ) ) )
234 : {
235 2832 : if ( digit->IsCalibrated() )
236 : {
237 0 : fLogger->Log("ERROR : trying to calibrate a digit twice");
238 0 : return;
239 : }
240 :
241 1416 : digit->Calibrated(kTRUE);
242 1416 : digit->ChargeInFC(kTRUE);
243 :
244 : Float_t charge(0.0);
245 1416 : Int_t statusMap;
246 1416 : Bool_t isSaturated(kFALSE);
247 :
248 1416 : ++fNumberOfPads;
249 :
250 7080 : Bool_t ok = IsValidDigit(digit->DetElemId(),digit->ManuId(),digit->ManuChannel(),&statusMap);
251 :
252 1416 : digit->SetStatusMap(statusMap);
253 :
254 1416 : if (ok)
255 : {
256 5664 : charge = CalibrateDigit(digit->DetElemId(),digit->ManuId(),digit->ManuChannel(),
257 2832 : digit->ADC(),fChargeSigmaCut,&isSaturated);
258 1416 : }
259 : else
260 : {
261 0 : ++fNumberOfBadPads;
262 : }
263 :
264 1416 : digit->SetCharge(charge);
265 1416 : digit->Saturated(isSaturated);
266 :
267 1416 : }
268 16 : }
269 :
270 : //_____________________________________________________________________________
271 : Float_t
272 : AliMUONDigitCalibrator::CalibrateDigit(Int_t detElemId, Int_t manuId, Int_t manuChannel,
273 : Float_t adc, Float_t nsigmas,
274 : Bool_t* isSaturated) const
275 :
276 : {
277 : /// Calibrate one digit
278 : /// Return the digit charge, in fC
279 :
280 2832 : if ( nsigmas < 0 )
281 : {
282 0 : nsigmas = fChargeSigmaCut;
283 0 : }
284 :
285 1416 : fLogger->Log(Form("ChargeSigmaCut used = %e",nsigmas));
286 :
287 1416 : AliMUONVCalibParam* pedestal = static_cast<AliMUONVCalibParam*>
288 1416 : (fPedestals->FindObject(detElemId,manuId));
289 :
290 1416 : if (!pedestal)
291 : {
292 : // no pedestal -> no charge
293 0 : fLogger->Log(Form("Got a null pedestal object for DE,manu=%d,%d",detElemId,manuId));
294 0 : return 0.0;
295 : }
296 :
297 1416 : Float_t padc = adc-pedestal->ValueAsFloat(manuChannel,0);
298 :
299 : // Gain (mV/fC) = 1/(a0*capa) with a0~1.25 and capa~0.2
300 : Float_t charge(0);
301 1416 : Float_t capa(AliMUONConstants::DefaultCapa()); // capa = 0.2 and a0 = 1.25
302 1416 : Float_t a0(AliMUONConstants::DefaultA0()); // is equivalent to gain = 4 mV/fC
303 1416 : Float_t adc2mv(AliMUONConstants::DefaultADC2MV()); // 1 ADC channel = 0.61 mV
304 : //
305 : // Note that the ChargeMax (for one pad) is roughly 4096 * 0.61 mV/channel / 4 mV/fC = 625 fC
306 :
307 1416 : if ( padc > nsigmas*pedestal->ValueAsFloat(manuChannel,1) )
308 : {
309 1324 : charge = a0*padc*capa*adc2mv;
310 1324 : }
311 :
312 1416 : if ( isSaturated )
313 : {
314 : const Int_t saturation(3000);
315 :
316 1416 : if ( padc >= saturation )
317 : {
318 0 : *isSaturated = kTRUE;
319 0 : }
320 : else
321 : {
322 1416 : *isSaturated = kFALSE;
323 : }
324 1416 : }
325 :
326 1416 : return ( charge > 0.0 ? charge : 0.0 );
327 1416 : }
328 :
329 : //_____________________________________________________________________________
330 : Bool_t
331 : AliMUONDigitCalibrator::IsValidDigit(Int_t detElemId, Int_t manuId, Int_t manuChannel,
332 : Int_t* statusMap) const
333 :
334 : {
335 : /// Check if a given pad is ok or not.
336 :
337 : // initialize the statusmap to dead by default
338 4248 : if (statusMap) *statusMap = AliMUONPadStatusMapMaker::SelfDeadMask();
339 :
340 : // First a protection against bad input parameters
341 1416 : AliMpDetElement* de = AliMpDDLStore::Instance()->GetDetElement(detElemId);
342 1416 : if (!de) return kFALSE; // not existing DE
343 1416 : if (!de->IsExistingChannel(manuId,manuChannel))
344 : {
345 : // non-existing (might happen when we get parity errors in read-out
346 : // that spoils the manuId
347 0 : return kFALSE;
348 : }
349 1416 : if (!de->IsConnectedChannel(manuId,manuChannel))
350 : {
351 : // existing (in read-out), but not connected channel
352 0 : return kFALSE;
353 : }
354 :
355 : // ok, now we have a valid channel number, so let's see if that pad
356 : // behaves or not ;-)
357 :
358 1416 : Int_t sm = StatusMap(detElemId,manuId,manuChannel);
359 :
360 2832 : if (statusMap) *statusMap = sm;
361 :
362 1416 : if ( ( sm & AliMUONPadStatusMapMaker::SelfDeadMask() ) != 0 )
363 : {
364 : // pad itself is bad (not testing its neighbours at this stage)
365 0 : return kFALSE;
366 : }
367 :
368 1416 : return kTRUE;
369 1416 : }
370 :
371 : //_____________________________________________________________________________
372 : Int_t
373 : AliMUONDigitCalibrator::PadStatus(Int_t detElemId, Int_t manuId, Int_t manuChannel) const
374 : {
375 : /// Return the status of the given pad
376 0 : return fStatusMaker->PadStatus(detElemId,manuId,manuChannel);
377 : }
378 :
379 : //_____________________________________________________________________________
380 : Int_t
381 : AliMUONDigitCalibrator::StatusMap(Int_t detElemId, Int_t manuId, Int_t manuChannel) const
382 : {
383 : /// Return the status map of the given pad
384 2832 : return fStatusMapMaker->StatusMap(detElemId,manuId,manuChannel);
385 :
386 : }
387 :
|