2 #include "art/Framework/Principal/Event.h"
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"
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"
34 using namespace WireCell;
35 using WireCell::Aux::SimpleTrace;
36 using WireCell::Aux::SimpleFrame;
37 using WireCell::Aux::DftTools::fwd_r2c;
39 namespace noisefilteralg {
47 void produce(art::Event&
evt);
51 void DoNoiseFilter(art::Event
const& evt,
52 const std::vector<raw::RawDigit>&,
53 std::vector<raw::RawDigit>&)
const;
67 WireCellNoiseFilter::WireCellNoiseFilter(fhicl::ParameterSet
const& pset) : EDProducer(pset)
70 produces<std::vector<raw::RawDigit>>();
80 auto dft_tn = pset.get<std::string>(
"dft",
"FftwDFT");
81 m_dft = Factory::find_tn<IDFT>(dft_tn);
94 art::ServiceHandle<lariov::DetPedestalService const>()->GetPedestalProvider();
96 art::Handle<std::vector<raw::RawDigit>> rawDigitHandle;
100 std::unique_ptr<std::vector<raw::RawDigit>> filteredRawDigit(
new std::vector<raw::RawDigit>);
102 if (rawDigitHandle.isValid() && rawDigitHandle->size() > 0) {
103 const std::vector<raw::RawDigit>& rawDigitVector(*rawDigitHandle);
106 size_t windowSize(std::min(
fWindowSize, rawDigitVector.at(0).NADC()));
109 throw cet::exception(
"WireCellNoiseFilter")
110 <<
"Ticks to drop + windowsize larger than input buffer\n";
117 size_t stopBin(startBin + windowSize);
121 for (
const auto& rawDigit : rawDigitVector) {
122 if (rawDigit.NADC() < windowSize)
continue;
126 unsigned int channel = rawDigit.Channel();
127 float pedestal = pedestalValues.
PedMean(channel);
130 rawAdcVec.begin() + startBin, rawAdcVec.begin() + stopBin, outputVector.begin());
132 filteredRawDigit->emplace_back(
134 filteredRawDigit->back().SetPedestal(pedestal, 2.0);
140 evt.put(std::move(filteredRawDigit));
145 const std::vector<raw::RawDigit>& inputWaveforms,
146 std::vector<raw::RawDigit>& outputWaveforms)
const
148 auto const runNum = e.run();
152 art::ServiceHandle<lariov::ChannelStatusService const>()->GetProvider();
154 art::ServiceHandle<lariov::DetPedestalService const>()->GetPedestalProvider();
156 art::ServiceHandle<lariov::ElectronicsCalibService const>()->GetProvider();
158 auto const clock_data =
159 art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(e);
161 const unsigned int n_channels = inputWaveforms.size();
165 const size_t nsamples = inputWaveforms.at(0).NADC();
166 const size_t windowSize = std::min(
fWindowSize, nsamples);
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());
177 const double unombl = 2048.0, vnombl = 2048.0, wnombl = 400.0;
180 std::vector<int> miscfgchan;
181 for (
int channelIdx = 0; channelIdx < nchans; channelIdx++) {
183 miscfgchan.push_back(channelIdx);
187 const double from_gain_mVfC = 4.7, to_gain_mVfC = 14.0, from_shaping = 1.0 *
units::microsecond,
191 std::vector<int> bad_channels;
192 for (
int channelIdx = 0; channelIdx < nchans; channelIdx++)
193 if (channelStatus.
IsBad(channelIdx)) bad_channels.push_back(channelIdx);
197 std::vector<int> rcrcchans(nchans);
198 std::iota(rcrcchans.begin(), rcrcchans.end(), 0);
201 std::vector<int> harmonicchans(uchans.size() + vchans.size());
202 std::iota(harmonicchans.begin(), harmonicchans.end(), 0);
204 std::vector<int> special_chans;
205 special_chans.push_back(2240);
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);
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];
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);
271 int uplane_time_shift = 79;
272 int vplane_time_shift = 82;
275 std::vector<std::vector<int>> channel_groups;
276 for (
unsigned int i = 0; i != 172; i++) {
278 std::vector<int> channel_group;
279 for (
int j = 0; j != 48; j++) {
280 channel_group.push_back(i * 48 + j);
282 channel_groups.push_back(channel_group);
285 auto noise =
new WireCell::SigProc::SimpleChannelNoiseDB;
287 noise->set_sampling(tick, nsamples);
289 noise->set_nominal_baseline(uchans, unombl);
290 noise->set_nominal_baseline(vchans, vnombl);
291 noise->set_nominal_baseline(wchans, wnombl);
293 noise->set_response(uchans, u_resp_freq);
294 noise->set_response(vchans, v_resp_freq);
296 noise->set_response_offset(uchans, uplane_time_shift);
297 noise->set_response_offset(vchans, vplane_time_shift);
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);
307 noise->set_gains_shapings(miscfgchan, from_gain_mVfC, to_gain_mVfC, from_shaping, to_shaping);
309 noise->set_rcrc_constant(rcrcchans, rcrc);
311 noise->set_bad_channels(bad_channels);
313 noise->set_filter(harmonicchans, hharmonic);
314 noise->set_filter(special_chans, hspecial);
315 noise->set_channel_groups(channel_groups);
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);
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);
327 noise->set_min_rms_cut_one(uchans.at(i), 0.9);
328 noise->set_max_rms_cut_one(uchans.at(i), 5);
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);
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);
341 noise->set_min_rms_cut_one(vchans.at(i), 1);
342 noise->set_max_rms_cut_one(vchans.at(i), 5);
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);
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);
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);
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);
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);
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);
378 noise->set_min_rms_cut(wchans, 1.3);
379 noise->set_max_rms_cut(wchans, 8.0);
382 std::shared_ptr<WireCell::IChannelNoiseDatabase> noise_sp(noise);
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);
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);
399 size_t stopBin(startBin + windowSize);
403 for (
unsigned int ich = 0; ich < n_channels; ich++) {
404 if (inputWaveforms.at(ich).NADC() < windowSize)
continue;
408 WireCell::ITrace::ChargeSequence charges;
410 charges.resize(nsamples);
412 std::transform(rawAdcVec.begin(), rawAdcVec.end(), charges.begin(), [](
auto& adcVal) {
413 return float(adcVal);
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));
422 SimpleFrame* sf =
new SimpleFrame(0, 0, traces);
423 WireCell::IFrame::pointer frame = WireCell::IFrame::pointer(sf);
424 WireCell::IFrame::pointer quiet = NULL;
431 if (quiet == NULL)
return;
434 std::vector<short> waveform(windowSize);
436 auto quiet_traces = quiet->traces();
437 for (
auto quiet_trace : *quiet_traces.get()) {
439 unsigned int channel = quiet_trace->channel();
441 auto& quiet_charges = quiet_trace->charge();
444 float pedestal = pedestalValues.
PedMean(channel);
447 quiet_charges.begin() + stopBin,
449 [pedestal](
auto charge) {
return std::round(charge + pedestal); });
452 outputWaveforms.back().SetPedestal(pedestal, 1.75);
Collection of charge vs time digitized from a single readout channel.
size_t fNumTicksToDropFront
const geo::GeometryCore * geometry
std::string fDigitModuleLabel
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.
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 of basic raw digits.
millisecond_as<> millisecond
Type of time stored in milliseconds, in double precision.
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.
Interface for experiment-specific service for pmt gain info.
void produce(art::Event &evt)
tick_as<> tick
Tick number, represented by std::ptrdiff_t.
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 "'$
virtual ~WireCellNoiseFilter()
Interface for experiment-specific channel quality info provider.
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