er  dev
ERNeuRadPixelSignal.cxx
1 // -------------------------------------------------------------------------
2 // ----- ERNeuRadPixelSignal source file -----
3 // -------------------------------------------------------------------------
4 
5 #include "ERNeuRadPixelSignal.h"
6 
7 #include "TMath.h"
8 
9 #include <iostream>
10 
11 const Double_t ERNeuRadPixelSignal::cdT = 0.1; // ns
12 
14  fModuleNb(-1),
15  fPixelNb(-1),
16  fPECount(0),
17  fCurFPoint(0),
18  fStartTime(99999999.),
19  fFinishTime(-1.),
20  fPEAmplitudesSum(0)
21 {
22 }
23 
24 ERNeuRadPixelSignal::ERNeuRadPixelSignal(Int_t iModule, Int_t iPixel, Int_t pe_count, Int_t side):
25  fModuleNb(iModule),
26  fPixelNb(iPixel),
27  fPECount(pe_count),
28  fCurFPoint(0),
29  fStartTime(99999999.),
30  fFinishTime(-1.),
31  fSide(side),
32  fPEAmplitudesSum(0)
33 {
34  fPEAmplitudes.Set(pe_count);
35  fPEAnodeTimes.Set(pe_count);
36  fPETimes.Set(pe_count);
37 }
38 
39 ERNeuRadPixelSignal::~ERNeuRadPixelSignal()
40 {
41 }
42 
43 void ERNeuRadPixelSignal::AddPhotoElectron(ERNeuRadPhotoElectron* pe)
44 {
45  // Добавляет фотоэлектрон к сигналу на PMT
46  fPEAmplitudes[fCurFPoint] = pe->Amplitude();
47  fPEAnodeTimes[fCurFPoint] = pe->AnodeTime();
48  // Вычисление длины фотоэлектронного сигнала в количестве cdT
49  fPETimes[fCurFPoint] = 40.;//OnePETime(pe->Amplitude());
50  // Сдвиг начального и коненого времени общего сигнала
51  if (pe->AnodeTime() < fStartTime) {
52  fStartTime = pe->AnodeTime();
53  }
54 
55  if (pe->AnodeTime()+fPETimes[fCurFPoint]*cdT > fFinishTime) {
56  fFinishTime = pe->AnodeTime()+fPETimes[fCurFPoint]*cdT;
57  }
58 
59  fPEAmplitudesSum+=pe->Amplitude();
60 
61  fCurFPoint++;
62 }
63 
64 void ERNeuRadPixelSignal::Generate()
65 {
66  // Добавление к общему сигналу
67  // Количество узлов во внешнем сигнале
68  Int_t gdTCount = (fFinishTime - fStartTime)/cdT+1;
69  fResFunction = new Float_t[gdTCount];
70 
71  for (Int_t i = 0; i < gdTCount; i++) {
72  fResFunction[i] = 0.;
73  }
74 
75  for (Int_t iPE = 0; iPE < fPECount; iPE++) {
76  // Вычисление функции сигнала в узлах сигнала
77  Float_t *sig_func = new Float_t[fPETimes[iPE]];
78  for (Int_t idT = 0; idT < fPETimes[iPE]; idT++) {
79  sig_func[idT] = OnePEFunction(idT*cdT, fPEAmplitudes[iPE]);
80  }
81 
82  // Сдвиг относительно общего сигнала
83  //@bug Это выражение вносит небольшую погрешность в расчёт стартового времени
84  Int_t shift = (Int_t) ((fPEAnodeTimes[iPE]-fStartTime)/cdT);
85  // Указатель на узел общего сигнала, который соответствует началу сигнала одноэлектрона
86  Float_t *cur_f = fResFunction + shift;
87  // Добавление к общему сигналу
88  for (Int_t idT = 0; idT < fPETimes[iPE]; idT++) {
89  cur_f[idT] += sig_func[idT];
90  }
91  delete [] sig_func;
92  }
93  fResFunctionRoot.Adopt(gdTCount,fResFunction);
94 }
95 
96 Double_t ERNeuRadPixelSignal::OnePEFunction(Double_t time, Double_t amplitude){
97  //Аналитическая функция одноэлектронного сигнала
98  //return 8.*amplitude*time*time*TMath::Exp(-time/0.45);
99  if(time>0) return 8.*amplitude*pow((time+0.22),5)*TMath::Exp(-pow((time+0.22),1.5)/0.4);
100  else return 0;
101 }
102 
103 // Вычисляем время сигнала одноэлектрона в количестве cdT.
104 Int_t ERNeuRadPixelSignal::OnePETime(Double_t amplitude)
105 {
106  Int_t counts = 0;
107  // Насчитываем отрезк времени пока сигнал имеет существенное для нас значение.
108  Bool_t find = kFALSE;
109  Double_t threshold = 0.001;
110  while(1) {
111  Double_t val = OnePEFunction((counts++)*cdT, amplitude);
112  if (!find && val>threshold) {
113  // Сигнал перевалил порог в первый раз
114  find = kTRUE;
115  }
116  if (find && val<threshold) {
117  break;
118  }
119  if (counts > 100) {
120  break;
121  }
122  }
123  return counts-1;
124 }
125 
126 // Возвращает точки пересечения с сигналом порога discriminatorThreshold
127 std::vector<Double_t> ERNeuRadPixelSignal::Intersections(Double_t discriminatorThreshold)
128 {
129  std::vector<Double_t> intersections;
130 
131  Bool_t startIntersect = kFALSE;
132  for (Int_t i = 0; i < fResFunctionRoot.GetSize(); i++) {
133  if (!startIntersect && fResFunctionRoot[i] > discriminatorThreshold) {
134  intersections.push_back(fStartTime + cdT*i);
135  startIntersect = kTRUE;
136  }
137  if (startIntersect && fResFunctionRoot[i] < discriminatorThreshold) {
138  intersections.push_back(fStartTime + cdT*i);
139  startIntersect = kFALSE;
140  }
141  }
142 
143  return intersections;
144 }
145 
146 // Вычисления интеграла сигнала методом трапеций
147 Double_t ERNeuRadPixelSignal::Integ(const Double_t start,const Double_t finish)
148 {
149  if (finish<fStartTime) {
150  return 0;
151  }
152 
153  Double_t res = 0;
154  // Начальная и конечная точки
155  Int_t st = (Int_t)((start-fStartTime)/cdT) + 1;
156  Int_t fn = (Int_t)((finish - fStartTime)/cdT);
157 
158  // Корректируем конечное время на последний узел сигнала
159  if ((fStartTime+fn*cdT) > fFinishTime) {
160  fn = (Int_t)(fFinishTime- fStartTime)/cdT;
161  }
162 
163  // Суммируем трапеции внутри промежутка
164  for(Int_t i = st; i < fResFunctionRoot.GetSize()-1; i++) {
165  res += 0.5*(fResFunctionRoot[i] + fResFunctionRoot[i+1])*cdT;
166  }
167 
168  return res;
169 }
170 
171 // Возвращает интеграл сигнала в окне window, начиная с начального узла сигнала
172 Double_t ERNeuRadPixelSignal::FirstInteg(const Double_t window)
173 {
174  if ((fStartTime + window) > fFinishTime ) {
175  return Integ(fStartTime, fFinishTime);
176  } else {
177  return Integ(fStartTime, fStartTime+window);
178  }
179 }
180 
181 // Возвращает время пересечения сигнала порога peThreshold [количество фотоэлектронов]
182 Float_t ERNeuRadPixelSignal::ThresholdTime(Float_t peThreshold)
183 {
184  Int_t i = 0;
185  while((fResFunctionRoot[i] < peThreshold*OnePEIntegral()) && i < (fResFunctionRoot.GetSize()-1)) {
186  i++;
187  }
188 
189  Int_t prevI = i-1;
190  Int_t lastI = i;
191  Float_t prevT = fStartTime + prevI*cdT;
192  Float_t lastT = fStartTime + lastI*cdT;
193  if (i==fResFunctionRoot.GetSize()-1) {
194  return -1;
195  }
196  return (peThreshold*OnePEIntegral()-fResFunctionRoot[prevI])/(fResFunctionRoot[lastI]-fResFunctionRoot[prevI])*(lastT-prevT)+prevT;
197 }
198 
199 Double_t ERNeuRadPixelSignal::OnePEIntegral()
200 {
201  Double_t res = 0.;
202  for (Int_t i=0; i<39; i++) {
203  res += 0.5*(OnePEFunction(i*cdT,8.) + OnePEFunction((i+1)*cdT,8.))*cdT;
204  }
205  return res;
206 }
207 
208 ClassImp(ERNeuRadPixelSignal)