All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TPCNoiseFilter1D_tool.cc
Go to the documentation of this file.
1 /**
2  * @file TPCNoiseFilter1DMC_tool.cc
3  *
4  * @brief This tool converts from daq to LArSoft format with noise filtering
5  *
6  */
7 
8 // Framework Includes
9 #include "art/Framework/Core/EDProducer.h"
10 #include "art/Framework/Principal/Event.h"
11 #include "art/Framework/Principal/Handle.h"
12 #include "art/Framework/Services/Registry/ServiceHandle.h"
13 #include "art/Persistency/Common/PtrMaker.h"
14 #include "art/Utilities/ToolMacros.h"
15 #include "art/Utilities/make_tool.h"
16 #include "cetlib/cpu_timer.h"
17 #include "fhiclcpp/ParameterSet.h"
18 #include "messagefacility/MessageLogger/MessageLogger.h"
19 
20 // LArSoft includes
22 
23 #include "sbndaq-artdaq-core/Overlays/ICARUS/PhysCrateFragment.hh"
24 
26 
27 #include "icarus_signal_processing/WaveformTools.h"
28 #include "icarus_signal_processing/Denoising.h"
29 #include "icarus_signal_processing/Filters/FFTFilterFunctions.h"
30 
31 // std includes
32 #include <string>
33 #include <iostream>
34 #include <memory>
35 
36 //------------------------------------------------------------------------------------------------------------------------------------------
37 // implementation follows
38 
39 namespace daq {
40 /**
41  * @brief TPCNoiseFilter1DMC class definiton
42  */
43 class TPCNoiseFilter1DMC : virtual public INoiseFilter
44 {
45 public:
46  /**
47  * @brief Constructor
48  *
49  * @param pset
50  */
51  explicit TPCNoiseFilter1DMC(fhicl::ParameterSet const &pset);
52 
53  /**
54  * @brief Destructor
55  */
57 
58  /**
59  * @brief Interface for configuring the particular algorithm tool
60  *
61  * @param ParameterSet The input set of parameters for configuration
62  */
63  virtual void configure(const fhicl::ParameterSet&) override;
64 
65  /**
66  * @brief Given a set of recob hits, run DBscan to form 3D clusters
67  *
68  * @param fragment The artdaq fragment to process
69  */
72  const icarus_signal_processing::ArrayFloat&,
73  const size_t&) override;
74 
75  /**
76  * @brief Recover the channels for the processed fragment
77  */
78  const icarus_signal_processing::VectorInt& getChannelIDs() const override {return fChannelIDVec;}
79 
80  /**
81  * @brief Recover the selection values
82  */
83  const icarus_signal_processing::ArrayBool& getSelectionVals() const override {return fSelectVals;};
84 
85  /**
86  * @brief Recover the ROI values
87  */
88  const icarus_signal_processing::ArrayBool& getROIVals() const override {return fROIVals;};
89 
90  /**
91  * @brief Recover the pedestal subtracted waveforms
92  */
93  const icarus_signal_processing::ArrayFloat& getRawWaveforms() const override {return fRawWaveforms;};
94 
95  /**
96  * @brief Recover the pedestal subtracted waveforms
97  */
98  const icarus_signal_processing::ArrayFloat& getPedCorWaveforms() const override {return fPedCorWaveforms;};
99 
100  /**
101  * @brief Recover the "intrinsic" RMS
102  */
103  const icarus_signal_processing::ArrayFloat& getIntrinsicRMS() const override {return fIntrinsicRMS;};
104 
105  /**
106  * @brief Recover the correction median values
107  */
108  const icarus_signal_processing::ArrayFloat& getCorrectedMedians() const override {return fCorrectedMedians;};
109 
110  /**
111  * @brief Recover the waveforms less coherent noise
112  */
113  const icarus_signal_processing::ArrayFloat& getWaveLessCoherent() const override {return fWaveLessCoherent;};
114 
115  /**
116  * @brief Recover the morphological filter waveforms
117  */
118  const icarus_signal_processing::ArrayFloat& getMorphedWaveforms() const override {return fMorphedWaveforms;};
119 
120  /**
121  * @brief Recover the pedestals for each channel
122  */
123  const icarus_signal_processing::VectorFloat& getPedestalVals() const override {return fPedestalVals;};
124 
125  /**
126  * @brief Recover the full RMS before coherent noise
127  */
128  const icarus_signal_processing::VectorFloat& getFullRMSVals() const override {return fFullRMSVals;};
129 
130  /**
131  * @brief Recover the truncated RMS noise
132  */
133  const icarus_signal_processing::VectorFloat& getTruncRMSVals() const override {return fTruncRMSVals;};
134 
135  /**
136  * @brief Recover the number of bins after truncation
137  */
138  const icarus_signal_processing::VectorInt& getNumTruncBins() const override {return fNumTruncBins;};
139 
140 private:
141 
142  using FloatPairVec = std::vector<std::pair<float,float>>;
143 
144  float fSigmaForTruncation; //< Selection cut for truncated rms calculation
145  size_t fCoherentNoiseOffset; //< Offset for midplane
146  size_t fStructuringElement; //< Structuring element for morphological filter
147  size_t fMorphWindow; //< Window for filter
148  std::vector<float> fThreshold; //< Threshold to apply for saving signal
149  bool fUseFFTFilter; //< Turn on/off the use of the FFT filter
150  bool fDiagnosticOutput; //< If true will spew endless messages to output
151  FloatPairVec fFFTSigmaValsVec; //< Gives the sigmas for the filter function
152  FloatPairVec fFFTCutoffValsVec; //< Gives the cutoffs for the filter function
153 
154  std::vector<std::string> fFilterModeVec; //< Allowed modes for the filter
155 
156  // Allocate containers for noise processing
157  icarus_signal_processing::VectorInt fChannelIDVec;
158  icarus_signal_processing::ArrayBool fSelectVals;
159  icarus_signal_processing::ArrayBool fROIVals;
160  icarus_signal_processing::ArrayFloat fRawWaveforms;
161  icarus_signal_processing::ArrayFloat fPedCorWaveforms;
162  icarus_signal_processing::ArrayFloat fIntrinsicRMS;
163  icarus_signal_processing::ArrayFloat fCorrectedMedians;
164  icarus_signal_processing::ArrayFloat fWaveLessCoherent;
165  icarus_signal_processing::ArrayFloat fMorphedWaveforms;
166 
167  icarus_signal_processing::VectorFloat fPedestalVals;
168  icarus_signal_processing::VectorFloat fFullRMSVals;
169  icarus_signal_processing::VectorFloat fTruncRMSVals;
170  icarus_signal_processing::VectorInt fNumTruncBins;
171  icarus_signal_processing::VectorInt fRangeBins;
172 
173  icarus_signal_processing::VectorFloat fThresholdVec;
174 
175  icarus_signal_processing::FilterFunctionVec fFilterFunctionVec;
176 
177  const geo::Geometry* fGeometry; //< pointer to the Geometry service
178 
179  // Keep track of the FFT
180  icarus_signal_processing::FFTFilterFunctionVec fFFTFilterFunctionVec;
181 };
182 
183 TPCNoiseFilter1DMC::TPCNoiseFilter1DMC(fhicl::ParameterSet const &pset)
184 {
185  this->configure(pset);
186 
187  fSelectVals.clear();
188  fROIVals.clear();
189  fRawWaveforms.clear();
190  fPedCorWaveforms.clear();
191  fIntrinsicRMS.clear();
192  fCorrectedMedians.clear();
193  fWaveLessCoherent.clear();
194  fMorphedWaveforms.clear();
195 
196  fPedestalVals.clear();
197  fFullRMSVals.clear();
198  fTruncRMSVals.clear();
199  fNumTruncBins.clear();
200  fRangeBins.clear();
201 
202  return;
203 }
204 
205 //------------------------------------------------------------------------------------------------------------------------------------------
206 
208 {
209 }
210 
211 //------------------------------------------------------------------------------------------------------------------------------------------
212 void TPCNoiseFilter1DMC::configure(fhicl::ParameterSet const &pset)
213 {
214  fSigmaForTruncation = pset.get<float >("NSigmaForTrucation", 3.5);
215  fCoherentNoiseOffset = pset.get<size_t >("CoherentOffset", 0);
216  fStructuringElement = pset.get<size_t >("StructuringElement", 20);
217  fMorphWindow = pset.get<size_t >("FilterWindow", 10);
218  fThreshold = pset.get<std::vector<float> >("Threshold", std::vector<float>()={5.0,3.5,3.5});
219  fUseFFTFilter = pset.get<bool >("UseFFTFilter", true);
220  fDiagnosticOutput = pset.get<bool >("DiagnosticOutput", false);
221  fFilterModeVec = pset.get<std::vector<std::string>>("FilterModeVec", std::vector<std::string>()={"e","g","d"});
222 
223  fFFTSigmaValsVec = pset.get<FloatPairVec >("FFTSigmaVals", FloatPairVec()={{1.5,20.}, {1.5,20.}, {2.0,20.}});
224  fFFTCutoffValsVec = pset.get<FloatPairVec >("FFTCutoffVals", FloatPairVec()={{8.,800.}, {8.,800.}, {0.0,800.}});
225 
226  fGeometry = art::ServiceHandle<geo::Geometry const>{}.get();
227 
228  fFFTFilterFunctionVec.clear();
229 
230  std::cout << "TPCNoiseFilter1D configure, fUseFFTFilter: " << fUseFFTFilter << std::endl;
231 
232  if (fUseFFTFilter)
233  {
234  for(int plane = 0; plane < 3; plane++)
235  {
236  //if (plane < 2) fFFTFilterFunctionVec.emplace_back(std::make_unique<icarus_signal_processing::WindowFFTFilter>(fFFTSigmaValsVec[plane], fFFTCutoffValsVec[plane]));
237  //else fFFTFilterFunctionVec.emplace_back(std::make_unique<icarus_signal_processing::NoFFTFilter>());
238  fFFTFilterFunctionVec.emplace_back(std::make_unique<icarus_signal_processing::WindowFFTFilter>(fFFTSigmaValsVec[plane], fFFTCutoffValsVec[plane]));
239 
240  std::cout << "TPCDecoderFilter1D FFT setup for plane " << plane << ", SigmaVals: " << fFFTSigmaValsVec[plane].first << "/" << fFFTSigmaValsVec[plane].second << ", cutoff: " << fFFTCutoffValsVec[plane].first << "/" << fFFTCutoffValsVec[plane].second << std::endl;
241  }
242  }
243 
244  return;
245 }
246 
248  const daq::INoiseFilter::ChannelPlaneVec& channelPlaneVec,
249  const icarus_signal_processing::ArrayFloat& dataArray,
250  const size_t& coherentNoiseGrouping)
251 {
252  cet::cpu_timer theClockTotal;
253 
254  theClockTotal.start();
255 
256  // Recover the number of channels and ticks
257  unsigned int numChannels = dataArray.size();
258  unsigned int numTicks = dataArray[0].size();
259 
260  if (fSelectVals.size() < numChannels) fSelectVals.resize(numChannels, icarus_signal_processing::VectorBool(numTicks));
261  if (fROIVals.size() < numChannels) fROIVals.resize(numChannels, icarus_signal_processing::VectorBool(numTicks));
262  if (fRawWaveforms.size() < numChannels) fRawWaveforms.resize(numChannels, icarus_signal_processing::VectorFloat(numTicks));
263  if (fPedCorWaveforms.size() < numChannels) fPedCorWaveforms.resize(numChannels, icarus_signal_processing::VectorFloat(numTicks));
264  if (fIntrinsicRMS.size() < numChannels) fIntrinsicRMS.resize(numChannels, icarus_signal_processing::VectorFloat(numTicks));
265  if (fCorrectedMedians.size() < numChannels) fCorrectedMedians.resize(numChannels, icarus_signal_processing::VectorFloat(numTicks));
266  if (fWaveLessCoherent.size() < numChannels) fWaveLessCoherent.resize(numChannels, icarus_signal_processing::VectorFloat(numTicks));
267  if (fMorphedWaveforms.size() < numChannels) fMorphedWaveforms.resize(numChannels, icarus_signal_processing::VectorFloat(numTicks));
268 
269  if (fChannelIDVec.size() < numChannels) fChannelIDVec.resize(numChannels);
270  if (fPedestalVals.size() < numChannels) fPedestalVals.resize(numChannels);
271  if (fFullRMSVals.size() < numChannels) fFullRMSVals.resize(numChannels);
272  if (fTruncRMSVals.size() < numChannels) fTruncRMSVals.resize(numChannels);
273  if (fNumTruncBins.size() < numChannels) fNumTruncBins.resize(numChannels);
274  if (fRangeBins.size() < numChannels) fRangeBins.resize(numChannels);
275 
276  if (fThresholdVec.size() < numChannels) fThresholdVec.resize(numChannels / coherentNoiseGrouping);
277 
278  if (fFilterFunctionVec.size() < numChannels) fFilterFunctionVec.resize(numChannels);
279 
280 // icarus_signal_processing::Denoiser1D_Protect denoiser;
281  icarus_signal_processing::Denoiser1D denoiser;
282  icarus_signal_processing::WaveformTools<float> waveformTools;
283 
284  // Make a pass throught to do pedestal corrections and get raw waveform information
285  for(size_t idx = 0; idx < numChannels; idx++)
286  {
287  icarus_signal_processing::VectorFloat& pedCorDataVec = fPedCorWaveforms[idx];
288 
289  // Keep track of the channel
290  fChannelIDVec[idx] = channelPlaneVec[idx].first;
291 
292  // We need to recover info on which plane we have
293  std::vector<geo::WireID> widVec = fGeometry->ChannelToWire(fChannelIDVec[idx]);
294 
295  // Handle the filter function to use for this channel
296  // Note the modulus... this to enable a workaround for the wirecell 2D drift which misses the channels with no signal
297  unsigned int plane = channelPlaneVec[idx].second % 3;
298 
299  // Set the threshold which toggles between planes
300  fThresholdVec[idx / coherentNoiseGrouping] = fThreshold[plane];
301 
302  switch(fFilterModeVec[plane][0])
303  {
304  case 'd' :
305  fFilterFunctionVec[idx] = std::make_unique<icarus_signal_processing::Dilation1D>(fStructuringElement);
306  break;
307  case 'e' :
308  fFilterFunctionVec[idx] = std::make_unique<icarus_signal_processing::Erosion1D>(fStructuringElement);
309  break;
310  case 'g' :
311  fFilterFunctionVec[idx] = std::make_unique<icarus_signal_processing::Gradient1D>(fStructuringElement);
312  break;
313  case 'a' :
314  fFilterFunctionVec[idx] = std::make_unique<icarus_signal_processing::Average1D>(fStructuringElement);
315  break;
316  case 'm' :
317  fFilterFunctionVec[idx] = std::make_unique<icarus_signal_processing::Median1D>(fStructuringElement);
318  break;
319  default:
320  std::cout << "***** FOUND NO MATCH FOR TYPE: " << fFilterModeVec[plane] << ", plane " << plane << " DURING INITIALIZATION OF FILTER FUNCTIONS IN TPCNoiseFilter1DMC" << std::endl;
321  break;
322  }
323 
324  // Now determine the pedestal and correct for it
325  waveformTools.getPedestalCorrectedWaveform(dataArray[idx],
326  pedCorDataVec,
328  fPedestalVals[idx],
329  fFullRMSVals[idx],
330  fTruncRMSVals[idx],
331  fNumTruncBins[idx],
332  fRangeBins[idx]);
333 
334  // Convolve with a filter function
335  if (fUseFFTFilter) (*fFFTFilterFunctionVec[plane])(pedCorDataVec);
336 
337  // Make sure our selection and ROI arrays are initialized
338  std::fill(fSelectVals[idx].begin(),fSelectVals[idx].end(),false);
339  }
340 
341  denoiser(fWaveLessCoherent.begin(),
342  fPedCorWaveforms.begin(),
343  fMorphedWaveforms.begin(),
344  fIntrinsicRMS.begin(),
345  fSelectVals.begin(),
346  fROIVals.begin(),
347  fCorrectedMedians.begin(),
348  fFilterFunctionVec.begin(),
350  numChannels,
351  coherentNoiseGrouping,
353  fMorphWindow);
354 
355  theClockTotal.stop();
356 
357  double totalTime = theClockTotal.accumulated_real_time();
358 
359  mf::LogDebug("TPCNoiseFilter1DMC") << " *totalTime: " << totalTime << std::endl;
360 
361  return;
362 }
363 
364 
365 DEFINE_ART_CLASS_TOOL(TPCNoiseFilter1DMC)
366 } // namespace lar_cluster3d
std::vector< std::string > fFilterModeVec
icarus_signal_processing::VectorInt fChannelIDVec
icarus_signal_processing::ArrayFloat fPedCorWaveforms
const icarus_signal_processing::ArrayFloat & getRawWaveforms() const override
Recover the pedestal subtracted waveforms.
icarus_signal_processing::ArrayFloat fRawWaveforms
std::vector< std::pair< float, float >> FloatPairVec
icarus_signal_processing::ArrayFloat fCorrectedMedians
icarus_signal_processing::ArrayBool fSelectVals
virtual void process_fragment(detinfo::DetectorClocksData const &, const daq::INoiseFilter::ChannelPlaneVec &, const icarus_signal_processing::ArrayFloat &, const size_t &) override
Given a set of recob hits, run DBscan to form 3D clusters.
This provides an art tool interface definition for tools which &quot;decode&quot; artdaq fragments into LArSoft...
icarus_signal_processing::ArrayBool fROIVals
std::vector< geo::WireID > ChannelToWire(raw::ChannelID_t const channel) const
Returns a list of wires connected to the specified TPC channel.
icarus_signal_processing::ArrayFloat fIntrinsicRMS
icarus_signal_processing::VectorInt fRangeBins
TPCNoiseFilter1DMC class definiton.
const icarus_signal_processing::ArrayFloat & getPedCorWaveforms() const override
Recover the pedestal subtracted waveforms.
auto end(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:585
icarus_signal_processing::FFTFilterFunctionVec fFFTFilterFunctionVec
void fill(const art::PtrVector< recob::Hit > &hits, int only_plane)
icarus_signal_processing::VectorFloat fThresholdVec
icarus_signal_processing::ArrayFloat fWaveLessCoherent
virtual void configure(const fhicl::ParameterSet &) override
Interface for configuring the particular algorithm tool.
icarus_signal_processing::FilterFunctionVec fFilterFunctionVec
The geometry of one entire detector, as served by art.
Definition: Geometry.h:181
icarus_signal_processing::VectorFloat fPedestalVals
IDecoderFilter interface class definiton.
Definition: INoiseFilter.h:32
std::vector< float > fThreshold
const geo::Geometry * fGeometry
auto begin(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:573
const icarus_signal_processing::VectorFloat & getFullRMSVals() const override
Recover the full RMS before coherent noise.
icarus_signal_processing::VectorInt fNumTruncBins
const icarus_signal_processing::ArrayBool & getSelectionVals() const override
Recover the selection values.
icarus_signal_processing::VectorFloat fTruncRMSVals
const icarus_signal_processing::ArrayBool & getROIVals() const override
Recover the ROI values.
Contains all timing reference information for the detector.
const icarus_signal_processing::ArrayFloat & getWaveLessCoherent() const override
Recover the waveforms less coherent noise.
TPCNoiseFilter1DMC(fhicl::ParameterSet const &pset)
Constructor.
const icarus_signal_processing::ArrayFloat & getCorrectedMedians() const override
Recover the correction median values.
const icarus_signal_processing::VectorInt & getNumTruncBins() const override
Recover the number of bins after truncation.
const icarus_signal_processing::VectorFloat & getTruncRMSVals() const override
Recover the truncated RMS noise.
const icarus_signal_processing::VectorFloat & getPedestalVals() const override
Recover the pedestals for each channel.
icarus_signal_processing::ArrayFloat fMorphedWaveforms
const icarus_signal_processing::VectorInt & getChannelIDs() const override
Recover the channels for the processed fragment.
const icarus_signal_processing::ArrayFloat & getMorphedWaveforms() const override
Recover the morphological filter waveforms.
art framework interface to geometry description
BEGIN_PROLOG could also be cout
icarus_signal_processing::VectorFloat fFullRMSVals
std::vector< ChannelPlanePair > ChannelPlaneVec
Definition: INoiseFilter.h:54
const icarus_signal_processing::ArrayFloat & getIntrinsicRMS() const override
Recover the &quot;intrinsic&quot; RMS.