22 #include "CLHEP/Random/RandFlat.h"
23 #include "CLHEP/Random/RandGaussQ.h"
24 #include "CLHEP/Random/JamesRandom.h"
34 #include "art/Framework/Core/ModuleMacros.h"
35 #include "art/Framework/Core/EDProducer.h"
36 #include "art/Framework/Principal/Event.h"
37 #include "art/Framework/Principal/Handle.h"
38 #include "art/Framework/Services/Registry/ServiceHandle.h"
39 #include "art_root_io/TFileService.h"
40 #include "art_root_io/TFileDirectory.h"
41 #include "art/Utilities/make_tool.h"
42 #include "fhiclcpp/ParameterSet.h"
43 #include "messagefacility/MessageLogger/MessageLogger.h"
45 #include "nurandom/RandomUtils/NuRandomService.h"
63 #include "icarus_signal_processing/Filters/ICARUSFFT.h"
78 void produce (art::Event&
evt);
123 const float adcsaturation = 4095;
136 using FFTPointer = std::unique_ptr<icarus_signal_processing::ICARUSFFT<double>>;
149 , fPedestalEngine(art::ServiceHandle<rndm::NuRandomService>()->createEngine(*
this,
"HepJamesRandom",
"pedestal", pset,
"SeedPedestal"))
150 , fUncNoiseEngine(art::ServiceHandle<rndm::NuRandomService>()->createEngine(*
this,
"HepJamesRandom",
"noise", pset,
"Seed"))
151 , fCorNoiseEngine(art::ServiceHandle<rndm::NuRandomService>()->createEngine(*
this,
"HepJamesRandom",
"cornoise", pset,
"Seed"))
152 , fGeometry(*lar::providerFrom<geo::Geometry>())
156 produces< std::vector<raw::RawDigit>>(fOutInstanceLabel);
158 TString
compression(pset.get< std::string >(
"CompressionType"));
164 SimWireICARUS::~SimWireICARUS() {}
168 fDriftEModuleLabel = p.get< art::InputTag >(
"DriftEModuleLabel",
"largeant");
169 fOutInstanceLabel = p.get< std::string >(
"OutputInstanceLabel",
"");
170 fProcessAllTPCs = p.get<
bool >(
"ProcessAllTPCs",
false);
171 fCryostat = p.get<
unsigned int >(
"Cryostat", 0);
172 fSimDeadChannels = p.get<
bool >(
"SimDeadChannels",
false);
173 fSuppressNoSignal = p.get<
bool >(
"SuppressNoSignal",
false);
174 fMakeHistograms = p.get<
bool >(
"MakeHistograms",
false);
175 fSmearPedestals = p.get<
bool >(
"SmearPedestals",
true);
176 fNumChanPerMB = p.get<
int >(
"NumChanPerMB", 32);
177 fTest = p.get<
bool >(
"Test",
false);
178 fTestWire = p.get<
size_t >(
"TestWire", 0);
179 fTestIndex = p.get< std::vector<size_t> >(
"TestIndex", std::vector<size_t>());
180 fTestCharge = p.get< std::vector<double> >(
"TestCharge", std::vector<double>());
182 using TPCValsPair = std::pair<unsigned int, unsigned int>;
183 using TPCValsVec = std::vector<TPCValsPair>;
185 TPCValsVec tempIDVec = p.get< TPCValsVec >(
"TPCVec", TPCValsVec());
187 for(
const auto& idPair : tempIDVec)
189 fTPCVec.push_back(
geo::TPCID(idPair.first,idPair.second));
192 if(fTestIndex.size() != fTestCharge.size())
193 throw cet::exception(__FUNCTION__)<<
"# test pulse mismatched: check TestIndex and TestCharge fcl parameters...";
195 std::vector<fhicl::ParameterSet> noiseToolParamSetVec = p.get<std::vector<fhicl::ParameterSet>>(
"NoiseGenToolVec");
197 for(
auto& noiseToolParams : noiseToolParamSetVec) {
198 fNoiseToolVec.push_back(art::make_tool<icarus_tool::IGenNoise>(noiseToolParams));
202 fShapingTimeOrder = { {0.6, 0}, {1, 1}, {1.3, 2}, {3.0, 3} };
205 auto const detProp = art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataForJob();
206 fNTimeSamples =
detProp.NumberTimeSamples();
208 fSignalShapingService = art::ServiceHandle<icarusutil::SignalShapingICARUSService>{}.get();
210 fFFT = std::make_unique<icarus_signal_processing::ICARUSFFT<double>>(fNTimeSamples);
215 void SimWireICARUS::beginJob()
218 art::ServiceHandle<art::TFileService>
tfs;
223 if(fGeometry.Nchannels()<=fTestWire)
224 throw cet::exception(__FUNCTION__)<<
"Invalid test wire channel: "<<fTestWire;
225 std::vector<unsigned int> channels;
226 for(
auto const& plane_id : fGeometry.IteratePlaneIDs())
227 channels.push_back(fGeometry.PlaneWireToChannel(plane_id.Plane,fTestWire));
228 double xyz[3] = { std::numeric_limits<double>::max() };
229 for(
auto const& ch : channels)
232 for(
size_t i=0; i<fTestIndex.size(); ++i)
234 fTestSimChannel_v.back().AddIonizationElectrons(-1,
238 std::numeric_limits<double>::max());
243 fSimCharge = tfs->make<TH1F>(
"fSimCharge",
"simulated charge", 150, 0, 1500);
244 fSimChargeWire = tfs->make<TH2F>(
"fSimChargeWire",
"simulated charge", 5600,0.,5600.,500, 0, 1500);
249 void SimWireICARUS::endJob()
251 void SimWireICARUS::produce(art::Event&
evt)
265 auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(evt);
279 std::vector<const sim::SimChannel*> channels(maxChannel,
nullptr);
282 std::vector<const sim::SimChannel*> chanHandle;
283 evt.getView(fDriftEModuleLabel,chanHandle);
285 for(
const auto& simChannel : chanHandle) channels.at(simChannel->Channel()) = simChannel;
288 for(
const auto& testChannel : fTestSimChannel_v) channels.at(testChannel.Channel()) = &testChannel;
292 std::unique_ptr< std::vector<raw::RawDigit>> digcol(
new std::vector<raw::RawDigit>);
293 digcol->reserve(maxChannel);
302 std::vector<short> adcvec(fNTimeSamples, 0);
308 if (chargeWork.size() < fNTimeSamples)
throw std::range_error(
"SimWireICARUS: chargeWork vector too small");
311 auto const detProp = art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataFor(evt);
314 for(
const auto& noiseTool : fNoiseToolVec) noiseTool->nextEvent();
323 using ChannelPair = std::pair<raw::ChannelID_t,raw::ChannelID_t>;
324 using ChannelPairVec = std::vector<ChannelPair>;
326 ChannelPairVec channelPairVec;
330 for (
geo::PlaneGeo const& plane : fGeometry.IteratePlanes(tpcid))
332 raw::ChannelID_t const planeStartChannel = fGeometry.PlaneWireToChannel({ plane.ID(), 0U });
333 raw::ChannelID_t const planeEndChannel = fGeometry.PlaneWireToChannel({ plane.ID(), plane.Nwires() - 1U }) + 1;
335 channelPairVec.emplace_back(planeStartChannel, planeEndChannel);
340 using MBWithSignalSet = std::set<raw::ChannelID_t>;
342 MBWithSignalSet mbWithSignalSet;
344 for(
const ChannelPair& channelPair : channelPairVec)
347 if (!fSuppressNoSignal)
352 for(
raw::ChannelID_t mbIdx = firstMBIdx; mbIdx < endMBIdx; mbIdx++) mbWithSignalSet.insert(mbIdx);
356 for(
const auto& simChan : channels)
362 if (channel >= channelPair.first && channel < channelPair.second) mbWithSignalSet.insert(channel/fNumChanPerMB);
369 for(
const auto& mb : mbWithSignalSet)
374 for(
raw::ChannelID_t channel = baseChannel; channel < baseChannel + fNumChanPerMB; channel++)
377 adcvec.resize(fNTimeSamples, 0);
378 noisetmp.resize(fNTimeSamples, 0.);
381 std::vector<geo::WireID> widVec = fGeometry.ChannelToWire(channel);
382 size_t plane = widVec[0].Plane;
383 size_t wire = widVec[0].Wire;
384 size_t board = wire / 32;
387 float ped_mean = pedestalRetrievalAlg.
PedMean(channel);
389 if (fSmearPedestals )
391 CLHEP::RandGaussQ rGaussPed(fPedestalEngine, 0.0, pedestalRetrievalAlg.
PedRms(channel));
392 ped_mean += rGaussPed.fire();
396 double noise_factor(0.);
397 auto tempNoiseVec = fSignalShapingService->GetNoiseFactVec();
398 double shapingTime = fSignalShapingService->GetShapingTime(plane);
399 double gain = fSignalShapingService->GetASICGain(channel) *
sampling_rate(clockData) * 1.e-3;
400 int timeOffset = fSignalShapingService->ResponseTOffset(channel);
405 if (fShapingTimeOrder.find( shapingTime ) != fShapingTimeOrder.end() )
406 noise_factor = tempNoiseVec[plane].at( fShapingTimeOrder.find( shapingTime )->second );
410 throw cet::exception(
"SimWireICARUS")
412 <<
"Shaping Time received from signalservices_icarus.fcl is not one of allowed values"
414 <<
"Allowed values: 0.6, 1.0, 1.3, 3.0 usec"
420 fNoiseToolVec[plane]->generateNoise(fUncNoiseEngine,
432 if(simChan && !(fSimDeadChannels && (ChannelStatusProvider.
IsBad(channel) || !ChannelStatusProvider.
IsPresent(channel))))
434 std::fill(chargeWork.begin(), chargeWork.end(), 0.);
439 int tdc = clockData.TPCTick2TDC(
tick);
442 if( tdc < 0 )
continue;
444 double charge = simChan->
Charge(tdc);
446 chargeWork[
tick] += charge/gain;
450 fFFT->convolute(chargeWork, response.
getConvKernel(), timeOffset);
453 MakeADCVec(adcvec, noisetmp, chargeWork, ped_mean);
456 else MakeADCVec(adcvec, noisetmp, zeroCharge, ped_mean);
465 raw::RawDigit rd(channel, fNTimeSamples, adcvec, fCompression);
467 if(fMakeHistograms && plane==2)
469 short area = std::accumulate(adcvec.begin(),adcvec.end(),0,[](
const auto& val,
const auto& sum){
return sum + val - 400;});
473 fSimCharge->Fill(area);
474 fSimChargeWire->Fill(widVec[0].Wire,area);
479 digcol->push_back(std::move(rd));
484 evt.put(std::move(digcol), fOutInstanceLabel);
492 for(
unsigned int i = 0; i < fNTimeSamples; ++i)
494 float adcval = noisevec[i] + chargevec[i] + ped_mean;
496 adcval = std::max(
float(0.), std::min(adcval, adcsaturation));
498 adcvec[i] = std::round(adcval);
std::vector< size_t > fTestIndex
TString compression(pset.get< std::string >("CompressionType"))
enum raw::_compress Compress_t
raw::Compress_t fCompression
compression type to use
Collection of charge vs time digitized from a single readout channel.
Energy deposited on a readout channel by simulated tracks.
std::vector< geo::TPCID > TPCIDVec
virtual bool IsBad(raw::ChannelID_t channel) const =0
Returns whether the specified channel is bad in the current run.
std::vector< double > fTestCharge
std::vector< std::unique_ptr< icarus_tool::IGenNoise > > fNoiseToolVec
Tool for generating noise.
CLHEP::HepRandomEngine & fUncNoiseEngine
Definition of basic raw digits.
ResponseParams(double charge, size_t time)
bool fSmearPedestals
If True then we smear the pedestals.
Access the description of detector geometry.
virtual bool IsPresent(raw::ChannelID_t channel) const =0
Returns whether the specified channel is physical and connected to wire.
std::string fOutInstanceLabel
The label to apply to the output data product.
double Charge(TDC_t tdc) const
Returns the total number of ionization electrons on this channel in the specified TDC...
Collect all the RawData header files together.
Geometry information for a single wire plane.The plane is represented in the geometry by a solid whic...
std::vector< SigProcPrecision > TimeVec
bool fSuppressNoSignal
If no signal on wire (simchannel) then suppress the channel.
tick_as<> tick
Tick number, represented by std::ptrdiff_t.
TPCIDVec fTPCVec
List of TPCs to process for this instance of the module.
void fill(const art::PtrVector< recob::Hit > &hits, int only_plane)
Class providing information about the quality of channels.
The data type to uniquely identify a TPC.
Description of geometry of one entire detector.
int fNumChanPerMB
Number of channels per motherboard.
virtual float PedMean(raw::ChannelID_t ch) const =0
Retrieve pedestal information.
bool fSimDeadChannels
if True, simulate dead channels using the ChannelStatus service. If false, do not simulate dead chann...
const geo::GeometryCore & fGeometry
std::map< double, int > fShapingTimeOrder
CLHEP::HepRandomEngine & fCorNoiseEngine
std::unique_ptr< icarus_signal_processing::ICARUSFFT< double >> FFTPointer
CLHEP::HepRandomEngine & fPedestalEngine
void SetPedestal(float ped, float sigma=1.)
Set pedestal and its RMS (the latter is 0 by default)
unsigned int fCryostat
If ProcessAllTPCs is false then cryostat to use.
bool fProcessAllTPCs
If true we process all TPCs.
unsigned int fNTimeSamples
number of ADC readout samples in all readout frames (per event)
object containing MC truth information necessary for making RawDigits and doing back tracking ...
Interface for experiment-specific channel quality info provider.
virtual float PedRms(raw::ChannelID_t ch) const =0
void Compress(std::vector< short > &adc, raw::Compress_t compress)
Compresses a raw data buffer.
std::vector< sim::SimChannel > fTestSimChannel_v
This is the interface class for a tool to handle a GenNoise for the overall response.
icarusutil::SignalShapingICARUSService * fSignalShapingService
art::ServiceHandle< art::TFileService > tfs
unsigned int ChannelID_t
Type representing the ID of a readout channel.
Interface for experiment-specific service for channel quality info.
double sampling_rate(DetectorClocksData const &data)
Returns the period of the TPC readout electronics clock.
Tools and modules for checking out the basics of the Monte Carlo.
art framework interface to geometry description
art::InputTag fDriftEModuleLabel
module making the ionization electrons