AdcDPhase3x1x1RoiBuilder_tool.cc
Go to the documentation of this file.
1 // AdcDPhase3x1x1RoiBuilder_tool.cc
2 // christoph.alt@cern.ch
3 
4 //********************************
5 // This code determines ROI that should be excluded from coherent noise removal
6 //
7 // A ROI is defined when three criteria are met:
8 // 1. a minimum number of consecutive bins above a relatively low threhsold -> temporary ROI
9 // 2. inside temporary ROI: a minimum number of consecutive bins above a medium threshold
10 // 3. inside temporary ROI: at least one bin above a high threshold
11 //
12 // All thresholds are relative to 0. Threshold 1 and 2 can be expressed
13 // both in absolute ADC counts or as multiples of the standard deviation.
14 // The standard deviation is calculated once for the first "BinsToAverageForRMS" ticks
15 //
16 //********************************
17 
19 #include <iostream>
20 #include <algorithm>
21 #include <sstream>
22 #include <iomanip>
24 
25 using std::vector;
26 using std::string;
27 using std::ostream;
28 using std::cout;
29 using std::endl;
30 using std::setw;
31 
32 //**********************************************************************
33 // Class methods.
34 //**********************************************************************
35 
37  m_LogLevel(ps.get<int>("LogLevel")),
38  m_BinsToAverageForRMS(ps.get<AdcIndex>("BinsToAverageForRMS")),
39  m_BinsToSkip(ps.get<AdcIndex>("BinsToSkip")),
40  m_UseStandardDeviation(ps.get<bool>("UseStandardDeviation")),
41  m_NConsecBinsAboveThreshold1(ps.get<AdcIndex>("NConsecBinsAboveThreshold1")),
42  m_NSigmaStart1(ps.get<AdcSignal>("NSigmaStart1")),
43  m_NSigmaEnd1(ps.get<AdcSignal>("NSigmaEnd1")),
44  m_NConsecBinsAboveThreshold2(ps.get<AdcIndex>("NConsecBinsAboveThreshold2")),
45  m_NSigmaStart2(ps.get<AdcSignal>("NSigmaStart2")),
46  m_NSigmaMax(ps.get<AdcSignal>("NSigmaMax")),
47  m_PadLow(ps.get<AdcIndex>("PadLow")),
48  m_PadHigh(ps.get<AdcIndex>("PadHigh")) {
49  const string myname = "AdcDPhase3x1x1RoiBuilder::ctor: ";
50  if ( m_LogLevel > 0 ) {
51  cout << myname << " Configuration: " << endl;
52  cout << myname << " LogLevel: " << m_LogLevel << endl;
53  cout << myname << " BinsToAverageForRMS: " << m_BinsToAverageForRMS << endl;
54  cout << myname << " BinsToSkip: " << m_BinsToSkip << endl;
55  cout << myname << " UseStandardDeviation: " << m_UseStandardDeviation << endl;
56  cout << myname << " NConsecBinsAboveThreshold1: " << m_NConsecBinsAboveThreshold1 << endl;
57  cout << myname << " NSigmaStart1: " << m_NSigmaStart1 << endl;
58  cout << myname << " NSigmaEnd1: " << m_NSigmaEnd1 << endl;
59  cout << myname << " NConsecBinsAboveThreshold2: " << m_NConsecBinsAboveThreshold2 << endl;
60  cout << myname << " NSigmaStart2: " << m_NSigmaStart2 << endl;
61  cout << myname << " NSigmaMax: " << m_NSigmaMax << endl;
62  cout << myname << " PadLow: " << m_PadLow << endl;
63  cout << myname << " PadHigh: " << m_PadHigh << endl;
64  }
65 }
66 
67 //**********************************************************************
68 
69 
71 }
72 
73 //**********************************************************************
74 
76  const string myname = "AdcDPhase3x1x1RoiBuilder:build: ";
77  if ( m_LogLevel >= 2 ) cout << myname << "Building ROIs for channel "
78  << data.channel() << "." << endl;
79  data.rois.clear();
80 
81  //Create dummy DataMap to return
82  DataMap res(0);
83  res.setInt("Test", 0);
84 
85  //Raw ADC.
86  AdcSignalVector sigs;
87  sigs = data.samples;
88 
89  // Build ROIS before padding and merging.
90  AdcFilterVector& signal = data.signal;
91  AdcRoiVector& rois = data.rois;
92  signal.clear();
93  signal.resize(sigs.size(), false);
94  bool inroi = false;
95  AdcSignal siglow1 = m_NSigmaEnd1;
96  AdcSignal sighigh1 = m_NSigmaStart1;
97  AdcSignal sighigh2 = m_NSigmaStart2;
98  AdcSignal sigmax = m_NSigmaMax;
99  AdcIndex nsig = sigs.size();
100 
101  int ROICount=0;
102  std::vector<AdcIndex> ROIStart;
103  std::vector<AdcIndex> ROIEnd;
104  ROIStart.clear();
105  ROIEnd.clear();
106 
107  if ( nsig < 1 ) {
108  if ( m_LogLevel >= 2 ) cout << myname << "Channel " << data.channel()
109  << " has no samples." << endl;
110  return res;
111  }
112 
113  //*****************************************
114  // FIRST ITERATION: BIN 0 TO LAST BIN ***
115  //*****************************************
116  double SumADCMinusPedestalSquared=0.;
117  double StandardDeviationPedestal=0.;
118 
119  //Calculate standard deviation for first m_BinsToAverageForRMS ticks
121  {
122  for ( AdcIndex isig=m_BinsToSkip; isig<m_BinsToAverageForRMS+m_BinsToSkip; ++isig )
123  {
124  SumADCMinusPedestalSquared+=pow(sigs[isig],2);
125  }
126  StandardDeviationPedestal = sqrt(SumADCMinusPedestalSquared/(m_BinsToAverageForRMS-1));
127  siglow1 = m_NSigmaEnd1*StandardDeviationPedestal;
128  sighigh1 = m_NSigmaStart1*StandardDeviationPedestal;
129  sighigh2 = m_NSigmaStart2*StandardDeviationPedestal;
130  }
131 
132  for ( AdcIndex isig = m_BinsToAverageForRMS+m_BinsToSkip; isig<sigs.size(); ++isig )
133  {
134  AdcSignal sig = sigs[isig];
135  if ( inroi )
136  {
137  if ( sig > siglow1 && isig < sigs.size()-1)
138  {
139  signal[isig] = true;
140  }
141  else
142  {
143  ROIEnd.push_back(isig-1);
144  ROICount++;
145 
146  //check second criterion in this temporary ROI.
147  bool KeepThisROI = false;
148  AdcIndex m_NConsecBinsAboveThreshold2Temp = std::min(m_NConsecBinsAboveThreshold2,(AdcIndex)(ROIEnd[ROICount-1]-ROIStart[ROICount-1]+1));
149  AdcIndex NConsecBinsAboveThreshold2Count=0;
150 
151  for(AdcIndex isigroi = ROIStart[ROICount-1]; isigroi <= ROIEnd[ROICount-1]; isigroi++)
152  {
153  if( sigs[isigroi] >= sighigh2 )
154  {
155  NConsecBinsAboveThreshold2Count++;
156  if(NConsecBinsAboveThreshold2Count == m_NConsecBinsAboveThreshold2Temp)
157  {
158  KeepThisROI = true;
159  break;
160  }
161  }
162  else
163  {
164  NConsecBinsAboveThreshold2Count = 0;
165  }
166  }
167 
168  //if second criterion for this temporary ROI is met, check third criterion
169  if(KeepThisROI)
170  {
171  KeepThisROI = false;
172  for(AdcIndex isigroi = ROIStart[ROICount-1]; isigroi <= ROIEnd[ROICount-1]; isigroi++)
173  {
174  if( sigs[isigroi] >= sigmax )
175  {
176  KeepThisROI = true;
177  break;
178  }
179  }
180  }
181 
182  //if second or third criteria is not met, delete temporary ROI. Otherwise keep it.
183  if(!KeepThisROI)
184  {
185  for(AdcIndex isigroi = ROIStart[ROICount-1]; isigroi <= ROIEnd[ROICount-1]; isigroi++)
186  {
187  signal[isigroi] = false;
188  }
189 
190  ROIStart.pop_back();
191  ROIEnd.pop_back();
192  ROICount--;
193  }
194 
195  inroi = false;
196  }
197  }
198  else
199  {
200  bool ROIStartIsHere = true;
201  for(AdcIndex isignext = isig; isignext < std::min((AdcIndex)sigs.size(),isig+m_NConsecBinsAboveThreshold1); isignext++)
202  {
203  if(sigs[isignext] < sighigh1 )
204  {
205  ROIStartIsHere = false;
206  break;
207  }
208  }
209 
210  if(ROIStartIsHere)
211  {
212  ROIStart.push_back(isig);
213  signal[isig] = true;
214  inroi = true;
215  }
216  }
217  }
218 
219 //removal isolated signal at the end of the waveform
220 if(signal[sigs.size()-1] && !signal[sigs.size()-2])
221 {
222 signal[sigs.size()-1] = false;
223 }
224 
225  //******************************************
226  // SECOND ITERATION: LAST BIN TO BIN 0 ***
227  //******************************************
228  AdcIndex StandardDeviationIndex=sigs.size()-1;
229  AdcIndex StandardDeviationCounter=0;
230  inroi = false;
231  siglow1 = m_NSigmaEnd1;
232  sighigh1 = m_NSigmaStart1;
233  sighigh2 = m_NSigmaStart2;
234 
235  SumADCMinusPedestalSquared=0.;
236  StandardDeviationPedestal=0.;
237 
238  ROIStart.clear();
239  ROIEnd.clear();
240  ROICount=0;
241 
242 
243  //Calculate standard deviation for last m_BinsToAverageForRMS ticks
245  {
246  StandardDeviationCounter=0;
247  StandardDeviationIndex=sigs.size()-1;
248  while(StandardDeviationCounter < m_BinsToAverageForRMS)
249  {
250  if(!signal[StandardDeviationIndex])
251  {
252  SumADCMinusPedestalSquared+=pow(sigs[StandardDeviationIndex],2);
253  StandardDeviationCounter++;
254  }
255  StandardDeviationIndex--;
256  }
257  StandardDeviationPedestal = sqrt(SumADCMinusPedestalSquared/(m_BinsToAverageForRMS-1));
258  siglow1 = m_NSigmaEnd1*StandardDeviationPedestal;
259  sighigh1 = m_NSigmaStart1*StandardDeviationPedestal;
260  sighigh2 = m_NSigmaStart2*StandardDeviationPedestal;
261  }
262 
263 
264  for ( AdcIndex isig = StandardDeviationIndex; isig >= m_BinsToSkip && isig <= StandardDeviationIndex; --isig )
265  {
266  if(signal[isig]) continue;
267  AdcSignal sig = sigs[isig];
268  if ( inroi )
269  {
270  if ( sig > siglow1 && isig > m_BinsToSkip)
271  {
272  signal[isig] = true;
273  }
274  else
275  {
276  ROIEnd.push_back(isig+1);
277  ROICount++;
278 
279  //check second criterion in this temporary ROI.
280  bool KeepThisROI = false;
281  AdcIndex m_NConsecBinsAboveThreshold2Temp = std::min(m_NConsecBinsAboveThreshold2,(AdcIndex)(ROIEnd[ROICount-1]-ROIStart[ROICount-1]+1));
282  AdcIndex NConsecBinsAboveThreshold2Count=0;
283 
284  for(AdcIndex isigroi = ROIStart[ROICount-1]; isigroi >= ROIEnd[ROICount-1]; isigroi--)
285  {
286  if( sigs[isigroi] >= sighigh2 )
287  {
288  NConsecBinsAboveThreshold2Count++;
289  if(NConsecBinsAboveThreshold2Count == m_NConsecBinsAboveThreshold2Temp)
290  {
291  KeepThisROI = true;
292  break;
293  }
294  }
295  else
296  {
297  NConsecBinsAboveThreshold2Count = 0;
298  }
299  }
300 
301  //if second criterion for this temporary ROI is met, check third criterion
302  if(KeepThisROI)
303  {
304  KeepThisROI = false;
305  for(AdcIndex isigroi = ROIStart[ROICount-1]; isigroi >= ROIEnd[ROICount-1]; isigroi--)
306  {
307  if( sigs[isigroi] >= sigmax )
308  {
309  KeepThisROI = true;
310  break;
311  }
312  }
313  }
314 
315  //if second or third criteria is not met, delete temporary ROI. Otherwise keep it.
316  if(!KeepThisROI)
317  {
318  for(AdcIndex isigroi = ROIStart[ROICount-1]; isigroi >= ROIEnd[ROICount-1]; isigroi--)
319  {
320  signal[isigroi] = false;
321  }
322 
323  ROIStart.pop_back();
324  ROIEnd.pop_back();
325  ROICount--;
326  }
327 
328  inroi = false;
329  }
330  }
331  else
332  {
333  bool ROIStartIsHere = true;
334  for(AdcIndex isignext = isig; isignext >= (AdcIndex)std::max((int)m_BinsToSkip,(int)isig-(int)m_NConsecBinsAboveThreshold1+1) && isignext <= StandardDeviationIndex ; isignext--)
335  {
336  if(sigs[isignext] < sighigh1 )
337  {
338  ROIStartIsHere = false;
339  break;
340  }
341  }
342 
343  if(ROIStartIsHere)
344  {
345  ROIStart.push_back(isig);
346  signal[isig] = true;
347  inroi = true;
348  }
349  }
350  }
351 
352 //removal isolated signal at the beginning of the waveform
353 if(signal[m_BinsToSkip] && !signal[m_BinsToSkip+1])
354 {
355 signal[m_BinsToSkip] = false;
356 }
357 
358  // Fill the unpadded ROIs.
359  data.roisFromSignal();
360  // Display ROIs before padding and merging.
361  if ( m_LogLevel >= 3 ) {
362  cout << myname << " ROIs before merge (size = " << rois.size() << "):" << endl;
363  for ( const AdcRoi& roi : rois ) {
364  cout << myname << setw(8) << roi.first << " " << setw(8) << roi.second << endl;
365  }
366  } else if ( m_LogLevel >= 2 ) {
367  cout << myname << " ROI count before merge: " << data.rois.size() << endl;
368  }
369  if ( rois.size() == 0 ) return res;
370  // Pad ROIs.
371  unsigned int isig1 = 0;
372  unsigned int isig2 = 0;
373  for ( AdcRoi roi : rois ) {
374  isig2 = roi.first;
375  isig1 = isig2 > m_PadLow ? isig2 - m_PadLow : 0;
376  for ( unsigned int isig=isig1; isig<isig2; ++isig ) signal[isig] = true;
377  isig1 = roi.second + 1;
378  isig2 = isig1 + m_PadHigh;
379  if ( isig2 > nsig ) isig2 = nsig;
380  for ( unsigned int isig=isig1; isig<isig2; ++isig ) signal[isig] = true;
381  }
382  // Fill the final ROIs.
383  data.roisFromSignal();
384  // Display final ROIs.
385  if ( m_LogLevel >= 3 ) {
386  cout << myname << " ROIs after merge (size = " << rois.size() << "):" << endl;
387  for ( const AdcRoi& roi : rois ) {
388  cout << myname << setw(8) << roi.first << " " << setw(8) << roi.second << endl;
389  }
390  } else if ( m_LogLevel >= 2 ) {
391  cout << myname << " ROI count after merge: " << data.rois.size() << endl;
392  }
393 
394  return res;
395 }
396 //**********************************************************************
397 
#define DEFINE_ART_CLASS_TOOL(tool)
Definition: ToolMacros.h:42
std::string string
Definition: nybbler.cc:12
float AdcSignal
Definition: AdcTypes.h:21
constexpr T pow(T x)
Definition: pow.h:72
struct vector vector
std::pair< AdcIndex, AdcIndex > AdcRoi
Definition: AdcTypes.h:54
AdcRoiVector rois
void setInt(Name name, int val)
Definition: DataMap.h:131
static int max(int a, int b)
static constexpr double ps
Definition: Units.h:99
unsigned int AdcIndex
Definition: AdcTypes.h:15
AdcDPhase3x1x1RoiBuilder(fhicl::ParameterSet const &ps)
Q_EXPORT QTSManip setw(int w)
Definition: qtextstream.h:331
std::vector< AdcRoi > AdcRoiVector
Definition: AdcTypes.h:55
Channel channel() const
AdcFilterVector signal
std::vector< bool > AdcFilterVector
Definition: AdcTypes.h:27
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
Definition: statistics.h:55
std::vector< AdcSignal > AdcSignalVector
Definition: AdcTypes.h:22
auto const & get(AssnsNode< L, R, D > const &r)
Definition: AssnsNode.h:115
int bool
Definition: qglobal.h:345
AdcSignalVector samples
QTextStream & endl(QTextStream &s)
DataMap update(AdcChannelData &acd) const override