15 #include <sys/types.h> 46 #include "cetlib/search_path.h" 51 #include "CLHEP/Random/RandFlat.h" 52 #include "CLHEP/Random/RandGaussQ.h" 71 namespace geo {
class Geometry; }
92 void ConvoluteResponseFunctions();
94 void SetFieldResponse();
95 void SetElectResponse();
97 void GenNoise(std::vector<float>&
array);
112 double fInd3DCorrection;
114 double fColFieldRespAmp;
127 std::vector< std::vector<float> >
fNoise;
145 this->reconfigure(pset);
147 produces< std::vector<raw::RawDigit> >();
150 std::string compression(pset.
get< std::string >(
"CompressionType"));
151 if(compression.compare(
"Huffman") == 0) fCompression =
raw::kHuffman;
156 ->createEngine(*
this, pset,
"Seed");
162 fColFieldResponse.clear();
163 fIndFieldResponse.clear();
167 fElectResponse.clear();
169 for(
unsigned int i = 0; i < fNoise.size(); ++i) fNoise[i].
clear();
172 LOG_WARNING(
"SimWire") <<
"SimWire is an example module that works for the " 173 <<
"MicroBooNE detector. Each experiment should implement " 174 <<
"its own version of this module to simulate electronics " 182 std::string fResponseFile = p.
get<std::string>(
"ResponseFile",
"");
184 fResponseSet = !fResponseFile.empty();
186 cet::search_path sp(
"FW_SEARCH_PATH");
187 sp.find_file(p.
get<std::string>(
"ResponseFile"), fResponseFile);
189 else fResponseFile.clear();
190 fDriftEModuleLabel= p.
get< std::string >(
"DriftEModuleLabel");
191 fNoiseFact = p.
get<
double >(
"NoiseFact");
192 fNoiseWidth = p.
get<
double >(
"NoiseWidth");
193 fLowCutoff = p.
get<
double >(
"LowCutoff");
194 fNFieldBins = p.
get<
int >(
"FieldBins");
195 fCol3DCorrection = p.
get<
double >(
"Col3DCorrection");
196 fInd3DCorrection = p.
get<
double >(
"Ind3DCorrection");
197 fColFieldRespAmp = p.
get<
double >(
"ColFieldRespAmp");
198 fIndFieldRespAmp = p.
get<
double >(
"IndFieldRespAmp");
199 fShapeTimeConst = p.
get< std::vector<double> >(
"ShapeTimeConst");
202 fSampleRate = detprop->SamplingRate();
203 fTriggerOffset = detprop->TriggerOffset();
204 fNSamplesReadout = detprop->NumberTimeSamples();
215 fNoiseDist = tfs->
make<TH1D>(
"Noise",
";Noise (ADC);", 1000, -10., 10.);
219 fChargeWork.resize(fNTicks, 0.);
226 for(
int p = 0; p < 100; ++p){
228 for(
int i = 0; i < fNTicks; ++i){
229 fNoiseDist->Fill(fNoise[p][i]);
236 ConvoluteResponseFunctions();
244 void SimWire::endJob()
256 unsigned int signalSize = fNTicks;
258 std::vector<short> adcvec(signalSize, 0);
260 std::vector<const sim::SimChannel*> chanHandle;
261 evt.
getView(fDriftEModuleLabel,chanHandle);
267 std::vector<const sim::SimChannel*> channels(geo->
Nchannels());
268 for(
size_t c = 0; c < chanHandle.size(); ++c){
269 channels[chanHandle[c]->Channel()] = chanHandle[c];
274 std::unique_ptr< std::vector<raw::RawDigit> > digcol(
new std::vector<raw::RawDigit>);
276 unsigned int chan = 0;
278 fChargeWork.resize(fNTicks, 0.);
284 CLHEP::HepRandomEngine &engine = rng->
getEngine();
285 CLHEP::RandFlat flat(engine);
288 for(chan = 0; chan < geo->
Nchannels(); chan++) {
292 fChargeWork.resize(fNTicks, 0.);
294 if( channels[chan] ){
300 for(
size_t t = 0; t < fChargeWork.size(); ++t)
301 fChargeWork[t] = sc->
Charge(t);
306 else fFFT->
Convolute(fChargeWork,fColShape);
313 int noisechan = TMath::Nint(flat.fire()*(1.*(fNoise.size()-1)+0.1));
314 for(
unsigned int i = 0; i < signalSize; ++i){
315 adcvec[i] = (short)TMath::Nint(fNoise[noisechan][i] + fChargeWork[i]);
317 adcvec.resize(fNSamplesReadout);
328 adcvec.resize(signalSize,0.0);
331 digcol->push_back(rd);
334 evt.
put(std::move(digcol));
340 void SimWire::ConvoluteResponseFunctions()
342 std::vector<double>
col(fNTicks, 0.);
343 std::vector<double> ind(fNTicks, 0.);
345 unsigned int mxbin = TMath::Min(fNTicks, (
int)fNElectResp + fNFieldBins);
350 for(
unsigned int i = 1; i < mxbin; ++i){
353 for(
unsigned int j = 0; j < (
unsigned int)fNFieldBins; ++j){
354 unsigned int k = i - j;
356 sumCol += fElectResponse[k]*fColFieldResponse[j];
357 sumInd += fElectResponse[k]*fIndFieldResponse[j];
365 ind.resize(fNTicks, 0.);
366 col.resize(fNTicks, 0.);
370 fColTimeShape = tfs->
make<TH1D>(
"ConvolutedCollection",
";ticks; Electronics#timesCollection",fNTicks,0,fNTicks);
371 fIndTimeShape = tfs->
make<TH1D>(
"ConvolutedInduction",
";ticks; Electronics#timesInduction",fNTicks,0,fNTicks);
373 fIndShape.resize(fNTicks/2+1);
374 fColShape.resize(fNTicks/2+1);
377 std::vector<double> delta(fNTicks);
379 delta[fNTicks-1]=1.0;
384 fFFT->
DoFFT(ind, fIndShape);
385 fFFT->
DoFFT(col, fColShape);
388 for(
unsigned int i = 0; i < ind.size(); ++i){
389 fColTimeShape->Fill(i, col[i]);
390 fIndTimeShape->Fill(i, ind[i]);
393 fColTimeShape->Write();
394 fIndTimeShape->Write();
401 void SimWire::GenNoise(std::vector<float>&
noise)
404 CLHEP::HepRandomEngine &engine = rng->
getEngine();
405 CLHEP::RandFlat flat(engine);
408 noise.resize(fNTicks, 0.);
409 std::vector<TComplex> noiseFrequency(fNTicks/2+1, 0.);
412 double lofilter = 0.;
414 double rnd[2] = {0.};
417 double binWidth = 1.0/(fNTicks*fSampleRate*1.0e-6);
418 for(
int i=0; i< fNTicks/2+1; ++i){
420 pval = fNoiseFact*exp(-(
double)i*binWidth/fNoiseWidth);
422 lofilter = 1.0/(1.0+exp(-(i-fLowCutoff/binWidth)/0.5));
424 flat.fireArray(2,rnd,0,1);
425 pval *= lofilter*(0.9+0.2*rnd[0]);
427 phase = rnd[1]*2.*TMath::Pi();
429 TComplex tc(pval*cos(phase),pval*sin(phase));
430 noiseFrequency[i] += tc;
437 fFFT->
DoInvFFT(noiseFrequency, noise);
439 noiseFrequency.clear();
444 for(
unsigned int i = 0; i < noise.size(); ++i) noise[i] *= 1.*fNTicks;
450 void SimWire::SetFieldResponse()
457 double xyz1[3] = {0.};
458 double xyz2[3] = {0.};
459 double xyzl[3] = {0.};
466 double pitch = xyz2[0] - xyz1[0];
468 fColFieldResponse.resize(fNFieldBins, 0.);
469 fIndFieldResponse.resize(fNFieldBins, 0.);
477 fIndFieldResp = tfs->
make<TH1D>(
"InductionFieldResponse",
";t (ns);Induction Response",fNTicks,0,fNTicks);
478 fColFieldResp = tfs->
make<TH1D>(
"CollectionFieldResponse",
";t (ns);Collection Response",fNTicks,0,fNTicks);
480 double driftvelocity=detprop->
DriftVelocity(detprop->Efield(),detprop->Temperature())/1000.;
481 int nbinc = TMath::Nint(fCol3DCorrection*(std::abs(pitch))/(driftvelocity*fSampleRate));
483 double integral = 0.;
484 for(
int i = 1; i < nbinc; ++i){
485 fColFieldResponse[i] = fColFieldResponse[i-1] + 1.0;
486 integral += fColFieldResponse[i];
489 for(
int i = 0; i < nbinc; ++i){
490 fColFieldResponse[i] *= fColFieldRespAmp/integral;
491 fColFieldResp->Fill(i, fColFieldResponse[i]);
496 int nbini = TMath::Nint(fInd3DCorrection*(std::abs(pitch))/(driftvelocity*fSampleRate));
497 for(
int i = 0; i < nbini; ++i){
498 fIndFieldResponse[i] = fIndFieldRespAmp/(1.*nbini);
499 fIndFieldResponse[nbini+i] = -fIndFieldRespAmp/(1.*nbini);
501 fIndFieldResp->Fill(i, fIndFieldResponse[i]);
502 fIndFieldResp->Fill(nbini+i, fIndFieldResponse[nbini+i]);
506 fColFieldResp->Write();
507 fIndFieldResp->Write();
513 void SimWire::SetElectResponse()
520 fElectResponse.resize(fNTicks, 0.);
521 std::vector<double> time(fNTicks,0.);
523 double norm = fShapeTimeConst[1]*TMath::Pi();
524 norm /= sin(fShapeTimeConst[1]*TMath::Pi()/fShapeTimeConst[0])/fSampleRate;
528 for(
int i = 0; i < fNTicks; ++i){
529 time[i] = (1.*i - 0.33333*fNTicks)*fSampleRate;
532 fElectResponse[i] = 120000.0*exp(-time[i]/fShapeTimeConst[0])/(1. + exp(-time[i]/fShapeTimeConst[1]))/norm;
534 if(fElectResponse[i] > peak){
535 peak = fElectResponse[i];
543 while(eitr != fElectResponse.end()){
545 fElectResponse.erase(eitr);
555 fNElectResp = fElectResponse.size();
559 fElectResp = tfs->
make<TH1D>(
"ElectronicsResponse",
";t (ns);Electronics Response",fNElectResp,0,fNElectResp);
560 for(
unsigned int i = 0; i < fNElectResp; ++i){
562 fElectResp->Fill(i, fElectResponse[i]);
double fIndFieldRespAmp
amplitude of response to field
unsigned int fNSamplesReadout
number of ADC readout samples in 1 readout frame
std::vector< TComplex > fColShape
response function for the field @ collection plane
enum raw::_compress Compress_t
PlaneGeo const & Plane(unsigned int const p, unsigned int const tpc=0, unsigned int const cstat=0) const
Returns the specified wire.
Collection of charge vs time digitized from a single readout channel.
Energy deposited on a readout channel by simulated tracks.
std::vector< double > fElectResponse
response function for the electronics
Encapsulate the construction of a single cyostat.
TH1D * fColTimeShape
convoluted shape for field x electronics @ col plane
std::string fDriftEModuleLabel
module making the ionization electrons
unsigned int fNElectResp
number of entries from response to use
TH1D * fNoiseDist
distribution of noise counts
Detector simulation of raw signals on wires.
Definition of basic raw digits.
raw::Compress_t fCompression
compression type to use
void DoFFT(std::vector< T > &input, std::vector< TComplex > &output)
SigType_t SignalType(geo::PlaneID const &pid) const
Returns the type of signal on the channels of specified TPC plane.
int fTriggerOffset
(units of ticks) time of expected neutrino event
void DoInvFFT(std::vector< TComplex > &input, std::vector< T > &output)
unsigned int Nchannels() const
Returns the number of TPC readout channels in the detector.
ProductID put(std::unique_ptr< PROD > &&product)
std::size_t getView(std::string const &moduleLabel, std::string const &productInstanceName, std::vector< ELEMENT const * > &result) const
bool fResponseSet
flag of whether to set the response functions or not
std::vector< double > fIndFieldResponse
response function for the field @ induction plane
base_engine_t & getEngine() const
std::vector< double > fChargeWork
auto array(Array const &a)
Returns a manipulator which will print the specified array.
#define DEFINE_ART_MODULE(klass)
Signal from induction planes.
std::vector< double > fColFieldResponse
response function for the field @ collection plane
std::vector< std::vector< float > > fNoise
noise on each channel for each time
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
Collect all the RawData header files together.
T get(std::string const &key) const
void Convolute(std::vector< T > &input, std::vector< T > &respFunc)
double fSampleRate
sampling rate in ns
An art service to assist in the distribution of guaranteed unique seeds to all engines within an art ...
#define LOG_WARNING(category)
double fLowCutoff
low frequency filter cutoff (kHz)
TH1D * fIndFieldResp
response function for the field @ induction plane
int fNTicks
number of ticks of the clock
std::string fResponseFile
response file for induction planes
T * make(ARGS...args) const
TH1D * fIndTimeShape
convoluted shape for field x electronics @ ind plane
Encapsulate the construction of a single detector plane.
void AlignedSum(std::vector< T > &input, std::vector< T > &output, bool add=true)
virtual double DriftVelocity(double efield=0., double temperature=0.) const =0
double fNoiseWidth
exponential noise width (kHz)
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.
int fNFieldBins
number of bins for field response
double fNoiseFact
noise scale factor
Namespace collecting geometry-related classes utilities.
TH1D * fColFieldResp
response function for the field @ collection plane
std::vector< double > fShapeTimeConst
time constants for exponential shaping
Tools and modules for checking out the basics of the Monte Carlo.
void LocalToWorld(const double *plane, double *world) const
Transform point from local plane frame to world frame.
art framework interface to geometry description
Encapsulate the construction of a single detector plane.