Diana Software
MPeakDetector.cc
Go to the documentation of this file.
1 #include "MPeakDetector.hh"
2 #include "QEvent.hh"
3 #include "QBaseType.hh"
4 #include "QVector.hh"
5 #include "QVectorI.hh"
6 #include "QPulse.hh"
7 #include "QPulseInfo.hh"
8 #include "QStdVector.hh"
9 #include "QCountPulsesData.hh"
10 #include <algorithm>
11 #include "QFir.hh"
12 #include <cmath>
13 
14 
16 
17 using namespace Diana;
18 using namespace std;
19 
21 {
22  fPulseLabel = GetString("PulseLabel","DAQ@Pulse",false);
23  fThreshold = GetDouble("ThresholdNumberOfSigma", 5);
24  if(fThreshold <= 2) Panic("ThresholdNumberOfSigma must be > 2");
25  fSubSampling = GetInt("SubSampling",5,false);
26  if(fSubSampling < 2) Panic("SubSampling must be > 1");
27 
28  ev.RequireByLabel<QPulse>(fPulseLabel);
29  ev.RequireByLabel<QPulseInfo>("DAQ@PulseInfo");
30 
31  ev.Add<QCountPulsesData>("CountPulsesData");
32 
33  if(fSubSampling > 1) {
34  QCFirData configuration;
35  configuration.fCutoff = 2./(fSubSampling);
36  configuration.fAttDB = 40;
37  configuration.fM = configuration.fAttDB*0.025/configuration.fCutoff;
38  if(configuration.fM%2 == 0) configuration.fM++;
39  configuration.fMethod = QCFirData::KayserBessel;
40  fFir = new QFir(configuration);
41 
42  } else {
43  fFir = 0;
44  }
45 }
46 
48 {
49  const QVector& samples = ev.GetByLabel<QPulse>(fPulseLabel).GetSamples();
50 
51  // number of samples to evaluate the RMS
52  const int minSamples = int(ev.Get<QPulseInfo>("DAQ","PulseInfo").GetMasterSample().GetSampleIndex()*3./4);
53 
54  // find peaks in window
55  vector<int> peakPositions = GetPeaks(samples,minSamples,1);
56  // find peaks in window subsampled by a factor fSubSampling
57  vector<int> peakPositionsSub = GetPeaks(samples,minSamples,fSubSampling);
58 
59  // merge peaks into save vector
60  std::vector<int> save = peakPositions;
61  for(size_t p = 0; p < peakPositions.size(); p++) {
62  int peakPos = peakPositions[p];
63  for(vector<int>::iterator pr = peakPositionsSub.begin(); pr != peakPositionsSub.end(); ) {
64  int peakPosSub = *pr;
65  int delta = abs(peakPosSub - peakPos);
66  if(delta <= 3*fSubSampling) {
67  pr = peakPositionsSub.erase(pr);
68  } else {
69  pr++;
70  }
71  }
72  }
73  for(size_t pr = 0; pr < peakPositionsSub.size(); pr++) {
74  save.push_back(peakPositionsSub[pr]);
75  }
76  std::sort(save.begin(),save.end());
77 
78  // save results to event
79  ev.Get<QCountPulsesData>("CountPulsesData").fNumberOfPulses = save.size();
80  QVector peakpos(save.size());
81  for(size_t i =0; i < save.size(); i++) peakpos[i] = save[i];
82  ev.Get<QCountPulsesData>("CountPulsesData").fTimeIntervals = peakpos;
83 
84 }
85 
87 {
88 }
89 
90 vector<int> MPeakDetector::GetPeaks(const QVector& samples, int minSamples, const size_t red)
91 {
92  QVector samplesReduced;
93  const int numSamples = samples.Size();
94  int offset = 0;
95 
96  if(red > 1) {
97  offset = fFir->GetFilterReduction();
98  QVector filtered;
99  fFir->Filter(samples,filtered);
100  samplesReduced.Resize(samples.Size()/red-offset);
101  samplesReduced.Initialize(0);
102  size_t j = 0;
103  for(int i = 0; i < numSamples; i++) {
104  if( i % red == 0 && j < samplesReduced.Size()) {
105  samplesReduced[j]=filtered[i];
106  j++;
107  }
108  }
109  } else {
110  samplesReduced = samples;
111  }
112 
113  minSamples /= red;
114 
115  QVector derivative = samplesReduced.Derivative3P();
116 
117 // derivative[0]=derivative[derivative.Size()-1]=0.;
118 // derivative[1]=derivative[derivative.Size()-2]=0.;
119  size_t i = 0;
120  double rmsMin = 1e20;
121  while(i < derivative.Size()-minSamples) {
122  double rms = derivative.GetRMS(minSamples,i);
123  if(rms < rmsMin) rmsMin = rms;
124  i += minSamples/2;
125  }
126  double thrrms = fThreshold*rmsMin;
127 
128  vector<int> peakPositions;
129  i = 0;
130  while ( i < derivative.Size() ) {
131  double prevDerivative = derivative[i];
132  int sign = 1;
133  if(prevDerivative < 0) sign = -1;
134 
135  int maxPos = i;
136  if(prevDerivative*sign > thrrms) {
137  i++;
138  // look for maximum
139  while(i < derivative.Size()) {
140  if(derivative[i]*sign < -2*rmsMin) {
141  maxPos = i;
142  break;
143  }
144  i++;
145  }
146  // come back to baseline
147  while (i < derivative.Size()) {
148  if(derivative[i]*sign > (fThreshold-1)*rmsMin) {
149  break;
150  }
151  i++;
152  }
153  peakPositions.push_back(maxPos*red+offset);
154  } else {
155  i++;
156  }
157 
158  }
159 
160  return peakPositions;
161 
162 }
#define REGISTER_MODULE(clazz)
Definition: QDriver.hh:133
Diana::QVector abs(const Diana::QVector &v)
Definition: QVector.cc:811
Module to detect peaks in window alternative to MBCountPulses.
void Init(Diana::QEvent &ev)
Init method.
void Do(Diana::QEvent &ev)
Do method. Declare and implement only one of the two versions.
void Done()
Done method.
std::vector< int > GetPeaks(const Diana::QVector &samples, int minSamples, const size_t red)
Data class for QFir (Ported from Calder)
Definition: QCFirData.hh:14
Method fMethod
Definition: QCFirData.hh:34
double fCutoff
Definition: QCFirData.hh:36
@ KayserBessel
Definition: QCFirData.hh:18
double fAttDB
Definition: QCFirData.hh:37
number of pulses and time interval beetwen peaks in the same acquired window
diana event
Definition: QEvent.hh:46
const Q & GetByLabel(const QEventLabel &label) const
Get a QObject in read mode by label.
Definition: QEvent.hh:135
void RequireByLabel(const QEventLabel &label) const
notify the QEvent that we need a QObject, if not found an exception is thrown
Definition: QEvent.hh:242
void Get(const char *owner, ReadHandle< Q > &handle) const
Get a QObject Handle in read mode.
Definition: QEvent.hh:74
void Add(WriteHandle< Q > &handle)
Add a QObject to the event.
Definition: QEvent.hh:193
QFir FIR low pass filter (Ported from Calder)
Definition: QFir.hh:17
Raw event: bolometer channel, trigger positions and types.
Definition: QPulseInfo.hh:18
const QSampleInfo & GetMasterSample() const
Get MasterSample.
Definition: QPulseInfo.hh:26
Raw event: sampled waveform.
Definition: QPulse.hh:22
Int_t GetSampleIndex() const
Get SampleIndex from the beginning of the waveform.
Definition: QSampleInfo.hh:51
the Diana namespace is needed because sometimes we use Qt libraries, that use same class names of our...