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