Skip to content
Snippets Groups Projects
CbmStsParAsic.cxx 6.54 KiB
/* Copyright (C) 2020 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
   SPDX-License-Identifier: GPL-3.0-only
   Authors: Volker Friese [committer] */

/** @file CbmStsParAsic.cxx
 ** @author Volker Friese <v.friese@gsi.de>
 ** @date 23.03.2020
 **/
#include "CbmStsParAsic.h"

#include <TF1.h>    // for TF1
#include <TMath.h>  // for Exp
#include <TRandom.h>

#include <sstream>  // for operator<<, basic_ostream, stringstream

#include <assert.h>  // for assert


// -----   Constructor   ---------------------------------------------------
CbmStsParAsic::CbmStsParAsic(UShort_t nChannels, UShort_t nAdc, double dynRange, double threshold, double timeResol,
                             double deadTime, double noise, double znr)
{
  Set(nChannels, nAdc, dynRange, threshold, timeResol, deadTime, noise, znr);
}
// -------------------------------------------------------------------------


// -----   Copy constructor   ----------------------------------------------
CbmStsParAsic::CbmStsParAsic(const CbmStsParAsic& other)
{
  Set(other.fNofChannels, other.fNofAdc, other.fDynRange, other.fThreshold, other.fTimeResolution, other.fDeadTime,
      other.fNoise, other.fZeroNoiseRate);
  SetTimeOffset(other.fTimeOffset);
  SetWalkCoef(other.fWalkCoef);
}
// -------------------------------------------------------------------------


// -----   Move constructor   ----------------------------------------------
CbmStsParAsic::CbmStsParAsic(CbmStsParAsic&& other)
{
  Set(other.fNofChannels, other.fNofAdc, other.fDynRange, other.fThreshold, other.fTimeResolution, other.fDeadTime,
      other.fNoise, other.fZeroNoiseRate);
  SetTimeOffset(other.fTimeOffset);
  SetWalkCoef(other.fWalkCoef);
}
// -------------------------------------------------------------------------


// -----   Copy assignment operator   --------------------------------------
CbmStsParAsic& CbmStsParAsic::operator=(const CbmStsParAsic& other)
{
  Set(other.fNofChannels, other.fNofAdc, other.fDynRange, other.fThreshold, other.fTimeResolution, other.fDeadTime,
      other.fNoise, other.fZeroNoiseRate);
  SetTimeOffset(other.fTimeOffset);
  SetWalkCoef(other.fWalkCoef);
  return *this;
}
// -------------------------------------------------------------------------


// -----   Move assignment operator   --------------------------------------
CbmStsParAsic& CbmStsParAsic::operator=(CbmStsParAsic&& other)
{
  Set(other.fNofChannels, other.fNofAdc, other.fDynRange, other.fThreshold, other.fTimeResolution, other.fDeadTime,
      other.fNoise, other.fZeroNoiseRate);
  SetTimeOffset(other.fTimeOffset);
  SetWalkCoef(other.fWalkCoef);
  return *this;
}
// -------------------------------------------------------------------------


// -----   Destructor   ----------------------------------------------------
CbmStsParAsic::~CbmStsParAsic()
{
  if (fNoiseCharge) delete fNoiseCharge;
}
// -------------------------------------------------------------------------


// -----  ADC channel from charge   ----------------------------------------
int16_t CbmStsParAsic::ChargeToAdc(double charge) const
{
  if (charge < fThreshold) return -1;                        // Underflow
  if (charge >= fThreshold + fDynRange) return fNofAdc - 1;  // Overflow
  return int16_t((charge - fThreshold) / fDynRange * double(fNofAdc));
}
// -------------------------------------------------------------------------


// -----   Deactivate channels   -------------------------------------------
uint16_t CbmStsParAsic::DeactivateRandomChannels(double fraction)
{

  if (fraction < 0.) return 0;

  // --- Average number of dead channels
  double meanDead = fraction * double(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 CbmStsParAsic::GetNoiseRate() const
{
  if (fNoise == 0.) return 0.;
  double ratio = fThreshold / fNoise;
  return 0.5 * fZeroNoiseRate * TMath::Exp(-0.5 * ratio * ratio);
}
// -------------------------------------------------------------------------


// -----   Random charge of a noise signal   -------------------------------
double CbmStsParAsic::GetRandomNoiseCharge() const
{
  assert(fIsInit);
  return fNoiseCharge->GetRandom();
}
// -------------------------------------------------------------------------

// -----   Initialise the noise charge distribution   ----------------------
void CbmStsParAsic::Init()
{
  if (fNoiseCharge) delete fNoiseCharge;
  fNoiseCharge = new TF1("Noise Charge", "TMath::Gaus(x, [0], [1])", fThreshold, 10. * fNoise);
  fNoiseCharge->SetParameters(0., fNoise);
  fIsInit = kTRUE;
}
// -------------------------------------------------------------------------


// -----   Set the parameters   ---------------------------------------------
void CbmStsParAsic::Set(UShort_t nChannels, UShort_t nAdc, double dynRange, double threshold, double timeResol,
                        double deadTime, double noise, double zeroNoiseRate, std::set<UShort_t> deadChannels)
{

  // Assert validity of parameters
  assert(dynRange > 0.);
  assert(threshold > 0.);
  assert(timeResol > 0.);
  assert(deadTime >= 0.);
  assert(noise >= 0.);
  assert(zeroNoiseRate >= 0.);

  fNofChannels    = nChannels;
  fNofAdc         = nAdc;
  fDynRange       = dynRange;
  fThreshold      = threshold;
  fTimeResolution = timeResol;
  fDeadTime       = deadTime;
  fNoise          = noise;
  fZeroNoiseRate  = zeroNoiseRate;
  fDeadChannels   = deadChannels;

  Init();
}
// --------------------------------------------------------------------------


// ----- String output   ----------------------------------------------------
std::string CbmStsParAsic::ToString() const
{
  std::stringstream ss;
  ss << "nAdc " << fNofAdc << " | dynRange " << fDynRange << " e | thresh. " << fThreshold << " e | tResol "
     << fTimeResolution << " ns | deadTime " << fDeadTime << " ns | noise " << fNoise << " e | ZNR " << fZeroNoiseRate
     << "/ns | SCNR " << GetNoiseRate() << "/ns";
  return ss.str();
}
// --------------------------------------------------------------------------


ClassImp(CbmStsParAsic)