LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
SimWire_module.cc
Go to the documentation of this file.
1 //
3 // SimWire class designed to simulate signal on a wire in the TPC
4 //
5 // katori@fnal.gov
6 //
7 // - Revised to use sim::RawDigit instead of rawdata::RawDigit, and to
8 // - save the electron clusters associated with each digit.
9 //
10 // mwang@fnal.gov (2/04/21)
11 //
12 // - Revised field response functions with quadratic and sinusoidal for
13 // collection and induction planes, respectively
14 // - Updated electronics response with uBooNE spice-based model
15 // - Included more realistic noise models:
16 // (a) modified uBooNE model -> "ModUBooNE" in fcl
17 // (b) ArgoNeuT data driven model -> "ArgoNeuT" in fcl
18 // - Included following distributions for fluctuating magnitude of
19 // noise frequency components:
20 // (a) simple modified Poisson -> "SimplePoisson" in fcl
21 // (b) weighted Poisson from ArgoNeuT DDN -> "WeightedPoisson" in fcl
22 // - Included choice for generating unique noise in each channel for
23 // each event
24 // - Updated ConvoluteResponseFunctions() to do things in same fashion
25 // as in a typical SignalShapingXXX service for a particular XXX
26 // experiment
27 //
29 
30 // ROOT includes
31 #include "TComplex.h"
32 #include "TMath.h"
33 
34 // C++ includes
35 #include <algorithm>
36 #include <memory>
37 #include <string>
38 #include <utility>
39 #include <vector>
40 
41 // Framework includes
46 #include "art_root_io/TFileService.h"
47 #include "cetlib_except/exception.h"
48 #include "fhiclcpp/ParameterSet.h"
50 
51 // art extensions
53 
54 #include "CLHEP/Random/RandFlat.h"
55 
56 // LArSoft includes
63 #include "lardataobj/RawData/raw.h"
65 
66 // Detector simulation of raw signals on wires
67 namespace detsim {
68 
69  class SimWire : public art::EDProducer {
70  public:
71  explicit SimWire(fhicl::ParameterSet const& pset);
72 
73  private:
74  void produce(art::Event& evt) override;
75  void beginJob() override;
76 
78 
79  void SetFieldResponse();
80  void SetElectResponse();
81 
82  void GenNoise(std::vector<float>& array, CLHEP::HepRandomEngine& engine);
83 
84  std::string fDriftEModuleLabel;
86 
87  int fNTicks;
88  double fSampleRate;
89  unsigned int fNSamplesReadout;
91  double fInd3DCorrection;
93  unsigned int fNElectResp;
96  double fShapeTimeConst;
100  std::string fNoiseModelChoice;
101  std::string fNoiseFluctChoice;
102 
103  std::vector<int> fFieldRespTOffset;
104  std::vector<int> fCalibRespTOffset;
105  std::vector<float> fColFieldParams;
106  std::vector<float> fIndFieldParams;
107  std::vector<double> fColFieldResponse;
108  std::vector<double> fIndFieldResponse;
109  std::vector<TComplex> fColShape;
110  std::vector<TComplex> fIndShape;
111  std::vector<double> fElectResponse;
112  std::vector<std::vector<float>> fNoise;
113  std::vector<double> fNoiseModelPar;
114  std::vector<double> fNoiseFluctPar;
115 
118  TH1D* fElectResp;
121  TH1D* fNoiseDist;
122  TF1* fNoiseFluct;
123 
124  CLHEP::HepRandomEngine& fEngine;
125  }; // class SimWire
126 
127 }
128 
129 namespace detsim {
130 
131  //-------------------------------------------------
133  : EDProducer{pset}
134  , fDriftEModuleLabel{pset.get<std::string>("DriftEModuleLabel")}
135  , fCompression{pset.get<std::string>("CompressionType") == "Huffman" ? raw::kHuffman :
136  raw::kNone}
137  , fCol3DCorrection{pset.get<double>("Col3DCorrection")}
138  , fInd3DCorrection{pset.get<double>("Ind3DCorrection")}
139  , fInputFieldRespSamplingPeriod{pset.get<double>("InputFieldRespSamplingPeriod")}
140  , fShapeTimeConst{pset.get<double>("ShapeTimeConst")}
141  , fADCPerPCAtLowestASICGain{pset.get<double>("ADCPerPCAtLowestASICGain")}
142  , fASICGainInMVPerFC{pset.get<double>("ASICGainInMVPerFC")}
143  , fNoiseNchToSim{pset.get<int>("NoiseNchToSim")}
144  , fNoiseModelChoice{pset.get<std::string>("NoiseModelChoice")}
145  , fNoiseFluctChoice{pset.get<std::string>("NoiseFluctChoice")}
146  , fFieldRespTOffset{pset.get<std::vector<int>>("FieldRespTOffset")}
147  , fCalibRespTOffset{pset.get<std::vector<int>>("CalibRespTOffset")}
148  , fColFieldParams{pset.get<std::vector<float>>("ColFieldParams")}
149  , fIndFieldParams{pset.get<std::vector<float>>("IndFieldParams")}
150  , fNoiseModelPar{pset.get<std::vector<double>>("NoiseModelPar")}
151  , fNoiseFluctPar{pset.get<std::vector<double>>("NoiseFluctPar")}
152  // create a default random engine; obtain the random seed from NuRandomService,
153  // unless overridden in configuration with key "Seed"
154  , fEngine(art::ServiceHandle<rndm::NuRandomService>()->registerAndSeedEngine(createEngine(0),
155  pset,
156  "Seed"))
157  {
158  auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataForJob();
159  auto const detProp =
161  fSampleRate = sampling_rate(clockData);
162  fNSamplesReadout = detProp.NumberTimeSamples();
163 
164  MF_LOG_WARNING("SimWire") << "SimWire is an example module that works for the "
165  << "MicroBooNE detector. Each experiment should implement "
166  << "its own version of this module to simulate electronics "
167  << "response.";
168 
169  produces<std::vector<raw::RawDigit>>();
170  }
171 
172  //-------------------------------------------------
174  {
175  // ... get access to the TFile service
177 
178  fNoiseDist = tfs->make<TH1D>("Noise", ";Noise (ADC);", 1000, -10., 10.);
179 
181  fNTicks = fFFT->FFTSize();
182 
183  // ... Poisson dist function for fluctuating magnitude of noise frequency component
184  if (fNoiseFluctChoice == "SimplePoisson") {
185  // .. simple modified Poisson with (x-1)! in denominator
186  double params[1];
187  fNoiseFluct = new TF1("_poisson", "[0]**(x) * exp(-[0]) / ROOT::Math::tgamma(x)", 0, 5.);
188  params[0] = fNoiseFluctPar[0]; // Poisson mean
189  fNoiseFluct->SetParameters(params);
190  }
191  else if (fNoiseFluctChoice == "WeightedPoisson") {
192  // .. weighted Poisson in ArgoNeuT DDN model
193  double params[3];
194  fNoiseFluct = new TF1(
195  "_poisson", "[0]*pow([1]/[2], x/[2])*exp(-[1]/[2])/ROOT::Math::tgamma(x/[2]+1.)", 0, 5.);
196  params[0] = fNoiseFluctPar[0];
197  params[1] = fNoiseFluctPar[1];
198  params[2] = fNoiseFluctPar[2];
199  fNoiseFluct->SetParameters(params);
200  }
201  else {
202  throw cet::exception("SimWire::beginJob")
203  << fNoiseFluctChoice << " is an unknown noise fluctuation choice" << std::endl;
204  }
205 
206  // ... generate the noise in advance depending on value of fNoiseNchToSim:
207  // positive - generate N=fNoiseNchToSim channels & randomly pick from pool when adding to signal
208  // zero - no noise
209  // negative - generate unique noise for each channel for each event
210  if (fNoiseNchToSim > 0) {
211  if (fNoiseNchToSim > 10000) {
212  throw cet::exception("SimWire::beginJob")
213  << fNoiseNchToSim << " noise channels requested exceeds 10000" << std::endl;
214  }
215  fNoise.resize(fNoiseNchToSim);
216  for (unsigned int p = 0; p < fNoise.size(); ++p) {
217  GenNoise(fNoise[p], fEngine);
218  for (int i = 0; i < fNTicks; ++i) {
219  fNoiseDist->Fill(fNoise[p][i]);
220  }
221  }
222  }
223 
224  // ... set field response and electronics response, then convolute them
228  }
229 
230  //-------------------------------------------------
232  {
233 
235 
236  // ... generate unique noise for each channel in each event
237  if (fNoiseNchToSim < 0) {
238  fNoise.clear();
239  fNoise.resize(geo->Nchannels());
240  for (unsigned int p = 0; p < geo->Nchannels(); ++p) {
241  GenNoise(fNoise[p], fEngine);
242  }
243  }
244 
245  // ... make a vector of const sim::SimChannel* that has same number
246  // of entries as the number of channels in the detector
247  // and set the entries for the channels that have signal on them
248  // using the chanHandle
249  std::vector<const sim::SimChannel*> chanHandle;
250  evt.getView(fDriftEModuleLabel, chanHandle);
251 
252  std::vector<const sim::SimChannel*> channels(geo->Nchannels());
253  for (size_t c = 0; c < chanHandle.size(); ++c) {
254  channels[chanHandle[c]->Channel()] = chanHandle[c];
255  }
256 
257  // ... make an unique_ptr of sim::SimDigits that allows ownership of the produced
258  // digits to be transferred to the art::Event after the put statement below
259  auto digcol = std::make_unique<std::vector<raw::RawDigit>>();
260 
262 
263  // ... Add all channels
264  CLHEP::RandFlat flat(fEngine);
265 
267  for (unsigned int chan = 0; chan < geo->Nchannels(); chan++) {
268 
269  std::vector<short> adcvec(fNTicks, 0);
270  std::vector<double> fChargeWork(fNTicks, 0.);
271 
272  if (channels[chan]) {
273 
274  // .. get the sim::SimChannel for this channel
275  const sim::SimChannel* sc = channels[chan];
276 
277  // .. loop over the tdcs and grab the number of electrons for each
278  for (int t = 0; t < fNTicks; ++t)
279  fChargeWork[t] = sc->Charge(t);
280 
281  int time_offset = 0;
282 
283  // .. Convolve charge with appropriate response function
284  if (geo->SignalType(chan) == geo::kInduction) {
285  fFFT->Convolute(fChargeWork, fIndShape);
286  time_offset = fFieldRespTOffset[1] + fCalibRespTOffset[1];
287  }
288  else {
289  fFFT->Convolute(fChargeWork, fColShape);
290  time_offset = fFieldRespTOffset[0] + fCalibRespTOffset[0];
291  }
292 
293  // .. Apply field response offset
294  std::vector<int> temp;
295  if (time_offset <= 0) {
296  temp.assign(fChargeWork.begin(), fChargeWork.begin() - time_offset);
297  fChargeWork.erase(fChargeWork.begin(), fChargeWork.begin() - time_offset);
298  fChargeWork.insert(fChargeWork.end(), temp.begin(), temp.end());
299  }
300  else {
301  temp.assign(fChargeWork.end() - time_offset, fChargeWork.end());
302  fChargeWork.erase(fChargeWork.end() - time_offset, fChargeWork.end());
303  fChargeWork.insert(fChargeWork.begin(), temp.begin(), temp.end());
304  }
305  }
306 
307  // ... Add noise to signal depending on value of fNoiseNchToSim
308  if (fNoiseNchToSim != 0) {
309  int noisechan = chan;
310  if (fNoiseNchToSim > 0) {
311  noisechan = TMath::Nint(flat.fire() * (1. * (fNoise.size() - 1) + 0.1));
312  }
313  for (int i = 0; i < fNTicks; ++i) {
314  adcvec[i] = (short)TMath::Nint(fNoise[noisechan][i] + fChargeWork[i]);
315  }
316  }
317  else {
318  for (int i = 0; i < fNTicks; ++i) {
319  adcvec[i] = (short)TMath::Nint(fChargeWork[i]);
320  }
321  }
322 
323  adcvec.resize(fNSamplesReadout);
324 
325  // ... compress the adc vector using the desired compression scheme,
326  // if raw::kNone is selected nothing happens to adcvec
327  // This shrinks adcvec, if fCompression is not kNone.
328  raw::Compress(adcvec, fCompression);
329 
330  // ... add this digit to the collection
331  digcol->emplace_back(chan, fNTicks, move(adcvec), fCompression);
332 
333  } //end loop over channels
334 
335  evt.put(std::move(digcol));
336 
337  return;
338  }
339 
340  //-------------------------------------------------
342  {
343  double tick, ticks, peak;
344 
345  std::vector<double> col(fNTicks, 0.);
346  std::vector<double> ind(fNTicks, 0.);
347  std::vector<TComplex> kern(fNTicks / 2 + 1);
348  std::vector<double> delta(fNTicks, 0.);
349 
351 
352  // ... do collection plane
353  fColShape.resize(fNTicks / 2 + 1);
355 
356  fFFT->DoFFT(fColFieldResponse, kern);
357  for (unsigned int i = 0; i < kern.size(); ++i)
358  fColShape[i] *= kern[i];
359 
360  fFFT->DoInvFFT(fColShape, col);
361 
362  delta[0] = 1.0;
363  peak = fFFT->PeakCorrelation(delta, col);
364  tick = 0.;
365  ticks = tick - peak;
366  fFFT->ShiftData(fColShape, ticks);
367  fFFT->DoInvFFT(fColShape, col);
368 
369  // ... do induction plane
370  fIndShape.resize(fNTicks / 2 + 1);
372 
373  kern.clear();
374  kern.resize(fNTicks / 2 + 1);
375  fFFT->DoFFT(fIndFieldResponse, kern);
376  for (unsigned int i = 0; i < kern.size(); ++i)
377  fIndShape[i] *= kern[i];
378 
379  fFFT->DoInvFFT(fIndShape, ind);
380 
381  delta.resize(0);
382  delta.resize(fNTicks, 0);
383  delta[0] = 1.0;
384  peak = fFFT->PeakCorrelation(delta, ind);
385  tick = 0.;
386  ticks = tick - peak;
387  fFFT->ShiftData(fIndShape, ticks);
388  fFFT->DoInvFFT(fIndShape, ind);
389 
390  // ... write the time-domain shapes out to a file
392  fColTimeShape = tfs->make<TH1D>(
393  "ConvolutedCollection", ";ticks; Electronics#timesCollection", fNTicks, 0, fNTicks);
394  fIndTimeShape = tfs->make<TH1D>(
395  "ConvolutedInduction", ";ticks; Electronics#timesInduction", fNTicks, 0, fNTicks);
396 
397  // ... check that you did the right thing
398  for (unsigned int i = 0; i < ind.size(); ++i) {
399  fColTimeShape->Fill(i, col[i]);
400  fIndTimeShape->Fill(i, ind[i]);
401  }
402 
403  fColTimeShape->Write();
404  fIndTimeShape->Write();
405  }
406 
407  //-------------------------------------------------
408  void SimWire::GenNoise(std::vector<float>& noise, CLHEP::HepRandomEngine& engine)
409  {
410  CLHEP::RandFlat flat(engine);
411 
412  noise.clear();
413  noise.resize(fNTicks, 0.);
414  std::vector<TComplex> noiseFrequency(fNTicks / 2 + 1, 0.); // noise in frequency space
415 
416  double pval = 0.;
417  double phase = 0.;
418  double rnd[2] = {0.};
419 
420  // .. width of frequencyBin in kHz
421  double binWidth = 1.0 / (fNTicks * fSampleRate * 1.0e-6);
422 
423  for (int i = 0; i < fNTicks / 2 + 1; ++i) {
424 
425  double x = (i + 0.5) * binWidth;
426 
427  if (fNoiseModelChoice == "Legacy") {
428  // ... Legacy exponential model kept here for reference:
429  // par[0]=NoiseFact, par[1]=NoiseWidth, par[2]=LowCutoff, par[3-7]=0
430  // example parameter values for fcl: NoiseModelPar:[ 1.32e-1,120,7.5,0,0,0,0,0 ]
431  pval = fNoiseModelPar[0] * exp(-(double)i * binWidth / fNoiseModelPar[1]);
432  double lofilter = 1.0 / (1.0 + exp(-(i - fNoiseModelPar[2] / binWidth) / 0.5));
433  flat.fireArray(1, rnd, 0, 1);
434  pval *= lofilter * (0.9 + 0.2 * rnd[0]);
435  }
436  else if (fNoiseModelChoice == "ModUBooNE") {
437  // ... Modified uBooNE model with additive exp to account for low freq region:
438  // example parameter values for fcl: NoiseModelPar:[
439  // 4450.,-530.,280.,110.,
440  // -0.85,18.,0.064,74. ]
441  pval = fNoiseModelPar[0] * exp(-0.5 * pow((x - fNoiseModelPar[1]) / fNoiseModelPar[2], 2)) *
442  exp(-0.5 * pow(x / fNoiseModelPar[3], fNoiseModelPar[4])) +
443  fNoiseModelPar[5] + exp(-fNoiseModelPar[6] * (x - fNoiseModelPar[7]));
444  double randomizer = fNoiseFluct->GetRandom();
445  pval = pval * randomizer / fNTicks;
446  }
447  else if (fNoiseModelChoice == "ArgoNeuT") {
448  // ... ArgoNeuT data driven model:
449  // In fcl set parameters to: NoiseModelPar:[
450  // 5000,-5.52058e2,2.81587e2,-5.66561e1,
451  // 4.10817e1,1.76284e1,1e-1,5.97838e1 ]
452  pval = fNoiseModelPar[0] * exp(-0.5 * pow((x - fNoiseModelPar[1]) / fNoiseModelPar[2], 2)) *
453  ((fNoiseModelPar[3] / (x + fNoiseModelPar[4])) + 1) +
454  fNoiseModelPar[5] + exp(-fNoiseModelPar[6] * (x - fNoiseModelPar[7]));
455  double randomizer = fNoiseFluct->GetRandom();
456  pval = pval * randomizer / fNTicks;
457  }
458  else {
459  throw cet::exception("SimWire::GenNoise")
460  << fNoiseModelChoice << " is an unknown choice for the noise model" << std::endl;
461  }
462 
463  flat.fireArray(1, rnd, 0, 1);
464  phase = rnd[0] * 2. * TMath::Pi();
465 
466  TComplex tc(pval * cos(phase), pval * sin(phase));
467  noiseFrequency[i] += tc;
468  }
469 
470  // .. inverse FFT MCSignal
472  fFFT->DoInvFFT(noiseFrequency, noise);
473 
474  noiseFrequency.clear();
475 
476  // .. multiply each noise value by fNTicks as the InvFFT
477  // divides each bin by fNTicks assuming that a forward FFT
478  // has already been done.
479  for (unsigned int i = 0; i < noise.size(); ++i)
480  noise[i] *= 1. * fNTicks;
481  }
482 
483  //-------------------------------------------------
485  {
486 
487  // ... Files to write the response functions to
489  fIndFieldResp =
490  tfs->make<TH1D>("InductionFieldResponse", ";t (ns);Induction Response", fNTicks, 0, fNTicks);
491  fColFieldResp = tfs->make<TH1D>(
492  "CollectionFieldResponse", ";t (ns);Collection Response", fNTicks, 0, fNTicks);
493 
494  fColFieldResponse.resize(fNTicks, 0.);
495  fIndFieldResponse.resize(fNTicks, 0.);
496 
497  // ... First set response for collection plane
498  int nbinc = fColFieldParams[0];
499 
500  double integral = 0.;
501  for (int i = 1; i < nbinc; ++i) {
502  fColFieldResponse[i] = i * i;
503  integral += fColFieldResponse[i];
504  }
505 
506  for (int i = 0; i < nbinc; ++i) {
507  fColFieldResponse[i] *= fColFieldParams[1] / integral;
508  fColFieldResp->Fill(i, fColFieldResponse[i]);
509  }
510 
511  // ... Now set response for induction plane
512  int nbini = fIndFieldParams[0];
513  unsigned short lastbini = 2 * nbini;
514 
515  integral = 0;
516  for (unsigned short i = 0; i < lastbini; ++i) {
517  double ang = i * TMath::Pi() / nbini;
518  fIndFieldResponse[i] = sin(ang);
519  if (fIndFieldResponse[i] > 0) { integral += fIndFieldResponse[i]; }
520  else {
521  fIndFieldResponse[i] *=
522  fIndFieldParams[2]; // scale the negative lobe by 10% (from ArgoNeuT)
523  }
524  }
525  ++lastbini;
526 
527  for (unsigned short i = 0; i < lastbini; ++i) {
528  fIndFieldResponse[i] *= fIndFieldParams[1] / integral;
529  fIndFieldResp->Fill(i, fIndFieldResponse[i]);
530  }
531 
532  // ... Save the field responses
533  fColFieldResp->Write();
534  fIndFieldResp->Write();
535  }
536 
537  //-------------------------------------------------
539  {
540  fElectResponse.resize(fNTicks, 0.);
541  std::vector<double> time(fNTicks, 0.);
542 
543  // ... Gain and shaping time variables from fcl file:
544  double Ao = 1.0;
545  double To = fShapeTimeConst; //peaking time
546 
547  // ... this is actually sampling time, in ns
548  mf::LogInfo("SimWire::SetElectResponse")
549  << "Check sampling intervals: " << fInputFieldRespSamplingPeriod << " ns"
550  << "Check number of samples: " << fNTicks;
551 
552  // ... The following sets the microboone electronics response function in
553  // time-space. Function comes from BNL SPICE simulation of DUNE35t
554  // electronics. SPICE gives the electronics transfer function in
555  // frequency-space. The inverse laplace transform of that function
556  // (in time-space) was calculated in Mathematica and is what is being
557  // used below. Parameters Ao and To are cumulative gain/timing parameters
558  // from the full (ASIC->Intermediate amp->Receiver->ADC) electronics chain.
559  // They have been adjusted to make the SPICE simulation to match the
560  // actual electronics response. Default params are Ao=1.4, To=0.5us.
561  double max = 0;
562 
563  for (size_t i = 0; i < fElectResponse.size(); ++i) {
564 
565  // ... convert time to microseconds, to match fElectResponse[i] definition
566  time[i] = (1. * i) * fInputFieldRespSamplingPeriod * 1e-3;
567  fElectResponse[i] =
568  4.31054 * exp(-2.94809 * time[i] / To) * Ao -
569  2.6202 * exp(-2.82833 * time[i] / To) * cos(1.19361 * time[i] / To) * Ao -
570  2.6202 * exp(-2.82833 * time[i] / To) * cos(1.19361 * time[i] / To) *
571  cos(2.38722 * time[i] / To) * Ao +
572  0.464924 * exp(-2.40318 * time[i] / To) * cos(2.5928 * time[i] / To) * Ao +
573  0.464924 * exp(-2.40318 * time[i] / To) * cos(2.5928 * time[i] / To) *
574  cos(5.18561 * time[i] / To) * Ao +
575  0.762456 * exp(-2.82833 * time[i] / To) * sin(1.19361 * time[i] / To) * Ao -
576  0.762456 * exp(-2.82833 * time[i] / To) * cos(2.38722 * time[i] / To) *
577  sin(1.19361 * time[i] / To) * Ao +
578  0.762456 * exp(-2.82833 * time[i] / To) * cos(1.19361 * time[i] / To) *
579  sin(2.38722 * time[i] / To) * Ao -
580  2.6202 * exp(-2.82833 * time[i] / To) * sin(1.19361 * time[i] / To) *
581  sin(2.38722 * time[i] / To) * Ao -
582  0.327684 * exp(-2.40318 * time[i] / To) * sin(2.5928 * time[i] / To) * Ao +
583  +0.327684 * exp(-2.40318 * time[i] / To) * cos(5.18561 * time[i] / To) *
584  sin(2.5928 * time[i] / To) * Ao -
585  0.327684 * exp(-2.40318 * time[i] / To) * cos(2.5928 * time[i] / To) *
586  sin(5.18561 * time[i] / To) * Ao +
587  0.464924 * exp(-2.40318 * time[i] / To) * sin(2.5928 * time[i] / To) *
588  sin(5.18561 * time[i] / To) * Ao;
589 
590  if (fElectResponse[i] > max) max = fElectResponse[i];
591 
592  } // end loop over time buckets
593 
594  // ... "normalize" fElectResponse[i], before the convolution
595 
596  for (auto& element : fElectResponse) {
597  element /= max;
598  element *= fADCPerPCAtLowestASICGain * 1.60217657e-7;
599  element *= fASICGainInMVPerFC / 4.7; // relative to lowest gain setting of 4.7 mV/fC
600  }
601 
602  fNElectResp = fElectResponse.size();
603 
604  // ... write the response out to a file
605 
607  fElectResp = tfs->make<TH1D>(
608  "ElectronicsResponse", ";t (ns);Electronics Response", fNElectResp, 0, fNElectResp);
609  for (unsigned int i = 0; i < fNElectResp; ++i) {
610  fElectResp->Fill(i, fElectResponse[i]);
611  }
612 
613  fElectResp->Write();
614  }
615 
616 }
617 
Float_t x
Definition: compare.C:6
intermediate_table::iterator iterator
base_engine_t & createEngine(seed_t seed)
Huffman Encoding.
Definition: RawTypes.h:10
unsigned int fNSamplesReadout
number of ADC readout samples in 1 readout frame
std::string fNoiseModelChoice
choice for noise model
std::vector< TComplex > fColShape
response function for the field @ collection plane
enum raw::_compress Compress_t
std::vector< float > fIndFieldParams
induction plane field function parameterization
Energy deposited on a readout channel by simulated tracks.
Definition: SimChannel.h:136
std::vector< double > fElectResponse
response function for the electronics
TF1 * fNoiseFluct
Poisson dist for fluctuations in magnitude of noise freq components.
TH1D * fColTimeShape
convoluted shape for field x electronics @ col plane
std::string fDriftEModuleLabel
module making the ionization electrons
int fNoiseNchToSim
number of noise channels to generate
void SetElectResponse()
response of electronics
void ShiftData(std::vector< TComplex > &input, double shift)
Definition: LArFFT.cc:116
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
double fADCPerPCAtLowestASICGain
ADCs/pC at lowest gain setting of 4.7 mV/fC.
EDProducer(fhicl::ParameterSet const &pset)
Definition: EDProducer.cc:6
unsigned int fNElectResp
number of entries from response to use
TH1D * fNoiseDist
distribution of noise counts
Detector simulation of raw signals on wires.
std::string fNoiseFluctChoice
choice for noise freq component mag fluctuations
Definition of basic raw digits.
raw::Compress_t fCompression
compression type to use
double fShapeTimeConst
time constants for exponential shaping
void DoFFT(std::vector< T > &input, std::vector< TComplex > &output)
Definition: LArFFT.h:95
std::vector< std::vector< float > > fNoise
noise on each channel for each time
T PeakCorrelation(std::vector< T > &shape1, std::vector< T > &shape2)
Definition: LArFFT.h:270
double fInputFieldRespSamplingPeriod
Sampling period in the input field response.
tick ticks
Alias for common language habits.
Definition: electronics.h:76
no compression
Definition: RawTypes.h:9
std::vector< float > fColFieldParams
collection plane field function parameterization
void DoInvFFT(std::vector< TComplex > &input, std::vector< T > &output)
Definition: LArFFT.h:117
unsigned int Nchannels() const
Returns the number of TPC readout channels in the detector.
unsigned int noise()
Definition: chem4.cc:261
PutHandle< PROD > put(std::unique_ptr< PROD > &&edp, std::string const &instance={})
Definition: Event.h:77
std::vector< int > fCalibRespTOffset
calib response time offset in ticks
std::vector< double > fIndFieldResponse
response function for the field @ induction plane
int FFTSize() const
Definition: LArFFT.h:66
void GenNoise(std::vector< float > &array, CLHEP::HepRandomEngine &engine)
auto array(Array const &a)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:250
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:65
Signal from induction planes.
Definition: geo_types.h:151
std::vector< double > fColFieldResponse
response function for the field @ collection plane
double Charge(TDC_t tdc) const
Returns the total number of ionization electrons on this channel in the specified TDC...
Definition: SimChannel.cxx:110
std::vector< TComplex > fIndShape
response function for the field @ induction plane
std::vector< double > fNoiseFluctPar
Poisson noise fluctuations params.
Int_t col[ntarg]
Definition: Style.C:29
void produce(art::Event &evt) override
Collect all the RawData header files together.
tick_as<> tick
Tick number, represented by std::ptrdiff_t.
Definition: electronics.h:73
void ConvoluteResponseFunctions()
convolute electronics and field response
double fSampleRate
sampling rate in ns
void SetFieldResponse()
response of wires to field
SimWire(fhicl::ParameterSet const &pset)
An art service to assist in the distribution of guaranteed unique seeds to all engines within an art ...
TH1D * fIndFieldResp
response function for the field @ induction plane
std::size_t getView(std::string const &moduleLabel, std::string const &productInstanceName, std::string const &processName, std::vector< ELEMENT const * > &result) const
int fNTicks
number of ticks of the clock
SigType_t SignalType(PlaneID const &pid) const
Returns the type of signal on the channels of specified TPC plane.
TH1D * fIndTimeShape
convoluted shape for field x electronics @ ind plane
std::vector< int > fFieldRespTOffset
field response time offset in ticks
Encapsulate the construction of a single detector plane.
Float_t sc
Definition: plot.C:23
double fASICGainInMVPerFC
actual gain setting used in mV/fC
object containing MC truth information necessary for making RawDigits and doing back tracking ...
TH1D * fElectResp
response function for the electronics
void Compress(std::vector< short > &adc, raw::Compress_t compress)
Compresses a raw data buffer.
Definition: raw.cxx:19
TCEvent evt
Definition: DataStructs.cxx:8
#define MF_LOG_WARNING(category)
CLHEP::HepRandomEngine & fEngine
Random-number engine owned by art.
Float_t e
Definition: plot.C:35
double sampling_rate(DetectorClocksData const &data)
Returns the period of the TPC readout electronics clock.
Namespace collecting geometry-related classes utilities.
TH1D * fColFieldResp
response function for the field @ collection plane
std::vector< double > fNoiseModelPar
noise model params
art framework interface to geometry description
void beginJob() override
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33