#include "AliMUONDigitCalibrator.h"
-#include "AliLog.h"
#include "AliMUONCalibrationData.h"
-#include "AliMUONConstants.h"
-#include "AliMUONData.h"
-#include "AliMUONDigit.h"
+#include "AliMUONVDigit.h"
+#include "AliMUONVDigitStore.h"
+#include "AliMUONLogger.h"
+#include "AliMUONPadStatusMaker.h"
+#include "AliMUONPadStatusMapMaker.h"
+#include "AliMUONVStore.h"
#include "AliMUONVCalibParam.h"
-#include "TClonesArray.h"
+#include "AliMpConstants.h"
+#include "AliMpDetElement.h"
+#include "AliMpDDLStore.h"
+#include "AliLog.h"
-///
+//-----------------------------------------------------------------------------
+/// \class AliMUONDigitCalibrator
/// Class used to calibrate digits (either real or simulated ones).
///
/// The calibration consists of subtracting the pedestal
/// information correctly (e.g. to set a quality for the cluster if it contains
/// bad digits).
///
+/// \author Laurent Aphecetche
+//-----------------------------------------------------------------------------
+
+/// \cond CLASSIMP
ClassImp(AliMUONDigitCalibrator)
+/// \endcond
-//_____________________________________________________________________________
-AliMUONDigitCalibrator::AliMUONDigitCalibrator(AliMUONData* muonData,
- AliMUONCalibrationData* calib)
-: TTask("AliMUONDigitCalibrator","Subtract pedestal from digit charge"),
- fData(muonData),
- fCalibrationData(calib)
-{
- //
- // ctor. This class need the muonData to get access to the digit,
- // and the calibrationData to get access to calibration parameters.
- //
-}
+const Int_t AliMUONDigitCalibrator::fgkNoGain(0);
+const Int_t AliMUONDigitCalibrator::fgkGainConstantCapa(1);
+const Int_t AliMUONDigitCalibrator::fgkGain(2);
//_____________________________________________________________________________
-AliMUONDigitCalibrator::AliMUONDigitCalibrator(const AliMUONDigitCalibrator&)
-: TTask()
+AliMUONDigitCalibrator::AliMUONDigitCalibrator(const AliMUONCalibrationData& calib,
+ const char* calibMode)
+: TObject(),
+fLogger(new AliMUONLogger(20000)),
+fStatusMaker(0x0),
+fStatusMapMaker(0x0),
+fPedestals(0x0),
+fGains(0x0),
+fApplyGains(0),
+fCapacitances(0x0)
{
- AliFatal("Implement me if needed");
+ /// ctor
+
+ TString cMode(calibMode);
+ cMode.ToUpper();
+
+ if ( cMode == "NOGAIN" )
+ {
+ fApplyGains = fgkNoGain;
+ AliInfo("Will NOT apply gain correction");
+ }
+ else if ( cMode == "GAINCONSTANTCAPA" )
+ {
+ fApplyGains = fgkGainConstantCapa;
+ AliInfo("Will apply gain correction, but with constant capacitance");
+ }
+ else if ( cMode == "GAIN" )
+ {
+ fApplyGains = fgkGain;
+ AliInfo("Will apply gain correction, with measured capacitances");
+ }
+ else
+ {
+ AliError(Form("Invalid calib mode = %s. Will use NOGAIN instead",calibMode));
+ fApplyGains = fgkNoGain;
+ }
+
+ fStatusMaker = new AliMUONPadStatusMaker(calib);
+
+ // this is here that we decide on our "goodness" policy, i.e.
+ // what do we call an invalid pad (a pad maybe bad because its HV
+ // was too low, or its pedestals too high, etc..)
+ // FIXME: find a way not to hard-code the goodness policy (i.e. the limits)
+ // here...
+ fStatusMaker->SetHVSt12Limits(1300,1600);
+ fStatusMaker->SetHVSt345Limits(1500,2000);
+ fStatusMaker->SetPedMeanLimits(50,200);
+ fStatusMaker->SetPedSigmaLimits(0.1,3);
+
+ Int_t mask(0x8080);
+ //FIXME: kind of fake one for the moment, we consider dead only
+ // if ped and/or hv value missing.
+ //WARNING : getting this mask wrong is a very effective way of getting
+ //no digits at all out of this class ;-)
+
+ Bool_t deferredInitialization = kTRUE;
+
+ fStatusMapMaker = new AliMUONPadStatusMapMaker(*fStatusMaker,mask,deferredInitialization);
+
+ fPedestals = calib.Pedestals();
+
+ fGains = calib.Gains(); // we get gains whatever the calibMode is, in order
+ // to get the saturation value...
+
+ if ( fApplyGains == fgkGain )
+ {
+ fCapacitances = calib.Capacitances();
+ }
}
//_____________________________________________________________________________
-AliMUONDigitCalibrator&
-AliMUONDigitCalibrator::operator=(const AliMUONDigitCalibrator&)
+AliMUONDigitCalibrator::~AliMUONDigitCalibrator()
{
- AliFatal("Implement me if needed");
- return *this;
+ /// dtor.
+ delete fStatusMaker;
+ delete fStatusMapMaker;
+
+ AliInfo("Summary of messages:");
+ fLogger->Print();
+
+ delete fLogger;
}
//_____________________________________________________________________________
-AliMUONDigitCalibrator::~AliMUONDigitCalibrator()
+void
+AliMUONDigitCalibrator::Calibrate(AliMUONVDigitStore& digitStore)
{
- //
- // empty dtor.
- //
+ /// Calibrate the digits contained in digitStore
+ TIter next(digitStore.CreateTrackerIterator());
+ AliMUONVDigit* digit;
+
+ while ( ( digit = static_cast<AliMUONVDigit*>(next() ) ) )
+ {
+ CalibrateDigit(*digit);
+ }
}
//_____________________________________________________________________________
void
-AliMUONDigitCalibrator::Exec(Option_t*)
+AliMUONDigitCalibrator::CalibrateDigit(AliMUONVDigit& digit)
{
- //
- // Main method.
- // We loop on tracking chambers (i.e. we do nothing for trigger)
- // and for each digit in that chamber, we calibrate it :
- // a) if the corresponding channel is known to be bad, we set the signal to 0
- // (so that digit can be suppressed later on)
- // b) we then apply pedestal and gain corrections.
+ /// Calibrate one digit
+
+ if ( digit.IsCalibrated() )
+ {
+ fLogger->Log("ERROR : trying to calibrate a digit twice");
+ return;
+ }
+
+ Int_t statusMap = fStatusMapMaker->StatusMap(digit.DetElemId(),
+ digit.ManuId(),
+ digit.ManuChannel());
+
+ digit.SetStatusMap(statusMap);
+ digit.Calibrated(kTRUE);
- for ( Int_t ch = 0; ch < AliMUONConstants::NTrackingCh(); ++ch )
+ if ( ( statusMap & AliMUONPadStatusMapMaker::SelfDeadMask() ) != 0 )
{
- TClonesArray* digitArray = fData->Digits(ch);
- Int_t nDigits = digitArray->GetEntriesFast();
- for ( Int_t d = 0; d < nDigits; ++d )
+ // pad itself is bad (not testing its neighbours at this stage)
+ digit.SetCharge(0);
+ fLogger->Log(Form("%s:%d:Channel detElemId %d manuId %d "
+ "manuChannel %d is bad %x",__FILE__,__LINE__,
+ digit.DetElemId(),digit.ManuId(),
+ digit.ManuChannel(),digit.StatusMap()));
+ }
+ else
+ {
+ // If the channel is good, go on with the calibration itself.
+
+ AliMUONVCalibParam* pedestal = static_cast<AliMUONVCalibParam*>
+ (fPedestals->FindObject(digit.DetElemId(),digit.ManuId()));
+
+ if (!pedestal)
+ {
+ // no pedestal -> no charge
+ digit.SetCharge(0);
+
+ fLogger->Log(Form("Got a null pedestal object for DE,manu=%d,%d",
+ digit.DetElemId(),digit.ManuId()));
+ return;
+ }
+
+
+ AliMUONVCalibParam* gain = static_cast<AliMUONVCalibParam*>
+ (fGains->FindObject(digit.DetElemId(),digit.ManuId()));
+
+ if (!gain)
{
- AliMUONDigit* digit =
- static_cast<AliMUONDigit*>(digitArray->UncheckedAt(d));
-
- // Very first check is whether this channel is known to be bad,
- // in which case we set the signal to zero.
- AliMUONVCalibParam* dead = static_cast<AliMUONVCalibParam*>
- (fCalibrationData->DeadChannels(digit->DetElemId(),digit->ManuId()));
- if ( dead && dead->ValueAsInt(digit->ManuChannel()) )
+ if ( fApplyGains != fgkNoGain )
{
- AliWarning(Form("Removing dead channel detElemId %d manuId %d "
- "manuChannel %d",digit->DetElemId(),digit->ManuId(),
- digit->ManuChannel()));
- digit->SetSignal(0);
- continue;
+ // no gain -> no charge
+ digit.SetCharge(0);
+
+ fLogger->Log(Form("Got a null gain object for DE,manu=%d,%d",
+ digit.DetElemId(),digit.ManuId()));
+ return;
}
-
- // If the channel is good, go on with the calibration itself.
-
- AliMUONVCalibParam* pedestal = static_cast<AliMUONVCalibParam*>
- (fCalibrationData->Pedestals(digit->DetElemId(),digit->ManuId()));
+ }
+
+ Int_t manuChannel = digit.ManuChannel();
+ Float_t adc = digit.ADC();
+ Float_t padc = adc-pedestal->ValueAsFloat(manuChannel,0);
+ Float_t charge(0);
+ Float_t capa(1.0);
+
+ if ( fApplyGains == fgkGainConstantCapa )
+ {
+ capa = 0.2; // pF
+ }
+ else if ( fApplyGains == fgkGain )
+ {
+ AliMpDetElement* de = AliMpDDLStore::Instance()->GetDetElement(digit.DetElemId());
- AliMUONVCalibParam* gain = static_cast<AliMUONVCalibParam*>
- (fCalibrationData->Gains(digit->DetElemId(),digit->ManuId()));
+ Int_t serialNumber = de->GetManuSerialFromId(digit.ManuId());
+
+ AliMUONVCalibParam* param = static_cast<AliMUONVCalibParam*>(fCapacitances->FindObject(serialNumber));
- if (!pedestal)
+ if ( param )
{
- AliFatal(Form("Got a null ped object for DE,manu=%d,%d",
- digit->DetElemId(),digit->ManuId()));
-
+ capa = param->ValueAsFloat(digit.ManuChannel());
}
- if (!gain)
+ else
{
- AliFatal(Form("Got a null gain object for DE,manu=%d,%d",
- digit->DetElemId(),digit->ManuId()));
+ fLogger->Log(Form("No capa found for serialNumber=%d",serialNumber));
+ capa = 0.0;
}
-
- Int_t manuChannel = digit->ManuChannel();
- Int_t adc = digit->Signal();
- Float_t padc = adc-pedestal->ValueAsFloat(manuChannel,0);
- if ( padc < 3.0*pedestal->ValueAsFloat(manuChannel,1) )
+ }
+
+ if ( padc > 3.0*pedestal->ValueAsFloat(manuChannel,1) )
+ {
+ if ( fApplyGains != fgkNoGain )
{
- padc = 0.0;
+ Float_t a0 = gain->ValueAsFloat(manuChannel,0);
+ Float_t a1 = gain->ValueAsFloat(manuChannel,1);
+ Int_t thres = gain->ValueAsInt(manuChannel,2);
+ if ( padc < thres )
+ {
+ charge = a0*padc;
+ }
+ else
+ {
+ charge = a0*thres + a0*(padc-thres) + a1*(padc-thres)*(padc-thres);
+ }
}
- Float_t charge = padc*gain->ValueAsFloat(manuChannel,0);
- Int_t signal = TMath::Nint(charge);
- digit->SetSignal(signal);
- Int_t saturation = gain->ValueAsInt(manuChannel,1);
- if ( signal >= saturation )
+ else
{
- digit->Saturated(kTRUE);
+ charge = padc;
}
}
+
+ charge *= capa;
+ digit.SetCharge(charge);
+
+ Int_t saturation(3000);
+
+ if ( gain )
+ {
+ saturation = gain->ValueAsInt(manuChannel,4);
+ }
+
+ if ( padc >= saturation )
+ {
+ digit.Saturated(kTRUE);
+ }
}
}