er  dev
ERNeuRadDigitizer.cxx
1 /********************************************************************************
2  * Copyright (C) Joint Institute for Nuclear Research *
3  * *
4  * This software is distributed under the terms of the *
5  * GNU Lesser General Public Licence version 3 (LGPL) version 3, *
6  * copied verbatim in the file "LICENSE" *
7  ********************************************************************************/
8 
9 #include "ERNeuRadDigitizer.h"
10 
11 #include <iostream>
12 #include <algorithm>
13 
14 using std::sort;
15 using std::vector;
16 using std::cerr;
17 using std::endl;
18 using namespace std;
19 
20 #include "TClonesArray.h"
21 #include "TVector3.h"
22 #include "TMath.h"
23 #include "TRandom3.h"
24 #include "TF1.h"
25 
26 #include "FairRootManager.h"
27 #include "FairRunAna.h"
28 #include "FairRuntimeDb.h"
29 
30 #include "EREventHeader.h"
31 
32 const Double_t ERNeuRadDigitizer::cSciFiLightYield= 8000.; // [photons/MeV]
33 const Double_t ERNeuRadDigitizer::cSpeedOfLight = 0.299792458e2; //[cm/ns]
34 const Double_t ERNeuRadDigitizer::cMaterialSpeedOfLight = ERNeuRadDigitizer::cSpeedOfLight/1.58;//[cm/ns]
35 const Double_t ERNeuRadDigitizer::cLightFractionInTotalIntReflection = 0.04;
36 //доля света захватываемая файбером в полное внутренне отражение в каждую сторону.
37 const Double_t ERNeuRadDigitizer::cPixelDelay=6.;//[ns] (H8500)
38 const Double_t ERNeuRadDigitizer::cPixelJitter = 0.4/2.36; //[ns] (H8500)
39 const Double_t ERNeuRadDigitizer::cScincilationTau = 3.2; //[ns]
40 
41 // ----------------------------------------------------------------------------
43  : FairTask("ER NeuRad Digitization scheme"),
44  fPixelJitter(cPixelJitter),
45  fPixelDelay(cPixelDelay),
46  fScincilationTau(cScincilationTau),
47  fPhotoElectronsCreatingTime(0),
48  fPixelSignalCreatingTime(0),
49  fNeuRadSetup(NULL),
50  fNeuRadPoints(NULL),
51  fNeuRadPhotoElectron(NULL),
52  fNeuRadPixelSignal(NULL),
53  fSumAmplitudeF(0),
54  fSumAmplitudeB(0),
55  fPECountF(0),
56  fPECountB(0),
57  fUseCrosstalks(kFALSE)
58 {
59  fPEA = new TF1("fPEA", "ERNeuRadDigitizer::PeFunc", 0., 2000., 7);
60  fPEA->SetParameters(85.8656,30.6158,447.112,447.111,52.,433.,141.);
61  //fPEA->SetParameters(3.2,30.6158,447.112,447.111,52.,433.,141.);
62 }
63 // ----------------------------------------------------------------------------
64 
65 // ----------------------------------------------------------------------------
67  : FairTask("ER NeuRad Digitization scheme ", verbose),
68  fPixelJitter(cPixelJitter),
69  fPixelDelay(cPixelDelay),
70  fScincilationTau(cScincilationTau),
71  fPhotoElectronsCreatingTime(0),
72  fPixelSignalCreatingTime(0),
73  fNeuRadSetup(NULL),
74  fNeuRadPoints(NULL),
75  fNeuRadPhotoElectron(NULL),
76  fNeuRadPixelSignal(NULL),
77  fSumAmplitudeF(0),
78  fSumAmplitudeB(0),
79  fPECountF(0),
80  fPECountB(0),
81  fUseCrosstalks(kFALSE)
82 {
83  fPEA = new TF1("fPEA", ERNeuRadDigitizer::PeFunc, 0., 2000., 7);
84  fPEA->SetParameters(85.8656,30.6158,447.112,447.111,52.,433.,141.);
85  //fPEA->SetParameters(3.2,30.6158,447.112,447.111,52.,433.,141.);
86 }
87 // ----------------------------------------------------------------------------
88 
89 // ----------------------------------------------------------------------------
91 {
92 }
93 // ----------------------------------------------------------------------------
94 
95 // ----------------------------------------------------------------------------
96 void ERNeuRadDigitizer::SetParContainers()
97 {
98  fNeuRadSetup = ERNeuRadSetup::Instance();
99  fNeuRadSetup->SetParContainers();
100 }
101 // ----------------------------------------------------------------------------
102 
103 // ----------------------------------------------------------------------------
105 {
106  // Get input array
107  cout << "Init" << endl;
108  FairRootManager* ioman = FairRootManager::Instance();
109  if ( ! ioman ) Fatal("Init", "No FairRootManager");
110 
111  fNeuRadPoints = (TClonesArray*) ioman->GetObject("NeuRadPoint");
112  if ( ! fNeuRadPoints) Fatal("ERNeuRadDigitizer::Init","No NeuRadPoint Collection");
113 
114  // Register output array NeuRadPhotoElectron and NeuRadDigi
115  fNeuRadPhotoElectron = new TClonesArray("ERNeuRadPhotoElectron",1000);
116  ioman->Register("NeuRadPhotoElectron", "NeuRad photoelectrons", fNeuRadPhotoElectron, kTRUE);
117  fNeuRadPixelSignal = new TClonesArray("ERNeuRadPixelSignal", 1000);
118  ioman->Register("NeuRadPixelSignal", "Signal Pixel", fNeuRadPixelSignal, kTRUE);
119 
120  fNeuRadSetup->Print();
121  return kSUCCESS;
122 }
123 // -------------------------------------------------------------------------
124 
125 // ----- Public method Exec --------------------------------------------
126 void ERNeuRadDigitizer::Exec(Option_t* opt)
127 {
128  fPECountF = 0;
129  fPECountB = 0;
130  fSumAmplitudeF = 0;
131  fSumAmplitudeB = 0;
132 
133  Int_t iEvent =
134  FairRunAna::Instance()->GetEventHeader()->GetMCEntryNumber();
135  std::cout << "Event " << iEvent << std::endl;
136  // Reset entries in output arrays
137  Reset();
138  Int_t nofPixels = fNeuRadSetup->NofPixels();
139  Int_t nofModules = fNeuRadSetup->NofModules();
140  //выделяем память под хранение фотоэлектронов по файберам
141  vector<ERNeuRadPhotoElectron* >** peInPixelsF = new vector<ERNeuRadPhotoElectron*>* [nofModules];
142  vector<ERNeuRadPhotoElectron* >** peInPixelsB = new vector<ERNeuRadPhotoElectron*>* [nofModules];
143  for (Int_t i = 0; i<nofModules; i++){
144  peInPixelsF[i] = new vector<ERNeuRadPhotoElectron*> [nofPixels];
145  peInPixelsB[i] = new vector<ERNeuRadPhotoElectron*> [nofPixels];
146  }
147 
148  Int_t points_count = fNeuRadPoints->GetEntries();
149  //Формируем промежуточные сущности PhotoElectrons
150 
151  fPhotoElectronsCreatingTimer.Start();
152  for (Int_t iPoint=0; iPoint < points_count; iPoint++) { // цикл
153  ERNeuRadPoint *point = (ERNeuRadPoint*) fNeuRadPoints->At(iPoint);
154  PhotoElectronsCreating(iPoint,point,peInPixelsF,0,fPECountF,fSumAmplitudeF);
155  PhotoElectronsCreating(iPoint,point,peInPixelsB,1,fPECountB,fSumAmplitudeB);
156  }
157  fPhotoElectronsCreatingTimer.Stop();
158 
159  fPhotoElectronsCreatingTime += fPhotoElectronsCreatingTimer.RealTime();
160  //Формируем сигналы на ФЭУ и digi
161  fPixelSignalCreatingTimer.Start();
162 
163  for (Int_t iModule = 0; iModule < nofModules; iModule++){
164  //Генерируем сигналы на пикселях
165  for (Int_t iPixel = 0; iPixel < nofPixels; iPixel++) {
166  PixelSignalsCreating(iModule, iPixel, peInPixelsF,0);
167  PixelSignalsCreating(iModule, iPixel, peInPixelsB,1);
168  }
169  }
170 
171  fPixelSignalCreatingTimer.Stop();
172  fPixelSignalCreatingTime += fPixelSignalCreatingTimer.RealTime();
173 
174  //освобождаем память
175  for (Int_t i = 0; i<nofModules; i++){
176  delete [] peInPixelsF[i];
177  delete [] peInPixelsB[i];
178  }
179  delete [] peInPixelsF;
180  delete [] peInPixelsB;
181 
182  FairRunAna* run = FairRunAna::Instance();
183  EREventHeader* header = (EREventHeader*)run->GetEventHeader();
184  header->SetNeuRadPECountF(fPECountF);
185  header->SetNeuRadPECountB(fPECountB);
186  header->SetNeuRadSumAmplitudeF(fSumAmplitudeF);
187  header->SetNeuRadSumAmplitudeB(fSumAmplitudeB);
188 }
189 //----------------------------------------------------------------------------
190 
191 //----------------------------------------------------------------------------
192 void ERNeuRadDigitizer::PhotoElectronsCreating(Int_t iPoint, ERNeuRadPoint *point,
193  std::vector<ERNeuRadPhotoElectron* >** peInPixels,Int_t side, Int_t& sumPECount,Float_t& sumAmplitude)
194 {
195  //Генерация фотоэлектронов для поинта iPoint
196 
197  //Получение информации о поинте
198  Double_t fiberLength = fNeuRadSetup->FiberLength();
199  Int_t pointModule = point->GetModuleNb();
200  Int_t pointPixel = point->GetPixelNb();
201  Double_t pointELoss = point->GetEnergyLoss(); //[GeV]
202  Double_t pointLYield = point->GetLightYield(); //[GeV]
203  Double_t pointZ = point->GetZInLocal();
204  Double_t pointTime = point->GetTimeIn();
205  //Double_t pointZInFiber = pointZ + fiberLength/2. - fNeuRadSetup->Z();
206  Double_t pointZInFiber = pointZ + fiberLength/2.;
207 
208  //Значение квантовой эффективности для конкретного пикселе
209  Double_t PixelQuantumEfficiency = fNeuRadSetup->PixelQuantumEfficiency(pointModule,pointPixel);
210 
211  //Количество фотонов
212  Double_t photonCount = pointLYield*1000.*cSciFiLightYield;
213 
214  //Две причины затухания света
215  Double_t k1 = 0.5-cLightFractionInTotalIntReflection;
216  Double_t k2 = cLightFractionInTotalIntReflection;
217  Double_t flightLength = 0;
218  if (side == 0)
219  flightLength = pointZInFiber;
220  else
221  flightLength = fiberLength-pointZInFiber;
222  Double_t pePhotonCount = photonCount*(k1*exp(-flightLength/0.5) + k2*exp(-flightLength/200.));
223 
224  //Квантовая эффективность
225  Int_t peCount = (Int_t)gRandom->Poisson(pePhotonCount*PixelQuantumEfficiency);
226  sumPECount+=peCount;
227 
228  for(Int_t iPE=0;iPE<peCount;iPE++){
229  //Экпоненциальный закон высвечивания. Обратное распределение
230  Double_t peLYTime = pointTime + (-1)*fScincilationTau*TMath::Log(1-gRandom->Uniform());
231  //Скорость света в материале.
232  Double_t peCathodeTime = peLYTime + flightLength/cMaterialSpeedOfLight;
233  //Учёт кросстолков
234  Int_t pePixel = pointPixel, peModule = pointModule;
235  if (fUseCrosstalks)
236  Crosstalks(pointModule,pointPixel, peModule, pePixel);
237  //Амплиту одноэлектронного сигнала
238  Double_t PixelGain = fNeuRadSetup->PixelGain(peModule,pePixel);
239  Double_t PixelSigma = fNeuRadSetup->PixelSigma(peModule,pePixel);
240  // Double_t peAmplitude = TMath::Abs(gRandom->Gaus(PixelGain, PixelSigma));
241  Double_t peAmplitude = TMath::Abs(fPEA->GetRandom());
242  sumAmplitude+=peAmplitude;
243  //Задержка динодной системы и джиттер
244  Double_t peAnodeTime = peCathodeTime + (Double_t)gRandom->Gaus(fPixelDelay, fPixelJitter);
245  // ERNeuRadPhotoElectron* pe = AddPhotoElectron(iPoint, side, peLYTime - pointTime, peCathodeTime, peAnodeTime, pePhotonCount, peAmplitude);
246  ERNeuRadPhotoElectron* pe = AddPhotoElectron(iPoint, side, peLYTime, peCathodeTime, peAnodeTime, pePhotonCount, peAmplitude);
247  peInPixels[peModule][pePixel].push_back(pe);
248  }
249 
250 }
251 
252 //----------------------------------------------------------------------------
253 Int_t ERNeuRadDigitizer::Crosstalks(Int_t pointModule, Int_t pointPixel, Int_t& peModule, Int_t& pePixel){
254  //Возвращает номер файбера в котором окажется фотоэлектрон после применения кростолков
255  //Пока для простоты ввода данных масштабирует, значение кростолков для одного модуля на все остальные
256  pePixel = pointPixel;
257  peModule = pointModule;
258  TArrayF crosstalks;
259  fNeuRadSetup->Crosstalks(pePixel, crosstalks);
260  Float_t prob = gRandom->Uniform();
261  Float_t curProb = 0;
262  Int_t csI = -1;
263  Int_t csJ = -1;
264  //Разбиваем отрезок от 0 до 1 на отрезки соответствующие веростностям кростолков.
265  //В какой имено промежуток вероятности попадёт prob, в тот файбер и перетечет фотоэлектрон
266  //Последний отрезок соответствует, тому что фотоэлектрон останется в своём волокне
267  for (Int_t i = 0; i < 3; i++){
268  for (Int_t j = 0; j < 3; j++){
269  if (crosstalks[i*3+j] == 0 || (i==1 && j==1))
270  continue;
271 
272  curProb += crosstalks[i*3+j];
273 
274  if (curProb > prob){
275  csI = i;
276  csJ = j;
277  break;
278  }
279  }
280  if (csI != -1)
281  break;
282  }
283  // Переход между строками волокон в модуле
284  if (csI == 0){
285  pePixel-= fNeuRadSetup->RowNofPixels();
286  }
287  if (csI == 2){
288  pePixel+=fNeuRadSetup->RowNofPixels();
289  }
290  // Переход между столбцами волокон в модуле
291  if (csJ == 0){
292  pePixel-=1;
293  }
294  if (csJ == 2){
295  pePixel+=1;
296  }
297 }
298 
299 //----------------------------------------------------------------------------
301 {
302  if (fNeuRadPhotoElectron){
303  fNeuRadPhotoElectron->Delete();
304  }
305  if (fNeuRadPixelSignal){
306  fNeuRadPixelSignal->Delete();
307  }
308 }
309 // ----------------------------------------------------------------------------
310 //-----------------------------------------------------------------------------
311 void ERNeuRadDigitizer::PixelSignalsCreating(Int_t iModule, Int_t iPixel,
312  std::vector<ERNeuRadPhotoElectron* >** peInPixels,Int_t side)
313 {
314  if(peInPixels[iModule][iPixel].size() > 0){
315  ERNeuRadPixelSignal* PixelSignal = AddPixelSignal(iModule, iPixel,peInPixels[iModule][iPixel].size(),side);
316  for(Int_t iPE = 0; iPE < peInPixels[iModule][iPixel].size(); iPE++){
317  ERNeuRadPhotoElectron* pe = peInPixels[iModule][iPixel][iPE];
318  PixelSignal->AddPhotoElectron(pe);
319  }
320  PixelSignal->Generate();
321  }
322 }
323 // ----------------------------------------------------------------------------
325 {
326  std::cout << "========== Finish of ERNeuRadDigitizer =================="<< std::endl;
327  std::cout << "===== Time on PhotoElectrons creating : " << fPhotoElectronsCreatingTime << " s" << std::endl;
328  std::cout << "===== Time on Pixel signal creating : " << fPixelSignalCreatingTime << " s" << std::endl;
329  std::cout << "=========================================================" << std::endl;
330 }
331 // ----------------------------------------------------------------------------
332 // ----------------------------------------------------------------------------
333 ERNeuRadPixelSignal* ERNeuRadDigitizer::AddPixelSignal(Int_t iModule, Int_t iPixel, Int_t fpoints_count, Int_t side){
334  ERNeuRadPixelSignal *PixelSignal = new((*fNeuRadPixelSignal)[PixelSignalCount()])
335  ERNeuRadPixelSignal(iModule, iPixel,fpoints_count, side); return PixelSignal;
336 }
337 // ----------------------------------------------------------------------------
338 ERNeuRadPhotoElectron* ERNeuRadDigitizer::AddPhotoElectron(Int_t iPoint, Int_t side, Double_t lytime, Double_t cathode_time, Double_t anode_time,
339  Int_t photonCount, Double_t amplitude){
340  ERNeuRadPhotoElectron *fp = new ((*fNeuRadPhotoElectron)[PhotoElectronCount()])
341  ERNeuRadPhotoElectron(PhotoElectronCount(),side, lytime, cathode_time, anode_time, photonCount, amplitude);
342  fp->AddLink(FairLink("NeuRadPoint",iPoint));
343  return fp;
344 }
345 //-----------------------------------------------------------------------------
346 
347 //-----------------------------------------------------------------------------
349  return fNeuRadPhotoElectron->GetEntriesFast();
350 }
351 //-----------------------------------------------------------------------------
352 
353 //-----------------------------------------------------------------------------
354 Int_t ERNeuRadDigitizer::PixelSignalCount() const {
355  return fNeuRadPixelSignal->GetEntriesFast();
356 }
357 //----------------------------------------------------------------------------
358 
359 //-----------------------------------------------------------------------------
360 Double_t ERNeuRadDigitizer::PeFunc(Double_t *x, Double_t *par) {
361  Double_t fitval;
362  if (x[0]<63) {
363  fitval = 0;
364  }
365  if (x[0]>=63 && x[0]<par[0]) {
366  fitval = (x[0]-63) * (par[1]) / (par[0]-63) + par[4]*exp( -0.5*(x[0]-par[5])*(x[0]-par[5])/(par[6]*par[6]));
367  }
368  if (x[0]>=par[0]) {
369  fitval = par[1]*(x[0]-par[2])*(x[0]+par[2]-2*par[3])/((par[0]-par[2])*(par[0]+par[2]-2*par[3])) + par[4]*exp( -0.5*(x[0]-par[5])*(x[0]-par[5])/(par[6]*par[6]));
370  }
371  if (x[0]>=par[2]) {
372  fitval = par[4]*exp( -0.5*(x[0]-par[5])*(x[0]-par[5])/(par[6]*par[6]));
373  }
374 
375  return fitval;
376 }
377 //-----------------------------------------------------------------------------
378 ClassImp(ERNeuRadDigitizer)
virtual InitStatus Init()
Int_t PhotoElectronCount() const
Class for the NeuRad digital response calculation.
virtual void Exec(Option_t *opt)
The data class for storing pieces of charged tracks in sensitive volumes in NeuRad.
Definition: ERNeuRadPoint.h:22