Diana Software
QPulseBasicParams.cc
Go to the documentation of this file.
1 #include "QPulseBasicParams.hh"
2 #include <math.h>
3 #include "TMath.h"
4 
5 using namespace Diana;
6 
7 QPulseBasicParams::QPulseBasicParams(const QVector& pulse, int triggerPosition, double baseline,double baselineRMS, int ADCMax, int ADCMin, int samplingFreq)
8 
9 {
10  fSamplingFreq = samplingFreq;
11  fBaseline = baseline;
12  fBaselineRMS = baselineRMS;
13  fTriggerPosition = triggerPosition;
14  FindMaximumPosition(pulse);
15  ComputeHeight(pulse);
16  FindEnd(pulse, 30,3);
17  FindStart(pulse,60);
18 // ComputeRaise(pulse,10,90);
19 // ComputeDecay(pulse,90,10);
20  ComputeDecayAndRise(pulse,7,0.1,0.9,0.3);
21  ComputeSlowDecay(pulse,7,0.3,0.1);
22  CheckSaturation(pulse, ADCMax, ADCMin);
23 }
24 
25 QPulseBasicParams::QPulseBasicParams(int triggerPosition, double baseline, double baselineRMS, int samplingFreq)
26 {
27  fSamplingFreq = samplingFreq;
28  fBaseline = baseline;
29  fBaselineRMS = baselineRMS;
30  fTriggerPosition = triggerPosition;
31 }
32 
34 {
36  // size_t window = 10;
37  int window = fTriggerPosition/2;
38  int size = (int) pulse.Size();
39  int from = fTriggerPosition-window;
40  double baseline = pulse.GetMean(TMath::FloorNint(0.8*fTriggerPosition));
41  QVector temp = pulse - baseline;
42  if(from < 0){
43  return QERR_OUT_OF_RANGE;
44  }
45  if((from+2*window)>=size){
46  return QERR_OUT_OF_RANGE;
47  }
48  //int currMax = -1, prevMax = -1;
49  //double prevMaxValue = -1e20, currMaxValue = -1e20;
50 
51  /*while(from+window < size){
52  currMax = pulse.GetMaxIndex(window,from);
53  currMaxValue = pulse[currMax];
54  if(currMaxValue < prevMaxValue) break;
55  else {
56  prevMaxValue = currMaxValue;
57  prevMax = currMax;
58  }
59  from += window;
60  }*/
61 
62  fMaxPos = (double)temp.Abs().GetMaxIndex(2*window,from);
63  //fMaxPos =(double) prevMax;
64  return err;
65 }
66 
67 
69 {
71  if(fMaxPos >= 0. && fMaxPos < pulse.Size())
72  fHeight = double(pulse[(size_t)lround(fMaxPos)] - fBaseline);
73  else fHeight = Q_DOUBLE_DEFAULT;
74  return err;
75 }
76 
77 QError QPulseBasicParams::FindEnd(const QVector& pulse, size_t meansize, double nBaseRMS)
78 {
80  size_t fNPoints = pulse.Size();
81  double temp=0;
82  if( fNPoints > 1000) {
83  meansize = meansize*2;
84  }
85  size_t bufsize=(fNPoints)/2;
86  double* binbuf = (double*) malloc(bufsize*sizeof(double));
87 
88  //fill buffer with mean of meansize subsequent
89  for (size_t i=0; i<bufsize; i++) {
90  binbuf[i]=0;
91  for (size_t j=0; j<meansize; j++) {
92  if ((fNPoints-bufsize+i+j)< fNPoints) {
93  temp = pulse[(fNPoints-bufsize)+i+j];
94  binbuf[i]+= temp;
95  }
96  else binbuf[i]+=temp;
97  }
98  binbuf[i]/=meansize;
99  }
100 
101  // compute fit end
102  fEnd = fNPoints - 1;
103  for (int i = bufsize-1; i>=0; i--)
104  if ((binbuf[i]-fBaseline) > nBaseRMS*fBaselineRMS) {
105  fEnd= (fNPoints-bufsize) + i ;
106  break;
107  }
108  free(binbuf);
109  return err;
110 }
111 
112 QError QPulseBasicParams::FindStart(const QVector& pulse, int bufsize)
113 {
114  double binv;
115  QError Err = QERR_SUCCESS;
116  double binbuf[bufsize];;
117  int maxbin = (int)fMaxPos;
118  fStart = 0;
119  if (maxbin<bufsize){ //if the maximum is in the pretrigger region
120  Err= QERR_UNKNOWN_ERR;
121  return Err;
122  }
123  for(int i = maxbin; i > maxbin - bufsize; i--){
124  binv = pulse[i] - fBaseline;
125  binbuf[i - (maxbin - bufsize) - 1] = binv;
126  }
127  if(fBaselineRMS == 0) fBaselineRMS = 1;
128  for(int i = maxbin - bufsize; i > 0; i--){
129  for(int j = bufsize - 1; j > 0; j--) {
130  binbuf[j] = binbuf[j-1];
131  }
132  binbuf[0] = pulse[i] - fBaseline;
133  if( binbuf[bufsize - 1] <= binbuf[0] + 2*fBaselineRMS && binbuf[bufsize - 1] >= binbuf[0] - 2*fBaselineRMS ){
134  fStart = i + bufsize -1;
135  Err = QERR_SUCCESS;
136  break;
137  }
138  }
139  return Err;
140 }
141 
142 QError QPulseBasicParams::ComputeRaise(const QVector& pulse, double percLow,double percHigh)
143 {
145  int t1 = (int)fStart;
146  int t2 = (int)fMaxPos;
147  for(int t = int(fStart)+1; t < fMaxPos; t++) {
148  if((pulse[t] - fBaseline) < percLow*fHeight/100) t1 = t;
149  if((pulse[t] - fBaseline) < percHigh*fHeight/100) t2 = t;
150  }
151  fRaise = t2 - t1;
152  return err;
153 }
154 
155 QError QPulseBasicParams::ComputeDecay(const QVector& pulse, double percHigh,double percLow)
156 {
158  int t1 = (int)fMaxPos;
159  int t2 = (int)fEnd;
160  for(int t = int(fMaxPos)+1; t < fEnd; t++) {
161  if((pulse[t] - fBaseline) > percHigh*fHeight/100) t1 = t;
162  if((pulse[t] - fBaseline) > percLow*fHeight/100) t2 = t;
163  }
164  fDecay = t2 - t1;
165  return err;
166 }
167 
168 QError QPulseBasicParams::CheckSaturation(const QVector& pulse, int ADCMax, int ADCMin)
169 {
171 
172 // double ADCMax = 65534.5;
173 // double ADCMin = 0.5;
174 
175  ADCMax -= 1;
176  ADCMin += 1;
177 
178  fIsSaturatedHigh=false;
179  fIsSaturatedLow=false;
180  double max = pulse.GetMax();
181  double min = pulse.GetMin();
182 
183  if(max > ADCMax) fIsSaturatedHigh=true;
184  if(min < ADCMin) fIsSaturatedLow=true;
185  return err;
186 }
187 
188 QError QPulseBasicParams::ComputeDecayAndRise(const QVector& pulse, int smoothingSize, float fracMin, float fracMax,float fracMinDecay)
189 {
191  double RT, DT;
192  QVector smoothed = pulse;
193 
194  int size = smoothed.Size();
195 
196  int num = smoothingSize;
197  for(int i=0;i<size;i++)
198  {
199  int n=num;
200  smoothed[i]*=num;
201  for(int k=1;k<=(num-1)/2;k++) {
202  if((i-k)>=0)
203  {
204  smoothed[i]+=pulse[i-k]*(num-2*k);
205  n+=num-2*k;
206  }
207  if((i+k)<size)
208  {
209  smoothed[i]+=pulse[i+k]*(num-2*k);
210  n+=num-2*k;
211  }
212  }
213  smoothed[i]/=n;
214  smoothed[i]-=fBaseline;
215  }
216 
217  // Rise
218  double max = fHeight;
219  int max_pos=(int) fMaxPos;
220  int n = 0;
221  double x1 = 0,x0 = 0;
222  bool times1 = false;
223  RT = 0;
224  if(max_pos>=0.) {
225  for(n = max_pos; n >= 0; n--) {
226  if(smoothed[n]<max*fracMax &&times1==false) {
227  x1=n+(max*fracMax-smoothed[n])/(smoothed[n+1]-smoothed[n]);
228  times1=true;
229  }
230  if(smoothed[n]<max*fracMin) {
231  x0=n+(max*fracMin-smoothed[n])/(smoothed[n+1]-smoothed[n]);
232  break;
233  }
234  }
235  if(n!=0) RT=(x1-x0);
236  }
237 
238 
239  // Decay
240  times1=false;
241  x1=x0=0;
242 
243  DT = 0;
244  if(max_pos != size-1 && max_pos >= 0.) {
245  for(n=max_pos;n<size;n++) {
246  if(smoothed[n]<max*fracMax &&times1==false) {
247  x1=n-1+((max*fracMax-smoothed[n-1])/(smoothed[n]-smoothed[n-1]));
248  times1=true;
249  }
250  if(smoothed[n]<max*fracMinDecay &&times1==true) {
251  x0=n-1+((max*fracMinDecay-smoothed[n-1])/(smoothed[n]-smoothed[n-1]));
252  break;
253  }
254  }
255  if(n!=size) DT=(x0-x1);
256  }
257  fDecay = DT;
258  fRaise = RT;
259  return err;
260 }
261 QError QPulseBasicParams::ComputeSlowDecay(const QVector& pulse, int smoothingSize, float fracMax,float fracMinDecay)
262 {
264  double DT;
265  QVector smoothed = pulse;
266 
267  int size = smoothed.Size();
268 
269  int num = smoothingSize;
270  for(int i=0;i<size;i++)
271  {
272  int n=num;
273  smoothed[i]*=num;
274  for(int k=1;k<=(num-1)/2;k++) {
275  if((i-k)>=0)
276  {
277  smoothed[i]+=pulse[i-k]*(num-2*k);
278  n+=num-2*k;
279  }
280  if((i+k)<size)
281  {
282  smoothed[i]+=pulse[i+k]*(num-2*k);
283  n+=num-2*k;
284  }
285  }
286  smoothed[i]/=n;
287  smoothed[i]-=fBaseline;
288  }
289 
290  // Decay
291  double max = fHeight;
292  int max_pos=(int) fMaxPos;
293  int n = 0;
294  double x1 = 0,x0 = 0;
295  bool times1 = false;
296 
297  DT = 0;
298  if(max_pos != size-1 && max_pos >= 0.) {
299  for(n=max_pos;n<size;n++) {
300  if(smoothed[n]<max*fracMax &&times1==false) {
301  x1=n-1+((max*fracMax-smoothed[n-1])/(smoothed[n]-smoothed[n-1]));
302  times1=true;
303  }
304  if(smoothed[n]<max*fracMinDecay &&times1==true) {
305  x0=n-1+((max*fracMinDecay-smoothed[n-1])/(smoothed[n]-smoothed[n-1]));
306  break;
307  }
308  }
309  if(n!=size) DT=(x0-x1);
310  }
311  fSlowDecay = DT;
312  return err;
313 }
double max
Definition: CheckOF.C:53
err
Definition: CheckOF.C:114
#define Q_DOUBLE_DEFAULT
Definition: QDiana.hh:24
@ QERR_UNKNOWN_ERR
Definition: QError.hh:108
@ QERR_OUT_OF_RANGE
Definition: QError.hh:28
@ QERR_SUCCESS
Definition: QError.hh:27
double min(const Diana::QVector &v)
Definition: QVector.cc:878
error class with error type and description
Definition: QError.hh:115
QError FindEnd(const Diana::QVector &pulse, size_t meansize, double nBaseRMS)
QPulseBasicParams(int triggerPosition, double baseline, double baselineRMS, int samplingFreq=1000)
QError FindMaximumPosition(const Diana::QVector &pulse)
QError ComputeRaise(const Diana::QVector &pulse, double percLow, double percHigh)
QError ComputeHeight(const Diana::QVector &pulse)
QError ComputeDecay(const Diana::QVector &pulse, double percHigh, double percLow)
QError ComputeDecayAndRise(const Diana::QVector &pulse, int smoothingSize, float fracMin, float fracMax, float fracMinDecay)
QError CheckSaturation(const Diana::QVector &pulse, int ADCMax, int ADCMin)
QError ComputeSlowDecay(const Diana::QVector &pulse, int smoothingSize, float fracMax, float fracMinDecay)
QError FindStart(const Diana::QVector &pulse, int bufsize)
the Diana namespace is needed because sometimes we use Qt libraries, that use same class names of our...