Being more realistic with gain calibration (Laurent)
[u/mrichter/AliRoot.git] / MUON / AliMUONDigitCalibrator.cxx
CommitLineData
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
d99769c3 20#include "AliLog.h"
42825ed9 21#include "AliMpConstants.h"
d99769c3 22#include "AliMUONCalibrationData.h"
42825ed9 23#include "AliMUONVDigit.h"
24#include "AliMUONVDigitStore.h"
fe6ed686 25#include "AliMUONLogger.h"
d1c20d08 26#include "AliMUONPadStatusMaker.h"
27#include "AliMUONPadStatusMapMaker.h"
42825ed9 28#include "AliMUONVStore.h"
c795d086 29#include "AliMUONVCalibParam.h"
d99769c3 30
7945aae7 31/// \class AliMUONDigitCalibrator
1171bb0a 32/// Class used to calibrate digits (either real or simulated ones).
33///
34/// The calibration consists of subtracting the pedestal
35/// and multiplying by a gain, so that
36/// Signal = (ADC-pedestal)*gain
37///
38/// Please note also that for the moment, if a digit lies on a dead channel
39/// we remove this digit from the list of digits.
40/// FIXME: this has to be revisited. By using the AliMUONDigit::fFlags we
41/// should in principle flag a digit as bad w/o removing it, but this
42/// then requires some changes in the cluster finder to deal with this extra
43/// information correctly (e.g. to set a quality for the cluster if it contains
44/// bad digits).
45///
7945aae7 46/// \author Laurent Aphecetche
47
1171bb0a 48
7945aae7 49/// \cond CLASSIMP
d99769c3 50ClassImp(AliMUONDigitCalibrator)
7945aae7 51/// \endcond
d99769c3 52
53//_____________________________________________________________________________
42825ed9 54AliMUONDigitCalibrator::AliMUONDigitCalibrator(const AliMUONCalibrationData& calib,
20356e33 55 Bool_t createAndUseStatusMap)
42825ed9 56: TObject(),
57fCalibrationData(calib),
58fStatusMap(0x0),
59fLogger(new AliMUONLogger(1000))
d99769c3 60{
42825ed9 61 /// ctor
62 if (createAndUseStatusMap)
63 {
64 AliMUONPadStatusMaker maker(fCalibrationData);
d1c20d08 65
42825ed9 66 // this is here that we decide on our "goodness" policy, i.e.
67 // what do we call an invalid pad (a pad maybe bad because its HV
68 // was too low, or its pedestals too high, etc..)
69 // FIXME: find a way not to hard-code the goodness policy (i.e. the limits)
70 // here...
71 maker.SetHVSt12Limits(1300,1600);
72 maker.SetHVSt345Limits(1500,2000);
73 maker.SetPedMeanLimits(50,200);
74 maker.SetPedSigmaLimits(0.1,3);
d1c20d08 75
42825ed9 76 // From this set of limits, compute the status of all tracker pads.
77 AliMUONVStore* status = maker.MakeStatus();
78 // we do not check that status is != 0x0, as this is supposed to be
79 // the responsability of the padStatusMaker.
80
81 AliMUONPadStatusMapMaker mapMaker(fCalibrationData);
82
83 Int_t mask(0x8080);
84 //FIXME: kind of fake one for the moment, we consider dead only
85 // if ped and/or hv value missing.
86 //WARNING : getting this mask wrong is a very effective way of getting
87 //no digits at all out of this class ;-)
88
89 fStatusMap = mapMaker.MakePadStatusMap(*status,mask);
90
91 delete status;
20356e33 92 }
42825ed9 93 else
94 {
95 // make a fake (empty) status map
96 fStatusMap = AliMUONPadStatusMapMaker::MakeEmptyPadStatusMap();
97 }
d99769c3 98}
99
100//_____________________________________________________________________________
101AliMUONDigitCalibrator::~AliMUONDigitCalibrator()
102{
d1c20d08 103 /// dtor.
104 delete fStatusMap;
fe6ed686 105
106 AliInfo("Summary of messages:");
107 fLogger->Print();
108
109 delete fLogger;
d99769c3 110}
111
112//_____________________________________________________________________________
113void
42825ed9 114AliMUONDigitCalibrator::Calibrate(AliMUONVDigitStore& digitStore)
d99769c3 115{
42825ed9 116 /// Calibrate the digits contained in digitStore
117 TIter next(digitStore.CreateTrackerIterator());
118 AliMUONVDigit* digit;
c795d086 119
42825ed9 120 while ( ( digit = static_cast<AliMUONVDigit*>(next() ) ) )
d99769c3 121 {
42825ed9 122 CalibrateDigit(*digit);
123 }
124}
125
126//_____________________________________________________________________________
127void
128AliMUONDigitCalibrator::CalibrateDigit(AliMUONVDigit& digit)
129{
130 /// Calibrate one digit
131
cf27231a 132 if ( digit.IsCalibrated() )
133 {
134 fLogger->Log("ERROR : trying to calibrate a digit twice");
135 return;
136 }
137
42825ed9 138 AliMUONVCalibParam* deadmap = static_cast<AliMUONVCalibParam*>
139 (fStatusMap->FindObject(digit.DetElemId(),digit.ManuId()));
140 Int_t statusMap = deadmap->ValueAsInt(digit.ManuChannel());
141 digit.SetStatusMap(statusMap);
142 digit.Calibrated(kTRUE);
143 if ( ( statusMap & AliMUONPadStatusMapMaker::SelfDeadMask() ) != 0 )
144 {
145 // pad itself is bad (not testing its neighbours at this stage)
146 digit.SetCharge(0);
147 fLogger->Log(Form("%s:%d:Channel detElemId %d manuId %d "
148 "manuChannel %d is bad %x",__FILE__,__LINE__,
149 digit.DetElemId(),digit.ManuId(),
150 digit.ManuChannel(),digit.StatusMap()));
151 }
152 else
153 {
154 // If the channel is good, go on with the calibration itself.
155
156 AliMUONVCalibParam* pedestal = static_cast<AliMUONVCalibParam*>
157 (fCalibrationData.Pedestals(digit.DetElemId(),digit.ManuId()));
158
159 AliMUONVCalibParam* gain = static_cast<AliMUONVCalibParam*>
160 (fCalibrationData.Gains(digit.DetElemId(),digit.ManuId()));
161
162 if (!pedestal)
d99769c3 163 {
42825ed9 164 AliFatal(Form("Got a null ped object for DE,manu=%d,%d",
165 digit.DetElemId(),digit.ManuId()));
c795d086 166
42825ed9 167 }
168 if (!gain)
169 {
170 AliFatal(Form("Got a null gain object for DE,manu=%d,%d",
171 digit.DetElemId(),digit.ManuId()));
172 }
173
174 Int_t manuChannel = digit.ManuChannel();
175 Float_t adc = digit.ADC();
176 Float_t padc = adc-pedestal->ValueAsFloat(manuChannel,0);
cf27231a 177 Float_t charge(0);
178 if ( padc > 3.0*pedestal->ValueAsFloat(manuChannel,1) )
42825ed9 179 {
cf27231a 180 Float_t a0 = gain->ValueAsFloat(manuChannel,0);
181 Float_t a1 = gain->ValueAsFloat(manuChannel,1);
182 Int_t thres = gain->ValueAsInt(manuChannel,2);
183 if ( padc < thres )
184 {
185 charge = a0*padc;
186 }
187 else
188 {
189 charge = a0*thres + a0*padc + a1*padc*padc;
190 }
42825ed9 191 }
42825ed9 192 digit.SetCharge(charge);
cf27231a 193 Int_t saturation = gain->ValueAsInt(manuChannel,4);
42825ed9 194 if ( charge >= saturation )
195 {
196 digit.Saturated(kTRUE);
d99769c3 197 }
198 }
199}