All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
OverlayICARUS_module.cc
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////
2 // $Id: OverlayICARUS.cxx,v 1.22 2010/04/23 20:30:53 seligman Exp $
3 //
4 // OverlayICARUS class designed to simulate signal on a wire in the TPC
5 //
6 // katori@fnal.gov
7 //
8 // - Revised to use sim::RawDigit instead of rawdata::RawDigit, and to
9 // - save the electron clusters associated with each digit.
10 //
11 ////////////////////////////////////////////////////////////////////////
12 
13 
14 // C/C++ standard library
15 #include <stdexcept> // std::range_error
16 #include <vector>
17 #include <string>
18 #include <algorithm> // std::fill()
19 #include <functional>
20 #include <random>
21 #include <chrono>
22 
23 // ROOT libraries
24 #include "TMath.h"
25 #include "TComplex.h"
26 #include "TString.h"
27 #include "TH2F.h"
28 #include "TH1D.h"
29 #include "TFile.h"
30 #include "TCanvas.h"
31 
32 // art library and utilities
33 #include "art/Framework/Core/ModuleMacros.h"
34 #include "art/Framework/Core/EDProducer.h"
35 #include "art/Framework/Principal/Event.h"
36 #include "art/Framework/Principal/Handle.h"
37 #include "art/Framework/Services/Registry/ServiceHandle.h"
38 #include "art_root_io/TFileService.h"
39 #include "art_root_io/TFileDirectory.h"
40 #include "art/Utilities/make_tool.h"
41 #include "fhiclcpp/ParameterSet.h"
42 #include "messagefacility/MessageLogger/MessageLogger.h"
43 
44 // art extensions
45 #include "nurandom/RandomUtils/NuRandomService.h"
46 
47 // LArSoft libraries
49 #include "lardataobj/RawData/raw.h"
63 #include "tools/IOverlay.h"
64 #include "icarus_signal_processing/Filters/ICARUSFFT.h"
65 
66 using namespace util;
67 ///Detector simulation of raw signals on wires
68 namespace detsim {
69 
70 // Base class for creation of raw signals on wires.
71 class OverlayICARUS : public art::EDProducer
72 {
73 public:
74 
75  explicit OverlayICARUS(fhicl::ParameterSet const& pset);
76  virtual ~OverlayICARUS();
77 
78  // read/write access to event
79  void produce (art::Event& evt);
80  void beginJob();
81  void endJob();
82  void reconfigure(fhicl::ParameterSet const& p);
83 
84 private:
85 
86  void MakeADCVec(std::vector<short>& adc, icarusutil::TimeVec const& charge, float ped_mean) const;
87 
88  art::InputTag fInputRawDataLabel; ///< Label for the underlying raw digit data
89  art::InputTag fDriftEModuleLabel; ///< module making the ionization electrons
90  raw::Compress_t fCompression; ///< compression type to use
91 
93 
94  TH1F* fSimCharge;
96 
97  //define max ADC value - if one wishes this can
98  //be made a fcl parameter but not likely to ever change
99  const float adcsaturation = 4095;
100 
101  // little helper class to hold the params of each charge dep
103  public:
104  ResponseParams(double charge, size_t time) : m_charge(charge), m_time(time) {}
105  double getCharge() { return m_charge; }
106  size_t getTime() { return m_time; }
107  private:
108  double m_charge;
109  size_t m_time;
110  };
111 
112  using FFTPointer = std::unique_ptr<icarus_signal_processing::ICARUSFFT<double>>;
113  FFTPointer fFFT; //< Object to handle thread safe FFT
114 
115  //services
117  icarusutil::SignalShapingICARUSService* fSignalShapingService; ///< Access to the response functions
118  const lariov::DetPedestalProvider& fPedestalRetrievalAlg; ///< Keep track of an instance to the pedestal retrieval alg
119 
120 }; // class OverlayICARUS
121 DEFINE_ART_MODULE(OverlayICARUS)
122 
123 //-------------------------------------------------
124 OverlayICARUS::OverlayICARUS(fhicl::ParameterSet const& pset)
125  : EDProducer{pset}
126  , fGeometry(*lar::providerFrom<geo::Geometry>()),
127  fPedestalRetrievalAlg(*lar::providerFrom<lariov::DetPedestalService>())
128 {
129  this->reconfigure(pset);
130 
131  produces< std::vector<raw::RawDigit> >();
133  TString compression(pset.get< std::string >("CompressionType"));
134  if(compression.Contains("Huffman",TString::kIgnoreCase)) fCompression = raw::kHuffman;
135 
136  return;
137 }
138 
139 //-------------------------------------------------
140 OverlayICARUS::~OverlayICARUS() {}
141 
142 //-------------------------------------------------
143 void OverlayICARUS::reconfigure(fhicl::ParameterSet const& p)
144 {
145  fInputRawDataLabel = p.get< art::InputTag >("InputRawDataLabel", "daq");
146  fDriftEModuleLabel = p.get< art::InputTag >("DriftEModuleLabel", "largeant");
147 
148  //detector properties information
149  auto const detprop = art::ServiceHandle<detinfo::DetectorPropertiesService>()->DataForJob();
150 
151  fSignalShapingService = art::ServiceHandle<icarusutil::SignalShapingICARUSService>{}.get();
152 
153  fFFT = std::make_unique<icarus_signal_processing::ICARUSFFT<double>>(detprop.NumberTimeSamples());
154 
155  return;
156 }
157 
158 //-------------------------------------------------
159 void OverlayICARUS::beginJob()
160 {
161  // get access to the TFile service
162  art::ServiceHandle<art::TFileService> tfs;
163 
164  fSimCharge = tfs->make<TH1F>("fSimCharge", "simulated charge", 150, 0, 1500);
165  fSimChargeWire = tfs->make<TH2F>("fSimChargeWire", "simulated charge", 5600,0.,5600.,500, 0, 1500);
166 
167  return;
168 }
169 
170 //-------------------------------------------------
171 void OverlayICARUS::endJob()
172 {}
173 
174 void OverlayICARUS::produce(art::Event& evt)
175 {
176  //--------------------------------------------------------------------
177  //
178  // Get all of the services we will be using
179  //
180  //--------------------------------------------------------------------
181 
182  // Recocver the input RawDigits we are going to add our signal too
183  art::Handle<std::vector<raw::RawDigit>> inputRawDigitHandle;
184 
185  evt.getByLabel(fInputRawDataLabel, inputRawDigitHandle);
186 
187  if (!inputRawDigitHandle.isValid()) throw std::runtime_error("Failed to read back RawDigits for overlay!");
188 
189  // Now recover the SimChannel information which will be overlaid
190  art::Handle<std::vector<sim::SimChannel>> simChanHandle;
191  evt.getByLabel(fDriftEModuleLabel, simChanHandle);
192 
193  if (!simChanHandle.isValid()) throw std::runtime_error("Failed to recover the SimChannel information for the overlay");
194 
195  // Keep track of the SimChannel information by channel
196  using SimChannelMap = std::unordered_map<raw::ChannelID_t, const sim::SimChannel*>;
197 
198  SimChannelMap simChannelMap;
199 
200  for(const auto& simChannel : *simChanHandle) simChannelMap[simChannel.Channel()] = &simChannel;
201 
202  // make a unique_ptr of sim::SimDigits that allows ownership of the produced
203  // digits to be transferred to the art::Event after the put statement below
204  std::unique_ptr< std::vector<raw::RawDigit>> digcol(new std::vector<raw::RawDigit>);
205  digcol->reserve(inputRawDigitHandle->size());
206 
207  // vectors for working in the following for loop
208  std::vector<short> adcvec;
209  icarusutil::TimeVec zeroCharge;
210 
211  //detector properties information
212  auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService>()->DataFor(evt);
213 
214  // The outer loop is over the input RawDigits which will always be written out
215  for(const auto& rawDigit : *inputRawDigitHandle)
216  {
217  // Recover the channel
218  raw::ChannelID_t channel = rawDigit.Channel();
219 
220  //use channel number to set some useful numbers
221  std::vector<geo::WireID> widVec = fGeometry.ChannelToWire(channel);
222 
223  // We skip channels that are not connected to a physical wire
224  if (!widVec.empty())
225  {
226  size_t plane = widVec[0].Plane;
227 
228  // Recover the ADC values and copy to local vector
229  const raw::RawDigit::ADCvector_t& adcVector = rawDigit.ADCs();
230 
231  // Make sure local vector is correct size (and note the vector above may be compressed so can't use its size yet)
232  adcvec.resize(rawDigit.Samples(),0);
233  zeroCharge.resize(rawDigit.Samples(),0);
234 
235  // and do the copyh
236  raw::Uncompress(adcVector, adcvec, rawDigit.Compression());
237 
238  // Check for the existence of a SimChannel for this channel
239  SimChannelMap::const_iterator simChanItr = simChannelMap.find(channel);
240 
241  if (simChanItr != simChannelMap.end())
242  {
243  // Recover the response function information for this channel
244  const icarus_tool::IResponse& response = fSignalShapingService->GetResponse(channel);
245 
246  // Recover the SimChannel (if one) for this channel
247  const sim::SimChannel* simChan = simChanItr->second;
248 
249  // Allocate local vector to hold the deposited charge
250  icarusutil::TimeVec chargeWork(adcvec.size(),0.);
251 
252  // Need the to convert from deposited number of electrons to ADC units
253  double gain = fSignalShapingService->GetASICGain(channel) * sampling_rate(clockData) * 1.e-3; // Gain returned is electrons/us, this converts to electrons/tick
254 
255  // Loop through the simchannel energy deposits
256  for(const auto& tdcide : simChan->TDCIDEMap())
257  {
258  unsigned int tdc = tdcide.first;
259 
260  // We need to convert this to a tick...
261  int tick = clockData.TPCTDC2Tick(tdc);
262 
263  // If out of range what is right thing to do?
264  if (tick < 0 ||tick > int(adcvec.size()))
265  {
266  std::cout << "tick out of range: " << tick << ", tdc: " << tdc << std::endl;
267  continue;
268  }
269 
270  // Recover the charge for this tick
271  double charge = simChan->Charge(tdc);
272 
273  chargeWork[tick] += charge / gain;
274  }
275 
276  // now we have the tempWork for the adjacent wire of interest
277  // convolve it with the appropriate response function
278  fFFT->convolute(chargeWork, response.getConvKernel(), fSignalShapingService->ResponseTOffset(channel));
279 
280  //Get the pedestal and rms from the input waveform
281  float pedestal = fPedestalRetrievalAlg.PedMean(channel);
282 
283  // "Make" the ADC vector
284  MakeADCVec(adcvec, chargeWork, pedestal);
285  }
286 
287  if(fMakeHistograms && plane==2)
288  {
289  short area = std::accumulate(adcvec.begin(),adcvec.end(),0,[](const auto& val,const auto& sum){return sum + val - 400;});
290 
291  if(area>0)
292  {
293  fSimCharge->Fill(area);
294  fSimChargeWire->Fill(widVec[0].Wire,area);
295  }
296  }
297  }
298 
299  // add this digit to the collection;
300  // adcvec is copied, not moved: in case of compression, adcvec will show
301  // less data: e.g. if the uncompressed adcvec has 9600 items, after
302  // compression it will have maybe 5000, but the memory of the other 4600
303  // is still there, although unused; a copy of adcvec will instead have
304  // only 5000 items. All 9600 items of adcvec will be recovered for free
305  // and used on the next loop.
306  raw::RawDigit rd(channel, adcvec.size(), adcvec, fCompression);
307 
308  rd.SetPedestal(rawDigit.GetPedestal(),rawDigit.GetSigma());
309  digcol->push_back(std::move(rd)); // we do move the raw digit copy, though
310  }
311 
312  evt.put(std::move(digcol));
313 
314  return;
315 }
316 //-------------------------------------------------
317 void OverlayICARUS::MakeADCVec(std::vector<short>& adcvec, icarusutil::TimeVec const& chargevec, float ped_mean) const
318 {
319  for(unsigned int i = 0; i < adcvec.size(); ++i)
320  {
321  // We offset for the channel's default pedestal
322  float adcval = chargevec[i] + ped_mean;
323 
324  // Now make sure to limit the range to that allowed for 12 bits
325  adcval = std::max(float(0.), std::min(adcval, adcsaturation));
326 
327  // Remove the temporary offset while we add the signal to the existing vector.
328  adcvec[i] += std::round(adcval - ped_mean);
329  }// end loop over signal size
330  // compress the adc vector using the desired compression scheme,
331  // if raw::kNone is selected nothing happens to adcvec
332  // This shrinks adcvec, if fCompression is not kNone.
333  raw::Compress(adcvec, fCompression);
334 
335  return;
336 }
337 
338 }
Huffman Encoding.
Definition: RawTypes.h:10
TString compression(pset.get< std::string >("CompressionType"))
enum raw::_compress Compress_t
std::map< int, art::Ptr< sim::SimChannel > > SimChannelMap
Collection of charge vs time digitized from a single readout channel.
Definition: RawDigit.h:69
Energy deposited on a readout channel by simulated tracks.
Definition: SimChannel.h:145
virtual const icarusutil::FrequencyVec & getConvKernel() const =0
pdgs p
Definition: selectors.fcl:22
std::vector< short > ADCvector_t
Type representing a (compressed) vector of ADC counts.
Definition: RawDigit.h:73
art::InputTag fDriftEModuleLabel
module making the ionization electrons
Definition of basic raw digits.
for pfile in ack l reconfigure(.*) override"` do echo "checking $
raw::Compress_t fCompression
compression type to use
no compression
Definition: RawTypes.h:9
icarusutil::SignalShapingICARUSService * fSignalShapingService
Access to the response functions.
Access the description of detector geometry.
This is the interface class for a tool to handle a GenNoise for the overall response.
double Charge(TDC_t tdc) const
Returns the total number of ionization electrons on this channel in the specified TDC...
Definition: SimChannel.cxx:138
Collect all the RawData header files together.
std::vector< SigProcPrecision > TimeVec
tick_as<> tick
Tick number, represented by std::ptrdiff_t.
Definition: electronics.h:75
Description of geometry of one entire detector.
art::InputTag fInputRawDataLabel
Label for the underlying raw digit data.
ResponseParams(double charge, size_t time)
const lariov::DetPedestalProvider & fPedestalRetrievalAlg
Keep track of an instance to the pedestal retrieval alg.
std::unique_ptr< icarus_signal_processing::ICARUSFFT< double >> FFTPointer
m_charge
void SetPedestal(float ped, float sigma=1.)
Set pedestal and its RMS (the latter is 0 by default)
Definition: RawDigit.cxx:68
object containing MC truth information necessary for making RawDigits and doing back tracking ...
Interface for experiment-specific channel quality info provider.
void Compress(std::vector< short > &adc, raw::Compress_t compress)
Compresses a raw data buffer.
Definition: raw.cxx:19
TDCIDEs_t const & TDCIDEMap() const
Returns all the deposited energy information as stored.
Definition: SimChannel.h:334
art::ServiceHandle< art::TFileService > tfs
const geo::GeometryCore & fGeometry
TCEvent evt
Definition: DataStructs.cxx:8
unsigned int ChannelID_t
Type representing the ID of a readout channel.
Definition: RawTypes.h:28
Interface for experiment-specific service for channel quality info.
void Uncompress(const std::vector< short > &adc, std::vector< short > &uncompressed, raw::Compress_t compress)
Uncompresses a raw data buffer.
Definition: raw.cxx:776
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
BEGIN_PROLOG could also be cout