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