X-Git-Url: http://git.uio.no/git/?a=blobdiff_plain;f=MUON%2FAliMUONDigitCalibrator.cxx;h=aecf7077aba64020ca70b872375054f3bdde71c7;hb=7d4c52b2f9aa7424f22e3092e6d9af178cc7fdcb;hp=136a611452b26e6296d2131052ae5c098293d0e9;hpb=f51d54cb3976eddcd8cba50fcd4b8b4b80ede228;p=u%2Fmrichter%2FAliRoot.git diff --git a/MUON/AliMUONDigitCalibrator.cxx b/MUON/AliMUONDigitCalibrator.cxx index 136a611452b..aecf7077aba 100644 --- a/MUON/AliMUONDigitCalibrator.cxx +++ b/MUON/AliMUONDigitCalibrator.cxx @@ -19,13 +19,24 @@ #include "AliLog.h" #include "AliMUONCalibrationData.h" -#include "AliMUONConstants.h" -#include "AliMUONData.h" -#include "AliMUONDigit.h" +#include "AliMUONLogger.h" +#include "AliMUONPadStatusMaker.h" +#include "AliMUONPadStatusMapMaker.h" +#include "AliMUONRecoParam.h" #include "AliMUONVCalibParam.h" -#include "TClonesArray.h" +#include "AliMUONVDigit.h" +#include "AliMUONVDigitStore.h" +#include "AliMUONVStore.h" +#include "AliMpBusPatch.h" +#include "AliMpConstants.h" +#include "AliMpCDB.h" +#include "AliMpDDLStore.h" +#include "AliMpDEIterator.h" +#include "AliMpDetElement.h" +#include "AliMpManuStore.h" -/// +//----------------------------------------------------------------------------- +/// \class AliMUONDigitCalibrator /// Class used to calibrate digits (either real or simulated ones). /// /// The calibration consists of subtracting the pedestal @@ -40,99 +51,383 @@ /// information correctly (e.g. to set a quality for the cluster if it contains /// bad digits). /// +/// \author Laurent Aphecetche +//----------------------------------------------------------------------------- + +/// \cond CLASSIMP ClassImp(AliMUONDigitCalibrator) +/// \endcond + +const Int_t AliMUONDigitCalibrator::fgkNoGain(0); +const Int_t AliMUONDigitCalibrator::fgkGainConstantCapa(1); +const Int_t AliMUONDigitCalibrator::fgkGain(2); + +//_____________________________________________________________________________ +AliMUONDigitCalibrator::AliMUONDigitCalibrator(const AliMUONCalibrationData& calib, + const AliMUONRecoParam* recoParams, + const char* calibMode) +: TObject(), +fLogger(new AliMUONLogger(20000)), +fStatusMaker(0x0), +fStatusMapMaker(0x0), +fPedestals(0x0), +fGains(0x0), +fApplyGains(0), +fCapacitances(0x0), +fNumberOfBadPads(0), +fNumberOfPads(0), +fChargeSigmaCut(0) +{ + /// ctor + + Ctor(calibMode,calib,recoParams); +} //_____________________________________________________________________________ -AliMUONDigitCalibrator::AliMUONDigitCalibrator(AliMUONData* muonData, - AliMUONCalibrationData* calib) -: TTask("AliMUONDigitCalibrator","Subtract pedestal from digit charge"), - fData(muonData), - fCalibrationData(calib) +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), +fNumberOfBadPads(0), +fNumberOfPads(0), +fChargeSigmaCut(0) { - // - // ctor. This class need the muonData to get access to the digit, - // and the calibrationData to get access to calibration parameters. - // + /// ctor + + Ctor(calibMode,calib,0x0); +} + +//_____________________________________________________________________________ +void +AliMUONDigitCalibrator::Ctor(const char* calibMode, + const AliMUONCalibrationData& calib, + const AliMUONRecoParam* recoParams) +{ + /// designated 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; + } + + // Load mapping manu store + if ( ! AliMpCDB::LoadManuStore() ) { + AliFatal("Could not access manu store from OCDB !"); + } + + fStatusMaker = new AliMUONPadStatusMaker(calib); + + // Set default values, as loose as reasonable + + fChargeSigmaCut = 3.0; + + Int_t mask(0x8080); // reject pads where ped *or* hv are missing + + if ( recoParams ) + { + // if we have reco params, we use limits and cuts from there : + + fStatusMaker->SetHVSt12Limits(recoParams->HVSt12LowLimit(),recoParams->HVSt12HighLimit()); + fStatusMaker->SetHVSt345Limits(recoParams->HVSt345LowLimit(),recoParams->HVSt345HighLimit()); + fStatusMaker->SetPedMeanLimits(recoParams->PedMeanLowLimit(),recoParams->PedMeanHighLimit()); + fStatusMaker->SetPedSigmaLimits(recoParams->PedSigmaLowLimit(),recoParams->PedSigmaHighLimit()); + fStatusMaker->SetGainA1Limits(recoParams->GainA1LowLimit(),recoParams->GainA1HighLimit()); + fStatusMaker->SetGainA2Limits(recoParams->GainA2LowLimit(),recoParams->GainA2HighLimit()); + fStatusMaker->SetGainThresLimits(recoParams->GainThresLowLimit(),recoParams->GainThresHighLimit()); + + mask = recoParams->PadGoodnessMask(); + //WARNING : getting this mask wrong is a very effective way of getting + //no digits at all out of this class ;-) + + fChargeSigmaCut = recoParams->ChargeSigmaCut(); + } + + 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() { - // - // empty dtor. - // + /// dtor. + delete fStatusMaker; + delete fStatusMapMaker; + + AliInfo("Summary of messages:"); + fLogger->Print(); + + AliInfo(Form("We have seen %g pads, and rejected %g (%7.2f %%)", + fNumberOfPads,fNumberOfBadPads, + ( fNumberOfPads > 0 ) ? fNumberOfBadPads*100.0/fNumberOfPads : 0 )); + + delete fLogger; } //_____________________________________________________________________________ void -AliMUONDigitCalibrator::Exec(Option_t*) +AliMUONDigitCalibrator::Calibrate(AliMUONVDigitStore& digitStore) { - // - // 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. - - for ( Int_t ch = 0; ch < AliMUONConstants::NTrackingCh(); ++ch ) + /// Calibrate the digits contained in digitStore + TIter next(digitStore.CreateTrackerIterator()); + AliMUONVDigit* digit; + Int_t detElemId(-1); + Double_t nsigmas = fChargeSigmaCut; + + AliDebug(1,Form("# of digits = %d",digitStore.GetSize())); + + while ( ( digit = static_cast(next() ) ) ) { - TClonesArray* digitArray = fData->Digits(ch); - Int_t nDigits = digitArray->GetEntriesFast(); - for ( Int_t d = 0; d < nDigits; ++d ) + if ( digit->IsCalibrated() ) { - AliMUONDigit* digit = - static_cast(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 - (fCalibrationData->DeadChannels(digit->DetElemId(),digit->ManuId())); - if ( dead && dead->ValueAsInt(digit->ManuChannel()) ) - { - AliWarning(Form("Removing dead channel detElemId %d manuId %d " - "manuChannel %d",digit->DetElemId(),digit->ManuId(), - digit->ManuChannel())); - digit->SetSignal(0); - continue; - } - - // If the channel is good, go on with the calibration itself. - - AliMUONVCalibParam* pedestal = static_cast - (fCalibrationData->Pedestals(digit->DetElemId(),digit->ManuId())); - - AliMUONVCalibParam* gain = static_cast - (fCalibrationData->Gains(digit->DetElemId(),digit->ManuId())); - - if (!pedestal) + fLogger->Log("ERROR : trying to calibrate a digit twice"); + return; + } + + digit->Calibrated(kTRUE); + + if ( digit->DetElemId() != detElemId ) + { + // Find out occupancy of that DE + detElemId = digit->DetElemId(); + AliMpDetElement* de = AliMpDDLStore::Instance()->GetDetElement(detElemId); + Double_t nchannels = de->NofChannels(); + Double_t occ = digitStore.GetSize(detElemId)/nchannels; + if ( occ > 0.05 ) { - AliFatal(Form("Got a null ped object for DE,manu=%d,%d", - digit->DetElemId(),digit->ManuId())); - + nsigmas = 10.0; // enlarge (a lot) sigma cut if occupancy is high + // (which probably means zero suppression was not exactly OK). + fLogger->Log(Form("Will use %5.0f*sigma cut for DE %04d " + "due to high occupancy",nsigmas,detElemId)); } - if (!gain) + else { - AliFatal(Form("Got a null gain object for DE,manu=%d,%d", - digit->DetElemId(),digit->ManuId())); + nsigmas = fChargeSigmaCut; } - - 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) ) + } + + Float_t charge(0.0); + Int_t statusMap; + Bool_t isSaturated(kFALSE); + + Bool_t ok = IsValidDigit(digit->DetElemId(),digit->ManuId(),digit->ManuChannel(),&statusMap); + + digit->SetStatusMap(statusMap); + + if (ok) + { + ++fNumberOfPads; + charge = CalibrateDigit(digit->DetElemId(),digit->ManuId(),digit->ManuChannel(), + digit->ADC(),nsigmas,&isSaturated); + } + else + { + ++fNumberOfBadPads; + } + + digit->SetCharge(charge); + digit->Saturated(isSaturated); + } +} + +//_____________________________________________________________________________ +Float_t +AliMUONDigitCalibrator::CalibrateDigit(Int_t detElemId, Int_t manuId, Int_t manuChannel, + Float_t adc, Float_t nsigmas, + Bool_t* isSaturated) const + +{ + /// Calibrate one digit + + + AliMUONVCalibParam* pedestal = static_cast + (fPedestals->FindObject(detElemId,manuId)); + + if (!pedestal) + { + // no pedestal -> no charge + fLogger->Log(Form("Got a null pedestal object for DE,manu=%d,%d",detElemId,manuId)); + return 0.0; + } + + + AliMUONVCalibParam* gain = static_cast + (fGains->FindObject(detElemId,manuId)); + + if (!gain) + { + if ( fApplyGains != fgkNoGain ) + { + // no gain -> no charge + fLogger->Log(Form("Got a null gain object for DE,manu=%d,%d", + detElemId,manuId)); + return 0.0; + } + } + + 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 ) + { + + + Int_t serialNumber + = AliMpManuStore::Instance()->GetManuSerial(detElemId, manuId); + + AliMUONVCalibParam* param = static_cast(fCapacitances->FindObject(serialNumber)); + + if ( param ) + { + capa = param->ValueAsFloat(manuChannel); + } + else + { + fLogger->Log(Form("No capa found for serialNumber=%d",serialNumber)); + capa = 0.0; + } + } + + if ( padc > nsigmas*pedestal->ValueAsFloat(manuChannel,1) ) + { + if ( fApplyGains != fgkNoGain ) + { + Float_t a0 = gain->ValueAsFloat(manuChannel,0); + Float_t a1 = gain->ValueAsFloat(manuChannel,1); + Int_t thres = gain->ValueAsInt(manuChannel,2); + if ( padc < thres ) { - padc = 0.0; + charge = a0*padc; } - 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 = a0*thres + a0*(padc-thres) + a1*(padc-thres)*(padc-thres); } } + else + { + charge = padc; + } + } + + charge *= capa; + + if ( isSaturated ) + { + Int_t saturation(3000); + + if ( gain ) + { + saturation = gain->ValueAsInt(manuChannel,4); + } + + if ( padc >= saturation ) + { + *isSaturated = kTRUE; + } + else + { + *isSaturated = kFALSE; + } } + + return charge; } + +//_____________________________________________________________________________ +Bool_t +AliMUONDigitCalibrator::IsValidDigit(Int_t detElemId, Int_t manuId, Int_t manuChannel, + Int_t* statusMap) const + +{ + /// Check if a given pad is ok or not. + + // First a protection against bad input parameters + AliMpDetElement* de = AliMpDDLStore::Instance()->GetDetElement(detElemId); + if (!de) return kFALSE; // not existing DE + if (!de->IsExistingChannel(manuId,manuChannel)) + { + // non-existing (might happen when we get parity errors in read-out + // that spoils the manuId + return kFALSE; + } + if (!de->IsConnectedChannel(manuId,manuChannel)) + { + // existing (in read-out), but not connected channel + return kFALSE; + } + + // ok, now we have a valid channel number, so let's see if that pad + // behaves or not ;-) + + Int_t sm = fStatusMapMaker->StatusMap(detElemId,manuId,manuChannel); + + if (statusMap) *statusMap = sm; + + if ( ( sm & AliMUONPadStatusMapMaker::SelfDeadMask() ) != 0 ) + { + // pad itself is bad (not testing its neighbours at this stage) + return kFALSE; + } + + return kTRUE; +} + +//_____________________________________________________________________________ +Int_t +AliMUONDigitCalibrator::PadStatus(Int_t detElemId, Int_t manuId, Int_t manuChannel) const +{ + /// Return the status of the given pad + return fStatusMaker->PadStatus(detElemId,manuId,manuChannel); +} + +//_____________________________________________________________________________ +Int_t +AliMUONDigitCalibrator::StatusMap(Int_t detElemId, Int_t manuId, Int_t manuChannel) const +{ + /// Return the status map of the given pad + return fStatusMapMaker->StatusMap(detElemId,manuId,manuChannel); + +} +