All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
WireCellNoiseFilter_module.cc
Go to the documentation of this file.
1 // Framework includes
2 #include "art/Framework/Principal/Event.h"
3 
4 #include "art/Framework/Core/EDProducer.h"
5 #include "art/Framework/Core/ModuleMacros.h"
6 #include "art/Framework/Principal/Handle.h"
7 #include "art/Framework/Services/Registry/ServiceHandle.h"
8 
18 
20 
21 #include "WireCellUtil/Units.h"
22 #include "WireCellUtil/NamedFactory.h"
23 #include "WireCellIface/IDFT.h"
24 #include "WireCellAux/SimpleFrame.h"
25 #include "WireCellAux/SimpleTrace.h"
26 #include "WireCellAux/DftTools.h"
27 #include "WireCellSigProc/Microboone.h"
28 #include "WireCellSigProc/OmnibusNoiseFilter.h"
29 #include "WireCellSigProc/SimpleChannelNoiseDB.h"
30 
31 #include <numeric> // iota
32 #include <string>
33 
34 using namespace WireCell;
35 using WireCell::Aux::SimpleTrace;
36 using WireCell::Aux::SimpleFrame;
37 using WireCell::Aux::DftTools::fwd_r2c;
38 
39 namespace noisefilteralg {
40 
41  class WireCellNoiseFilter : public art::EDProducer {
42 
43  public:
44  explicit WireCellNoiseFilter(fhicl::ParameterSet const& pset);
45  virtual ~WireCellNoiseFilter();
46 
47  void produce(art::Event& evt);
48  void reconfigure(fhicl::ParameterSet const& pset);
49 
50  private:
51  void DoNoiseFilter(art::Event const& evt,
52  const std::vector<raw::RawDigit>&,
53  std::vector<raw::RawDigit>&) const;
54 
55  //******************************
56  //Variables Taken from FHICL File
57  IDFT::pointer m_dft; // revised FFT API
58  std::string fDigitModuleLabel; // label for rawdigit module
59  bool fDoNoiseFiltering; // Allows for a "pass through" mode
60  size_t fNumTicksToDropFront; // If we are truncating then this is non-zero
61  size_t fWindowSize; // Number of ticks in the output RawDigit
62 
63  // services
64  }; //end class Noise
65 
66  //-------------------------------------------------------------------
67  WireCellNoiseFilter::WireCellNoiseFilter(fhicl::ParameterSet const& pset) : EDProducer(pset)
68  {
69  this->reconfigure(pset);
70  produces<std::vector<raw::RawDigit>>();
71  }
72 
73  //-------------------------------------------------------------------
75 
76  //-------------------------------------------------------------------
77  void
78  WireCellNoiseFilter::reconfigure(fhicl::ParameterSet const& pset)
79  {
80  auto dft_tn = pset.get<std::string>("dft", "FftwDFT");
81  m_dft = Factory::find_tn<IDFT>(dft_tn);
82  fDigitModuleLabel = pset.get<std::string>("DigitModuleLabel", "daq");
83  fDoNoiseFiltering = pset.get<bool>("DoNoiseFiltering", true);
84  fNumTicksToDropFront = pset.get<size_t>("NumTicksToDropFront", 2400);
85  fWindowSize = pset.get<size_t>("WindowSize", 6400);
86  }
87 
88  //-------------------------------------------------------------------
89  void
91  {
92  // Recover services we will need
93  const lariov::DetPedestalProvider& pedestalValues =
94  art::ServiceHandle<lariov::DetPedestalService const>()->GetPedestalProvider();
95 
96  art::Handle<std::vector<raw::RawDigit>> rawDigitHandle;
97  evt.getByLabel(fDigitModuleLabel, rawDigitHandle);
98 
99  // Define the output vector (in case we don't do anything)
100  std::unique_ptr<std::vector<raw::RawDigit>> filteredRawDigit(new std::vector<raw::RawDigit>);
101 
102  if (rawDigitHandle.isValid() && rawDigitHandle->size() > 0) {
103  const std::vector<raw::RawDigit>& rawDigitVector(*rawDigitHandle);
104 
105  // Make sure we have the correct window size (e.g. window size = 9600 but data is 9595)
106  size_t windowSize(std::min(fWindowSize, rawDigitVector.at(0).NADC()));
107 
108  if (fNumTicksToDropFront + windowSize > rawDigitVector.at(0).NADC())
109  throw cet::exception("WireCellNoiseFilter")
110  << "Ticks to drop + windowsize larger than input buffer\n";
111 
112  if (fDoNoiseFiltering)
113  DoNoiseFilter(evt, rawDigitVector, *filteredRawDigit);
114  else {
115  // Enable truncation
116  size_t startBin(fNumTicksToDropFront);
117  size_t stopBin(startBin + windowSize);
118 
119  raw::RawDigit::ADCvector_t outputVector(windowSize);
120 
121  for (const auto& rawDigit : rawDigitVector) {
122  if (rawDigit.NADC() < windowSize) continue;
123 
124  const raw::RawDigit::ADCvector_t& rawAdcVec = rawDigit.ADCs();
125 
126  unsigned int channel = rawDigit.Channel();
127  float pedestal = pedestalValues.PedMean(channel);
128 
129  std::copy(
130  rawAdcVec.begin() + startBin, rawAdcVec.begin() + stopBin, outputVector.begin());
131 
132  filteredRawDigit->emplace_back(
133  raw::RawDigit(channel, outputVector.size(), outputVector, raw::kNone));
134  filteredRawDigit->back().SetPedestal(pedestal, 2.0);
135  }
136  }
137  }
138 
139  //filtered raw digits
140  evt.put(std::move(filteredRawDigit));
141  }
142 
143  void
145  const std::vector<raw::RawDigit>& inputWaveforms,
146  std::vector<raw::RawDigit>& outputWaveforms) const
147  {
148  auto const runNum = e.run();
149 
150  // Recover services we will need
151  const lariov::ChannelStatusProvider& channelStatus =
152  art::ServiceHandle<lariov::ChannelStatusService const>()->GetProvider();
153  const lariov::DetPedestalProvider& pedestalValues =
154  art::ServiceHandle<lariov::DetPedestalService const>()->GetPedestalProvider();
155  const lariov::ElectronicsCalibProvider& elec_provider =
156  art::ServiceHandle<lariov::ElectronicsCalibService const>()->GetProvider();
157  const geo::GeometryCore& geometry = *lar::providerFrom<geo::Geometry>();
158  auto const clock_data =
159  art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(e);
160 
161  const unsigned int n_channels = inputWaveforms.size();
162 
163  // S&C microboone sampling parameter database
164  const double tick = sampling_rate(clock_data); // 0.5 * units::microsecond;
165  const size_t nsamples = inputWaveforms.at(0).NADC();
166  const size_t windowSize = std::min(fWindowSize, nsamples);
167 
168  // Q&D microboone channel map
169  std::vector<int> uchans(geometry.Nwires(0)), vchans(geometry.Nwires(1)),
170  wchans(geometry.Nwires(2));
171  const int nchans = uchans.size() + vchans.size() + wchans.size();
172  std::iota(uchans.begin(), uchans.end(), 0);
173  std::iota(vchans.begin(), vchans.end(), vchans.size());
174  std::iota(wchans.begin(), wchans.end(), vchans.size() + uchans.size());
175 
176  // Q&D nominal baseline
177  const double unombl = 2048.0, vnombl = 2048.0, wnombl = 400.0;
178 
179  // Q&D miss-configured channel database
180  std::vector<int> miscfgchan;
181  for (int channelIdx = 0; channelIdx < nchans; channelIdx++) {
182  if (elec_provider.ExtraInfo(channelIdx).GetBoolData("is_misconfigured")) {
183  miscfgchan.push_back(channelIdx);
184  }
185  }
186 
187  const double from_gain_mVfC = 4.7, to_gain_mVfC = 14.0, from_shaping = 1.0 * units::microsecond,
188  to_shaping = 2.0 * units::microsecond;
189 
190  // Recover bad channels from the database
191  std::vector<int> bad_channels;
192  for (int channelIdx = 0; channelIdx < nchans; channelIdx++)
193  if (channelStatus.IsBad(channelIdx)) bad_channels.push_back(channelIdx);
194 
195  // Q&D RC+RC time constant - all have same.
196  const double rcrc = 1.0 * units::millisecond;
197  std::vector<int> rcrcchans(nchans);
198  std::iota(rcrcchans.begin(), rcrcchans.end(), 0);
199 
200  //harmonic noises
201  std::vector<int> harmonicchans(uchans.size() + vchans.size());
202  std::iota(harmonicchans.begin(), harmonicchans.end(), 0);
203 
204  std::vector<int> special_chans;
205  special_chans.push_back(2240);
206 
207  WireCell::SigProc::SimpleChannelNoiseDB::mask_t h36kHz(0, 169, 173);
208  WireCell::SigProc::SimpleChannelNoiseDB::mask_t h108kHz(0, 513, 516);
209  WireCell::SigProc::SimpleChannelNoiseDB::mask_t hspkHz(0, 17, 19);
210  WireCell::SigProc::SimpleChannelNoiseDB::multimask_t hharmonic;
211  hharmonic.push_back(h36kHz);
212  hharmonic.push_back(h108kHz);
213  WireCell::SigProc::SimpleChannelNoiseDB::multimask_t hspecial;
214  hspecial.push_back(h36kHz);
215  hspecial.push_back(h108kHz);
216  hspecial.push_back(hspkHz);
217 
218  float u_resp_array[120] = {
219  0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
220  0.0, 0.0, 0.0, 0.0, 0.364382, 0.387949,
221  0.411053, 0.433979, 0.456863, 0.479746, 0.502641, 0.52554,
222  0.548441, 0.57134, 0.591765, 0.609448, 0.626848, 0.644094,
223  0.661364, 0.678859, 0.695231, 0.710462, 0.726147, 0.742373,
224  0.761332, 0.783313, 0.806325, 0.830412, 0.857676, 0.888412,
225  0.920705, 0.954624, 0.990242, 1.02766, 1.06121, 1.09027,
226  1.12037, 1.15157, 1.18392, 1.21748, 1.25229, 1.28824,
227  1.32509, 1.36256, 1.40051, 1.43907, 1.47857, 1.51933,
228  1.56134, 1.60404, 1.72665, 1.94005, 2.16994, 2.42041,
229  2.69475, 3.07222, 3.67375, 4.60766, 5.91864, 7.30178,
230  8.3715, 8.94736, 8.93705, 8.40339, 7.2212, 5.76382,
231  3.8931, 1.07893, -3.52481, -11.4593, -20.4011, -29.1259,
232  -34.9544, -36.9358, -35.3303, -31.2068, -25.8614, -20.3613,
233  -15.3794, -11.2266, -7.96091, -5.50138, -3.71143, -2.44637,
234  -1.57662, -0.99733, -0.62554, -0.393562, -0.249715, -0.15914,
235  -0.100771, -0.062443, -0.037283, -0.0211508, -0.0112448, -0.00552085,
236  -0.00245133, -0.000957821, -0.000316912, -8.51679e-05, -2.21299e-05, -1.37496e-05,
237  -1.49806e-05, -1.36935e-05, -9.66758e-06, -5.20773e-06, -7.4787e-07, 3.71199e-06,
238  8.17184e-06, 1.26317e-05, 1.70916e-05, 2.15514e-05, 2.60113e-05, 3.04711e-05};
239  float v_resp_array[120] = {
240  0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
241  0.0, 0.0, 0.0, 0.0, 0.0865303, 0.0925559,
242  0.0983619, 0.104068, 0.109739, 0.115403, 0.121068, 0.126735,
243  0.132403, 0.138072, 0.143739, 0.149408, 0.155085, 0.160791,
244  0.166565, 0.172454, 0.178514, 0.184795, 0.191341, 0.198192,
245  0.205382, 0.212944, 0.220905, 0.229292, 0.238129, 0.247441,
246  0.257256, 0.267601, 0.278502, 0.28999, 0.298745, 0.304378,
247  0.310105, 0.315921, 0.321818, 0.327796, 0.333852, 0.339967,
248  0.346098, 0.352169, 0.358103, 0.363859, 0.36945, 0.374915,
249  0.380261, 0.385401, 0.39016, 0.394378, 0.39804, 0.401394,
250  0.405145, 0.410714, 0.4205, 0.437951, 0.467841, 0.516042,
251  0.587738, 0.694157, 0.840763, 1.01966, 1.22894, 1.5612,
252  2.12348, 3.31455, 5.59355, 9.10709, 14.1756, 18.4603,
253  19.9517, 17.4166, 10.6683, 1.40656, -10.0638, -19.034,
254  -23.654, -24.0558, -21.4418, -17.3229, -12.9485, -9.08912,
255  -6.05941, -3.86946, -2.38669, -1.43678, -0.853335, -0.503951,
256  -0.296551, -0.173029, -0.0990099, -0.0547172, -0.0287882, -0.0142758,
257  -0.00661815, -0.00284757, -0.00115702, -0.000456456, -0.000183439, -8.04214e-05,
258  -4.20533e-05, -2.62903e-05, -1.64098e-05, -6.68039e-06, 3.04903e-06, 1.27784e-05,
259  2.25079e-05, 3.22373e-05, 4.19667e-05, 5.16961e-05, 6.14255e-05, 7.11549e-05};
260  WireCell::Waveform::realseq_t u_resp(nsamples);
261  WireCell::Waveform::realseq_t v_resp(nsamples);
262  for (int i = 0; i != 120; i++) {
263  u_resp.at(i) = u_resp_array[i];
264  v_resp.at(i) = v_resp_array[i];
265  }
266  // WireCell::Waveform::compseq_t u_resp_freq = WireCell::Waveform::dft(u_resp);
267  // WireCell::Waveform::compseq_t v_resp_freq = WireCell::Waveform::dft(v_resp);
268  WireCell::Waveform::compseq_t u_resp_freq = fwd_r2c(m_dft, u_resp);
269  WireCell::Waveform::compseq_t v_resp_freq = fwd_r2c(m_dft, v_resp);
270 
271  int uplane_time_shift = 79;
272  int vplane_time_shift = 82;
273 
274  // do the coherent subtraction
275  std::vector<std::vector<int>> channel_groups;
276  for (unsigned int i = 0; i != 172; i++) {
277  //for (int i=150;i!=151;i++){
278  std::vector<int> channel_group;
279  for (int j = 0; j != 48; j++) {
280  channel_group.push_back(i * 48 + j);
281  }
282  channel_groups.push_back(channel_group);
283  }
284 
285  auto noise = new WireCell::SigProc::SimpleChannelNoiseDB;
286  // initialize
287  noise->set_sampling(tick, nsamples);
288  // set nominal baseline
289  noise->set_nominal_baseline(uchans, unombl);
290  noise->set_nominal_baseline(vchans, vnombl);
291  noise->set_nominal_baseline(wchans, wnombl);
292 
293  noise->set_response(uchans, u_resp_freq);
294  noise->set_response(vchans, v_resp_freq);
295 
296  noise->set_response_offset(uchans, uplane_time_shift);
297  noise->set_response_offset(vchans, vplane_time_shift);
298 
299  noise->set_pad_window_front(uchans, 20);
300  noise->set_pad_window_back(uchans, 10);
301  noise->set_pad_window_front(vchans, 10);
302  noise->set_pad_window_back(vchans, 10);
303  noise->set_pad_window_front(wchans, 10);
304  noise->set_pad_window_back(wchans, 10);
305 
306  // set misconfigured channels
307  noise->set_gains_shapings(miscfgchan, from_gain_mVfC, to_gain_mVfC, from_shaping, to_shaping);
308  // do the RCRC
309  noise->set_rcrc_constant(rcrcchans, rcrc);
310  // set initial bad channels
311  noise->set_bad_channels(bad_channels);
312  // set the harmonic filter
313  noise->set_filter(harmonicchans, hharmonic);
314  noise->set_filter(special_chans, hspecial);
315  noise->set_channel_groups(channel_groups);
316 
317  for (unsigned int i = 0; i != uchans.size(); i++) {
318  if (uchans.at(i) < 100) {
319  noise->set_min_rms_cut_one(uchans.at(i), 1);
320  noise->set_max_rms_cut_one(uchans.at(i), 5);
321  }
322  else if (uchans.at(i) < 2000) {
323  noise->set_min_rms_cut_one(uchans.at(i), 1.9);
324  noise->set_max_rms_cut_one(uchans.at(i), 11);
325  }
326  else {
327  noise->set_min_rms_cut_one(uchans.at(i), 0.9);
328  noise->set_max_rms_cut_one(uchans.at(i), 5);
329  }
330  }
331  for (unsigned int i = 0; i != vchans.size(); i++) {
332  if (vchans.at(i) < 290 + (int)uchans.size()) {
333  noise->set_min_rms_cut_one(vchans.at(i), 1);
334  noise->set_max_rms_cut_one(vchans.at(i), 5);
335  }
336  else if (vchans.at(i) < 2200 + (int)uchans.size()) {
337  noise->set_min_rms_cut_one(vchans.at(i), 1.9);
338  noise->set_max_rms_cut_one(vchans.at(i), 11);
339  }
340  else {
341  noise->set_min_rms_cut_one(vchans.at(i), 1);
342  noise->set_max_rms_cut_one(vchans.at(i), 5);
343  }
344  }
345 
346  // these are the one after the Hardware Fix
347  if (runNum > 8000) {
348  for (unsigned int i = 0; i != uchans.size(); i++) {
349  if (uchans.at(i) < 600) {
350  noise->set_min_rms_cut_one(uchans.at(i), 1 + (1.7 - 1) / 600. * i);
351  noise->set_max_rms_cut_one(uchans.at(i), 5);
352  }
353  else if (uchans.at(i) < 1800) {
354  noise->set_min_rms_cut_one(uchans.at(i), 1.7);
355  noise->set_max_rms_cut_one(uchans.at(i), 11);
356  }
357  else {
358  noise->set_min_rms_cut_one(uchans.at(i), 1 + (1.7 - 1) / 600. * (2399 - i));
359  noise->set_max_rms_cut_one(uchans.at(i), 5);
360  }
361  }
362  for (unsigned int i = 0; i != vchans.size(); i++) {
363  if (vchans.at(i) < 600 + (int)uchans.size()) {
364  noise->set_min_rms_cut_one(vchans.at(i), 0.8 + (1.7 - 0.8) / 600. * i);
365  noise->set_max_rms_cut_one(vchans.at(i), 5);
366  }
367  else if (vchans.at(i) < 1800 + (int)uchans.size()) {
368  noise->set_min_rms_cut_one(vchans.at(i), 1.7);
369  noise->set_max_rms_cut_one(vchans.at(i), 11);
370  }
371  else {
372  noise->set_min_rms_cut_one(vchans.at(i), 0.8 + (1.7 - 0.8) / 600. * (2399 - i));
373  noise->set_max_rms_cut_one(vchans.at(i), 5);
374  }
375  }
376  }
377 
378  noise->set_min_rms_cut(wchans, 1.3);
379  noise->set_max_rms_cut(wchans, 8.0);
380 
381  //Define database object
382  std::shared_ptr<WireCell::IChannelNoiseDatabase> noise_sp(noise);
383 
384  auto one = new WireCell::SigProc::Microboone::OneChannelNoise;
385  one->set_channel_noisedb(noise_sp);
386  std::shared_ptr<WireCell::IChannelFilter> one_sp(one);
387  auto many = new WireCell::SigProc::Microboone::CoherentNoiseSub;
388  many->set_channel_noisedb(noise_sp);
389  std::shared_ptr<WireCell::IChannelFilter> many_sp(many);
390 
391  //define noisefilter object
392  WireCell::SigProc::OmnibusNoiseFilter bus;
393  bus.set_channel_filters({one_sp});
394  bus.set_grouped_filters({many_sp});
395  bus.set_channel_noisedb(noise_sp);
396 
397  // Enable truncation
398  size_t startBin(fNumTicksToDropFront);
399  size_t stopBin(startBin + windowSize);
400 
401  //load waveforms into traces
403  for (unsigned int ich = 0; ich < n_channels; ich++) {
404  if (inputWaveforms.at(ich).NADC() < windowSize) continue;
405 
406  const raw::RawDigit::ADCvector_t& rawAdcVec = inputWaveforms.at(ich).ADCs();
407 
408  WireCell::ITrace::ChargeSequence charges;
409 
410  charges.resize(nsamples);
411 
412  std::transform(rawAdcVec.begin(), rawAdcVec.end(), charges.begin(), [](auto& adcVal) {
413  return float(adcVal);
414  });
415 
416  unsigned int chan = inputWaveforms.at(ich).Channel();
417  SimpleTrace* st = new SimpleTrace(chan, 0.0, charges);
418  traces.push_back(WireCell::ITrace::pointer(st));
419  }
420 
421  //Load traces into frame
422  SimpleFrame* sf = new SimpleFrame(0, 0, traces);
423  WireCell::IFrame::pointer frame = WireCell::IFrame::pointer(sf);
424  WireCell::IFrame::pointer quiet = NULL;
425 
426  //Do filtering
427  bus(frame, quiet);
428 
429  //std::cout << "HERE" << std::endl;
430  //return;
431  if (quiet == NULL) return;
432 
433  //Output results
434  std::vector<short> waveform(windowSize);
435 
436  auto quiet_traces = quiet->traces();
437  for (auto quiet_trace : *quiet_traces.get()) {
438  //int tbin = quiet_trace->tbin();
439  unsigned int channel = quiet_trace->channel();
440 
441  auto& quiet_charges = quiet_trace->charge();
442 
443  // Recover the database version of the pedestal, we'll offset the waveforms so it matches
444  float pedestal = pedestalValues.PedMean(channel);
445 
446  std::transform(quiet_charges.begin() + startBin,
447  quiet_charges.begin() + stopBin,
448  waveform.begin(),
449  [pedestal](auto charge) { return std::round(charge + pedestal); });
450 
451  outputWaveforms.emplace_back(raw::RawDigit(channel, waveform.size(), waveform, raw::kNone));
452  outputWaveforms.back().SetPedestal(pedestal, 1.75);
453  }
454 
455  return;
456  }
457 
458  DEFINE_ART_MODULE(WireCellNoiseFilter)
459 
460 } //end namespace WireCellNoiseFilteralg
Collection of charge vs time digitized from a single readout channel.
Definition: RawDigit.h:69
static constexpr Sample_t transform(Sample_t sample)
const geo::GeometryCore * geometry
virtual bool IsBad(raw::ChannelID_t channel) const =0
Returns whether the specified channel is bad in the current run.
microsecond_as<> microsecond
Type of time stored in microseconds, in double precision.
Definition: spacetime.h:119
void DoNoiseFilter(art::Event const &evt, const std::vector< raw::RawDigit > &, std::vector< raw::RawDigit > &) const
std::vector< short > ADCvector_t
Type representing a (compressed) vector of ADC counts.
Definition: RawDigit.h:73
Definition of basic raw digits.
for pfile in ack l reconfigure(.*) override"` do echo "checking $
no compression
Definition: RawTypes.h:9
millisecond_as<> millisecond
Type of time stored in milliseconds, in double precision.
Definition: spacetime.h:102
unsigned int Nwires(unsigned int p, unsigned int tpc=0, unsigned int cstat=0) const
Returns the total number of wires in the specified plane.
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:265
Interface for experiment-specific service for pmt gain info.
tick_as<> tick
Tick number, represented by std::ptrdiff_t.
Definition: electronics.h:75
Class providing information about the quality of channels.
Description of geometry of one entire detector.
virtual float PedMean(raw::ChannelID_t ch) const =0
Retrieve pedestal information.
void reconfigure(fhicl::ParameterSet const &pset)
then echo Cowardly refusing to create a new FHiCL file with the same name as the original one('${SourceName}')." >&2 exit 1 fi echo "'$
bool GetBoolData(std::string const &label) const
Interface for experiment-specific channel quality info provider.
do i e
T copy(T const &v)
TCEvent evt
Definition: DataStructs.cxx:8
Interface for experiment-specific service for channel quality info.
double sampling_rate(DetectorClocksData const &data)
Returns the period of the TPC readout electronics clock.
art framework interface to geometry description
virtual CalibrationExtraInfo const & ExtraInfo(raw::ChannelID_t ch) const =0