42 #include "art/Framework/Core/EDProducer.h"
43 #include "art/Framework/Core/ModuleMacros.h"
44 #include "art/Framework/Principal/Event.h"
45 #include "art/Framework/Services/Registry/ServiceHandle.h"
46 #include "art_root_io/TFileService.h"
47 #include "messagefacility/MessageLogger/MessageLogger.h"
48 #include "fhiclcpp/ParameterSet.h"
49 #include "cetlib_except/exception.h"
52 #include "nurandom/RandomUtils/NuRandomService.h"
54 #include "CLHEP/Random/RandFlat.h"
71 explicit SimWire(fhicl::ParameterSet
const& pset);
82 void GenNoise(std::vector<float>&
array, CLHEP::HepRandomEngine& engine);
134 , fDriftEModuleLabel{pset.get<std::string>(
"DriftEModuleLabel")}
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")}
154 ,
fEngine(art::ServiceHandle<rndm::NuRandomService> {}->createEngine(*
this, pset,
"Seed"))
156 auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataForJob();
158 art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataForJob(clockData);
162 MF_LOG_WARNING(
"SimWire") <<
"SimWire is an example module that works for the "
163 <<
"MicroBooNE detector. Each experiment should implement "
164 <<
"its own version of this module to simulate electronics "
167 produces<std::vector<raw::RawDigit>>();
175 art::ServiceHandle<art::TFileService const>
tfs;
177 fNoiseDist = tfs->make<TH1D>(
"Noise",
";Noise (ADC);", 1000, -10., 10.);
179 art::ServiceHandle<util::LArFFT const> fFFT;
186 fNoiseFluct =
new TF1(
"_poisson",
"[0]**(x) * exp(-[0]) / ROOT::Math::tgamma(x)", 0, 5.);
192 fNoiseFluct =
new TF1(
"_poisson",
"[0]*pow([1]/[2], x/[2])*exp(-[1]/[2])/ROOT::Math::tgamma(x/[2]+1.)", 0, 5.);
199 <<
" is an unknown noise fluctuation choice" << std::endl;
209 <<
" noise channels requested exceeds 10000" << std::endl;
212 for (
unsigned int p = 0;
p <
fNoise.size(); ++
p) {
214 for (
int i = 0; i <
fNTicks; ++i) {
232 art::ServiceHandle<geo::Geometry const> geo;
237 fNoise.resize(geo->Nchannels());
238 for(
unsigned int p = 0;
p < geo->Nchannels(); ++
p){
247 std::vector<const sim::SimChannel*> chanHandle;
250 std::vector<const sim::SimChannel*> channels(geo->Nchannels());
251 for(
size_t c = 0; c < chanHandle.size(); ++c){
252 channels[chanHandle[c]->Channel()] = chanHandle[c];
257 auto digcol = std::make_unique<std::vector<raw::RawDigit>>();
259 art::ServiceHandle<util::LArFFT> fFFT;
264 std::map<int,double>::iterator mapIter;
265 for(
unsigned int chan = 0; chan < geo->Nchannels(); chan++) {
267 std::vector<short> adcvec(
fNTicks, 0);
268 std::vector<double> fChargeWork(
fNTicks, 0.);
270 if( channels[chan] ){
276 for(
int t = 0; t <
fNTicks; ++t)
277 fChargeWork[t] = sc->
Charge(t);
291 std::vector<int> temp;
292 if (time_offset <=0){
293 temp.assign(fChargeWork.begin(),fChargeWork.begin()-time_offset);
294 fChargeWork.erase(fChargeWork.begin(),fChargeWork.begin()-time_offset);
295 fChargeWork.insert(fChargeWork.end(),temp.begin(),temp.end());
297 temp.assign(fChargeWork.end()-time_offset,fChargeWork.end());
298 fChargeWork.erase(fChargeWork.end()-time_offset,fChargeWork.end());
299 fChargeWork.insert(fChargeWork.begin(),temp.begin(),temp.end());
306 int noisechan = chan;
308 noisechan = TMath::Nint(flat.fire()*(1.*(
fNoise.size()-1)+0.1));
310 for(
int i = 0; i <
fNTicks; ++i){
311 adcvec[i] = (short)TMath::Nint(
fNoise[noisechan][i] + fChargeWork[i]);
314 for(
int i = 0; i <
fNTicks; ++i){
315 adcvec[i] = (short)TMath::Nint(fChargeWork[i]);
331 evt.put(std::move(digcol));
342 std::vector<double> col(
fNTicks, 0.);
343 std::vector<double> ind(
fNTicks, 0.);
344 std::vector<TComplex> kern(
fNTicks/2 + 1);
345 std::vector<double> delta(
fNTicks, 0.);
347 art::ServiceHandle<util::LArFFT> fFFT;
354 for(
unsigned int i=0; i<kern.size(); ++i)
360 peak = fFFT->PeakCorrelation(delta, col);
373 for(
unsigned int i=0; i<kern.size(); ++i)
381 peak = fFFT->PeakCorrelation(delta, ind);
388 art::ServiceHandle<art::TFileService const>
tfs;
390 "ConvolutedCollection",
";ticks; Electronics#timesCollection",
fNTicks,0,
fNTicks);
392 "ConvolutedInduction",
";ticks; Electronics#timesInduction",
fNTicks,0,
fNTicks);
395 for(
unsigned int i = 0; i < ind.size(); ++i){
397 fIndTimeShape->Fill(i, ind[i]);
401 fIndTimeShape->Write();
409 CLHEP::RandFlat flat(engine);
413 std::vector<TComplex> noiseFrequency(
fNTicks/2+1, 0.);
417 double rnd[2] = {0.};
422 for (
int i=0; i<
fNTicks/2+1; ++i) {
424 double x=(i+0.5)*binWidth;
432 flat.fireArray(1, rnd, 0, 1);
433 pval *= lofilter * (0.9 + 0.2 * rnd[0]);
443 pval = pval * randomizer/
fNTicks;
453 pval = pval * randomizer/
fNTicks;
456 <<
" is an unknown choice for the noise model" << std::endl;
459 flat.fireArray(1,rnd,0,1);
460 phase = rnd[0]*2.*TMath::Pi();
462 TComplex tc(pval*cos(phase),pval*sin(phase));
463 noiseFrequency[i] += tc;
467 art::ServiceHandle<util::LArFFT> fFFT;
468 fFFT->DoInvFFT(noiseFrequency, noise);
470 noiseFrequency.clear();
475 for (
unsigned int i = 0; i < noise.size(); ++i)
485 art::ServiceHandle<art::TFileService const>
tfs;
495 double integral = 0.;
496 for (
int i = 1; i < nbinc; ++i) {
501 for (
int i = 0; i < nbinc; ++i) {
508 unsigned short lastbini = 2 * nbini;
511 for (
unsigned short i = 0; i < lastbini; ++i) {
512 double ang = i * TMath::Pi() / nbini;
522 for (
unsigned short i = 0; i < lastbini; ++i) {
528 fColFieldResp->Write();
537 std::vector<double> time(
fNTicks,0.);
544 mf::LogInfo(
"SimWire::SetElectResponse") <<
"Check sampling intervals: "
546 <<
"Check number of samples: " <<
fNTicks;
564 4.31054*
exp(-2.94809*time[i]/To)*Ao - 2.6202*
exp(-2.82833*time[i]/To)*cos(1.19361*time[i]/To)*Ao
565 -2.6202*
exp(-2.82833*time[i]/To)*cos(1.19361*time[i]/To)*cos(2.38722*time[i]/To)*Ao
566 +0.464924*
exp(-2.40318*time[i]/To)*cos(2.5928*time[i]/To)*Ao
567 +0.464924*
exp(-2.40318*time[i]/To)*cos(2.5928*time[i]/To)*cos(5.18561*time[i]/To)*Ao
568 +0.762456*
exp(-2.82833*time[i]/To)*sin(1.19361*time[i]/To)*Ao
569 -0.762456*
exp(-2.82833*time[i]/To)*cos(2.38722*time[i]/To)*sin(1.19361*time[i]/To)*Ao
570 +0.762456*
exp(-2.82833*time[i]/To)*cos(1.19361*time[i]/To)*sin(2.38722*time[i]/To)*Ao
571 -2.6202*
exp(-2.82833*time[i]/To)*sin(1.19361*time[i]/To)*sin(2.38722*time[i]/To)*Ao
572 -0.327684*
exp(-2.40318*time[i]/To)*sin(2.5928*time[i]/To)*Ao +
573 +0.327684*
exp(-2.40318*time[i]/To)*cos(5.18561*time[i]/To)*sin(2.5928*time[i]/To)*Ao
574 -0.327684*
exp(-2.40318*time[i]/To)*cos(2.5928*time[i]/To)*sin(5.18561*time[i]/To)*Ao
575 +0.464924*
exp(-2.40318*time[i]/To)*sin(2.5928*time[i]/To)*sin(5.18561*time[i]/To)*Ao;
593 art::ServiceHandle<art::TFileService const>
tfs;
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.
std::vector< double > fElectResponse
response function for the electronics
TF1 * fNoiseFluct
Poisson dist for fluctuations in magnitude of noise freq components.
process_name opflash particleana ie x
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
double fADCPerPCAtLowestASICGain
ADCs/pC at lowest gain setting of 4.7 mV/fC.
unsigned int fNElectResp
number of entries from response to use
TH1D * fNoiseDist
distribution of noise counts
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
std::vector< std::vector< float > > fNoise
noise on each channel for each time
double fInputFieldRespSamplingPeriod
Sampling period in the input field response.
tick ticks
Alias for common language habits.
std::vector< float > fColFieldParams
collection plane field function parameterization
std::vector< int > fCalibRespTOffset
calib response time offset in ticks
std::vector< double > fIndFieldResponse
response function for the field @ induction plane
void GenNoise(std::vector< float > &array, CLHEP::HepRandomEngine &engine)
then echo ***************************************echo array
Signal from induction planes.
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...
std::vector< TComplex > fIndShape
response function for the field @ induction plane
std::vector< double > fNoiseFluctPar
Poisson noise fluctuations params.
MF_LOG_WARNING("SimWire")<< "SimWire is an example module that works for the "<< "MicroBooNE detector. Each experiment should implement "<< "its own version of this module to simulate electronics "<< "response."
void produce(art::Event &evt) override
Collect all the RawData header files together.
fEngine(art::ServiceHandle< rndm::NuRandomService >() ->createEngine(*this, pset,"Seed"))
tick_as<> tick
Tick number, represented by std::ptrdiff_t.
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)
TH1D * fIndFieldResp
response function for the field @ induction plane
int fNTicks
number of ticks of the clock
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.
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.
art::ServiceHandle< art::TFileService > tfs
CLHEP::HepRandomEngine & fEngine
Random-number engine owned by art.
double sampling_rate(DetectorClocksData const &data)
Returns the period of the TPC readout electronics clock.
TH1D * fColFieldResp
response function for the field @ collection plane
std::vector< double > fNoiseModelPar
noise model params
art framework interface to geometry description