From 40164976e6eea42a0e01a8207e005746885743cb Mon Sep 17 00:00:00 2001 From: gconesab Date: Tue, 10 Nov 2009 18:13:34 +0000 Subject: [PATCH] --- Access to bad channel map implemented in reconstruction chain. -A first method to calculate the distance from a cluster to closest bad channel implemented. Output kept in AliESDCaloClusters::GetDistanceToBadChannel -Ideal map (no dead channels) committed to OCDB/EMCAL/Calib/Pedestals Example macro to create a bad channel map to be put in OCDB is in EMCAL/macros/PedestalDB --- EMCAL/AliCaloCalibPedestal.cxx | 34 +++- EMCAL/AliCaloCalibPedestal.h | 18 ++- EMCAL/AliEMCALClusterizerv1.cxx | 52 +++++- EMCAL/AliEMCALClusterizerv1.h | 17 +- EMCAL/AliEMCALLoader.cxx | 23 ++- EMCAL/AliEMCALLoader.h | 18 ++- EMCAL/AliEMCALRecPoint.cxx | 61 ++++++- EMCAL/AliEMCALRecPoint.h | 66 ++++---- EMCAL/AliEMCALReconstructor.cxx | 26 ++- EMCAL/AliEMCALReconstructor.h | 14 +- EMCAL/macros/PedestalDB/AliEMCALPedestalCDB.C | 151 ++++++++++++++++++ .../Calib/Pedestals/Run0_999999999_v0_s0.root | Bin 0 -> 22233 bytes 12 files changed, 408 insertions(+), 72 deletions(-) create mode 100644 EMCAL/macros/PedestalDB/AliEMCALPedestalCDB.C create mode 100644 OCDB/EMCAL/Calib/Pedestals/Run0_999999999_v0_s0.root diff --git a/EMCAL/AliCaloCalibPedestal.cxx b/EMCAL/AliCaloCalibPedestal.cxx index 1e2ac9dfb86..ed6c369aabd 100644 --- a/EMCAL/AliCaloCalibPedestal.cxx +++ b/EMCAL/AliCaloCalibPedestal.cxx @@ -311,7 +311,12 @@ void AliCaloCalibPedestal::Reset() // Parameter/cut handling //_____________________________________________________________________ void AliCaloCalibPedestal::SetParametersFromFile(const char *parameterFile) -{ +{ + // Note: this method is a bit more complicated than it really has to be + // - allowing for multiple entries per line, arbitrary order of the + // different variables etc. But I wanted to try and do this in as + // correct a C++ way as I could (as an exercise). + static const string delimitor("::"); // open, check input file @@ -321,10 +326,6 @@ void AliCaloCalibPedestal::SetParametersFromFile(const char *parameterFile) return; } - // Note: this method is a bit more complicated than it really has to be - // - allowing for multiple entries per line, arbitrary order of the - // different variables etc. But I wanted to try and do this in as - // correct a C++ way as I could (as an exercise). // read in char readline[1024]; @@ -390,6 +391,8 @@ void AliCaloCalibPedestal::SetParametersFromFile(const char *parameterFile) //_____________________________________________________________________ void AliCaloCalibPedestal::WriteParametersToFile(const char *parameterFile) { + //Write parameters in file. + static const string delimitor("::"); ofstream out( parameterFile ); out << "// " << parameterFile << endl; @@ -831,3 +834,24 @@ void AliCaloCalibPedestal::ComputeDeadTowers(int threshold, const char * deadMap fResurrectedTowers = countRes; } +//_____________________________________________________________________ +Bool_t AliCaloCalibPedestal::IsBadChannel(int imod, int icol, int irow) const +{ + //Check if channel is dead or hot. + + Int_t status = ((TH2D*)fDeadMap[imod])->GetBinContent(icol,irow); + if(status == kAlive) + return kFALSE; + else + return kTRUE; + +} + +//_____________________________________________________________________ +void AliCaloCalibPedestal::SetChannelStatus(int imod, int icol, int irow, int status) +{ + //Set status of channel dead, hot, alive ... + + ((TH2D*)fDeadMap[imod])->SetBinContent(icol,irow, status); + +} diff --git a/EMCAL/AliCaloCalibPedestal.h b/EMCAL/AliCaloCalibPedestal.h index 67fcb3eeb03..30302375c77 100644 --- a/EMCAL/AliCaloCalibPedestal.h +++ b/EMCAL/AliCaloCalibPedestal.h @@ -36,7 +36,7 @@ class AliCaloCalibPedestal : public TObject { public: enum kDetType {kPhos, kEmCal, kNone};//The detector types - enum kDeadMapEntry{kAlive = 0, kDead, kResurrected, kRecentlyDeceased, kNumDeadMapStates};//The entries being put to the deadmap + enum kDeadMapEntry{kAlive = 0, kDead, kHot, kResurrected, kRecentlyDeceased, kNumDeadMapStates};//The entries being put to the deadmap AliCaloCalibPedestal(kDetType detectorType = kPhos); virtual ~AliCaloCalibPedestal(); @@ -80,8 +80,15 @@ class AliCaloCalibPedestal : public TObject { TProfile2D * GetPeakProfileLowGainRatio(int i){ValidateComparisonProfiles(); return (TProfile2D*)fPeakMinusPedLowGainRatio[i];}; // Return a pointer to the low-gain peak-pedestal profile ratio TProfile2D * GetPeakProfileHighGainRatio(int i){ValidateComparisonProfiles(); return (TProfile2D*)fPeakMinusPedHighGainRatio[i];}; // Return a pointer to the high-gain peak-pedestal profile ratio - TH2D * GetDeadMap(int i) const {return (TH2D*)fDeadMap[i];}; - + TH2D * GetDeadMap(int i) const {return (TH2D*)fDeadMap[i];} + //void SetDeadMap(int i, TH2D *h) const {((TH2D*)fDeadMap[i])=h;} + + Bool_t IsBadChannel(int imod, int icol, int irow) const; + void SetChannelStatus(int imod, int icol, int irow, int status); + + TObjArray GetDeadMap() const {return fDeadMap;} + void SetDeadMap(TObjArray map) {fDeadMap = map;} + // Basic info: getters kDetType GetDetectorType() const {return fDetType;};//Returns if this is a PHOS or EMCAL object TString GetCaloString() const {return fCaloString;}; //Returns if this is a PHOS or EMCAL object @@ -112,6 +119,7 @@ class AliCaloCalibPedestal : public TObject { ///////////////////////////// //Analysis functions + void SetDeadTowerCount(Int_t dead) {fDeadTowers = dead;};//Returns the number of dead towers, by counting the bins in peak-pedestal smaller than threshold int GetDeadTowerCount() const {return fDeadTowers;};//Returns the number of dead towers, by counting the bins in peak-pedestal smaller than threshold double GetDeadTowerRatio() const {return fDeadTowers/(double)(fRows*fColumns);}; //returns the percentage of dead towers, relative to a full module int GetDeadTowerNew() const {return fNewDeadTowers;}; //return the new dead towers compared to the reference @@ -163,7 +171,7 @@ class AliCaloCalibPedestal : public TObject { int fNChanFills; //# total channel fills (NChan * NEvents if not zero-suppressed) //The dead tower counts - int fDeadTowers; //! + int fDeadTowers; // Number of towers found dead. int fNewDeadTowers; //! Towers that have died since the reference run int fResurrectedTowers; //! Towers that have been resurrected from the dead, compared to the reference @@ -188,7 +196,7 @@ class AliCaloCalibPedestal : public TObject { static const int fgkPhosCols = 56; // number of columns per module for PHOS static const int fgkPhosModules = 5; // number of modules for PHOS - ClassDef(AliCaloCalibPedestal, 5) + ClassDef(AliCaloCalibPedestal, 6) }; diff --git a/EMCAL/AliEMCALClusterizerv1.cxx b/EMCAL/AliEMCALClusterizerv1.cxx index f2f6c3f5d65..ff25ebc72b2 100644 --- a/EMCAL/AliEMCALClusterizerv1.cxx +++ b/EMCAL/AliEMCALClusterizerv1.cxx @@ -76,6 +76,7 @@ class TSystem; #include "AliEMCALRecParam.h" #include "AliEMCALReconstructor.h" #include "AliCDBManager.h" +#include "AliCaloCalibPedestal.h" class AliCDBStorage; #include "AliCDBEntry.h" @@ -88,7 +89,7 @@ AliEMCALClusterizerv1::AliEMCALClusterizerv1() fGeom(0), fDefaultInit(kFALSE), fToUnfold(kFALSE), - fNumberOfECAClusters(0),fCalibData(0), + fNumberOfECAClusters(0),fCalibData(0),fCaloPed(0), fADCchannelECA(0.),fADCpedestalECA(0.),fECAClusteringThreshold(0.),fECALocMaxCut(0.), fECAW0(0.),fTimeCut(0.),fMinECut(0.) { @@ -103,7 +104,7 @@ AliEMCALClusterizerv1::AliEMCALClusterizerv1(AliEMCALGeometry* geometry) fGeom(geometry), fDefaultInit(kFALSE), fToUnfold(kFALSE), - fNumberOfECAClusters(0),fCalibData(0), + fNumberOfECAClusters(0),fCalibData(0), fCaloPed(0), fADCchannelECA(0.),fADCpedestalECA(0.),fECAClusteringThreshold(0.),fECALocMaxCut(0.), fECAW0(0.),fTimeCut(0.),fMinECut(0.) { @@ -127,12 +128,12 @@ AliEMCALClusterizerv1::AliEMCALClusterizerv1(AliEMCALGeometry* geometry) } //____________________________________________________________________________ -AliEMCALClusterizerv1::AliEMCALClusterizerv1(AliEMCALGeometry* geometry, AliEMCALCalibData * calib) +AliEMCALClusterizerv1::AliEMCALClusterizerv1(AliEMCALGeometry* geometry, AliEMCALCalibData * calib, AliCaloCalibPedestal * caloped) : AliEMCALClusterizer(), fGeom(geometry), fDefaultInit(kFALSE), fToUnfold(kFALSE), -fNumberOfECAClusters(0),fCalibData(calib), +fNumberOfECAClusters(0),fCalibData(calib), fCaloPed(caloped), fADCchannelECA(0.),fADCpedestalECA(0.),fECAClusteringThreshold(0.),fECALocMaxCut(0.), fECAW0(0.),fTimeCut(0.),fMinECut(0.) { @@ -181,7 +182,13 @@ Float_t AliEMCALClusterizerv1::Calibrate(Int_t amp, Int_t AbsId) } fGeom->GetCellPhiEtaIndexInSModule(iSupMod,nModule,nIphi, nIeta,iphi,ieta); - + + // Check if channel is bad (dead, hot ...), in this case return 0. + if(fCaloPed->IsBadChannel(iSupMod,ieta,iphi)) { + AliDebug(2,Form("Tower from SM %d, ieta %d, iphi %d is BAD!!!\n",iSupMod,ieta,iphi)); + return 0; + } + fADCchannelECA = fCalibData->GetADCchannel (iSupMod,ieta,iphi); fADCpedestalECA = fCalibData->GetADCpedestal(iSupMod,ieta,iphi); @@ -208,7 +215,9 @@ void AliEMCALClusterizerv1::Digits2Clusters(Option_t * option) //Get calibration parameters from file or digitizer default values. GetCalibrationParameters() ; - + //Get dead channel map from file or digitizer default values. + GetCaloCalibPedestal() ; + fNumberOfECAClusters = 0; MakeClusters() ; //only the real clusters @@ -221,6 +230,8 @@ void AliEMCALClusterizerv1::Digits2Clusters(Option_t * option) //Evaluate position, dispersion and other RecPoint properties for EC section for(index = 0; index < fRecPoints->GetEntries(); index++) { dynamic_cast(fRecPoints->At(index))->EvalAll(fECAW0,fDigitsArr) ; + //For each rec.point set the distance to the nearest bad crystal + dynamic_cast(fRecPoints->At(index))->EvalDistanceToBadChannels(fCaloPed); } fRecPoints->Sort() ; @@ -359,6 +370,32 @@ void AliEMCALClusterizerv1::GetCalibrationParameters() } +//____________________________________________________________________________ +void AliEMCALClusterizerv1::GetCaloCalibPedestal() +{ + // Set calibration parameters: + // if calibration database exists, they are read from database, + // otherwise, they are taken from digitizer. + // + // It is a user responsilibity to open CDB before reconstruction, + // for example: + // AliCDBStorage* storage = AliCDBManager::Instance()->GetStorage("local://CalibDB"); + + //Check if calibration is stored in data base + + if(!fCaloPed) + { + AliCDBEntry *entry = (AliCDBEntry*) + AliCDBManager::Instance()->Get("EMCAL/Calib/Pedestals"); + if (entry) fCaloPed = (AliCaloCalibPedestal*) entry->GetObject(); + } + + if(!fCaloPed) + AliFatal("Pedestal info not found in CDB!"); + +} + + //____________________________________________________________________________ void AliEMCALClusterizerv1::Init() { @@ -386,7 +423,8 @@ void AliEMCALClusterizerv1::InitParameters() fTimeCut = 300e-9 ; // 300 ns time cut (to be tuned) fCalibData = 0 ; - + fCaloPed = 0 ; + const AliEMCALRecParam* recParam = AliEMCALReconstructor::GetRecParam(); if(!recParam) { AliFatal("Reconstruction parameters for EMCAL not set!"); diff --git a/EMCAL/AliEMCALClusterizerv1.h b/EMCAL/AliEMCALClusterizerv1.h index b02a181efd8..5c695dbae2e 100644 --- a/EMCAL/AliEMCALClusterizerv1.h +++ b/EMCAL/AliEMCALClusterizerv1.h @@ -30,6 +30,7 @@ class AliEMCALDigit ; class AliEMCALDigitizer ; class AliEMCALGeometry ; class AliEMCALCalibData ; +class AliCaloCalibPedestal ; class AliEMCALClusterizerv1 : public AliEMCALClusterizer { @@ -37,7 +38,7 @@ public: AliEMCALClusterizerv1() ; AliEMCALClusterizerv1(AliEMCALGeometry* geometry); - AliEMCALClusterizerv1(AliEMCALGeometry* geometry, AliEMCALCalibData * calib); + AliEMCALClusterizerv1(AliEMCALGeometry* geometry, AliEMCALCalibData * calib, AliCaloCalibPedestal * pedestal); virtual ~AliEMCALClusterizerv1() ; @@ -71,8 +72,9 @@ public: virtual const char * Version() const { return "clu-v1" ; } void PrintRecoInfo(); //*MENU* - void SetCalibrationParameters(AliEMCALCalibData * calib) { fCalibData = calib ; } - + void SetCalibrationParameters(AliEMCALCalibData * calib) { fCalibData = calib ; } + void SetCaloCalibPedestal(AliCaloCalibPedestal * caloped) { fCaloPed = caloped ; } + protected: virtual void MakeClusters(); @@ -82,7 +84,8 @@ private: AliEMCALClusterizerv1 & operator = (const AliEMCALClusterizerv1 &); void GetCalibrationParameters(void) ; - + void GetCaloCalibPedestal(void) ; + Bool_t FindFit(AliEMCALRecPoint * emcRP, AliEMCALDigit ** MaxAt, const Float_t * maxAtEnergy, Int_t NPar, Float_t * FitParametres) const; //Used in UnfoldClusters, calls TMinuit void Init() ; @@ -103,7 +106,9 @@ private: //Calibration parameters... to be replaced by database - AliEMCALCalibData * fCalibData ; //! Calibration database if aval + AliEMCALCalibData * fCalibData ; //! Calibration database if aval + AliCaloCalibPedestal * fCaloPed ; //! Tower status map if aval + Float_t fADCchannelECA ; // width of one ADC channel for EC section (GeV) Float_t fADCpedestalECA ; // pedestal of ADC for EC section (GeV) @@ -113,7 +118,7 @@ private: Float_t fTimeCut ; // Maximum time difference between the digits in ont EMC cluster Float_t fMinECut; // Minimum energy for a digit to be a member of a cluster - ClassDef(AliEMCALClusterizerv1,7) // Clusterizer implementation version 1 + ClassDef(AliEMCALClusterizerv1,8) // Clusterizer implementation version 1 }; diff --git a/EMCAL/AliEMCALLoader.cxx b/EMCAL/AliEMCALLoader.cxx index 2373496c921..21fa357c1ba 100644 --- a/EMCAL/AliEMCALLoader.cxx +++ b/EMCAL/AliEMCALLoader.cxx @@ -57,7 +57,8 @@ ClassImp(AliEMCALLoader) const TString AliEMCALLoader::fgkECARecPointsBranchName("EMCALECARP");//Name for branch with ECA Reconstructed Points -AliEMCALCalibData* AliEMCALLoader::fgCalibData = 0; //calibation data +AliEMCALCalibData* AliEMCALLoader::fgCalibData = 0; //calibation data +AliCaloCalibPedestal* AliEMCALLoader::fgCaloPed = 0; //dead map data //____________________________________________________________________________ AliEMCALLoader::AliEMCALLoader() @@ -141,6 +142,26 @@ AliEMCALCalibData* AliEMCALLoader::CalibData() } +//____________________________________________________________________________ +AliCaloCalibPedestal* AliEMCALLoader::PedestalData() +{ + // Check if the instance of AliCaloCalibPedestal exists, if not, create it if + // the OCDB is available, and finally return it. + + if(!fgCaloPed && (AliCDBManager::Instance()->IsDefaultStorageSet())) + { + AliCDBEntry *entry = (AliCDBEntry*) + AliCDBManager::Instance()->Get("EMCAL/Calib/Pedestals"); + if (entry) fgCaloPed = (AliCaloCalibPedestal*) entry->GetObject(); + } + + if(!fgCaloPed) + AliFatal("Pedestal info not found in CDB!"); + + return fgCaloPed; + +} + //____________________________________________________________________________ Int_t AliEMCALLoader::CalibrateRaw(Double_t energy, Int_t module, diff --git a/EMCAL/AliEMCALLoader.h b/EMCAL/AliEMCALLoader.h index a923c84c37d..f9bd188073a 100644 --- a/EMCAL/AliEMCALLoader.h +++ b/EMCAL/AliEMCALLoader.h @@ -27,6 +27,7 @@ class TTask ; // --- AliRoot header files --- #include "AliLoader.h" #include "AliEMCALCalibData.h" +#include "AliCaloCalibPedestal.h" class AliLoader ; class AliEMCAL ; @@ -66,7 +67,7 @@ class AliEMCALLoader : public AliLoader { // ************ TClonesArrays Access functions - TClonesArray* Hits(void) { return fHits;} + TClonesArray* Hits(void) const { return fHits;} const AliEMCALHit* Hit(Int_t index) { if (fHits) @@ -74,21 +75,21 @@ class AliEMCALLoader : public AliLoader { return 0x0; } - TClonesArray* SDigits() { return fSDigits;} + TClonesArray* SDigits() const { return fSDigits;} const AliEMCALDigit* SDigit(Int_t index) { if (fSDigits) return (const AliEMCALDigit*) fSDigits->At(index); return 0x0; } - TClonesArray* Digits() { return fDigits;} + TClonesArray* Digits() const { return fDigits;} const AliEMCALDigit * Digit(Int_t index) { if (fDigits) return (const AliEMCALDigit*) fDigits->At(index); return 0x0; } - TObjArray * RecPoints() { return fRecPoints;} + TObjArray * RecPoints() const { return fRecPoints;} const AliEMCALRecPoint * RecPoint(Int_t index) { if (fRecPoints) return (const AliEMCALRecPoint*) fRecPoints->At(index); @@ -104,6 +105,10 @@ class AliEMCALLoader : public AliLoader { void SetCalibData(AliEMCALCalibData* calibda) { fgCalibData = calibda; } AliEMCALCalibData * CalibData(); // to get the calibration CDB object + void SetPedestalData(AliCaloCalibPedestal* caloped) { fgCaloPed = caloped; } + AliCaloCalibPedestal* PedestalData(); // to get the pedestal CDB object + + private: // assignement operator requested by coding convention, but not needed @@ -122,9 +127,10 @@ private: TClonesArray *fSDigits; //! TClonesArray of sdigits (for tree reading) TObjArray *fRecPoints; //! TClonesArray of recpoints (for tree reading) - static AliEMCALCalibData * fgCalibData; // calibration data + static AliEMCALCalibData * fgCalibData; // calibration data + static AliCaloCalibPedestal * fgCaloPed; // dead map - ClassDef(AliEMCALLoader,2) // Algorithm class that provides methods to retrieve objects from a list knowing the index + ClassDef(AliEMCALLoader,3) // Algorithm class that provides methods to retrieve objects from a list knowing the index }; diff --git a/EMCAL/AliEMCALRecPoint.cxx b/EMCAL/AliEMCALRecPoint.cxx index b4d94fc38d8..408f5e9956f 100644 --- a/EMCAL/AliEMCALRecPoint.cxx +++ b/EMCAL/AliEMCALRecPoint.cxx @@ -16,6 +16,8 @@ //_________________________________________________________________________ // Reconstructed Points for the EMCAL // A RecPoint is a cluster of digits +// +// //*-- Author: Yves Schutz (SUBATECH) //*-- Author: Dmitri Peressounko (RRC KI & SUBATECH) //*-- Author: Heather Gray (LBL) merged AliEMCALRecPoint and AliEMCALTowerRecPoint 02/04 @@ -43,6 +45,8 @@ class AliEMCAL; #include "AliEMCALHit.h" #include "AliEMCALDigit.h" #include "AliEMCALRecPoint.h" +#include "AliCaloCalibPedestal.h" +#include "AliEMCALGeoParams.h" ClassImp(AliEMCALRecPoint) @@ -58,7 +62,7 @@ AliEMCALRecPoint::AliEMCALRecPoint() fTime(0.), fNExMax(0), fCoreRadius(10), //HG check this fDETracksList(0), fMulParent(0), fMaxParent(0), fParentsList(0), fDEParentsList(0), fSuperModuleNumber(0), - fDigitIndMax(-1) + fDigitIndMax(-1), fDistToBadTower(-1) { // ctor fGeomPtr = AliEMCALGeometry::GetInstance(); @@ -80,7 +84,7 @@ AliEMCALRecPoint::AliEMCALRecPoint(const char *) fAbsIdList(new Int_t[fMaxDigit]), fTime(-1.), fNExMax(0), fCoreRadius(10), fDETracksList(new Float_t[fMaxTrack]), fMulParent(0), fMaxParent(1000), fParentsList(new Int_t[fMaxParent]), fDEParentsList(new Float_t[fMaxParent]), - fSuperModuleNumber(0), fDigitIndMax(-1) + fSuperModuleNumber(0), fDigitIndMax(-1), fDistToBadTower(-1) { // ctor for (Int_t i = 0; i < fMaxTrack; i++) @@ -110,7 +114,8 @@ AliEMCALRecPoint::AliEMCALRecPoint(const AliEMCALRecPoint & rp) fDETracksList(new Float_t[rp.fMaxTrack]), fMulParent(rp.fMulParent), fMaxParent(rp.fMaxParent), fParentsList(new Int_t[rp.fMaxParent]), fDEParentsList(new Float_t[rp.fMaxParent]), - fSuperModuleNumber(rp.fSuperModuleNumber), fDigitIndMax(rp.fDigitIndMax) + fSuperModuleNumber(rp.fSuperModuleNumber), fDigitIndMax(rp.fDigitIndMax), + fDistToBadTower(rp.fDistToBadTower) { //copy ctor fLambda[0] = rp.fLambda[0]; @@ -193,7 +198,9 @@ AliEMCALRecPoint& AliEMCALRecPoint::operator= (const AliEMCALRecPoint &rp) fLambda[0] = rp.fLambda[0]; fLambda[1] = rp.fLambda[1]; - + + fDistToBadTower = rp.fDistToBadTower; + return *this; } @@ -430,7 +437,7 @@ void AliEMCALRecPoint::EvalAll(Float_t logWeight,TClonesArray * digits) EvalTime(digits) ; EvalPrimaries(digits) ; EvalParents(digits); - + //Called last because it sets the global position of the cluster? EvalLocal2TrackingCSTransform(); @@ -497,6 +504,49 @@ void AliEMCALRecPoint::EvalDispersion(Float_t logWeight, TClonesArray * digits) fDispersion = TMath::Sqrt(d) ; } +//____________________________________________________________________________ +void AliEMCALRecPoint::EvalDistanceToBadChannels(AliCaloCalibPedestal* caloped) +{ + //For each EMC rec. point set the distance to the nearest bad channel. + //AliInfo(Form("%d bad channel(s) found.\n", caloped->GetDeadTowerCount())); + //Needs to be carefully checked!!! Gustavo 10-11-2009 + + if(!caloped->GetDeadTowerCount()) return; + + //Number of supermodule this cluster belongs. + Int_t iSM = GetSuperModuleNumber(); + + //Get channels map of the supermodule where the cluster is + TH2D* hMap = caloped->GetDeadMap(iSM); + + TVector3 dR; + TVector3 cellpos; + + Int_t minDist = 100000; + Int_t dist = 0; + Int_t absId = -1; + + //Loop on tower status map + for(Int_t irow = 0; irow < AliEMCALGeoParams::fgkEMCALRows; irow++){ + for(Int_t icol = 0; icol < AliEMCALGeoParams::fgkEMCALCols; icol++){ + //Check if tower is bad. + if(hMap->GetBinContent(icol,irow)==AliCaloCalibPedestal::kAlive) continue; + //printf("AliEMCALRecPoint::EvalDistanceToBadChannels() - Bad channel in SM %d, col %d, row %d\n",iSM,icol, irow); + //Tower is bad, get the absId of the index. + absId = fGeomPtr->GetAbsCellIdFromCellIndexes(iSM, irow, icol); + //Get the position of this tower. + fGeomPtr->RelPosCellInSModule(absId,cellpos); + //Calculate distance between this tower and cluster, set if is smaller than previous. + dR = cellpos-fLocPos; + dist = dR.Mag(); + if(distGet("EMCAL/Calib/Pedestals"); + if (entry) fPedestalData = (AliCaloCalibPedestal*) entry->GetObject(); + } + + if(!fPedestalData) + AliFatal("Dead map not found in CDB!"); + + //Init the clusterizer with geometry and calibration pointers, avoid doing it twice. - fgClusterizer = new AliEMCALClusterizerv1(fGeom, fCalibData); + fgClusterizer = new AliEMCALClusterizerv1(fGeom, fCalibData,fPedestalData); if(!fGeom) AliFatal(Form("Could not get geometry!")); @@ -294,8 +306,10 @@ void AliEMCALReconstructor::FillESD(TTree* digitsTree, TTree* clustersTree, const AliEMCALDigit * dig = (const AliEMCALDigit*)digits->At(idig); if(dig->GetAmp() > 0 ){ energy = (static_cast (fgClusterizer))->Calibrate(dig->GetAmp(),dig->GetId()); - emcCells.SetCell(idignew,dig->GetId(),energy, dig->GetTime()); - idignew++; + if(energy > 0){ //Digits tagged as bad (dead, hot, not alive) are set to 0 in calibrate, remove them + emcCells.SetCell(idignew,dig->GetId(),energy, dig->GetTime()); + idignew++; + } } } emcCells.SetNumberOfCells(idignew); @@ -383,6 +397,10 @@ void AliEMCALReconstructor::FillESD(TTree* digitsTree, TTree* clustersTree, ec->SetClusterType(AliESDCaloCluster::kEMCALClusterv1); ec->SetPosition(xyz); ec->SetE(clust->GetEnergy()); + + //Distance to the nearest bad crystal + ec->SetDistanceToBadChannel(clust->GetDistanceToBadTower()); + ec->SetNCells(newCellMult); //Change type of list from short to ushort UShort_t *newAbsIdList = new UShort_t[newCellMult]; diff --git a/EMCAL/AliEMCALReconstructor.h b/EMCAL/AliEMCALReconstructor.h index 4fd2b6424a9..8b491f9294b 100644 --- a/EMCAL/AliEMCALReconstructor.h +++ b/EMCAL/AliEMCALReconstructor.h @@ -10,6 +10,12 @@ //*-- //*-- Author: Yves Schutz (SUBATECH) //*-- Dmitri Peressounko (SUBATECH & Kurchatov Institute) +// Reconstruction class. Redesigned from the old AliReconstructionner class and +// derived from STEER/AliReconstructor. +// +//-- Aleksei Pavlinov : added staf for EMCAL jet trigger 9Apr 25, 2008) +// : fgDigitsArr should read just once at event + // --- ROOT system --- class TList; @@ -32,6 +38,7 @@ class AliRawReader ; class AliEMCALRawUtils; class AliEMCALGeometry; class AliEMCALCalibData ; +class AliCaloCalibPedestal ; // --- Standard library --- @@ -63,7 +70,7 @@ public: void ReadDigitsArrayFromTree(TTree *digitsTree) const; - TList *GetList() {return fList;} + TList *GetList() const {return fList;} static const AliEMCALRecParam* GetRecParam() { return dynamic_cast(AliReconstructor::GetRecoParam(6)); } @@ -88,9 +95,10 @@ private: static AliEMCALRawUtils* fgRawUtils; // raw utilities class - // only need one per reco static TClonesArray* fgDigitsArr; // Array with EMCAL digits - AliEMCALCalibData * fCalibData ; //! Calibration database if aval + AliEMCALCalibData * fCalibData ; //! Calibration database if aval + AliCaloCalibPedestal * fPedestalData ; //! Tower status database if aval - ClassDef(AliEMCALReconstructor,7) // Reconstruction algorithm class (Base Class) + ClassDef(AliEMCALReconstructor,8) // Reconstruction algorithm class (Base Class) }; diff --git a/EMCAL/macros/PedestalDB/AliEMCALPedestalCDB.C b/EMCAL/macros/PedestalDB/AliEMCALPedestalCDB.C new file mode 100644 index 00000000000..b9821072be1 --- /dev/null +++ b/EMCAL/macros/PedestalDB/AliEMCALPedestalCDB.C @@ -0,0 +1,151 @@ +// Script to create dead channel map and store them into CDB +// - 4 sets of maps parameters can be created, with now dead channels +// and 5%, 10%, 20% and 30% of dead channels +// - it reads the stored map in a given file. +// Author: Gustavo Conesa + +//.x $ALICE_ROOT/EMCAL/macros/CalibrationDB/AliEMCALSetTowerStatusCDB.C + +#if !defined(__CINT__) +#include +#include +#include +#include +#include +#include +#include + +#include "AliRun.h" +#include "AliCaloCalibPedestal.h" +#include "AliEMCALGeoParams.h" +#include "AliCDBMetaData.h" +#include "AliCDBId.h" +#include "AliCDBEntry.h" +#include "AliCDBManager.h" +#include "AliCDBStorage.h" +#endif + + +void AliEMCALPedestalCDB() +{ + TControlBar *menu = new TControlBar("vertical","EMCAL CDB"); + menu->AddButton("Help to run EMCAL CDB","Help()", + "Explains how to use EMCAL CDS menus"); + menu->AddButton("Equal Tower Status Map, all Alive","SetTowerStatusMap(0)", + "Set all channels to alive"); + menu->AddButton("Create Random Status Map, 5% dead","SetTowerStatusMap(5)", + "Set randomly 5% of the channels dead"); + menu->AddButton("Create Random Status Map, 10% dead","SetTowerStatusMap(10)", + "Set randomly 10% of the channels dead"); + menu->AddButton("Create Random Status Map, 20% dead","SetTowerStatusMap(20)", + "Set randomly 20% of the channels dead"); + menu->AddButton("Create Random Status Map, 30% dead","SetTowerStatusMap(30)", + "Set randomly 30% of the channels dead"); + menu->AddButton("Read Tower Status Map","GetTowerStatusMap()", + "Read initial equal calibration coefficients"); + menu->Show(); +} + +//------------------------------------------------------------------------ +void Help() +{ + char *string = + "\nSet tower status map (dead, hot, alive) and write them into ALICE CDB. Press button \"Equal kAlive\" to set all channels alive. Press button \"Random, 5% dead\" to create random dead channel map at 5%\n"; + printf(string); +} + +//------------------------------------------------------------------------ +void SetTowerStatusMap(Int_t percent=0) +{ + // Writing status of all the channels in the OCDB with equal value + // except a percent to be not alive. Right now only "alive" or "dead", + // we need to implement the other cases like "hot" + + TString sDBFolder ="local://PedestalsDB"; + Int_t firstRun = 0; + Int_t lastRun = 999999999; + Int_t beamPeriod = 1; + char* objFormat = Form("%d percent decalibrated channels", percent); + + AliCaloCalibPedestal *caloped=new AliCaloCalibPedestal(AliCaloCalibPedestal::kEmCal); + TObjArray map = caloped->GetDeadMap(); + printf("MAP entries %d\n",map.GetEntries()); + TRandom rn; + //for(Int_t iSM = 0; iSM < AliEMCALGeoParams::fgkEMCALModules; iSM ++){ + for(Int_t iSM = 0; iSM < map.GetEntries(); iSM ++){ + Int_t ndead = 0; + printf(" >>> SM %d <<< Entries %d, NbinsX %d, NbinsY %d\n",iSM,((TH2D*)map[iSM])->GetEntries(),((TH2D*)map[iSM])->GetNbinsX(),((TH2D*)map[iSM])->GetNbinsY()); + for(Int_t i = 0; i < ((TH2D*)map[iSM])->GetNbinsX() ; i++){ + for(Int_t j = 0; j < ((TH2D*)map[iSM])->GetNbinsY() ; j++){ + //printf("Bin (%d-%d) Content, before: %d ",i,j,((TH2D*)map[iSM])->GetBinContent(i, j)); + + if(rn.Uniform(0,100) > percent) + ((TH2D*)map[iSM])->SetBinContent(i, j, AliCaloCalibPedestal::kAlive); + else{ + ((TH2D*)map[iSM])->SetBinContent(i, j, AliCaloCalibPedestal::kDead); + ndead++; + } + //printf("; after: %d \n",((TH2D*)map[iSM])->GetBinContent(i, j)); + } + } + caloped->SetDeadTowerCount(caloped->GetDeadTowerCount()+ndead); + printf("--- dead %d\n",ndead); + } + + printf("--- total dead %d\n",caloped->GetDeadTowerCount()); + + caloped->SetDeadMap(map); + + //Store map into database + + AliCDBMetaData md; + md.SetComment(objFormat); + md.SetBeamPeriod(beamPeriod); + md.SetResponsible("Gustavo Conesa"); + + AliCDBId id("EMCAL/Calib/Pedestals",firstRun,lastRun); // create in EMCAL/Calib/Pedestal sDBFolder + + AliCDBManager* man = AliCDBManager::Instance(); + AliCDBStorage* loc = man->GetStorage(sDBFolder.Data()); + loc->Put(caloped, id, &md); + +} + +//------------------------------------------------------------------------ +void GetTowerStatusMap() +{ + // Read status map + + TString sDBFolder ="local://PedestalsDB"; + Int_t runNumber = 0; + + AliCaloCalibPedestal* caloped = (AliCaloCalibPedestal*) + (AliCDBManager::Instance() + ->GetStorage(sDBFolder.Data()) + ->Get("EMCAL/Calib/Pedestals", + runNumber)->GetObject()); + + cout<GetDeadMap(); + printf("MAP entries %d\n",map.GetEntries()); + for(Int_t iSM = 0; iSM < map.GetEntries(); iSM ++){ + TCanvas *cMap = new TCanvas(Form("cMap%d",iSM),Form("SM %d dead map",iSM), 12,12,400,400); + cMap->Divide(1,1); + Int_t ndead = 0; + printf(" >>> SM %d <<< Entries %d, NbinsX %d, NbinsY %d\n",iSM,((TH2D*)map[iSM])->GetEntries(),((TH2D*)map[iSM])->GetNbinsX(),((TH2D*)map[iSM])->GetNbinsY()); + for(Int_t i = 0; i < ((TH2D*)map[iSM])->GetNbinsX() ; i++){ + for(Int_t j = 0; j < ((TH2D*)map[iSM])->GetNbinsY() ; j++){ + //printf("Bin (%d-%d) Content: %d \n",i,j,((TH2D*)map[iSM])->GetBinContent(i, j)); + + if(((TH2D*)map[iSM])->GetBinContent(i, j)==AliCaloCalibPedestal::kDead) + ndead++; + } + } + printf("--- dead %d\n",ndead); + cMap->cd(iSM); + (TH2D*)map[iSM])->Draw("lego2"); + } + + printf("Total DEAD %d\n", caloped->GetDeadTowerCount()); + +} diff --git a/OCDB/EMCAL/Calib/Pedestals/Run0_999999999_v0_s0.root b/OCDB/EMCAL/Calib/Pedestals/Run0_999999999_v0_s0.root new file mode 100644 index 0000000000000000000000000000000000000000..ab758d7f03208b2b273ed79882a9c7d4965829b3 GIT binary patch literal 22233 zcmd^n2T)Z}vMnGWNrFTri)4vP&H{quoZ*rYB}vXfg5)4k6i^V5oO1@bWKeRvfR`M- zs*IwQGINIAgBO R!@{BOz%`0ha`D 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

