OmnibusPMTNoiseFilter.cxx
Go to the documentation of this file.
2 
4 
5 
7 
10 
12 
13 #include "FrameUtils.h"
14 
18 
19 
20 #include "PMTNoiseROI.h"
21 
22 using namespace WireCell;
23 
24 using namespace WireCell::SigProc;
25 
26 
27 std::vector<PMTNoiseROI*> PMT_ROIs;
28 
29 OmnibusPMTNoiseFilter::OmnibusPMTNoiseFilter(const std::string anode_tn, int pad_window, int min_window_length, int threshold, float rms_threshold, int sort_wires, float ind_th1, float ind_th2, int nwire_pmt_col_th )
30  : m_intag("quiet"), m_outtag("raw"), m_anode_tn(anode_tn)
31  , m_pad_window(pad_window)
32  , m_min_window_length(min_window_length)
33  , m_threshold(threshold)
34  , m_rms_threshold(rms_threshold)
35  , m_sort_wires(sort_wires)
36  , m_ind_th1(ind_th1)
37  , m_ind_th2(ind_th2)
38  , m_nwire_pmt_col_th(nwire_pmt_col_th)
39 {
40 }
42 {
43 }
44 
46 {
47  m_anode_tn = get(config, "anode", m_anode_tn);
48  m_anode = Factory::find_tn<IAnodePlane>(m_anode_tn);
49  if (!m_anode) {
50  THROW(KeyError() << errmsg{"failed to get IAnodePlane: " + m_anode_tn});
51  }
52 
53  m_pad_window = get(config,"pad_window", m_pad_window);
54  m_min_window_length = get(config,"min_window_length",m_min_window_length);
55  m_threshold = get(config,"threshold",m_threshold);
56  m_rms_threshold = get(config,"rms_threshold",m_rms_threshold);
57  m_sort_wires = get(config,"sort_wires",m_sort_wires);
58  m_ind_th1 = get(config,"ind_th1",m_ind_th1);
59  m_ind_th2 = get(config,"ind_th2",m_ind_th2);
60  m_nwire_pmt_col_th = get(config,"nwire_pmt_col_th",m_nwire_pmt_col_th);
61  m_intag = get(config, "intraces", m_intag);
62  m_outtag = get(config, "outtraces", m_outtag);
63 }
65 {
67  cfg["anode"] = m_anode_tn;
68  cfg["pad_window"] = m_pad_window;
69  cfg["min_window_length"] = m_min_window_length;
70  cfg["threshold"] = m_threshold;
71  cfg["rms_threshold"]= m_rms_threshold;
72  cfg["sort_wires"]=m_sort_wires;
73  cfg["ind_th1"]=m_ind_th1;
74  cfg["ind_th2"]=m_ind_th2;
75  cfg["nwire_pmt_col_th"] = m_nwire_pmt_col_th;
76  cfg["intraces"] = m_intag;
77  cfg["outtraces"] = m_outtag;
78  return cfg;
79 }
80 
82 {
83  if (!in) { // eos processing
84  out = nullptr;
85  return true;
86  }
87 
88  std::map<int, Waveform::realseq_t> bychan_coll;
89  std::map<int, Waveform::realseq_t> bychan_indu;
90  std::map<int, Waveform::realseq_t> bychan_indv;
91  std::map<int,double> by_chan_rms;
92  // go through all channels and calculate RMS as well as categorize them
93  auto traces = wct::sigproc::tagged_traces(in, m_intag);
94  for (auto trace : traces) {
95  int ch = trace->channel();
96 
97  auto wpid = m_anode->resolve(ch);
98  const int iplane = wpid.index();
99 
100  Waveform::realseq_t signal=trace->charge();
101  std::pair<double,double> results = Derivations::CalcRMS(signal);
102  by_chan_rms[ch] = results.second;
103 
104  //std::cout << iplane << " " << ch << " " << results.second << std::endl;
105 
106  if (iplane ==0){
107  bychan_indu[ch] = trace->charge();
108  }else if (iplane == 1){
109  bychan_indv[ch] = trace->charge();
110  }else{
111  bychan_coll[ch] = trace->charge();
112  }
113 
114  }
115 
116  // Remove PMT signal from Collection
117  for (auto cs : bychan_coll) {
118  // ignore dead channels ...
119  if (by_chan_rms[cs.first]>m_rms_threshold)
120  IDPMTSignalCollection(bychan_coll[cs.first],by_chan_rms[cs.first],cs.first);
121  }
122 
123 
124  // ID PMT signal in induction signal
125  for (auto cs : bychan_indu) {
126  // ignore dead channels ...
127  if (by_chan_rms[cs.first]>m_rms_threshold)
128  IDPMTSignalInduction(bychan_indu[cs.first],by_chan_rms[cs.first],cs.first,0);
129  }
130  for (auto cs : bychan_indv) {
131  // ignore dead channels ...
132  if (by_chan_rms[cs.first]>m_rms_threshold)
133  IDPMTSignalInduction(bychan_indv[cs.first],by_chan_rms[cs.first],cs.first,1);
134  }
135 
136  // Remove PMT signal from Induction ...
137 
138  for (int i=0;i!=int(PMT_ROIs.size());i++){
139  PMT_ROIs.at(i)->sort_wires(m_sort_wires);
140  //int flag_qx = 0;
141  if (PMT_ROIs.at(i)->get_sorted_uwires().size() > 0 && PMT_ROIs.at(i)->get_sorted_vwires().size() > 0){
142  for (int j=0;j!=int(PMT_ROIs.at(i)->get_sorted_uwires().size());j++){
143  if (PMT_ROIs.at(i)->get_average_uwires_peak_height(j) < m_ind_th1* PMT_ROIs.at(i)->get_average_wwires_peak_height() &&
144  PMT_ROIs.at(i)->get_max_uwires_peak_height(j) < m_ind_th2 * PMT_ROIs.at(i)->get_max_wwires_peak_height() &&
145  PMT_ROIs.at(i)->get_sorted_uwires().at(j).size() <= PMT_ROIs.at(i)->get_sorted_wwires().size()
146  ){
147  // flag_qx = 1;
148  for (int k=0;k!=int(PMT_ROIs.at(i)->get_sorted_uwires().at(j).size());k++){
149  RemovePMTSignal(bychan_indu[PMT_ROIs.at(i)->get_sorted_uwires().at(j).at(k)],PMT_ROIs.at(i)->get_start_bin(),PMT_ROIs.at(i)->get_end_bin());
150  //RemovePMTSignalInduction(hu[PMT_ROIs.at(i)->get_sorted_uwires().at(j).at(k)],PMT_ROIs.at(i)->get_start_bin(),PMT_ROIs.at(i)->get_end_bin());
151  }
152 
153  // std::cout << i << " " << PMT_ROIs.at(i)->get_peaks().at(0) << " " << PMT_ROIs.at(i)->get_peaks().size() << " " << PMT_ROIs.at(i)->get_sorted_uwires().at(j).size() << " " << j << " " << PMT_ROIs.at(i)->get_average_uwires_peak_height(j) << " " << PMT_ROIs.at(i)->get_average_wwires_peak_height() << " " << PMT_ROIs.at(i)->get_max_uwires_peak_height(j) << " " << PMT_ROIs.at(i)->get_max_wwires_peak_height() << " " << PMT_ROIs.at(i)->get_sorted_uwires().at(j).size() << " " << PMT_ROIs.at(i)->get_sorted_wwires().size() << std::endl;
154  }
155  }
156 
157  for (int j=0;j!=int(PMT_ROIs.at(i)->get_sorted_vwires().size());j++){
158  if (PMT_ROIs.at(i)->get_average_vwires_peak_height(j) < m_ind_th1 * PMT_ROIs.at(i)->get_average_wwires_peak_height() &&
159  PMT_ROIs.at(i)->get_max_vwires_peak_height(j) < m_ind_th2 * PMT_ROIs.at(i)->get_max_wwires_peak_height() &&
160  PMT_ROIs.at(i)->get_sorted_vwires().at(j).size() <= PMT_ROIs.at(i)->get_sorted_wwires().size()
161  ){
162  //flag_qx = 1;
163  for (int k=0;k!=int(PMT_ROIs.at(i)->get_sorted_vwires().at(j).size());k++){
164  RemovePMTSignal(bychan_indv[PMT_ROIs.at(i)->get_sorted_vwires().at(j).at(k)],PMT_ROIs.at(i)->get_start_bin(),PMT_ROIs.at(i)->get_end_bin());
165  //RemovePMTSignalInduction(hv[PMT_ROIs.at(i)->get_sorted_vwires().at(j).at(k)],PMT_ROIs.at(i)->get_start_bin(),PMT_ROIs.at(i)->get_end_bin());
166  }
167  // std::cout << i << " " << PMT_ROIs.at(i)->get_peaks().at(0) << " " << PMT_ROIs.at(i)->get_peaks().size() << " " << PMT_ROIs.at(i)->get_sorted_vwires().at(j).size() << " " << j << " " << PMT_ROIs.at(i)->get_average_vwires_peak_height(j) << " " << PMT_ROIs.at(i)->get_average_wwires_peak_height() << " " << PMT_ROIs.at(i)->get_max_vwires_peak_height(j) << " " << PMT_ROIs.at(i)->get_max_wwires_peak_height() << " " << PMT_ROIs.at(i)->get_sorted_vwires().at(j).size() << " " << PMT_ROIs.at(i)->get_sorted_wwires().size() << std::endl;
168  }
169  }
170 
171  if (int(PMT_ROIs.at(i)->get_sorted_wwires().size()) >= m_nwire_pmt_col_th){
172  for (int j=0;j!=int(PMT_ROIs.at(i)->get_sorted_wwires().size());j++){
173  RemovePMTSignal(bychan_coll[PMT_ROIs.at(i)->get_sorted_wwires().at(j)],PMT_ROIs.at(i)->get_start_bin(),PMT_ROIs.at(i)->get_end_bin(),1);
174  }
175  }
176 
177 
178  //if (flag_qx == 1) std::cout << i << " " << PMT_ROIs.at(i)->get_peaks().at(0) << " " << PMT_ROIs.at(i)->get_peaks().size() << " " << PMT_ROIs.at(i)->get_uwires().size() << " " << PMT_ROIs.at(i)->get_vwires().size() << " " << PMT_ROIs.at(i)->get_sorted_uwires().size() << " " << PMT_ROIs.at(i)->get_sorted_vwires().size() << " " << PMT_ROIs.at(i)->get_sorted_wwires().size() << " " << PMT_ROIs.at(i)->get_average_uwires_peak_height() << " " << PMT_ROIs.at(i)->get_average_vwires_peak_height() << " " << PMT_ROIs.at(i)->get_average_wwires_peak_height() << " " << PMT_ROIs.at(i)->get_max_uwires_peak_height() << " " << PMT_ROIs.at(i)->get_max_vwires_peak_height() << " " << PMT_ROIs.at(i)->get_max_wwires_peak_height() << std::endl;
179  }
180  delete PMT_ROIs.at(i);
181  }
182  PMT_ROIs.clear();
183 
184 
185  //load results ...
186 
187  ITrace::vector itraces;
188  for (auto cs : bychan_indu) {
189  // fixme: that tbin though
190  SimpleTrace *trace = new SimpleTrace(cs.first, 0, cs.second);
191  itraces.push_back(ITrace::pointer(trace));
192  }
193  for (auto cs : bychan_indv) {
194  // fixme: that tbin though
195  SimpleTrace *trace = new SimpleTrace(cs.first, 0, cs.second);
196  itraces.push_back(ITrace::pointer(trace));
197  }
198  for (auto cs : bychan_coll) {
199  // fixme: that tbin though
200  SimpleTrace *trace = new SimpleTrace(cs.first, 0, cs.second);
201  itraces.push_back(ITrace::pointer(trace));
202  }
203 
204  IFrame::trace_list_t indices(itraces.size());
205  for (size_t ind=0; ind<itraces.size(); ++ind) {
206  indices[ind] = ind;
207  }
208 
209  SimpleFrame* sframe = new SimpleFrame(in->ident(), in->time(), itraces, in->tick(), in->masks());
210  sframe->tag_traces(m_outtag, indices);
211  out = IFrame::pointer(sframe);
212 
213  return true;
214 }
215 
216 
218 
219  int flag_start = 0;
220  int start_bin=0;
221  int end_bin=0;
222  int peak_bin=0;
223 
224  // std::cout << m_threshold << " " << m_pad_window << " " << m_min_window_length << " " << rms << " " << ch << std::endl;
225 
226  for (int i=0;i!=int(signal.size());i++){
227  float content = signal.at(i);
228 
229  if (flag_start ==0){
230  if (content < -m_threshold * rms){
231  start_bin = i;
232  flag_start = 1;
233  }
234  }else{
235  if (content >= -m_threshold * rms){
236  end_bin = i-1;
237  if (end_bin > start_bin + m_min_window_length){
238  float min = signal.at(start_bin);
239  peak_bin = start_bin;
240  for (int j=start_bin+1;j!=end_bin;j++){
241  if (signal.at(j) < min)
242  peak_bin = j;
243  }
244 
245  PMTNoiseROI *ROI = new PMTNoiseROI(start_bin,end_bin,peak_bin,ch,signal.at(peak_bin));
246 
247  //std::cout << start_bin << " " << end_bin << std::endl;
248  if (PMT_ROIs.size()==0){
249  PMT_ROIs.push_back(ROI);
250  }else{
251  bool flag_merge = false;
252  for (int i=0;i!=int(PMT_ROIs.size());i++){
253  flag_merge = PMT_ROIs.at(i)->merge_ROI(*ROI);
254  if (flag_merge){
255  delete ROI;
256  break;
257  }
258  }
259  if (!flag_merge){
260  PMT_ROIs.push_back(ROI);
261  }
262  }
263  // std::cout << "h " << PMT_ROIs.size() << std::endl;
264 
265  flag_start = 0;
266 
267 
268  // //adaptive baseline
269  // float start_content =signal.at(start_bin);
270  // for (int j=start_bin;j>=start_bin - m_pad_window;j--){
271  // if (j<0) continue;
272  // if (fabs(signal.at(j)) < fabs(start_content)){
273  // start_bin = j;
274  // start_content = signal.at(start_bin);
275  // }
276  // }
277  // float end_content = signal.at(end_bin);
278  // for (int j=end_bin; j<=end_bin+m_pad_window;j++){
279  // if (j>=int(signal.size())) continue;
280  // if (fabs(signal.at(j)) < fabs(end_content)){
281  // end_bin = j;
282  // end_content = signal.at(end_bin);
283  // }
284  // }
285 
286  // for (int j=start_bin;j<=end_bin;j++){
287  // float content = start_content + (end_content - start_content) * (j - start_bin) / (end_bin - start_bin*1.0);
288  // signal.at(j)=content;
289  // }
290 
291 
292  }
293  }
294  }
295  }
296 
297 }
298 
299 
300 void OmnibusPMTNoiseFilter::IDPMTSignalInduction(Waveform::realseq_t& signal, double rms, int ch, int plane){
301  //std::cout << PMT_ROIs.size() << std::endl;
302 
303  for (int i=0;i!=int(PMT_ROIs.size());i++){
304  PMTNoiseROI* ROI= PMT_ROIs.at(i);
305  for (int j=0;j!= int(ROI->get_peaks().size());j++){
306  int peak = ROI->get_peaks().at(j);
307  int peak_m1 = peak - 1; if (peak_m1 <0) peak_m1 = 0;
308  int peak_m2 = peak - 2; if (peak_m2 <0) peak_m2 = 0;
309  int peak_m3 = peak - 3; if (peak_m3 <0) peak_m3 = 0;
310  int peak_p1 = peak + 1; if (peak_p1 >= int(signal.size())) peak_p1 = int(signal.size())-1;
311  int peak_p2 = peak + 2; if (peak_p2 >= int(signal.size())) peak_p2 = int(signal.size())-1;
312  int peak_p3 = peak + 3; if (peak_p3 >= int(signal.size())) peak_p3 = int(signal.size())-1;
313 
314  if (fabs(signal.at(peak))> m_threshold * rms &&
315  fabs(signal.at(peak)) + fabs(signal.at(peak_m1)) + fabs(signal.at(peak_p1)) > fabs(signal.at(peak_m1)) + fabs(signal.at(peak_m2)) + fabs(signal.at(peak)) &&
316  fabs(signal.at(peak)) + fabs(signal.at(peak_m1)) + fabs(signal.at(peak_p1)) > fabs(signal.at(peak_p1)) + fabs(signal.at(peak_p2)) + fabs(signal.at(peak)) &&
317  fabs(signal.at(peak)) + fabs(signal.at(peak_m1)) + fabs(signal.at(peak_p1)) > fabs(signal.at(peak_m2)) + fabs(signal.at(peak_m3)) + fabs(signal.at(peak_m1)) &&
318  fabs(signal.at(peak)) + fabs(signal.at(peak_m1)) + fabs(signal.at(peak_p1)) > fabs(signal.at(peak_p2)) + fabs(signal.at(peak_p3)) + fabs(signal.at(peak_p1)) ){
319 
320  // fabs(signal.at(peak))>= fabs(signal.at(peak_m2)) &&
321  // fabs(signal.at(peak))>= fabs(signal.at(peak_p1)) &&
322  // fabs(signal.at(peak))>= fabs(signal.at(peak_p2)) &&
323  // fabs(signal.at(peak))>= fabs(signal.at(peak_p3)) &&
324  // fabs(signal.at(peak))>= fabs(signal.at(peak_m3))
325  // ){
326  if (plane == 0 ){
327  ROI->insert_uwires(ch,fabs(signal.at(peak)));
328  break;
329  }else{
330  ROI->insert_vwires(ch,fabs(signal.at(peak)));
331  break;
332  }
333  }
334  }
335  }
336 }
337 
338 void OmnibusPMTNoiseFilter::RemovePMTSignal(Waveform::realseq_t& signal, int start_bin, int end_bin, int flag){
339 
340  //int flag_start = 0;
341 
342  //adaptive baseline
343  float start_content = signal.at(start_bin);
344  for (int j=start_bin;j>=start_bin - m_pad_window;j--){
345  if (j<0) continue;
346  if (fabs(signal.at(j)) < fabs(start_content)){
347  start_bin = j;
348  start_content = signal.at(start_bin);
349  }
350  }
351  float end_content = signal.at(end_bin);
352  for (int j=end_bin; j<=end_bin+m_pad_window;j++){
353  if (j>=int(signal.size())) continue;
354  if (fabs(signal.at(j)) < fabs(end_content)){
355  end_bin = j;
356  end_content = signal.at(end_bin);
357  }
358  }
359 
360  for (int j=start_bin;j<=end_bin;j++){
361  float content = start_content + (end_content - start_content) * (j - start_bin) / (end_bin - start_bin*1.0);
362  if (flag==1){
363  if (signal.at(j)<0)
364  signal.at(j) = content;
365  }else{
366  signal.at(j)=content;
367  }
368  }
369 }
370 // Local Variables:
371 // mode: c++
372 // c-basic-offset: 2
373 // End:
std::shared_ptr< const ITrace > pointer
Definition: IData.h:19
Sequence< real_t > realseq_t
Definition: Waveform.h:31
double rms(sqlite3 *db, std::string const &table_name, std::string const &column_name)
Definition: statistics.cc:39
void tag_traces(const tag_t &tag, const IFrame::trace_list_t &indices, const IFrame::trace_summary_t &summary=IFrame::trace_summary_t(0))
Definition: SimpleFrame.cxx:76
std::string string
Definition: nybbler.cc:12
boost::error_info< struct tag_errmsg, std::string > errmsg
Definition: Exceptions.h:54
WIRECELL_FACTORY(OmnibusPMTNoiseFilter, WireCell::SigProc::OmnibusPMTNoiseFilter, WireCell::IFrameFilter, WireCell::IConfigurable) using namespace WireCell
void IDPMTSignalInduction(Waveform::realseq_t &signal, double rms, int ch, int plane)
void insert_uwires(int wire_no, float peak_height)
Definition: PMTNoiseROI.cxx:30
std::pair< double, double > CalcRMS(const WireCell::Waveform::realseq_t &signal)
Definition: Derivations.cxx:7
cfg
Definition: dbjson.py:29
std::vector< pointer > vector
Definition: IData.h:21
virtual void configure(const WireCell::Configuration &config)
IConfigurable interface.
void IDPMTSignalCollection(Waveform::realseq_t &signal, double rms, int ch)
Explicitly inject required services.
std::shared_ptr< const IFrame > input_pointer
Definition: IFunctionNode.h:39
virtual bool operator()(const input_pointer &in, output_pointer &out)
IFrameFilter interface.
static Config * config
Definition: config.cpp:1054
constexpr std::array< std::size_t, geo::vect::dimension< Vector >)> indices()
Returns a sequence of indices valid for a vector of the specified type.
#define THROW(e)
Definition: Exceptions.h:25
void RemovePMTSignal(Waveform::realseq_t &signal, int start_bin, int end_bin, int flag=0)
OmnibusPMTNoiseFilter(const std::string anode_tn="AnodePlane", int pad_window=5, int min_window_length=4, int threshold=4, float rms_threshold=0.5, int sort_wires=4, float ind_th1=2.0, float ind_th2=0.5, int nwire_pmt_col_th=6)
Create an OmnibusPMTNoiseFilter.
std::shared_ptr< const IFrame > output_pointer
Definition: IFunctionNode.h:40
Definition: Main.h:22
std::vector< PMTNoiseROI * > PMT_ROIs
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
Definition: statistics.h:55
WireCell::ITrace::vector tagged_traces(WireCell::IFrame::pointer frame, WireCell::IFrame::tag_t tag)
Json::Value Configuration
Definition: Configuration.h:50
std::vector< int > & get_peaks()
Definition: PMTNoiseROI.h:23
void insert_vwires(int wire_no, float peak_height)
Definition: PMTNoiseROI.cxx:37
const char * cs
virtual WireCell::Configuration default_configuration() const
Optional, override to return a hard-coded default configuration.
std::vector< size_t > trace_list_t
Definition: IFrame.h:36
Thrown when a wrong key or has been encountered.
Definition: Exceptions.h:43