ExponentialChannelNoiseService_service.cc
Go to the documentation of this file.
1 // ExponentialChannelNoiseService.cxx
2 
5 #include <sstream>
10 #include "nurandom/RandomUtils/NuRandomService.h"
11 #include "art_root_io/TFileService.h"
12 #include "CLHEP/Random/JamesRandom.h"
13 #include "CLHEP/Random/RandFlat.h"
14 #include "CLHEP/Random/RandGauss.h"
15 #include "TH1F.h"
16 #include "TRandom3.h"
17 
18 using std::cout;
19 using std::ostream;
20 using std::endl;
21 using std::string;
22 using std::ostringstream;
23 using rndm::NuRandomService;
24 using CLHEP::HepJamesRandom;
25 
26 //**********************************************************************
27 
30 : fRandomSeed(0), fLogLevel(1),
31  fNoiseHistZ(nullptr), fNoiseHistU(nullptr), fNoiseHistV(nullptr),
32  fNoiseChanHist(nullptr),
33  m_pran(nullptr) {
34  const string myname = "ExponentialChannelNoiseService::ctor: ";
35  fNoiseNormZ = pset.get<double>("NoiseNormZ");
36  fNoiseWidthZ = pset.get<double>("NoiseWidthZ");
37  fLowCutoffZ = pset.get<double>("LowCutoffZ");
38  fNoiseNormU = pset.get<double>("NoiseNormU");
39  fNoiseWidthU = pset.get<double>("NoiseWidthU");
40  fLowCutoffU = pset.get<double>("LowCutoffU");
41  fNoiseNormV = pset.get<double>("NoiseNormV");
42  fNoiseWidthV = pset.get<double>("NoiseWidthV");
43  fLowCutoffV = pset.get<double>("LowCutoffV");
44  fWhiteNoiseZ = pset.get<double>("WhiteNoiseZ");
45  fWhiteNoiseU = pset.get<double>("WhiteNoiseU");
46  fWhiteNoiseV = pset.get<double>("WhiteNoiseV");
47  fNoiseArrayPoints = pset.get<unsigned int>("NoiseArrayPoints");
48  fOldNoiseIndex = pset.get<bool>("OldNoiseIndex");
49  bool haveSeed = pset.get_if_present<int>("RandomSeed", fRandomSeed);
50  if ( fRandomSeed == 0 ) haveSeed = false;
51  pset.get_if_present<int>("LogLevel", fLogLevel);
52  fNoiseZ.resize(fNoiseArrayPoints);
53  fNoiseU.resize(fNoiseArrayPoints);
54  fNoiseV.resize(fNoiseArrayPoints);
55  int seed = fRandomSeed;
57  fNoiseHistZ = tfs->make<TH1F>("znoise", ";Z Noise [ADC counts];", 1000, -10., 10.);
58  fNoiseHistU = tfs->make<TH1F>("unoise", ";U Noise [ADC counts];", 1000, -10., 10.);
59  fNoiseHistV = tfs->make<TH1F>("vnoise", ";V Noise [ADC counts];", 1000, -10., 10.);
60  fNoiseChanHist = tfs->make<TH1F>("NoiseChan", ";Noise channel;", fNoiseArrayPoints, 0, fNoiseArrayPoints);
61  // Assign a unique name for the random number engine ExponentialChannelNoiseServiceVIII
62  // III = for each instance of this class.
63  string rname = "ExponentialChannelNoiseService";
64  if ( haveSeed ) {
65  if ( fLogLevel > 0 ) cout << myname << "WARNING: Using hardwired seed." << endl;
66  m_pran = new HepJamesRandom(seed);
67  } else {
68  if ( fLogLevel > 0 ) cout << myname << "Using NuRandomService." << endl;
70  m_pran = new HepJamesRandom;
71  if ( fLogLevel > 0 ) cout << myname << " Initial seed: " << m_pran->getSeed() << endl;
72  seedSvc->registerEngine(NuRandomService::CLHEPengineSeeder(m_pran), rname);
73  }
74  if ( fLogLevel > 0 ) cout << myname << " Registered seed: " << m_pran->getSeed() << endl;
75 
76  auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataForJob();
77  for ( unsigned int isam=0; isam<fNoiseArrayPoints; ++isam ) {
78  generateNoise(clockData, fNoiseNormZ, fNoiseWidthZ, fLowCutoffZ, fNoiseZ[isam], fNoiseHistZ);
79  generateNoise(clockData, fNoiseNormU, fNoiseWidthU, fLowCutoffU, fNoiseU[isam], fNoiseHistU);
80  generateNoise(clockData, fNoiseNormV, fNoiseWidthV, fLowCutoffV, fNoiseV[isam], fNoiseHistV);
81  }
82  if ( fLogLevel > 1 ) print() << endl;
83 }
84 
85 //**********************************************************************
86 
90 
91 //**********************************************************************
92 
94  const string myname = "ExponentialChannelNoiseService::dtor: ";
95  if ( fLogLevel > 0 ) {
96  cout << myname << "Deleting random engine with seed " << m_pran->getSeed() << endl;
97  }
98  delete m_pran;
99 }
100 
101 //**********************************************************************
102 
105  Channel chan, AdcSignalVector& sigs) const {
106  CLHEP::RandFlat flat(*m_pran);
107  CLHEP::RandGauss gaus(*m_pran);
108  unsigned int noisechan = 0;
109  if ( fOldNoiseIndex ) {
110  // Keep this strange way of choosing noise channel to be consistent with old results.
111  // The relative weights of the first and last channels are 0.5 and 0.6.
112  noisechan = nearbyint(flat.fire()*(1.*(fNoiseArrayPoints-1)+0.1));
113  } else {
114  noisechan = flat.fire()*fNoiseArrayPoints;
115  if ( noisechan == fNoiseArrayPoints ) --noisechan;
116  }
117  fNoiseChanHist->Fill(noisechan);
119  const geo::View_t view = geo->View(chan);
120  for ( unsigned int itck=0; itck<sigs.size(); ++itck ) {
121  double tnoise = 0.0;
122  double wnoise = 0.0;
123  if ( view==geo::kU ) {
124  tnoise = fNoiseU[noisechan][itck];
125  wnoise = fWhiteNoiseU;
126  } else if ( view==geo::kV ) {
127  tnoise = fNoiseV[noisechan][itck];
128  wnoise = fWhiteNoiseV;
129  } else {
130  tnoise = fNoiseZ[noisechan][itck];
131  wnoise = fWhiteNoiseZ;
132  }
133  if ( wnoise != 0.0 ) tnoise += wnoise*gaus.fire();
134  sigs[itck] += tnoise;
135  }
136  return 0;
137 }
138 
139 //**********************************************************************
140 
141 ostream& ExponentialChannelNoiseService::print(ostream& out, string prefix) const {
142  out << prefix << "ExponentialChannelNoiseService: " << endl;
143  out << prefix << " NoiseNormZ: " << fNoiseNormZ << endl;
144  out << prefix << " NoiseWidthZ: " << fNoiseWidthZ << endl;
145  out << prefix << " LowCutoffZ: " << fLowCutoffZ << endl;
146  out << prefix << " NoiseNormU: " << fNoiseNormU << endl;
147  out << prefix << " NoiseWidthU: " << fNoiseWidthU << endl;
148  out << prefix << " LowCutoffU: " << fLowCutoffU << endl;
149  out << prefix << " NoiseNormV: " << fNoiseNormV << endl;
150  out << prefix << " NoiseWidthV: " << fNoiseWidthV << endl;
151  out << prefix << " LowCutoffV: " << fLowCutoffV << endl;
152  out << prefix << " NoiseArrayPoints: " << fNoiseArrayPoints << endl;
153  out << prefix << " OldNoiseIndex: " << fOldNoiseIndex << endl;
154  out << prefix << " WhiteNoiseZ: " << fWhiteNoiseZ << endl;
155  out << prefix << " WhiteNoiseU: " << fWhiteNoiseU << endl;
156  out << prefix << " WhiteNoiseV: " << fWhiteNoiseV << endl;
157  out << prefix << " RandomSeed: " << fRandomSeed << endl;
158  out << prefix << " LogLevel: " << fLogLevel << endl;
159  out << prefix << " Actual random seed: " << m_pran->getSeed();
160  return out;
161 }
162 
163 //**********************************************************************
164 
167  float aNoiseNorm, float aNoiseWidth, float aLowCutoff,
168  AdcSignalVector& noise, TH1* aNoiseHist) const {
169  const string myname = "ExponentialChannelNoiseService::generateNoise: ";
170  if ( fLogLevel > 1 ) {
171  cout << myname << "Generating noise." << endl;
172  if ( fLogLevel > 2 ) {
173  cout << myname << " Norm: " << aNoiseNorm << endl;
174  cout << myname << " Width: " << aNoiseWidth << endl;
175  cout << myname << " Cutoff: " << aLowCutoff << endl;
176  cout << myname << " Seed: " << m_pran->getSeed() << endl;
177  }
178  }
179  // Fetch sampling rate.
180  float sampleRate = sampling_rate(clockData);
181  // Fetch FFT service and # ticks.
183  unsigned int ntick = pfft->FFTSize();
184  CLHEP::RandFlat flat(*m_pran);
185  // Create noise spectrum in frequency.
186  unsigned nbin = ntick/2 + 1;
187  std::vector<TComplex> noiseFrequency(nbin, 0.);
188  double pval = 0.;
189  double lofilter = 0.;
190  double phase = 0.;
191  double rnd[2] = {0.};
192  // width of frequencyBin in kHz
193  double binWidth = 1.0/(ntick*sampleRate*1.0e-6);
194  bool flatAtLowFreq = aLowCutoff < 0.0;
195  double frqCutoff = flatAtLowFreq ? -aLowCutoff : 0.0;
196  for ( unsigned int i=0; i<ntick/2+1; ++i ) {
197  double frq = double(i)*binWidth;
198  // For aLowCutoff < 0, we have constant noise below -aLowCutoff.
199  // For positive values, we keep the old albeit questionable behavior.
200  if ( flatAtLowFreq ) {
201  lofilter = 1.0;
202  if ( frq < frqCutoff ) frq = frqCutoff;
203  } else {
204  lofilter = 1.0/(1.0+exp(-(i-aLowCutoff/binWidth)/0.5));
205  }
206  // exponential noise spectrum
207  pval = aNoiseNorm*exp(-frq/aNoiseWidth);
208  // low frequency cutoff
209  // randomize 10%
210  flat.fireArray(2, rnd, 0, 1);
211  pval *= lofilter*(0.9 + 0.2*rnd[0]);
212  // random phase angle
213  phase = rnd[1]*2.*TMath::Pi();
214  TComplex tc(pval*cos(phase),pval*sin(phase));
215  noiseFrequency[i] += tc;
216  }
217  // Obtain time spectrum from frequency spectrum.
218  noise.clear();
219  noise.resize(ntick,0.0);
220  std::vector<double> tmpnoise(noise.size());
221  pfft->DoInvFFT(noiseFrequency, tmpnoise);
222  noiseFrequency.clear();
223  // Multiply each noise value by ntick as the InvFFT
224  // divides each bin by ntick assuming that a forward FFT
225  // has already been done.
226  // DLA Feb 2016: Change factor from ntick --> sqrt(ntick) so that the RMS
227  // does not depend on ntick (FFT size).
228  for ( unsigned int itck=0; itck<noise.size(); ++itck ) {
229  noise[itck] = sqrt(ntick)*tmpnoise[itck];
230  }
231  for ( unsigned int itck=0; itck<noise.size(); ++itck ) {
232  aNoiseHist->Fill(noise[itck]);
233  }
234 }
235 
236 //**********************************************************************
237 
239  fNoiseZ.resize(fNoiseArrayPoints);
240  fNoiseU.resize(fNoiseArrayPoints);
241  fNoiseV.resize(fNoiseArrayPoints);
242  for ( unsigned int inch=0; inch<fNoiseArrayPoints; ++inch ) {
246  }
247 }
248 
249 //**********************************************************************
250 
252 
253 //**********************************************************************
float fNoiseWidthV
exponential noise width (kHz) for V plane
enum geo::_plane_proj View_t
Enumerate the possible plane projections.
std::string string
Definition: nybbler.cc:12
Planes which measure V.
Definition: geo_types.h:130
float fNoiseNormV
noise scale factor for V plane
AdcSignalVectorVector fNoiseV
noise on each channel for each time for V plane
float fNoiseNormZ
noise scale factor for Z (collection) plane
void generateNoise(detinfo::DetectorClocksData const &clockData, float aNoiseNorm, float aNoiseWidth, float aLowCutoff, AdcSignalVector &noise, TH1 *aNoiseHist) const
float fLowCutoffV
low frequency filter cutoff (kHz) for V plane
float fLowCutoffZ
low frequency filter cutoff (kHz) for Z (collection) plane
float fNoiseWidthZ
exponential noise width (kHz) for Z (collection) plane
art framework interface to geometry description
void DoInvFFT(std::vector< TComplex > &input, std::vector< T > &output)
Definition: LArFFT.h:120
int addNoise(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, Channel chan, AdcSignalVector &sigs) const
Planes which measure U.
Definition: geo_types.h:129
int FFTSize() const
Definition: LArFFT.h:69
float fWhiteNoiseU
Level (per freq bin) for white noise for U.
float fWhiteNoiseV
Level (per freq bin) for white noise for V.
T gaus(T x, T amplitude, T mean, T sigma)
Tests GausssianFit object with a known input.
std::ostream & print(std::ostream &out=std::cout, std::string prefix="") const
AdcSignalVectorVector fNoiseZ
noise on each channel for each time for Z (collection) plane
T get(std::string const &key) const
Definition: ParameterSet.h:271
TH1 * fNoiseHistU
distribution of noise counts for U
float fLowCutoffU
low frequency filter cutoff (kHz) for U plane
View_t View(geo::PlaneID const &pid) const
Returns the view (wire orientation) on the channels of specified TPC plane.
float fNoiseWidthU
exponential noise width (kHz) for U plane
float fWhiteNoiseZ
Level (per freq bin) for white noise for Z.
bool fOldNoiseIndex
Use old selection of noise array index.
TH1 * fNoiseHistV
distribution of noise counts for V
pval
Definition: tracks.py:168
ExponentialChannelNoiseService(fhicl::ParameterSet const &pset)
Contains all timing reference information for the detector.
int fLogLevel
Log message level: 0=quiet, 1=init only, 2+=every event.
std::optional< T > get_if_present(std::string const &key) const
Definition: ParameterSet.h:224
float fNoiseNormU
noise scale factor for U plane
std::vector< AdcSignal > AdcSignalVector
Definition: AdcTypes.h:22
TH1 * fNoiseChanHist
distribution of accessed noise samples
AdcSignalVectorVector fNoiseU
noise on each channel for each time for U plane
TH1 * fNoiseHistZ
distribution of noise counts for Z
double sampling_rate(DetectorClocksData const &data)
Returns the period of the TPC readout electronics clock.
LArSoft geometry interface.
Definition: ChannelGeo.h:16
int fRandomSeed
Seed for random number service. If absent or zero, use SeedSvc.
QTextStream & endl(QTextStream &s)
unsigned int fNoiseArrayPoints
number of points in randomly generated noise array
#define DEFINE_ART_SERVICE_INTERFACE_IMPL(svc, iface)