1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
18 #include "AliMUONDigitCalibrator.h"
21 #include "AliMUONCalibrationData.h"
22 #include "AliMUONLogger.h"
23 #include "AliMUONPadStatusMaker.h"
24 #include "AliMUONPadStatusMapMaker.h"
25 #include "AliMUONRecoParam.h"
26 #include "AliMUONVCalibParam.h"
27 #include "AliMUONVDigit.h"
28 #include "AliMUONVDigitStore.h"
29 #include "AliMUONVStore.h"
30 #include "AliMpBusPatch.h"
31 #include "AliMpConstants.h"
32 #include "AliMpDDLStore.h"
33 #include "AliMpDEIterator.h"
34 #include "AliMpDetElement.h"
36 //-----------------------------------------------------------------------------
37 /// \class AliMUONDigitCalibrator
38 /// Class used to calibrate digits (either real or simulated ones).
40 /// The calibration consists of subtracting the pedestal
41 /// and multiplying by a gain, so that
42 /// Signal = (ADC-pedestal)*gain
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
52 /// \author Laurent Aphecetche
53 //-----------------------------------------------------------------------------
57 ClassImp(AliMUONDigitCalibrator)
60 const Int_t AliMUONDigitCalibrator::fgkNoGain(0);
61 const Int_t AliMUONDigitCalibrator::fgkGainConstantCapa(1);
62 const Int_t AliMUONDigitCalibrator::fgkGain(2);
64 //_____________________________________________________________________________
65 AliMUONDigitCalibrator::AliMUONDigitCalibrator(const AliMUONCalibrationData& calib,
66 const AliMUONRecoParam* recoParams,
67 const char* calibMode)
69 fLogger(new AliMUONLogger(20000)),
82 Ctor(calibMode,calib,recoParams);
85 //_____________________________________________________________________________
86 AliMUONDigitCalibrator::AliMUONDigitCalibrator(const AliMUONCalibrationData& calib,
87 const char* calibMode)
89 fLogger(new AliMUONLogger(20000)),
102 Ctor(calibMode,calib,0x0);
105 //_____________________________________________________________________________
107 AliMUONDigitCalibrator::Ctor(const char* calibMode,
108 const AliMUONCalibrationData& calib,
109 const AliMUONRecoParam* recoParams)
113 TString cMode(calibMode);
116 if ( cMode == "NOGAIN" )
118 fApplyGains = fgkNoGain;
119 AliInfo("Will NOT apply gain correction");
121 else if ( cMode == "GAINCONSTANTCAPA" )
123 fApplyGains = fgkGainConstantCapa;
124 AliInfo("Will apply gain correction, but with constant capacitance");
126 else if ( cMode == "GAIN" )
128 fApplyGains = fgkGain;
129 AliInfo("Will apply gain correction, with measured capacitances");
133 AliError(Form("Invalid calib mode = %s. Will use NOGAIN instead",calibMode));
134 fApplyGains = fgkNoGain;
137 fStatusMaker = new AliMUONPadStatusMaker(calib);
139 // Set default values, as loose as reasonable
141 fChargeSigmaCut = 3.0;
143 Int_t mask(0x8080); // reject pads where ped *or* hv are missing
147 // if we have reco params, we use limits and cuts from there :
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());
157 mask = recoParams->PadGoodnessMask();
158 //WARNING : getting this mask wrong is a very effective way of getting
159 //no digits at all out of this class ;-)
161 fChargeSigmaCut = recoParams->ChargeSigmaCut();
164 Bool_t deferredInitialization = kTRUE;
166 fStatusMapMaker = new AliMUONPadStatusMapMaker(*fStatusMaker,mask,deferredInitialization);
168 fPedestals = calib.Pedestals();
170 fGains = calib.Gains(); // we get gains whatever the calibMode is, in order
171 // to get the saturation value...
173 if ( fApplyGains == fgkGain )
175 fCapacitances = calib.Capacitances();
179 //_____________________________________________________________________________
180 AliMUONDigitCalibrator::~AliMUONDigitCalibrator()
184 delete fStatusMapMaker;
186 AliInfo("Summary of messages:");
189 AliInfo(Form("We have seen %g pads, and rejected %g (%7.2f %%)",
190 fNumberOfPads,fNumberOfBadPads,
191 ( fNumberOfPads > 0 ) ? fNumberOfBadPads*100.0/fNumberOfPads : 0 ));
196 //_____________________________________________________________________________
198 AliMUONDigitCalibrator::Calibrate(AliMUONVDigitStore& digitStore)
200 /// Calibrate the digits contained in digitStore
201 TIter next(digitStore.CreateTrackerIterator());
202 AliMUONVDigit* digit;
204 Double_t nsigmas = fChargeSigmaCut;
206 AliDebug(1,Form("# of digits = %d",digitStore.GetSize()));
208 while ( ( digit = static_cast<AliMUONVDigit*>(next() ) ) )
210 if ( digit->IsCalibrated() )
212 fLogger->Log("ERROR : trying to calibrate a digit twice");
216 digit->Calibrated(kTRUE);
218 if ( digit->DetElemId() != detElemId )
220 // Find out occupancy of that DE
221 detElemId = digit->DetElemId();
222 AliMpDetElement* de = AliMpDDLStore::Instance()->GetDetElement(detElemId);
223 Double_t nchannels = de->NofChannels();
224 Double_t occ = digitStore.GetSize(detElemId)/nchannels;
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));
234 nsigmas = fChargeSigmaCut;
240 Bool_t isSaturated(kFALSE);
242 Bool_t ok = IsValidDigit(digit->DetElemId(),digit->ManuId(),digit->ManuChannel(),&statusMap);
244 digit->SetStatusMap(statusMap);
249 charge = CalibrateDigit(digit->DetElemId(),digit->ManuId(),digit->ManuChannel(),
250 digit->ADC(),nsigmas,&isSaturated);
257 digit->SetCharge(charge);
258 digit->Saturated(isSaturated);
262 //_____________________________________________________________________________
264 AliMUONDigitCalibrator::CalibrateDigit(Int_t detElemId, Int_t manuId, Int_t manuChannel,
265 Float_t adc, Float_t nsigmas,
266 Bool_t* isSaturated) const
269 /// Calibrate one digit
272 AliMUONVCalibParam* pedestal = static_cast<AliMUONVCalibParam*>
273 (fPedestals->FindObject(detElemId,manuId));
277 // no pedestal -> no charge
278 fLogger->Log(Form("Got a null pedestal object for DE,manu=%d,%d",detElemId,manuId));
283 AliMUONVCalibParam* gain = static_cast<AliMUONVCalibParam*>
284 (fGains->FindObject(detElemId,manuId));
288 if ( fApplyGains != fgkNoGain )
290 // no gain -> no charge
291 fLogger->Log(Form("Got a null gain object for DE,manu=%d,%d",
297 Float_t padc = adc-pedestal->ValueAsFloat(manuChannel,0);
301 if ( fApplyGains == fgkGainConstantCapa )
305 else if ( fApplyGains == fgkGain )
307 AliMpDetElement* de = AliMpDDLStore::Instance()->GetDetElement(detElemId);
309 Int_t serialNumber = de->GetManuSerialFromId(manuId);
311 AliMUONVCalibParam* param = static_cast<AliMUONVCalibParam*>(fCapacitances->FindObject(serialNumber));
315 capa = param->ValueAsFloat(manuChannel);
319 fLogger->Log(Form("No capa found for serialNumber=%d",serialNumber));
324 if ( padc > nsigmas*pedestal->ValueAsFloat(manuChannel,1) )
326 if ( fApplyGains != fgkNoGain )
328 Float_t a0 = gain->ValueAsFloat(manuChannel,0);
329 Float_t a1 = gain->ValueAsFloat(manuChannel,1);
330 Int_t thres = gain->ValueAsInt(manuChannel,2);
337 charge = a0*thres + a0*(padc-thres) + a1*(padc-thres)*(padc-thres);
350 Int_t saturation(3000);
354 saturation = gain->ValueAsInt(manuChannel,4);
357 if ( padc >= saturation )
359 *isSaturated = kTRUE;
363 isSaturated = kFALSE;
370 //_____________________________________________________________________________
372 AliMUONDigitCalibrator::IsValidDigit(Int_t detElemId, Int_t manuId, Int_t manuChannel,
373 Int_t* statusMap) const
376 /// Check if a given pad is ok or not.
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))
383 // non-existing (might happen when we get parity errors in read-out
384 // that spoils the manuId
387 if (!de->IsConnectedChannel(manuId,manuChannel))
389 // existing (in read-out), but not connected channel
393 // ok, now we have a valid channel number, so let's see if that pad
394 // behaves or not ;-)
396 Int_t sm = fStatusMapMaker->StatusMap(detElemId,manuId,manuChannel);
398 if (statusMap) *statusMap = sm;
400 if ( ( sm & AliMUONPadStatusMapMaker::SelfDeadMask() ) != 0 )
402 // pad itself is bad (not testing its neighbours at this stage)
409 //_____________________________________________________________________________
411 AliMUONDigitCalibrator::PadStatus(Int_t detElemId, Int_t manuId, Int_t manuChannel) const
413 /// Return the status of the given pad
414 return fStatusMaker->PadStatus(detElemId,manuId,manuChannel);
417 //_____________________________________________________________________________
419 AliMUONDigitCalibrator::StatusMap(Int_t detElemId, Int_t manuId, Int_t manuChannel) const
421 /// Return the status map of the given pad
422 return fStatusMapMaker->StatusMap(detElemId,manuId,manuChannel);