From af4c4fe9ac12e33bc9fe85e0a87e95b0130abee8 Mon Sep 17 00:00:00 2001 From: Volker Friese <v.friese@gsi.de> Date: Fri, 4 Dec 2020 20:02:26 +0100 Subject: [PATCH] Enable global deactivation of random channels in the STS simulation. --- core/detectors/sts/CbmStsParAsic.cxx | 58 ++++++++++++++++++----- core/detectors/sts/CbmStsParAsic.h | 24 ++++++++-- core/detectors/sts/CbmStsParModule.cxx | 15 +++++- core/detectors/sts/CbmStsParModule.h | 7 +++ core/detectors/sts/CbmStsParSetModule.cxx | 26 +++++++++- core/detectors/sts/CbmStsParSetModule.h | 15 +++++- sim/detectors/sts/CbmStsDigitize.cxx | 37 +++++++++------ sim/detectors/sts/CbmStsDigitize.h | 16 ++++++- 8 files changed, 165 insertions(+), 33 deletions(-) diff --git a/core/detectors/sts/CbmStsParAsic.cxx b/core/detectors/sts/CbmStsParAsic.cxx index b45d072377..75e07c4945 100644 --- a/core/detectors/sts/CbmStsParAsic.cxx +++ b/core/detectors/sts/CbmStsParAsic.cxx @@ -6,28 +6,31 @@ #include <TF1.h> // for TF1 #include <TMath.h> // for Exp +#include <TRandom.h> #include <assert.h> // for assert #include <sstream> // for operator<<, basic_ostream, stringstream ClassImp(CbmStsParAsic) - // ----- Constructor --------------------------------------------------- - CbmStsParAsic::CbmStsParAsic(UShort_t nAdc, - Double_t dynRange, - Double_t threshold, - Double_t timeResol, - Double_t deadTime, - Double_t noise, - Double_t znr) { - Set(nAdc, dynRange, threshold, timeResol, deadTime, noise, znr); +// ----- Constructor --------------------------------------------------- +CbmStsParAsic::CbmStsParAsic(UShort_t nChannels, + UShort_t nAdc, + Double_t dynRange, + Double_t threshold, + Double_t timeResol, + Double_t deadTime, + Double_t noise, + Double_t znr) { + Set(nChannels, nAdc, dynRange, threshold, timeResol, deadTime, noise, znr); } // ------------------------------------------------------------------------- // ----- Copy constructor ---------------------------------------------- CbmStsParAsic::CbmStsParAsic(const CbmStsParAsic& other) { - Set(other.fNofAdc, + Set(other.fNofChannels, + other.fNofAdc, other.fDynRange, other.fThreshold, other.fTimeResolution, @@ -40,7 +43,8 @@ CbmStsParAsic::CbmStsParAsic(const CbmStsParAsic& other) { // ----- Copy assignment operator -------------------------------------- CbmStsParAsic& CbmStsParAsic::operator=(const CbmStsParAsic& other) { - Set(other.fNofAdc, + Set(other.fNofChannels, + other.fNofAdc, other.fDynRange, other.fThreshold, other.fTimeResolution, @@ -68,6 +72,34 @@ Short_t CbmStsParAsic::ChargeToAdc(Double_t charge) const { // ------------------------------------------------------------------------- +// ----- Deactivate channels ------------------------------------------- +UInt_t CbmStsParAsic::DeactivateRandomChannels(Double_t fraction) { + + if ( fraction < 0. ) return 0; + + // --- Average number of dead channels + Double_t meanDead = fraction * Double_t(fNofChannels); + if ( meanDead > fNofChannels) meanDead = fNofChannels; + + // --- Sample actual number of dead channels from Poissonian + Int_t nDead = gRandom->Poisson(meanDead); + + // --- Deactivate the given number of channels + Int_t nDeactivated = 0; + while(nDeactivated < nDead) { + Int_t channel = Int_t(gRandom->Uniform(0, fNofChannels)); + if ( IsChannelActive(channel) ) { + fDeadChannels.insert(channel); + nDeactivated++; + } //? Channel was active + } //# Deactivated channels + + assert(nDeactivated == nDead); + return nDead; +} +// ------------------------------------------------------------------------- + + // ----- Single-channel noise rate ------------------------------------- Double_t CbmStsParAsic::GetNoiseRate() const { if (fNoise == 0.) return 0.; @@ -97,7 +129,8 @@ void CbmStsParAsic::Init() { // ----- Set the parameters --------------------------------------------- -void CbmStsParAsic::Set(UShort_t nAdc, +void CbmStsParAsic::Set(UShort_t nChannels, + UShort_t nAdc, Double_t dynRange, Double_t threshold, Double_t timeResol, @@ -114,6 +147,7 @@ void CbmStsParAsic::Set(UShort_t nAdc, assert(noise >= 0.); assert(zeroNoiseRate >= 0.); + fNofChannels = nChannels; fNofAdc = nAdc; fDynRange = dynRange; fThreshold = threshold; diff --git a/core/detectors/sts/CbmStsParAsic.h b/core/detectors/sts/CbmStsParAsic.h index 5678bb3df2..79977e6eb5 100644 --- a/core/detectors/sts/CbmStsParAsic.h +++ b/core/detectors/sts/CbmStsParAsic.h @@ -30,6 +30,7 @@ public: /** @brief Constructor with parameters + ** @param nChannels Number of readout channels ** @param nAdc Number of ADC channels ** @param dynRange Dynamic range of ADC [e] ** @param threshold ADC threshold [e] @@ -38,7 +39,8 @@ public: ** @param noise Noise RMS [e] ** @param znr Zero-crossing noise rate [1/ns] **/ - CbmStsParAsic(UShort_t nAdc, + CbmStsParAsic(UShort_t nChannels, + UShort_t nAdc, Double_t dynRange, Double_t threshold, Double_t timeResol, @@ -76,6 +78,13 @@ public: } + /** @brief Randomly deactivate a fraction of the channels + ** @param fraction Fraction of channels to deactivate + ** @return Number of deactivated channels + **/ + UInt_t DeactivateRandomChannels(Double_t fraction); + + /** @brief ADC channel for a given charge ** @param charge Charge [e] ** @return ADC channel number @@ -103,6 +112,12 @@ public: UShort_t GetNofAdc() const { return fNofAdc; } + /** @brief Number of readout channels + ** @return Number of readout channels + **/ + UShort_t GetNofChannels() const { return fNofChannels; } + + /** @brief Electronic noise RMS ** @return Noise RMS [e] **/ @@ -160,6 +175,7 @@ public: /** @brief Set parameters + ** @param nChannels Number of readout channels ** @param nAdc Number of ADC channels ** @param dynRange Dynamic range [e] ** @param threshold Threshold [e] @@ -169,7 +185,8 @@ public: ** @param zeroNoiseRate Zero-crossing noise rate ** @param deadChannels Set of dead channels **/ - void Set(UShort_t nAdc, + void Set(UShort_t nChannels, + UShort_t nAdc, Double_t dynRange, Double_t threshold, Double_t timeResol, @@ -184,6 +201,7 @@ public: private: + UShort_t fNofChannels = 0; ///< Number of readout channels UShort_t fNofAdc = 0; ///< Number of ADC channels Double_t fDynRange = 0.; ///< Dynamic range [e] Double_t fThreshold = 0.; ///< Threshold [e] @@ -199,7 +217,7 @@ private: ** method in order to avoid frequent re-calculation. **/ TF1* fNoiseCharge = nullptr; //! - ClassDefNV(CbmStsParAsic, 2); + ClassDefNV(CbmStsParAsic, 3); }; #endif /* CBMSTSPARASIC_H */ diff --git a/core/detectors/sts/CbmStsParModule.cxx b/core/detectors/sts/CbmStsParModule.cxx index f15b92cc99..03340beebf 100644 --- a/core/detectors/sts/CbmStsParModule.cxx +++ b/core/detectors/sts/CbmStsParModule.cxx @@ -25,6 +25,18 @@ ClassImp(CbmStsParModule) // ------------------------------------------------------------------------- +// ----- Randomly deactivate channels ---------------------------------- +UInt_t CbmStsParModule::DeactivateRandomChannels(Double_t fraction) { + if ( fraction <= 0. ) return 0; + UInt_t nDeactivated = 0; + for ( auto& asic : fAsicPars ) { + nDeactivated += asic.DeactivateRandomChannels(fraction); + } + return nDeactivated; +} +// ------------------------------------------------------------------------- + + // ----- Get ASIC parameters ------------------------------------------- const CbmStsParAsic& CbmStsParModule::GetParAsic(UInt_t channel) const { assert(!fAsicPars.empty()); @@ -36,7 +48,7 @@ const CbmStsParAsic& CbmStsParModule::GetParAsic(UInt_t channel) const { // ------------------------------------------------------------------------- -// ----- Check for a chennel being active ------------------------------ +// ----- Check for a channel being active ------------------------------ Bool_t CbmStsParModule::IsChannelActive(UInt_t channel) const { const CbmStsParAsic& parAsic = GetParAsic(channel); UShort_t asicChannel = channel % fNofAsicChannels; @@ -47,6 +59,7 @@ Bool_t CbmStsParModule::IsChannelActive(UInt_t channel) const { // ----- Set parameters for all ASICs ---------------------------------- void CbmStsParModule::SetAllAsics(const CbmStsParAsic& asicPar) { + assert(asicPar.GetNofChannels() == fNofAsicChannels); for (auto& par : fAsicPars) { par = asicPar; par.Init(); diff --git a/core/detectors/sts/CbmStsParModule.h b/core/detectors/sts/CbmStsParModule.h index 850a159acb..29a666e1f1 100644 --- a/core/detectors/sts/CbmStsParModule.h +++ b/core/detectors/sts/CbmStsParModule.h @@ -43,6 +43,13 @@ public: ~CbmStsParModule() {}; + /** @brief Randomly deactivate a fraction of the channels + ** @param fraction Fraction of channels to deactivate + ** @return Number of deactivated channels + **/ + UInt_t DeactivateRandomChannels(Double_t fraction); + + /** @brief ASIC parameters for a given channel ** @param channel Channel number ** @return ASIC parameters diff --git a/core/detectors/sts/CbmStsParSetModule.cxx b/core/detectors/sts/CbmStsParSetModule.cxx index f4d1289e29..d370dfd31e 100644 --- a/core/detectors/sts/CbmStsParSetModule.cxx +++ b/core/detectors/sts/CbmStsParSetModule.cxx @@ -12,6 +12,7 @@ #include <sstream> // for operator<<, basic_ostream, stringstream #include <string> // for char_traits + ClassImp(CbmStsParSetModule) // ----- Constructor ---------------------------------------------------- @@ -37,6 +38,18 @@ void CbmStsParSetModule::clear() { // -------------------------------------------------------------------------- +// ----- Randomly deactivate channels ----------------------------------- +UInt_t CbmStsParSetModule::DeactivateRandomChannels(Double_t fraction) { + if ( fraction <= 0. ) return 0; + UInt_t nDeactivated = 0; + for ( auto& entry : fParams ) { + nDeactivated += entry.second.DeactivateRandomChannels(fraction); + } + return nDeactivated; +} +// -------------------------------------------------------------------------- + + // ----- Read parameters from ASCII file -------------------------------- Bool_t CbmStsParSetModule::getParams(FairParamList*) { LOG(fatal) << GetName() << ": ASCII input is not defined!"; @@ -45,7 +58,7 @@ Bool_t CbmStsParSetModule::getParams(FairParamList*) { // -------------------------------------------------------------------------- -// ----- Get condition parameters of a sensor --------------------------- +// ----- Get condition parameters of a module --------------------------- const CbmStsParModule& CbmStsParSetModule::GetParModule(UInt_t address) { if (fUseGlobal) return fGlobalParams; assert(fParams.count(address)); @@ -61,6 +74,17 @@ void CbmStsParSetModule::putParams(FairParamList*) { // -------------------------------------------------------------------------- +// ----- Set module parameters ------------------------------------------ +void CbmStsParSetModule::SetParModule(UInt_t address, + const CbmStsParModule& par) { + if (fParams.count(address)) + LOG(fatal) << GetName() << ": Replacing parameters for sensor address " + << address; + fParams[address] = par; +} +// -------------------------------------------------------------------------- + + // ----- Info to string ------------------------------------------------ std::string CbmStsParSetModule::ToString() const { std::stringstream ss; diff --git a/core/detectors/sts/CbmStsParSetModule.h b/core/detectors/sts/CbmStsParSetModule.h index 987f228377..47054ec4f0 100644 --- a/core/detectors/sts/CbmStsParSetModule.h +++ b/core/detectors/sts/CbmStsParSetModule.h @@ -56,6 +56,13 @@ public: virtual void clear(); + /** @brief Randomly deactivate a fraction of the channels + ** @param fraction Fraction of channels to deactivate + ** @return Number of deactivated channels + **/ + UInt_t DeactivateRandomChannels(Double_t fraction); + + /** @brief Reading parameters from ASCII. Abstract in base class. ** ** An ASCII I/O is not implemented. The method throws an error. @@ -102,6 +109,12 @@ public: fUseGlobal = kTRUE; } + /** @brief Set the parameters for a module + ** @param address Module address + ** @param par Module parameter object + **/ + void SetParModule(UInt_t address, const CbmStsParModule& par); + /** @brief Info to string **/ std::string ToString() const; @@ -114,7 +127,7 @@ private: /** @brief Global parameters, used for all modules **/ CbmStsParModule fGlobalParams {}; - /** @brief Map of parameters. Key is sensor address. **/ + /** @brief Map of parameters. Key is module address. **/ std::map<UInt_t, CbmStsParModule> fParams {}; diff --git a/sim/detectors/sts/CbmStsDigitize.cxx b/sim/detectors/sts/CbmStsDigitize.cxx index d3956d2c10..7554c2bf33 100644 --- a/sim/detectors/sts/CbmStsDigitize.cxx +++ b/sim/detectors/sts/CbmStsDigitize.cxx @@ -438,12 +438,20 @@ void CbmStsDigitize::InitParams() { assert(fUserParModule); assert(fUserParAsic); fUserParModule->SetAllAsics(*fUserParAsic); - fParSetModule->SetGlobalPar(*fUserParModule); + for (Int_t iModule = 0; iModule < fSetup->GetNofModules(); iModule++) { + UInt_t address = fSetup->GetModule(iModule)->GetAddress(); + fParSetModule->SetParModule(address, *fUserParModule); + } + UInt_t deactivated = 0; + if ( fUserFracDeadChan > 0. ) { + deactivated = fParSetModule->DeactivateRandomChannels(fUserFracDeadChan); + } fParSetModule->setChanged(); fParSetModule->setInputVersion(-2, 1); LOG(info) << "--- Using global ASIC parameters: \n " << fUserParAsic->ToString(); LOG(info) << "--- Module parameters: " << fParSetModule->ToString(); + LOG(info) << "--- Deactive channels: " << deactivated << " " << fUserFracDeadChan; // --- Sensor parameters // TODO: The code above is highly unsatisfactory. A better implementation @@ -714,24 +722,23 @@ void CbmStsDigitize::SetGlobalDefaults() { // through the base class CbmDigitizeBase, such that the settings here // will be overwritten later (in Init). + // --- Module parameters + if (fUserParModule) delete fUserParModule; + UInt_t nChannels = 2048; // Number of module readout channels + UInt_t nAsicChannels = 128; // Number of readout channels per ASIC + fUserParModule = new CbmStsParModule(nChannels, nAsicChannels); + // --- ASIC parameters if (fUserParAsic) delete fUserParAsic; - UInt_t nAdc = 32; // Number of ADC channels (5 bit) + UShort_t nAdc = 32; // Number of ADC channels (5 bit) Double_t dynRange = 75000.; // Dynamic range [e] Double_t threshold = 3000.; // Threshold [e] Double_t timeResol = 5.; // Time resolution [ns] Double_t deadTime = 800.; // Channel dead time [ns] Double_t noiseRms = 1000.; // RMS of noise [e] Double_t znr = 3.9789e-3; // Zero-crossing noise rate [1/ns] - fUserParAsic = new CbmStsParAsic( - nAdc, dynRange, threshold, timeResol, deadTime, noiseRms, znr); - - // --- Module parameters - if (fUserParModule) delete fUserParModule; - UInt_t nChannels = 2048; // Number of module readout channels - UInt_t nAsicChannels = 128; // Number of readout channels per ASIC - fUserParModule = new CbmStsParModule(nChannels, nAsicChannels); - + fUserParAsic = new CbmStsParAsic(nAsicChannels, nAdc, dynRange, threshold, + timeResol, deadTime, noiseRms, znr); // --- Sensor parameters // --- Here, only the default pitch and stereo angles are defined. The // --- other parameters are extracted from the geometry. @@ -762,7 +769,8 @@ void CbmStsDigitize::SetGlobalDefaults() { // ----- Set the global module parameters ------------------------------ -void CbmStsDigitize::SetGlobalAsicParams(UInt_t nAdc, +void CbmStsDigitize::SetGlobalAsicParams(UShort_t nChannels, + UShort_t nAdc, Double_t dynRange, Double_t threshold, Double_t timeResolution, @@ -772,8 +780,9 @@ void CbmStsDigitize::SetGlobalAsicParams(UInt_t nAdc, assert(!fIsInitialised); assert(nAdc > 0); if (fUserParAsic) delete fUserParAsic; - fUserParAsic = new CbmStsParAsic( - nAdc, dynRange, threshold, timeResolution, deadTime, noise, zeroNoiseRate); + fUserParAsic = new CbmStsParAsic(nChannels, nAdc, dynRange, threshold, + timeResolution, deadTime, noise, + zeroNoiseRate); } // ------------------------------------------------------------------------- diff --git a/sim/detectors/sts/CbmStsDigitize.h b/sim/detectors/sts/CbmStsDigitize.h index f4b96e90a3..f8ce957de1 100644 --- a/sim/detectors/sts/CbmStsDigitize.h +++ b/sim/detectors/sts/CbmStsDigitize.h @@ -116,6 +116,7 @@ public: /** @brief Set the global ASIC parameters + ** @param nChannels Number of readout channels ** @param nAdc Number of ADC channels ** @param dynRange Dynamic range [e] ** @param threshold Threshold [e] @@ -126,7 +127,8 @@ public: ** ** These parameters will be applied to all ASICS in all modules. **/ - void SetGlobalAsicParams(UInt_t nAdc, + void SetGlobalAsicParams(UShort_t nChannels, + UShort_t nAdc, Double_t dynRange, Double_t threshold, Double_t timeResolution, @@ -135,6 +137,17 @@ public: Double_t zeroNoiseRate); + /** @brief Set global fraction of dead channels + ** @param fraction Fraction of dead channels + ** + ** If this number is different from zero, in each ASIC a number of + ** channels corresponding to this fraction are deactivated. + **/ + void SetGlobalFracDeadChannels(Double_t fraction) { + fUserFracDeadChan = fraction; + } + + /** @brief Set the global module parameters ** @param nChannels Number of readout channels ** @param nAsicChannels Number of readout channels per ASIC @@ -253,6 +266,7 @@ private: CbmStsParSensor* fUserParSensor = nullptr; ///< User defined, global CbmStsParSensorCond* fUserParCond = nullptr; ///< User defined, global Double_t fUserDinactive = 0.; ///< Size of inactive sensor border [cm] + Double_t fUserFracDeadChan = 0.; ///< Fraction of inactive ASIC channels // --- Module and sensor parameters for runtime DB output CbmStsParSim* fParSim = nullptr; ///< Simulation settings -- GitLab