]> git.uio.no Git - u/mrichter/AliRoot.git/blame_incremental - MUON/AliMUONDigitCalibrator.cxx
Iteration number stored into output file
[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 "AliMUONVCalibParam.h"
26#include "AliMUONVDigit.h"
27#include "AliMUONVDigitStore.h"
28#include "AliMUONVStore.h"
29#include "AliMpBusPatch.h"
30#include "AliMpConstants.h"
31#include "AliMpDDLStore.h"
32#include "AliMpDEIterator.h"
33#include "AliMpDetElement.h"
34
35//-----------------------------------------------------------------------------
36/// \class AliMUONDigitCalibrator
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///
51/// \author Laurent Aphecetche
52//-----------------------------------------------------------------------------
53
54
55/// \cond CLASSIMP
56ClassImp(AliMUONDigitCalibrator)
57/// \endcond
58
59const Int_t AliMUONDigitCalibrator::fgkNoGain(0);
60const Int_t AliMUONDigitCalibrator::fgkGainConstantCapa(1);
61const Int_t AliMUONDigitCalibrator::fgkGain(2);
62
63//_____________________________________________________________________________
64AliMUONDigitCalibrator::AliMUONDigitCalibrator(const AliMUONCalibrationData& calib,
65 const char* calibMode)
66: TObject(),
67fLogger(new AliMUONLogger(20000)),
68fStatusMaker(0x0),
69fStatusMapMaker(0x0),
70fPedestals(0x0),
71fGains(0x0),
72fApplyGains(0),
73fCapacitances(0x0)
74{
75 /// ctor
76
77 TString cMode(calibMode);
78 cMode.ToUpper();
79
80 if ( cMode == "NOGAIN" )
81 {
82 fApplyGains = fgkNoGain;
83 AliInfo("Will NOT apply gain correction");
84 }
85 else if ( cMode == "GAINCONSTANTCAPA" )
86 {
87 fApplyGains = fgkGainConstantCapa;
88 AliInfo("Will apply gain correction, but with constant capacitance");
89 }
90 else if ( cMode == "GAIN" )
91 {
92 fApplyGains = fgkGain;
93 AliInfo("Will apply gain correction, with measured capacitances");
94 }
95 else
96 {
97 AliError(Form("Invalid calib mode = %s. Will use NOGAIN instead",calibMode));
98 fApplyGains = fgkNoGain;
99 }
100
101 fStatusMaker = new AliMUONPadStatusMaker(calib);
102
103 // this is here that we decide on our "goodness" policy, i.e.
104 // what do we call an invalid pad (a pad maybe bad because its HV
105 // was too low, or its pedestals too high, etc..)
106 // FIXME: find a way not to hard-code the goodness policy (i.e. the limits)
107 // here...
108 fStatusMaker->SetHVSt12Limits(1300,1600);
109 fStatusMaker->SetHVSt345Limits(1500,2000);
110 fStatusMaker->SetPedMeanLimits(50,200);
111 fStatusMaker->SetPedSigmaLimits(0.1,3);
112
113 Int_t mask(0x8080);
114 //FIXME: kind of fake one for the moment, we consider dead only
115 // if ped and/or hv value missing.
116 //WARNING : getting this mask wrong is a very effective way of getting
117 //no digits at all out of this class ;-)
118
119 Bool_t deferredInitialization = kTRUE;
120
121 fStatusMapMaker = new AliMUONPadStatusMapMaker(*fStatusMaker,mask,deferredInitialization);
122
123 fPedestals = calib.Pedestals();
124
125 fGains = calib.Gains(); // we get gains whatever the calibMode is, in order
126 // to get the saturation value...
127
128 if ( fApplyGains == fgkGain )
129 {
130 fCapacitances = calib.Capacitances();
131 }
132}
133
134//_____________________________________________________________________________
135AliMUONDigitCalibrator::~AliMUONDigitCalibrator()
136{
137 /// dtor.
138 delete fStatusMaker;
139 delete fStatusMapMaker;
140
141 AliInfo("Summary of messages:");
142 fLogger->Print();
143
144 delete fLogger;
145}
146
147//_____________________________________________________________________________
148void
149AliMUONDigitCalibrator::Calibrate(AliMUONVDigitStore& digitStore)
150{
151 /// Calibrate the digits contained in digitStore
152 TIter next(digitStore.CreateTrackerIterator());
153 AliMUONVDigit* digit;
154 Int_t detElemId(-1);
155 Double_t nsigmas(3.0);
156
157 AliDebug(1,Form("# of digits = %d",digitStore.GetSize()));
158
159 while ( ( digit = static_cast<AliMUONVDigit*>(next() ) ) )
160 {
161 if ( digit->DetElemId() != detElemId )
162 {
163 // Find out occupancy of that DE
164 detElemId = digit->DetElemId();
165 AliMpDetElement* de = AliMpDDLStore::Instance()->GetDetElement(detElemId);
166 Double_t nchannels = de->NofChannels();
167 Double_t occ = digitStore.GetSize(detElemId)/nchannels;
168 if ( occ > 0.05 )
169 {
170 nsigmas = 10.0; // enlarge (a lot) sigma cut if occupancy is high
171 // (which probably means zero suppression was not exactly OK).
172 fLogger->Log(Form("Will use %5.0f*sigma cut for DE %04d "
173 "due to high occupancy",nsigmas,detElemId));
174 }
175 else
176 {
177 nsigmas = 3.0;
178 }
179 }
180
181 CalibrateDigit(*digit,nsigmas);
182 }
183}
184
185//_____________________________________________________________________________
186void
187AliMUONDigitCalibrator::CalibrateDigit(AliMUONVDigit& digit, Double_t nsigmas)
188{
189 /// Calibrate one digit
190
191 if ( digit.IsCalibrated() )
192 {
193 fLogger->Log("ERROR : trying to calibrate a digit twice");
194 return;
195 }
196
197 Int_t statusMap = fStatusMapMaker->StatusMap(digit.DetElemId(),
198 digit.ManuId(),
199 digit.ManuChannel());
200
201 digit.SetStatusMap(statusMap);
202 digit.Calibrated(kTRUE);
203
204 if ( ( statusMap & AliMUONPadStatusMapMaker::SelfDeadMask() ) != 0 )
205 {
206 // pad itself is bad (not testing its neighbours at this stage)
207 digit.SetCharge(0);
208 fLogger->Log(Form("%s:%d:Channel detElemId %d manuId %d "
209 "manuChannel %d is bad %x",__FILE__,__LINE__,
210 digit.DetElemId(),digit.ManuId(),
211 digit.ManuChannel(),digit.StatusMap()));
212 }
213 else
214 {
215 // If the channel is good, go on with the calibration itself.
216
217 AliMUONVCalibParam* pedestal = static_cast<AliMUONVCalibParam*>
218 (fPedestals->FindObject(digit.DetElemId(),digit.ManuId()));
219
220 if (!pedestal)
221 {
222 // no pedestal -> no charge
223 digit.SetCharge(0);
224
225 fLogger->Log(Form("Got a null pedestal object for DE,manu=%d,%d",
226 digit.DetElemId(),digit.ManuId()));
227 return;
228 }
229
230
231 AliMUONVCalibParam* gain = static_cast<AliMUONVCalibParam*>
232 (fGains->FindObject(digit.DetElemId(),digit.ManuId()));
233
234 if (!gain)
235 {
236 if ( fApplyGains != fgkNoGain )
237 {
238 // no gain -> no charge
239 digit.SetCharge(0);
240
241 fLogger->Log(Form("Got a null gain object for DE,manu=%d,%d",
242 digit.DetElemId(),digit.ManuId()));
243 return;
244 }
245 }
246
247 Int_t manuChannel = digit.ManuChannel();
248 Float_t adc = digit.ADC();
249 Float_t padc = adc-pedestal->ValueAsFloat(manuChannel,0);
250 Float_t charge(0);
251 Float_t capa(1.0);
252
253 if ( fApplyGains == fgkGainConstantCapa )
254 {
255 capa = 0.2; // pF
256 }
257 else if ( fApplyGains == fgkGain )
258 {
259 AliMpDetElement* de = AliMpDDLStore::Instance()->GetDetElement(digit.DetElemId());
260
261 Int_t serialNumber = de->GetManuSerialFromId(digit.ManuId());
262
263 AliMUONVCalibParam* param = static_cast<AliMUONVCalibParam*>(fCapacitances->FindObject(serialNumber));
264
265 if ( param )
266 {
267 capa = param->ValueAsFloat(digit.ManuChannel());
268 }
269 else
270 {
271 fLogger->Log(Form("No capa found for serialNumber=%d",serialNumber));
272 capa = 0.0;
273 }
274 }
275
276 if ( padc > nsigmas*pedestal->ValueAsFloat(manuChannel,1) )
277 {
278 if ( fApplyGains != fgkNoGain )
279 {
280 Float_t a0 = gain->ValueAsFloat(manuChannel,0);
281 Float_t a1 = gain->ValueAsFloat(manuChannel,1);
282 Int_t thres = gain->ValueAsInt(manuChannel,2);
283 if ( padc < thres )
284 {
285 charge = a0*padc;
286 }
287 else
288 {
289 charge = a0*thres + a0*(padc-thres) + a1*(padc-thres)*(padc-thres);
290 }
291 }
292 else
293 {
294 charge = padc;
295 }
296 }
297
298 charge *= capa;
299 digit.SetCharge(charge);
300
301 Int_t saturation(3000);
302
303 if ( gain )
304 {
305 saturation = gain->ValueAsInt(manuChannel,4);
306 }
307
308 if ( padc >= saturation )
309 {
310 digit.Saturated(kTRUE);
311 }
312 }
313}