11 #ifndef OpDetDigitizerDUNEDP_h 12 #define OpDetDigitizerDUNEDP_h 1 23 #include "art_root_io/TFileService.h" 24 #include "art_root_io/TFileDirectory.h" 25 #include "CLHEP/Random/RandFlat.h" 29 #include "nurandom/RandomUtils/NuRandomService.h" 46 #include "CLHEP/Random/RandGauss.h" 47 #include "CLHEP/Random/RandExponential.h" 48 #include "CLHEP/Random/RandFlat.h" 76 if(from < 0) from = 0;
79 for(
unsigned int i = 0; i <
ranges.size(); ++i){
80 std::pair<int, int>&
r =
ranges[i];
82 if(from >= r.first && to <= r.second)
return;
84 if(from >= r.first && from <= r.second){
89 if(to >= r.first && to <= r.second){
95 ranges.emplace_back(from, to);
98 std::vector<std::pair<int, int>>
ranges;
158 void AddPulse(
size_t timeBin,
int scale,
159 std::vector< double >& waveform,
166 double getQE(
int OpDet);
167 double getGain(
int OpDet);
171 void CheckFHiCLParameters()
const;
174 void CreateSinglePEWaveform();
182 std::vector<FocusList>&);
189 std::vector<FocusList>&);
192 void AddLineNoise(
std::vector< std::vector< double > >&,
193 const std::vector<FocusList>& fls)
const;
195 void AddDarkNoise(
std::vector< std::vector< double > >&,
196 std::vector<FocusList>& fls,
int opDet);
198 unsigned short CrossTalk()
const;
202 std::vector< short > VectorOfDoublesToVectorOfShorts
203 (std::vector< double >
const&)
const;
207 std::map< size_t, std::vector< short > >
208 SplitWaveform(std::vector< short >
const&,
215 double TickToTime(
size_t tick)
const;
216 size_t TimeToTick(
double time)
const;
218 int PMTSaturationFunction(
int);
219 double SumOfElements(std::vector<double>);
252 produces< std::vector< raw::OpDetWaveform > >();
255 fInputModule = pset.get<std::vector<std::string>>(
"InputModule",{
"largeant"});
258 fCrossTalk = pset.get<
double >(
"CrossTalk" );
259 fPedestal = pset.get<
double >(
"Pedestal" );
264 fPadding = pset.get<
int >(
"Padding" );
265 fGain = pset.get<
double >(
"Gain" );
268 fCustomQE = pset.get<
bool >(
"CustomQEperOpDet",false );
269 fCustomGain = pset.get<
bool >(
"CustomGainperOpDet",false );
270 fGainsError = pset.get<
double >(
"GainsError",0.0 );
271 fSPEWidth = pset.get<
double >(
"SPEWidth",0.0 );
274 if(fCustomQE)
fQEVector = pset.get<std::vector<double>>(
"QEVector");
275 if(fCustomGain)
fGainVector = pset.get<std::vector<double>>(
"GainVector");
277 fThreshAlg = std::make_unique< pmtana::AlgoSSPLeadingEdge >
280 if(fDigiTree_SSP_LED){
282 arvore2 = tfs->make<TTree>(
"PhotonData",
"Photon_analysis");
291 fSampleFreq = clockData.OpticalClock().Frequency();
297 if (fDefaultSimWindow)
305 fTimeEnd = detProp.ReadOutWindowSize() / clockData.TPCClock().Frequency();
323 fRandGauss = std::make_unique< CLHEP::RandGauss >(engine);
325 fRandFlat = std::make_unique< CLHEP::RandFlat >(engine);
329 nOpDet=geometry->NOpDets();
333 std::cout <<
"Smearing gains vector by " << fGainsError <<
" percent. " <<
std::endl;
334 std::vector<double> newGains;
345 std::vector <double> aux;
358 aux.resize(1);aux[0]=1.0;
362 double normalization =0;
368 std::cout <<
"\tReadoutWindow" << fReadoutWindow <<
" "<<
std::endl;
369 std::cout <<
"\tfPreTrigger" << fPreTrigger <<
" "<<
std::endl;
377 if(fExportWaveformTree)
382 double *vaux; vaux = (
double*)malloc(
sizeof(
double)*
nOpDet);
383 fRunInfo = tfs->make<TTree>(
"RunInfo",
"MonteCarlo Run Info");
385 fRunInfo->Branch(
"nOpDet" , &nOpDet , Form(
"nOpDet/I") );
386 fRunInfo->Branch(
"Gains" , vaux , Form(
"Gains[nOpDet]/D") );
388 for (
unsigned int i=0; i<
nOpDet; i++) std::cout <<
" Gain [ " << i <<
" ] = " << vaux[i] <<
" ADCxticks/PE" << std::endl;
392 fWaveformTree = tfs->make<TTree>(
"WaveformTree",
"Waveforms Tree");
396 fWaveformTree->Branch(
"NSamples" , &nSamples ,
"NSamples/I" );
397 for (
unsigned int i=0; i<
nOpDet; i++)
fWaveformTree->Branch(Form(
"adc_channel_%i",i),
adc_value[i] , Form(
"adc_value_%i[NSamples]/S",i) );
415 std::unique_ptr< std::vector< raw::OpDetWaveform > >
416 pulseVecPtr(std::make_unique< std::vector< raw::OpDetWaveform > >());
421 if (!fUseLitePhotons)
423 <<
"Sorry, but for now only Lite Photon digitization is implemented!" 444 for(
unsigned int opDet=0; opDet<
nOpDet; opDet++)
447 std::vector< std::vector< double > > pdWaveforms(nChannelsPerOpDet, std::vector< double >(
nSamples, static_cast< double >(
fPedestal)));
448 std::vector<std::vector<FocusList>> fls(nOpDet,std::vector<FocusList>(nChannelsPerOpDet,
FocusList(
nSamples,
fPadding)));
456 if(fUseLitePhotons) litePhotonHandle = evt.
getHandle< std::vector< sim::SimPhotonsLite > >(mod);
459 if(!fUseLitePhotons) PhotonHandle = evt.
getHandle< std::vector< sim::SimPhotons > >(mod);
465 for (
auto const& litePhotons : (*litePhotonHandle))
469 if(opDet == (
unsigned)litePhotons.OpChannel)
475 CreatePDWaveform(litePhotons, *odResponse, *geometry, pdWaveforms, fls[opDet]);
476 if((
unsigned)modulecounter<fInputModule.size())
continue;
479 hardwareChannel < nChannelsPerOpDet; ++hardwareChannel) fls[opDet][hardwareChannel].AddRange(0,
SampleSize);
499 for (
unsigned int hardwareChannel = 0;
500 hardwareChannel < nChannelsPerOpDet; ++hardwareChannel)
502 for(
const std::pair<int, int>&
p: fls[opDet][hardwareChannel].
ranges){
505 const std::vector<double>
sub(pdWaveforms[hardwareChannel].
begin()+
p.first,
506 pdWaveforms[hardwareChannel].begin()+
p.second+1);
508 std::vector< short > waveformOfShorts =
512 std::map< size_t, std::vector < short > > mapTickWaveform =
514 SplitWaveform(waveformOfShorts, fls[opDet][hardwareChannel]) :
515 std::map< size_t, std::vector< short > >{ std::make_pair(0,
519 unsigned int opChannel = geometry->
OpChannel(opDet, hardwareChannel);
520 for (
auto const& pairTickWaveform : mapTickWaveform)
523 static_cast< double >(
TickToTime(pairTickWaveform.first+
p.first));
529 pairTickWaveform.second.size());
531 for (
short const&
value : pairTickWaveform.second)
534 adcVec.emplace_back(value); counter++;
538 pulseVecPtr->emplace_back(
std::move(adcVec));
549 for (
auto const& Photons : (*PhotonHandle))
551 if(opDet == (
unsigned)Photons.OpChannel())
554 if((
unsigned)modulecounter<fInputModule.size())
continue;
563 for (
unsigned int hardwareChannel = 0;
564 hardwareChannel < nChannelsPerOpDet; ++hardwareChannel)
566 for(
const std::pair<int, int>&
p: fls[opDet][hardwareChannel].
ranges){
569 const std::vector<double>
sub(pdWaveforms[hardwareChannel].
begin()+
p.first,
570 pdWaveforms[hardwareChannel].begin()+
p.second+1);
572 std::vector< short > waveformOfShorts =
575 std::map< size_t, std::vector < short > > mapTickWaveform =
577 SplitWaveform(waveformOfShorts, fls[opDet][hardwareChannel]) :
578 std::map< size_t, std::vector< short > >{ std::make_pair(0,
582 unsigned int opChannel = geometry->
OpChannel(opDet, hardwareChannel);
583 for (
auto const& pairTickWaveform : mapTickWaveform)
586 static_cast< double >(
TickToTime(pairTickWaveform.first+
p.first));
592 pairTickWaveform.second.size());
594 for (
short const&
value : pairTickWaveform.second)
597 adcVec.emplace_back(value); counter++;
601 pulseVecPtr->emplace_back(
std::move(adcVec));
608 if(fUseLitePhotons) litePhotonHandle.
clear();
609 if(!fUseLitePhotons) PhotonHandle.clear();
622 for(
unsigned int j=0; j < pulseVecPtr->size(); j++)
624 unsigned int opDet= pulseVecPtr->at(j).ChannelNumber();
626 for (
unsigned int i = 0; i< pulseVecPtr->at(j).Waveform().size() ; i++)
adc_value[opDet][i] = pulseVecPtr->at(j).Waveform()[i];
642 int scale, std::vector< double >& waveform,
645 if(timeBin>waveform.size())
return;
649 pulseLength = (waveform.size() - timeBin);
651 fl.AddRange(timeBin, timeBin+pulseLength-1);
654 double interbinallignment =
fRandFlat->fire(1.0);
661 else bincharge = interbinallignment*scale*customGain*fSinglePEWaveform[
tick] + (1-interbinallignment)*scale*customGain*fSinglePEWaveform[
tick-1];
664 else waveform[timeBin +
tick] -= (double)bincharge;
675 std::vector<FocusList>& fls)
678 unsigned int const opDet = litePhotons.
OpChannel;
688 for (
auto const& pulse : photonsMap)
691 double photonTime =
static_cast< double >(pulse.first)/1000.0;
695 for (
int i = 0; i < NumberOfPEs; ++i)
700 if (CLHEP::RandFlat::shoot(1.0) <
getQE(opDet))
709 unsigned int opChannel = geometry.
OpChannel(opDet, hardwareChannel);
729 std::vector<FocusList>& fls)
732 unsigned int const opDet = Photons.
OpChannel();
736 std::map< int, int > photonsMap;
737 for(
unsigned int i=0; i<Photons.size();i++)photonsMap[Photons[i].Time]=0;
738 for(
unsigned int i=0; i<Photons.size();i++)photonsMap[Photons[i].Time]++;
742 for (
auto const& pulse : photonsMap)
745 double photonTime =
static_cast< double >(pulse.first)/1000.0;
749 for (
int i = 0; i < NumberOfPEs; ++i)
754 if (CLHEP::RandFlat::shoot(1.0) <
getQE(opDet))
763 unsigned int opChannel = geometry.
OpChannel(opDet, hardwareChannel);
781 const std::vector<FocusList>& fls)
const 784 for(
auto& waveform : waveforms){
785 for(
unsigned int j = 0; j < fls[i].ranges.size(); ++j){
786 const std::pair<int, int>&
p = fls[i].ranges[j];
787 for(
int k = p.first;
k <= p.second; ++
k){
798 std::vector<FocusList>& fls,
int optDet)
801 for (
auto& waveform : waveforms)
811 darkNoiseTime +=
static_cast< double > 830 (std::vector< double >
const& vectorOfDoubles)
const 833 return std::vector<short>(vectorOfDoubles.begin(), vectorOfDoubles.end());
853 std::map< size_t, std::vector< short > > mapTickWaveform;
859 fThreshAlg->Reconstruct(waveform,ped_mean,ped_sigma);
861 std::vector< pmtana::pulse_param > pulses;
862 for (
size_t pulseCounter = 0; pulseCounter <
fThreshAlg->GetNPulse();
864 pulses.emplace_back(
fThreshAlg->GetPulse(pulseCounter));
869 if (pulse.t_end <= pulse.t_start)
872 <<
"Pulse ends before or at the same time it starts!\n";
875 waveform.begin() +
static_cast< size_t >(pulse.t_start);
877 waveform.begin() +
static_cast< size_t >(pulse.t_end );
878 mapTickWaveform.emplace(static_cast< size_t >(pulse.t_start),
879 std::vector< short >(window_start, window_end));
885 return mapTickWaveform;
895 double maxDrift = 0.0;
898 if (maxDrift < tpc.DriftDistance()) maxDrift = tpc.DriftDistance();
940 <<
"Line noise RMS should be non-negative!\n";
945 <<
"Dark noise rate should be non-negative!\n";
951 <<
"Pretrigger window has to be shorter than readout window!\n";
957 <<
"TimeBegin should be less than TimeEnd!\n";
965 for (
auto&
n : aa) sum+=
n;
base_engine_t & createEngine(seed_t seed)
Store parameters for running LArG4.
void CreatePDWaveform(sim::SimPhotonsLite const &, opdet::OpDetResponseInterface const &, geo::Geometry const &, std::vector< std::vector< double > > &, std::vector< FocusList > &)
EventNumber_t event() const
void AddDarkNoise(std::vector< std::vector< double > > &, std::vector< FocusList > &fls, int opDet)
std::vector< double > PedestalSigma_t
int OpChannel() const
Returns the optical channel number this object is associated to.
void produce(art::Event &)
void AddPulse(size_t timeBin, int scale, std::vector< double > &waveform, FocusList &fl, double Gain) const
std::unique_ptr< CLHEP::RandFlat > fRandFlat
FocusList(int nSamples, int padding)
Handle< PROD > getHandle(SelectorBase const &) const
void AddRange(int from, int to)
double GetDriftWindow(detinfo::DetectorPropertiesData const &detProp) const
Geometry information for a single TPC.
std::unique_ptr< CLHEP::RandGauss > fRandGauss
unsigned int NOpHardwareChannels(int opDet) const
unsigned short CrossTalk() const
size_t TimeToTick(double time) const
void CheckFHiCLParameters() const
std::vector< double > t_photon
std::map< int, int > DetectedPhotons
Number of photons detected at each given time: time tick -> photons.
std::vector< std::pair< int, int > > ranges
double SumOfElements(std::vector< double >)
Simulation objects for optical detectors.
std::unique_ptr< pmtana::AlgoSSPLeadingEdge > fThreshAlg
#define DEFINE_ART_MODULE(klass)
std::vector< int > op_photon
unsigned int HardwareChannelFromOpChannel(int opChannel) const
Convert unique channel to hardware channel.
double TickToTime(size_t tick) const
int OpChannel
Optical detector channel associated to this data.
tick_as<> tick
Tick number, represented by std::ptrdiff_t.
SubRunNumber_t subRun() const
ProductID put(std::unique_ptr< PROD > &&edp, std::string const &instance={})
double DriftVelocity(double efield=0., double temperature=0.) const
cm/us
The geometry of one entire detector, as served by art.
std::vector< double > fQEVector
std::unique_ptr< CLHEP::RandExponential > fRandExponential
virtual bool detectedLite(int OpChannel, int &newOpChannel) const
std::vector< short > VectorOfDoublesToVectorOfShorts(std::vector< double > const &) const
std::vector< std::string > fInputModule
void AddLineNoise(std::vector< std::vector< double > > &, const std::vector< FocusList > &fls) const
unsigned int OpChannel(int detNum, int hardwareChannel) const
Convert detector number and hardware channel to unique channel.
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
unsigned int GetRandomNumberSeed()
Collection of photons which recorded on one channel.
std::vector< short * > adc_value
Compact representation of photons on a channel.
std::vector< double > fSinglePEWaveform
decltype(auto) constexpr begin(T &&obj)
ADL-aware version of std::begin.
int PMTSaturationFunction(int)
OpDetDigitizerDUNEDP(fhicl::ParameterSet const &)
Tools and modules for checking out the basics of the Monte Carlo.
double getGain(int OpDet)
std::vector< double > fGainVector
std::vector< double > PedestalMean_t
std::map< size_t, std::vector< short > > SplitWaveform(std::vector< short > const &, const FocusList &)
bool UseLitePhotons() const
QTextStream & endl(QTextStream &s)
std::string sub(const std::string &a, const std::string &b)