AlcapDAQ  1
TOctalFADCIsland.cpp
Go to the documentation of this file.
1 #include "TOctalFADCIsland.h"
2 #include "Parameters.h"
3 #include <algorithm>
4 #include <iostream>
5 #include <cmath>
6 #include <math.h>
7 #include <TH1I.h>
8 #include <TF1.h>
9 
10 extern OCTALFADC_PARAM octalfadc_parameters;
11 
12 using std::cout; using std::cerr; using std::endl;
13 using std::vector;
14 
15 int TOctalFADCIsland::GetMax(int first, int last) const
16 {
17  if(last < first || last >= fData.size() || first < 0){
18  cerr << "TOctalFADCIsland::GetMax() : Error! arguments out of range." << endl;
19  }
20  // max_element returns an iterator to the maximum element in the range.
21  return *(std::max_element(fData.begin() + first, fData.begin() + last + 1));
22 }
23 
24 int TOctalFADCIsland::GetMaxBin(int first, int last) const
25 {
26  if(last < first || last >= fData.size() || first < 0)
27  {
28  cout << "first = " << first << " last : " << last << " size : " << fData.size() << endl;
29  cerr << "TOctalFADCIsland::GetMaxBin() : Error! arguments out of range." << endl;
30  }
31  //cout << "(good one) first = " << first << " last : " << last << " size : " << fData.size() << endl;
32  // vector iterators obey pointer arithmetic - the subtraction gives the index
33  return std::max_element(fData.begin()+first,fData.begin()+last+1)
34  - fData.begin();
35 
36 }
37 
38 
39 double TOctalFADCIsland::GetAverageMax(int nAv, int first, int last) const
40 {
41  if(last < first || last >= fData.size() || first < 0 || nAv < 0){
42  cerr << "TOctalFADCIsland::GetAverageMax() : Error! arguments out of range." << endl;
43  }
44 
45  int maxbin = GetMaxBin(first,last);
46  int sum = *(std::max_element(fData.begin()+first,fData.begin()+last+1));
47  int skipped = 0;
48  int ind;
49 
50  for(int i = 1; i <= nAv; i++)
51  {
52  ind = maxbin + static_cast<int>((i/2.+ 0.5)*pow(-1,i));
53  if(ind > first && ind < last){sum = sum + fData[ind];}
54  else{skipped++;}
55  }
56 
57  return static_cast<double>(sum)/(nAv+1.-skipped);
58 }
59 
60 
61 
62 int TOctalFADCIsland::GetMaxBinBlockTime(int first, int last) const
63 {
64  if(last < first || last >= fData.size() || first < 0){
65  cerr << "TOctalFADCIsland::GetMaxBinBlockTime() : Error! arguments out of range." << endl;
66  }
67  return GetTime() + GetMaxBin(first,last);
68 }
69 
70 int TOctalFADCIsland::GetCFBlockTime(int first, int last) const //
71 {
72  if(last < first || last >= fData.size() || first < 0){
73  cerr << "TOctalFADCIsland::GetCFBlockTime() : Error! arguments out of range."
74  << endl;
75  }
76  return GetCFBin(first,last)+GetTime();
77 }
78 
79 int TOctalFADCIsland::GetCFBin(int first, int last) const //Will miss a bit if there is a overflow of the FADC. If the timing of high energy signals becomes an issue, this algorithm will have to be come a little bit more sofisticated
80 {
81  if(last < first || last >= fData.size() || first < 0){
82  cerr << "TOctalFADCIsland::GetCFBlockTime() : Error! arguments out of range." << endl;
83 
84  }
85 
86  int max = GetMax(first,last)-fData[first];//taken the non zero pedestal into account
87  int maxbin = GetMaxBin(first,last);
88  double halfmax = max/2.;
89  int constantFraction = first;
90  double value = -1.;
91 
92  while( value < halfmax && constantFraction < maxbin)
93  {
94  value = static_cast<double>(fData[constantFraction]);
95  constantFraction++;
96  }
97 
98  return constantFraction;
99 }
100 
101 double TOctalFADCIsland::GetAverage(int first, int last) const
102 {
103  if(last < first ){return -1.;}
104  if(first<0){first=0;}
105  if(last >= fData.size()){last = fData.size();}
106 
107  int sum = 0;
108  int N = 0;
109 
110  for(int i = first; i <= last; i++)
111  {
112  sum += fData[i];
113  N += 1;
114  }
115 
116  return static_cast<double>(sum)/N;
117 }
118 
119 
121 {
122  double period = octalfadc_parameters.kClockPeriod[fChannel];
123  return fTime*period;
124 }
125 
126 double TOctalFADCIsland::GetIntegral(int first, int last) const
127 {
128  if(last < first ){return -1.;}
129  if(first<0){first=0;}
130  if(last >= fData.size()){last = fData.size();}
131 
132  int sum = 0;
133 
134  for(int i = first; i <= last; i++)
135  {
136  sum += fData[i];
137  }
138 
139  return static_cast<double>(sum);
140 }
141 
142 
143 
144 //this is optimized for a Ge detector!
145 bool TOctalFADCIsland::GoodPulse(int shapTime, double clockPeriod, int level) // Do not reject pulse with noisy spikes, just tag them in the hits object
146 {
147  int secondSample = 1;
148  int oneButLast = fData.size() - 1;
149  int maxbin = GetMaxBin();
150  int channel = GetFADCChannel();
151  int threshold = octalfadc_parameters.threshold[channel];
152 
153  if(fData.size()*clockPeriod < static_cast<double>(shapTime) && level >= 1){SetPulseQuality(1);return false;} //A good pulse is longer then the shaping time. For a non-shaped PMT pulse you just can send the width,
154 
155  //This doesn`t work so well. Energy samples which are missing a piece, but have a nice maximum, are not accepted. Also good timing pulses with an undershoot don`t make it.
156  //else if( abs(fData[secondSample] - fData[oneButLast] ) > 50 && level >= 2){return false;} //The first and the last few samples should be about the same value. "50" is somewhat arbitary
157 
158  //Alternative: asking that the maximum doesn`t set at the edge (12.5% on each side) of the island
159  else if( ( static_cast<double>(maxbin) < fData.size()/12. || static_cast<double>(maxbin) > 11*fData.size()/12. ) && level >=2) { SetPulseQuality(2);return false;}
160 
161  else if( ( GetMax() < threshold && level >=3 )) {SetPulseQuality(3);return false;}
162 
163  else if( abs(*(std::max_element(fData.begin(), fData.begin() + fData.size())) - *(std::max_element(fData.begin(), fData.begin() + fData.size()) + 1)) > 50 && level >= 4){SetPulseQuality(4);return false;} //eleminating spikes, again the "50" is arbitary. Might be dangerous for very sharp PMT pulses
164 
165  else{SetPulseQuality(0);return true;}
166 
167 }
168 
169 // This method is customized for the run4 Ge datasets
170 bool TOctalFADCIsland::GoodPulse(int shapTime, double clockPeriod, int ped, int runnr, int level, int channel)
171 {
172  int secondSample = 1;
173  int oneButLast = fData.size() - 1;
174  int maxbin = GetMaxBin();
175  double max = static_cast<double>(GetMax());
176  double leftAv = GetAverage(maxbin-40,maxbin-30);
177  double rightAv = GetAverage(maxbin+30,maxbin+40);
178  double totalAv = GetAverage();
179  double pedestal = static_cast<double>(ped);
180 
181  double ampCut_a = 0;
182  double ampCut_b = 0;
183  double avCut_a = 1.;
184  double avCut_b = 0.;//"_a" is for the Drop Maximum method, "_b" is for the Island Average method
185 
186  if((runnr >= 51683) &&(runnr <= 51984))
187  {
188  if(channel == 1){ampCut_a = 2500; avCut_a = 0.04; ampCut_b = 2700; avCut_b = 0.75;} //channel 1 = HG, channel 2 = LG
189  if(channel == 2){ampCut_a = 1380; avCut_a = 0.032; ampCut_b = 1385; avCut_b = 0.975;}
190  }
191  if((runnr >= 51985) &&(runnr <= 52280))
192  {
193  if(channel == 1){ampCut_a = 2500; avCut_a = 0.04; ampCut_b = 2500; avCut_b = 0.8;}
194  if(channel == 2){ampCut_a = 1500; avCut_a = 0.022; ampCut_b = 1510; avCut_b = 0.935;}
195  //if(channel == 2){ampCut_a = 1500; avCut_a = 0.022; ampCut_b = 1510; avCut_b = 0.935;}
196  }
197 
198  if(fData.size()*clockPeriod < static_cast<double>(shapTime) && level >= 1){SetPulseQuality(1);return false;} //A good pulse is longer then the shaping time. For a non-shaped PMT pulse you just can send the width,
199 
200  //This doesn`t work so well. Energy samples which are missing a piece, but have a nice maximum, are not accepted. Also good timing pulses with an undershoot don`t make it.
201  //else if( abs(fData[secondSample] - fData[oneButLast] ) > 50 && level >= 2){return false;} //The first and the last few samples should be about the same value. "50" is somewhat arbitary
202 
203  //Alternative: asking that the maximum doesn`t set at the edge (12.5% on each side) of the island
204  else if( ( static_cast<double>(maxbin) < fData.size()/12. || static_cast<double>(maxbin) > 11*fData.size()/12. ) && level >=2){ SetPulseQuality(2);return false;}
205 
206  else if( abs(*(std::max_element(fData.begin(), fData.begin() + fData.size())) - *(std::max_element(fData.begin(), fData.begin() + fData.size()) + 1)) > 50 && level >= 3){SetPulseQuality(3);return false;} //eleminating spikes, again the "50" is arbitary. Might be dangerous for very sharp PMT pulses
207 
208  //This checks if the pulse drops fast enough next to the maximum
209  else if( level >=4 && ( fabs((leftAv - max)/(max - pedestal)) < avCut_a && max > ampCut_a) ){SetPulseQuality(4);return false;}
210  else if( level >=4 && ( fabs((rightAv - max)/(max - pedestal)) < avCut_a && max > ampCut_a) ){SetPulseQuality(4);return false;}
211 
212  //checks if the Average (~integral) is consistent with the amplitude
213  else if( level >=5 && ( totalAv/max > avCut_b && max > ampCut_b ) ) {SetPulseQuality(5);return false;}
214 
215 
216  else{SetPulseQuality(0);return true;}
217 //printf("max = %f,avCut_a = %f, ampCut_a = %f, Figure of Merit (R) = %f\n",max ,avCut_a,ampCut_a,fabs((rightAv - max)/(max - pedestal)));
218 //printf("max = %f, avCut_a = %f, ampCut_a = %f, Figure of Merit (L) = %f\n",max ,avCut_a,ampCut_a,fabs((leftAv - max)/(max - pedestal)));
219 //printf("Max = %f, Pedestal = %f, LeftAv = %f, Figure of merit = %f \n", max,pedestal,leftAv,fabs((leftAv - max)/(max - pedestal)) );printf("Max = %f, Pedestal = %f, RightAv = %f, Figure of merit = %f \n", max,pedestal, rightAv,fabs((rightAv - max)/(max - pedestal)) );
220 
221 }
222 
223 int TOctalFADCIsland::FitGauss(int left, int right, int shapTime, double clockPeriod, int pedestal)
224 {
225  int size = fData.size();
226  if( GetMaxBin() - left < 1) { return 0; }
227  if(GetMaxBin() + right > size -1) { return 0; }
228 
229  TH1I* hIsland = new TH1I("hIsland","The OctalFADCIsland as a Histogram instead of a vector",size,0,size);
230  for(int i = 0; i<size; i++) { hIsland->SetBinContent(i+1,fData[i]);}
231 
232  TF1* myG = new TF1("myG", "gaus(0)+[3]", GetMaxBin()-left,GetMaxBin()+right);
233  myG->SetParLimits(1, left+1., right-1.);
234  myG->SetParLimits(2, shapTime/(4.*clockPeriod), (shapTime*4.)/clockPeriod);
235  myG->FixParameter(3, pedestal*1.);
236  //myG->SetParLimits(3,octalfadc_parameters.pedestalGeHighGainchannel-500,octalfadc_parameters.pedestalGeHighGainchannel+100);
237 
238  hIsland->Fit("myG","RQ");
239 
240  double chiSqr = myG->GetChisquare();
241  double maxbin = myG->GetParameter(1);
242  double max = myG->GetMaximum();
243  int NDF = myG->GetNDF();
244 
245  SetChiSqrRed(chiSqr/NDF);
246  SetMaxBinGauss (maxbin);
247  SetMaxGauss(max);
248 
249  //printf("Size = %d Pulse Quality = %d Chi Sqr = %.1f NDF = %d Fitted amp = %f Amplitude = %d \n", size, GetPulseQuality(), myG->GetChisquare(), myG->GetNDF(),max,GetMax());
250 
251  delete hIsland;
252  delete myG;
253 
254  if(chiSqr/NDF > 5.){ return 0; }
255 
256  return 1;
257 }
258 
259