C)9MIre6;Wb zE0V+Z!VySheX7&7l`z6{O)f43q?|=joj$4UiIRao&K=;#@bl@ox|1pu5bd2s`$mAAAz ze;^>`+Z*HpW#FTNTS%IplH$|ucr>{P;3FvJjluN*gTJ{oI8>yo7=FqRl|h9D*qO9y zy2!)rV_zmwfW1YNucb2FKB823vvzKFP#pjEs`La@x%uy`N(AuL)X8bu_%t*M=%_wA z)4u7_@!Wo|yB(vZ=mb^GYEn^T%%A%BH;%(dUSwcdBpY&54yyP^<)A3?|2wtA_P<{{ zyC~sHyDO?Hf1qG$i0&3K$B_;()}b5nH%$uX6D= z)TJm=n>K}HxOYKB(qCE{VS9XjL~^wD`ezPS8RlKPBvQ@Oo~37Be(4olZqw{-N%06( zsQA=2@72x~j%U(1N-R-RiQI)hj{A!fN$t=g&}^WT;!m?jSWS~73Aer&fQiuT{V8k$ z;9)N%2s78T_Sl7~(_zsi<>k4y32(?BD3Lk@lO^N4ZDY<7y6UF)CWdc^S6k2ndI$lo z(GdfP`UV?7+KT=o(ze|HV9(O5qAKq9uZ~kr!uHYgi>2WxQlUisRaX|i`KIYX!S3Gm zezp3{q^o^4$PPf$!v3_S;|NYpDNVdB1M1_x=B2rTxYZ4%efAA^rwW*xAgt7eo~IYS zkS|Wclhb|0cSXDr2+ARk@Ry_TI#n6rj>-N&KmP?P^v{z+_|XN%7U5)6Hbi?uQ$YYK z*$n_NA$tIT@%g&f)-}S4bJY+mh(i!Ahy%M7M7yTBR-!-~X?(uSz2wP!MhUyo9&mTp zAfwQchVFr7>}-(WcX4A*WDjVdhcyC~y8~uUa3id*X&=lX;{n|RpL;v=AW+`|`rrN~ zo3I-pSpgwSq;75T(Aw{lcIlBiHl^&mq+Zi-V#)(ZC5svH6^B zJUh^Z@cAD_rcTbw2B6um?*_;St>+KAIOS@K+4E}cJZmnz>?l<6nLKg)dgkD>{I)^2 zC>!kL0dY(?UkYE92fz19*fx_lGK31 zwPnGR%d>3^yEym)B?XZNkUi9B*t^Z_9pEL>9JQWphf5-JmIxpvBDDoFj#{G~-?l@? zgLeg_2H2-)oQMz}OPCZ;v?FdXPgCNz=jx+C==Z^CtrMnF$ry0JFx0`bj_l)Bk}6Hg7Zl z_`yG;0dc@?B{eq=K1Zj!^VXuTy&>+S-RzgTtHWC|va1#Q zQAeJlFRVgA*H$qjC)b`$XH#c-PFZoOiox@Rnk_b0zjFtwWX2L#lq)>0GGX8A)GpUw zo7omkL1ZcYI4%p<--GxRGxoNx?<9*k#oT^(02K*ITI2Q*y!g!__?xd0Aep0SC|El= zL1SZW_r}5;_{Yf^I1&GW2uVX4$sKvj;EfH%giAAp z(9axb&NzGe+oUps4Gvee%2r)8C@wyZQmw@l!y-S|OOXZ>61zqxR$Zssmr!`>jd4sHEj)nUq}-nRmJvU49fldtFt&XqVtz?&#~v%O>LcD2S}9d2yUewAuleUOWrK zv{kjpDIFS;q)hZJH~@;H?!fdSfHHBrus!qh8W`fRsU?M%6BH_?9%rjTyf}b;rwcoh zH2!UaNaAL-Y`f!YH4GTe5$NU*qZ7Cj-)Mou}-+*bA7O!0b}6n&YRMFvqf{XGmTOmGRv{+xcLhtgF{kqoXI| zlHjXW@bS1*=%WCu6*4_XvETB1^w%p?NK=3tZT(WV-Y=05l*fY4_+g@hF<N(ta6_{p!9JgzVxtq8@7Nag3%I`Q5|wkAKU^yL57MIKzH+g4=HmnAqyL2 zw{oE3Nnn7qq#FCB5>i6B(n5XHLc=L=Cvr_U%WF%zPaegWwVNx9elUTgyUwa{S}iAV zM&l5%?H~1EadlC@6Nab+HG+c*xoB6NpC3J^+6>Y_b*!YN*H3<_6_+^!p%Y}DJNjm^ zk~3h+-DKWFQH*V=S~-1huUBIw1)7`!UF7fYud^WQTv#CFJ}_4L)>%`&=B3MuQ8*im z`daAd-aQ?m7b^+)_RNhXn0MTcAMAdJPOh|KNK!a%j32sd#Tu(C{I*C~fib-onVt4- zcBX=0wR4jSq{@5OT!n?iCug(vReE7Wc%e1JrT_ygZ#bjww6#527R82b>O7xjXNgm% zMe)gqV9PgfEc!HE+(SuznbJ43>7@bK$)AnqB&Rj{Vs@5@GvYy|66jQGh03Gd+0!sIlh0_Y>T8Xx!|5Dsb6d z^d-W#?71J`8{1QG|BiHS%q!H4f1zx_)Rap#^0hvchpeR8I(LCc4lPWde&RizS@DtL zrveu9q_n)NZA#6}=h zwtam>Qoqh(xJ8}g&gm4Ib-jRxou}#6b8OQS&wj;V>Ydt%rP?*<$*QwwJg}y?A9ncmM@Ga;|G))!;tvnPrPMVIqd(sw- zo=GVVaMa12<}O8AETg1ohDxL3Yg;OYFsWfZxlVZ1jCPfpxj3WHp|2qMBG)9N$#~gB zhts`WzSfu|+=G>${Ezx0r0W0{5xy3NJ0(cmx`t~<5*kU%S`Xe>jQ3lGwOclMhpt3F z8a8=Up|GU9DRnfnN-6gJ>)RN`AtHisxdq-CJ`uF~?k^01qS=8vWgID0DLx*;(+?l( znRZ=qpRZCjOp48yWF6+LdgBGA@CY)q+g=w4I1DG=-@cCITS%Q zRcneBPg-clj*C2FjCDs=Oia+j`(WvtdMp{|bNgR>i?q1z>;`vA5_BkvI}+=?BvX>ZnZn7#8y!DM@nbDy?R)k71vl}DnBAt0VzHvqgg2T}H~)23ktsS;yj3z?V=@`XfP2PI-R}pZhMJf! zz`69_cuOsx+`(d|?XVEo9+wDZhL!BHUn7|ZvOxElu(%!&R+-9u5w9?PD8PT8FI}HV z-74Rgn<)u(&XU6zsp^roH93g21rxPqG$wVs`i)D&cB0ne&D|kz*A|2G)}^TUYwhf# zN2&6TkqS`gp;LX5?V- zhLQ5y15^J&<4T*N5fsd*xQ_$e6{_Weydj+TrH?M1V@vZ^-upLXFL2|yeYEg0NVetR z;^yykf*AqY5ei((ov&EgeeDyEjq4^|3Jc;76DX=R})t)~?b_zBr_8#Tbez3Cf{@rP&n*K|&g#oiFk*tEE2`auz z-Ia=; z%nZ%6%;IU%;?yTVUDTHd-Su>0Fv z&&`fNI~M)NSt2bC>FRoy&S4%^4W8)*n!LYW3t;`yw|#;+Y^&^Ux0ZO(5r-YMz_W_l z*;p4sljP@5tXI7^3QENlR!f=FY%S(=sQEERpLDogDR3m9cQ{K97R}@_Z+KGe_b`P6 z^G?^RlxU9*Lsz2jyTuIb-@4+2VEiFXQyQ~AII+yeYa_C&F7ZF#WN_5!%3-1ADy3^i zpfTko$n*x`WEh_6;!dU%FQd}aL%Y{KNrZI2hv-|Kq2xbMfZ?Bszu@OpqvKO6x9tNt z?C8ymR^d1V_5zS(6~B?PulG-6Q#I0~56=^qP2+0;T+IgnQk!TZQAyW^U2y*o5^t=2s#nXr@R>c-I{3m;cy_G&+Q1c{8 zwzS7~zK8_xht|EyVN-jS&wY_khxoY}7=;v-u6faZ z5ct3PsvY}qyf^OQPU*v=^)YQjKUgqG>|9YpAw1=|huRMvI%)sccEHD$$}BLNc%|>B zNbg-hggc2+1Wh?ckx;h*Zx)YMmkVX!B5AK`BsM{H4hyFiL_fDAKyR=dFpE9FOQu^F z8y7z#!VFuzdM4lT>>G!uxQ8t0;)~YV6TS;$=JggPoLR%)yoCE}#>*;<@_xC7Q5AaH z67k}NDEGcgi^N7YYekzMSR|<`f*T)pgi&92#$^zwa6)R|@qLf-{i-ELr1VuTU?Fzq z)eExPhC#J(3!9p@u&>>*%R$Uf>!YWcxoZU8XjTq?aKuuqAuZ!7eg|%!&iSdAKy=d0 z^tqtD)iA+7Vk-OF?{M@ab2NsB+V@Q>-lEaw^=y_6CeitLhaaj|P(@G%y@cscs9%RY z>@nVwdaL$AyNH`bk;IpT5#8ojdOj0f()M;F_r+Z>x5Qe<%=6bso47S8@3M>zuuGlKC*pGd~( z>&qT7B%HW&bUF20zap)7woKwg4(pDw&0t>##|LKqf9{!}^yo z>me1TS6%fvYa}0DcR>Q07PSUYY#*94ZuO;vPe&YlsB}zu%UF}Ns)8K6p^sI*srySO zJgT*S%ty!R&ZcevbbW;F3$1or+b>0vZ$Y7s#APp{QAv9W{3x8>prRX=rM0r%%djfj z?SeQIC@6nRT~kT>W#jCp=}N@-T?Geefb~hu)MV@e^O^{8o-MJ}NTU=ZhXmyusZQu) zrw>V)VA8K@89X<6o1=KOsyTnMo-vYWi%oxWXcKHoZZPqV=K)#?UAospkE(E_I2v(Y z@&X+Gkle&biBL3~QLQ+UDsM*lv`jo9a`DfbcCRtt%Kc=)!R0>GBqNKnayEN245h3G>0nx+fs_DHPPx{c=ZS7T|e3v ztXiTyO;QA}(3VYdgsup-lj!9hePw(3J^}wYf%kCg*CY#x`E$p?azd3YZ__z%&5XAj zj_yBw9%!?P z&;G-MjM6|&iFFuJBOip3=}j}jX9?@B+Gwf#K%i!xz;l3PszQw0=2;6$4jXk`y7 zo$YkU6B}Z*qi|=!{Y_mX!*;me;I)f9~D7eyvktTEJDssMC|$fT6{^nQKv3`)6fS9mf5ni5qU%cVkB z?l};Yj41)hRopkSv&B>p`u^rz>4&<0Q_1=>9hj4!$mRW$fYF(sWiMaarhE^P((e);f5 z9odtx{4k`j>7nCZ)q-?&jT@ykKKEHE#T-`&nUY@Y%xp+c4m6?=3(-r&!r z>*oy;^X19`YxkSQ`+F$TyOFCD+#%)k=xBe;&p92Ih+ItOe?sMdR_@cBa9!o}Uy#k4 z`TicHDmu!b$mk8DHar<1(7+6doEP`tG;cKQ!>31<6^~#N=UpW5hPo6{6zS^Vqa)=` zUHsVd!t@%%Nxm;l;VD(A5b(S%MBn}gS5tzilKab`tEsfn0R=p^=Jed`ev!(ZR8pR- z9V=j!FzGzbnn=^&R+36wll0{5vNk@5S~6LcZd%Xq3kBa(M5 z`g`Z2diiU9x)H+VIH(%&ebRWhhzcUk&h;P*E%qs+ zc+f|Fk4Nn^3DkHTUs00f$elvx9)Yt0(~G*GCR5-KwBbD5^?Pvush7Vr3Bkl*p<#4Z zezxiJBvh-w=@`vS5s#bs!UYR$+M#KH*9(FbF8f*_)D2e?xoo;+FSc0&)BTw}TCGvT z_m6qxU7*zz$>Nbd`lq#zDGUPJwkP=xT!aez+>jnTCCN|cijam0*&a-I3}Gj3iu;`e z*e%yz|HRT42+nmYAk(k(%@eOs5-QYGSZ2@nNZF9dspcZ)E;oJh0qZ_C zjO~|dcm=bLYQbZa$lMchT;0P%T4H43Q}2Xf+gg`zFs`Z-kO&`9B0yqx0^j#ULgKrn zHgCU+3VajvmfHN+e-{-P7ob)V{^BU`Sjz1ru>Nxrx1W#&_}TvllK`fmHRZ;Wfb_or D9Gjhv literal 0 HcmV?d00001 -- 2.43.0