AlcapDAQ  1
TNaIAnalysis.cpp
Go to the documentation of this file.
1 #include "TNaIAnalysis.h"
2 
3 #include "TOctalFADCBankReader.h"
4 #include "TOctalFADCIsland.h"
5 #include "TMucapData.h"
6 #include "midas.h"
7 #include "TNaIHit.h"
8 #include "TTimeWindow.h"
9 
10 #include <vector>
11 #include <algorithm>
12 
13 using std::vector;
14 
15 /******* global variables **********/
16 extern TMucapData *gData;
17 extern OCTALFADC_PARAM octalfadc_parameters;
18 /******* end global variables **********/
19 
20 TNaIAnalysis::TNaIAnalysis()
21 {
22  hXRayAmplitude = new TH2F("hXRayAmplitude","X ray det pulse amplitude vs channel", 5000,0,5000, 4,0.5,4.5 );
23  hXRayAmplitude->GetXaxis()->SetTitle("Amplitude (channels)");
24 
25  hXRayAmplitudeMissed = new TH2F("hXRayAmplitudeMissed","X ray det rejected pulse amplitudes vs channel", 5000,0,5000, 4,0.5,4.5 );
26  hXRayAmplitudeMissed->GetXaxis()->SetTitle("Amplitude (channels)");
27 
28 // hXRayAvAmplitude = new TH2F("hXRayAvAmplitude","X ray det pulse averaged amplitude vs channel", 5000,0,5000, 4,0.5,4.5 );
29 // hXRayAvAmplitude->GetXaxis()->SetTitle("Amplitude (channels)");
30 
31 // hXRayFitAmplitude = new TH2F("hXRayFitAmplitude","X ray det pulse fit amplitude vs channel", 5000,0,5000, 4,0.5,4.5 );
32 // hXRayFitAmplitude->GetXaxis()->SetTitle("Amplitude (channels)");
33 
34 
35  hXRayTime = new TH2F("hXRayTime","X ray pulse trigger time vs channel", 40,0,4e8, 4,0.5,4.5);
36  hXRayTime->GetXaxis()->SetTitle("Block time (ns)");
37  hXRayTimingEnergyTDiffVsAmplitude = new TH3F("hXRayTimingEnergyTDiffVsAmplitude", "XRay T diff energy channel and timing channel versus amplitude", 200,-8000,8000,100,0,5000,2,0.5,2.5);
38  hXRayTimingEnergyTDiffVsAmplitude->GetXaxis()->SetTitle("Time difference (ns)");
39  hXRayTimingEnergyTDiffVsAmplitude->GetZaxis()->SetTitle("Detector Nr.");
40  hXRayTimingEnergyTDiffVsAmplitude->GetYaxis()->SetTitle("Amplitude");
41 // hNaITimingAmpVsEnergyAmp = new TH2F("hNaITimingAmpVsEnergyAmp", "NaI Hits: Amplitude of timing channel vs energy channel",4096,0,4096,4096,0,4096);
42 
43 // hNaIAmplitudeVsSizeIslandAccept = new TH3F("hNaIAmplitudeVsSizeIslandAccept","Accepted NaI pulse amplitude vs Size Island", 500,0,5000,100,0,1000,2,0.5,2.5 );
44 // hNaIAmplitudeVsSizeIslandReject = new TH3F("hNaIAmplitudeVsSizeIslandReject","Rejected NaI pulse amplitude vs Size Island", 500,0,5000,100,0,1000,2,0.5,2.5 );
45 
46 // hNaIAverageVsAmpAccept = new TH3F("hNaIAverageVsAmpAccept","Accepted NaI pulse amplitude Vs Average Island / Amp", 310,1000,4100,440,0,1.1,2,0.5,2.5 );
47 // hNaIAverageVsAmpReject = new TH3F("hNaIAverageVsAmpReject","Rejected NaI pulse amplitude Vs Average Island / Amp", 310,1000,4100,440,0,1.1,2,0.5,2.5 );
48 
49 // hNaIPileUp= new TH1I("hNaIPileUp","NaI Pile Ups, no pile up = 1, pile up = 2", 2,0.5,2.5);
50 // hNaICount = new TH1I("hNaICount","Ambiguous or missed hits, ok = 1, ambiguous time tagging = 2, missed E signal = 3", 3,0.5,3.5 );
51 
52  hXRayStats = new TH1I("hXRayStats","X ray stats", 20,0.5,20.5);
53  hXRayStats->GetXaxis()->SetBinLabel(1, "NaI-fast islands");
54  hXRayStats->GetXaxis()->SetBinLabel(2, "NaI-slow islands");
55  hXRayStats->GetXaxis()->SetBinLabel(3, "CsI-fast islands");
56  hXRayStats->GetXaxis()->SetBinLabel(4, "CsI-slow islands");
57  hXRayStats->GetXaxis()->SetBinLabel(5, "NaI-fast bad islands");
58  hXRayStats->GetXaxis()->SetBinLabel(6, "NaI-slow bad islands");
59  hXRayStats->GetXaxis()->SetBinLabel(7, "CsI-fast bad islands");
60  hXRayStats->GetXaxis()->SetBinLabel(8, "CsI-slow bad islands");\
61  hXRayStats->GetXaxis()->SetBinLabel(9, "NaI hits");
62  hXRayStats->GetXaxis()->SetBinLabel(10, "CsI hits");
63  hXRayStats->GetXaxis()->SetBinLabel(11, "NaI Pile ups");
64  hXRayStats->GetXaxis()->SetBinLabel(12, "CsI Pile ups");
65  hXRayStats->GetXaxis()->SetBinLabel(13, "NaI double counts");
66  hXRayStats->GetXaxis()->SetBinLabel(14, "CsI double counts");
67 
68 
69  levelGoodPulse = 3;
70  nAverage = 4;
71  tLow = +4000.;//coincidence window for making hits
72  tHigh = +5600.;
73 
74  //get runnr
75  fRunInfoEvent = gData->runinfoEvent;
76  runnr = fRunInfoEvent->GetRunNumber();
77 
78 
79  kNaITimingChannel = OCTALFADC_PARAM::kNaITimingChannel;
80  kNaIEnergyChannel = OCTALFADC_PARAM::kNaIEnergyChannel;
81 
82  kCsITimingChannel = OCTALFADC_PARAM::kCsITimingChannel;
83  kCsIEnergyChannel = OCTALFADC_PARAM::kCsIEnergyChannel;
84 
85  //Get the shaping times, clock periods and pedestals
86  shapNaIEnergyChannel = OCTALFADC_PARAM::shapNaIEnergyChannel;
87  shapNaITimingChannel = OCTALFADC_PARAM::shapNaITimingChannel;
88 
89  shapCsIEnergyChannel = OCTALFADC_PARAM::shapCsIEnergyChannel;
90  shapCsITimingChannel = OCTALFADC_PARAM::shapCsITimingChannel;
91 
92  timingNaIClockPeriod = octalfadc_parameters.kClockPeriod[kNaITimingChannel];
93  energyNaIClockPeriod = octalfadc_parameters.kClockPeriod[kNaIEnergyChannel];
94 
95  timingCsIClockPeriod = octalfadc_parameters.kClockPeriod[kCsITimingChannel];
96  energyCsIClockPeriod = octalfadc_parameters.kClockPeriod[kCsIEnergyChannel];
97 
98  pedestalNaIEnergyChannel = OCTALFADC_PARAM::pedestalNaITimingChannel;
99  pedestalNaITimingChannel = OCTALFADC_PARAM::pedestalNaITimingChannel;
100 
101  pedestalCsIEnergyChannel = OCTALFADC_PARAM::pedestalCsIEnergyChannel;
102  pedestalCsITimingChannel = OCTALFADC_PARAM::pedestalCsITimingChannel;
103 }
104 
105 TNaIAnalysis::~TNaIAnalysis()
106 {
107  delete hXRayAmplitude;
108  delete hXRayAmplitudeMissed;
109 // delete hXRayAvAmplitude;
110 // delete hXRayFitAmplitude;
111  delete hXRayTime;
112  delete hXRayStats;
113 // delete hNaIAvAmplitude;
114 // delete hNaIAmplitudePP;
115 // delete hNaIAmplitudeMissed;
116 // delete hNaITime;
117  delete hXRayTimingEnergyTDiffVsAmplitude;
118 // delete hNaITimingAmpVsEnergyAmp;
119 
120 // delete hNaIAmplitudeVsSizeIslandAccept;
121 // delete hNaIAmplitudeVsSizeIslandReject;
122 
123 // delete hNaIAverageVsAmpAccept;
124 // delete hNaIAverageVsAmpReject;
125 
126 // delete hNaIPileUp;
127 // delete hNaICount;
128 
129 }
130 
131 INT TNaIAnalysis::ProcessEvent(EVENT_HEADER *pheader, void *pevent)
132 {
133  printf("Running TNaIAnalysis (NaI + CsI run 5)...\n");
134 
135  if(gData->fGeFADCBanks.size() < 8)
136  {
137  printf("TNaIAnalysis::ProcessEvent : Could not find NaI Detector banks.\n");
138  return SUCCESS;
139  }
140 
141 
142  // Get the banks
143  TOctalFADCBankReader& bNaI_timing = gData->fGeFADCBanks.at(kNaITimingChannel);
144  TOctalFADCBankReader& bNaI_energy = gData->fGeFADCBanks.at(kNaIEnergyChannel);
145 
146  TOctalFADCBankReader& bCsI_energy = gData->fGeFADCBanks.at(kCsIEnergyChannel);
147  TOctalFADCBankReader& bCsI_timing = gData->fGeFADCBanks.at(kCsITimingChannel);
148 
149  // Get the vector of islands
150  vector<TOctalFADCIsland>& vNaI_timing = bNaI_timing.GetIslandVector();
151  vector<TOctalFADCIsland>& vNaI_energy = bNaI_energy.GetIslandVector();
152 
153  vector<TOctalFADCIsland>& vCsI_timing = bCsI_timing.GetIslandVector();
154  vector<TOctalFADCIsland>& vCsI_energy = bCsI_energy.GetIslandVector();
155 
156 //std::cout << "timingNaIClockPeriod " << timingNaIClockPeriod << "timingCsIClockPeriod " << timingCsIClockPeriod << std::endl;
157 //std::cout << "kNaITimingChannel " << kNaITimingChannel << " kNaIEnergyChannel " << kNaIEnergyChannel << std::endl;
158 
159 
160  //loop all channels and fill hAmplitude and time and set pulse quality flags
161  for(int i=0; i < vNaI_timing.size(); i++)
162  {
163  hXRayStats->Fill(1);
164  if(vNaI_timing[i].GoodPulse(shapNaITimingChannel,timingNaIClockPeriod,levelGoodPulse))
165  {
166  hXRayAmplitude->Fill(vNaI_timing[i].GetMax(), kNaITimingChannel+1 );
167  hXRayTime->Fill(vNaI_timing[i].GetTimeNs(),kNaITimingChannel+1 );
168  }
169  else{hXRayStats->Fill(5);hXRayAmplitudeMissed->Fill(vNaI_timing[i].GetMax(), kNaITimingChannel+1 );}
170  }
171 
172 
173  for(int i=0; i < vNaI_energy.size(); i++)
174  {
175  hXRayStats->Fill(2);
176  if(vNaI_energy[i].GoodPulse(shapNaIEnergyChannel,energyNaIClockPeriod,levelGoodPulse))
177  {
178  hXRayAmplitude->Fill(vNaI_energy[i].GetMax(), kNaIEnergyChannel+1 );
179  // hXRayAvAmplitude->Fill( vNaI_energy[i].GetAverageMax(nAverage), kNaIEnergyChannel+1 );
180  //if(vNaI_energy[i].FitGauss(10, 10, shapNaIEnergyChannel, energyNaIClockPeriod, pedestalNaIEnergyChannel)) { hXRayFitAmplitude->Fill( vNaI_energy[i].GetMaxGauss(), kNaIEnergyChannel+1 ); }
181  hXRayTime->Fill(vNaI_energy[i].GetTimeNs(),kNaIEnergyChannel+1 );
182  }
183  else{hXRayStats->Fill(6);hXRayAmplitudeMissed->Fill(vNaI_energy[i].GetMax(), kNaIEnergyChannel+1 );}
184  }
185 
186 
187  for(int i=0; i < vCsI_timing.size(); i++)
188  {
189  hXRayStats->Fill(3);
190  if(vCsI_timing[i].GoodPulse(shapCsITimingChannel,timingCsIClockPeriod,levelGoodPulse))
191  {
192  hXRayAmplitude->Fill(vCsI_timing[i].GetMax(), kCsITimingChannel+1 );
193  hXRayTime->Fill(vCsI_timing[i].GetTimeNs(),kCsITimingChannel+1 );
194  }
195  else{hXRayStats->Fill(7);hXRayAmplitudeMissed->Fill(vCsI_timing[i].GetMax(), kCsITimingChannel+1 );}
196  }
197 
198 
199  for(int i=0; i < vCsI_energy.size(); i++)
200  {
201  hXRayStats->Fill(4);
202  if(vCsI_energy[i].GoodPulse(shapCsIEnergyChannel,energyCsIClockPeriod,levelGoodPulse))
203  {
204  hXRayAmplitude->Fill(vCsI_energy[i].GetMax(), kCsIEnergyChannel+1 );
205  // hXRayAvAmplitude->Fill(nAverage, vCsI_energy[i].GetAverageMax(nAverage), kCsIEnergyChannel+1 );
206  // if(vCsI_energy[i].FitGauss(10, 10, shapCsIEnergyChannel, energyCsIClockPeriod, pedestalCsIEnergyChannel)) { hXRayFitAmplitude->Fill( vCsI_energy[i].GetMaxGauss(), kCsIEnergyChannel+1 ); }
207  hXRayTime->Fill(vCsI_energy[i].GetTimeNs(),kCsIEnergyChannel+1 );
208  }
209  else {hXRayStats->Fill(8);hXRayAmplitudeMissed->Fill(vCsI_energy[i].GetMax(), kCsIEnergyChannel+1 );}
210  }
211 
212 
213  gData->fNaIHits.clear();
214  MakeHits(vNaI_timing, vNaI_energy);
215  MakeHits(vCsI_timing, vCsI_energy);
216  PileUpProtectHits();
217  SortHits();//After PP algorithm!
218 
219  return SUCCESS;
220 
221 }
222 
223 void TNaIAnalysis::MakeHits(vector<TOctalFADCIsland>& vec_timing,vector<TOctalFADCIsland>& vec_energy)
224 {
225  vector<TNaIHit>& vHits = gData->fNaIHits;
226 
227  //get channel
228  if(vec_timing.empty() || vec_energy.empty()) return;
229  int channel = vec_timing[0].GetFADCChannel();
230  //printf("Making a hits for channel %d and channel %d\n",vec_timing[0].GetFADCChannel(),vec_energy[0].GetFADCChannel());
231 
232  //set (channel specific) parameters
233  double timingClockPeriod, energyClockPeriod;
234 
235  if(channel == kNaITimingChannel)
236  {
237  timingClockPeriod = timingNaIClockPeriod;
238  energyClockPeriod = energyNaIClockPeriod;
239  }
240  else if(channel == kCsITimingChannel)
241  {
242  timingClockPeriod = timingCsIClockPeriod;
243  energyClockPeriod = energyCsIClockPeriod;
244  }
245  else {printf("Invalid parameters to construct NaIHits!!!\n");};
246 
247 
248  int lastEnergyPulse=0; // stays just behind the time of the timing pulse
249  int count = 0;
250  int energyHit = -1;
251 
252  //make coincidences and construct hits
253  for(int iTime=0; iTime < vec_timing.size(); iTime++)
254  {
255  if(vec_timing[iTime].GetPulseQuality() == 0)
256  {
257  double timingT = vec_timing[iTime].GetCFBlockTime()*timingClockPeriod;
258  TTimeWindow coincWindow(timingT + tLow, timingT + tHigh);
259 
260  for(int iEgy=lastEnergyPulse; iEgy<vec_energy.size(); iEgy++)
261  {
262  if(vec_energy[iEgy].GetPulseQuality() == 0)
263  {
264  double energyT = vec_energy[iEgy].GetMaxBinBlockTime()*energyClockPeriod;
265 
266  if(coincWindow.IsLow(energyT)) { lastEnergyPulse = iEgy; }
267  else if(coincWindow.Includes(energyT))
268  {
269  count++;
270  energyHit = iEgy;
271  if(channel == kNaITimingChannel) { hXRayTimingEnergyTDiffVsAmplitude->Fill(energyT-timingT,vec_energy[iEgy].GetMax(),1.); } //printf("NaI tDiff = %f\n",energyT-timingT); }
272  else { hXRayTimingEnergyTDiffVsAmplitude->Fill(energyT-timingT,vec_energy[iEgy].GetMax(),2.); } //printf("CsI tDiff = %f\n",energyT-timingT);}
273  }
274  else if(coincWindow.IsHigh(energyT)) break;
275  }
276  }
277 
278  //the idea is that only one (slow) E signal lines up with a fast signal, otherwise there is a problem (and the hit is flagged with ncount > 1
279  if(count>0)
280  {
281  if( channel == kNaITimingChannel) { hXRayStats->Fill(9); } else { hXRayStats->Fill(10); }
282  TNaIHit naihit(vec_timing[iTime],vec_energy[energyHit],count);
283  vHits.push_back(naihit);
284  }
285  count=0;
286  }
287  }
288 
289 
290 }
291 
292 
293 void TNaIAnalysis::PileUpProtectHits()
294 {
295  vector<TNaIHit>& vHits = gData->fNaIHits;
296  //printf("Loop through %d Xray hist for PP\n",vHits.size());
297  if(vHits.size() == 0 || vHits.size() == 1) return;
298 
299  //Hits are stacked first for one detector, than for the other, so a single loop is sufficient
300  for(int i = 1; i < vHits.size()-1; i++)
301  {
302  //printf("%d Xray hit : time = %f, energy = %f, detector = %d P\n",i, vHits[i].GetTime(),vHits[i].GetEnergy(),vHits[i].GetDetector() );
303  //the actual pile up algorithm
304  if(vHits[i-1].GetEnergyTime()==vHits[i].GetEnergyTime())
305  {
306  vHits[i-1].SetPileUp(true);
307  vHits[i].SetPileUp(true);
308  }
309  //Filling histograms
310  if(vHits[i-1].GetPileUp()) { hXRayStats->Fill(vHits[i-1].GetDetector()+10); }
311  if(vHits[i-1].GetCount() > 1) {hXRayStats->Fill(vHits[i-1].GetDetector()+12);}
312  }
313 
314  //this "strange second step is to avoid a second for loop over all hits. don`t know if it makes much of a difference though
315  if(vHits[vHits.size()-1].GetPileUp()){ hXRayStats->Fill(vHits[vHits.size()-1].GetDetector()+10); }
316  if(vHits[vHits.size()-1].GetCount() > 1){ hXRayStats->Fill(vHits[vHits.size()-1].GetDetector()+12); }
317 }
318 
319 void TNaIAnalysis::SortHits()
320 {
321  vector<TNaIHit>& vHits = gData->fNaIHits;
322  std::sort(vHits.begin(), vHits.end(),TNaIHit::TimeSortNaIHits());
323 }
324 
325 /*void TNaIAnalysis::MakeNaIHits(vector<TOctalFADCIsland>& vec_timing,vector<TOctalFADCIsland>& vec_energy)
326 {
327  vector<TNaIHit>& vHits = gData->fNaIHits;
328 
329  const double timingClockPeriod = octalfadc_parameters.kClockPeriod[OCTALFADC_PARAM::kNaITimingChannel];
330  const double energyClockPeriod = octalfadc_parameters.kClockPeriod[OCTALFADC_PARAM::kNaIEnergyChannel];
331 
332  const double shapNaITimingChannel = octalfadc_parameters.shapNaITimingChannel;
333  const double shapNaIEnergyChannel = octalfadc_parameters.shapNaIEnergyChannel;
334 
335  int lastEnergyPulse=0; // stays just behind the time of the timing pulse
336  int count = 0;
337  int energyHit = -1;
338 
339 
340  for(int iTime=0; iTime<vec_timing.size(); iTime++)
341  {
342  if(vec_timing[iTime].GoodPulse(shapNaITimingChannel,timingClockPeriod,levelGoodPulse))
343  {
344  double timingT = vec_timing[iTime].GetTime()*timingClockPeriod;
345  TTimeWindow coincWindow(timingT + 3000.,timingT +7000.);
346 
347  for(int iEgy=lastEnergyPulse; iEgy<vec_energy.size(); iEgy++)
348  {
349  if(vec_energy[iEgy].GoodPulse(shapNaIEnergyChannel,energyClockPeriod,levelGoodPulse))
350  {
351  double energyT = vec_energy[iEgy].GetMaxBinBlockTime()*energyClockPeriod;
352 
353  if(coincWindow.IsLow(energyT))
354  {
355  lastEnergyPulse = iEgy;
356  continue;
357  }
358  else if(coincWindow.Includes(energyT))
359  {
360  count++;
361  energyHit = iEgy;
362  hNaITimingEnergyTDiff->Fill(energyT-timingT);
363  continue;
364  }
365  else if(coincWindow.IsHigh(energyT)) break;
366  }
367  }
368 
369  //if(vec_timing[iTime].GetNSamples()<10000 && vec_energy[energyHit].GetNSamples()<10000){TNaIHit naihit(vec_timing[iTime],vec_energy[energyHit],count,nAverage);vHits.push_back(naihit);}
370  if(count>0)
371  {
372  TNaIHit naihit(vec_timing[iTime],vec_energy[energyHit],count,nAverage);
373  vHits.push_back(naihit);
374  }
375  count=0;
376  }
377  }
378 
379 }*/
380 
381 /*void TNaIAnailysis::PileUpProtectHits()
382 {
383  vector<TNaIHit>& vHits = gData->fNaIHits;
384 
385  if(vHits.size() == 0) return;
386  if(vHits.size() == 1) return;
387 
388  for(int i =1; i < vHits.size()-1; i++)
389  {
390  //the actual pile up algorithm
391  if(vHits[i-1].GetEnergyTime()==vHits[i].GetEnergyTime())
392  {
393  vHits[i-1].SetPileUp(true);
394  vHits[i].SetPileUp(true);
395  }
396 
397  //Filling histograms
398  if(!(vHits[i-1].GetPileUp()))
399  {
400  if(vHits[i-1].GetCount()==1){ hNaIAmplitudePP->Fill(vHits[i-1].GetEnergyAmp(),1); hNaIAmplitudePP->Fill(vHits[i-1].GetTimingAmp(),2); }
401  hNaIPileUp->Fill(1);
402  }else{hNaIPileUp->Fill(2);}
403 
404  if(vHits[i-1].GetCount() == 1)
405  {
406  hNaICount->Fill(1 );
407  }
408  else if(vHits[i-1].GetCount() > 2){hNaICount->Fill(2);}
409  else {hNaICount->Fill(3);}
410  }
411 
412  //this "strange second step is to avoid a second for loop over all hits. don`t know if it makes much of a difference though
413 
414  if(!(vHits[vHits.size()-1].GetPileUp()))
415  {
416  if(vHits[vHits.size()-1].GetCount()==1){hNaIAmplitudePP->Fill(vHits[vHits.size()].GetEnergyAmp(),1);}
417  hNaIPileUp->Fill(1);
418  }else{hNaIPileUp->Fill(2);}
419 
420  if(vHits[vHits.size()-1].GetCount() == 1)
421  {
422  hNaICount->Fill(1, 1 );
423  }
424  else if(vHits[vHits.size()-1].GetCount() > 2){hNaICount->Fill(2 );}
425  else {hNaICount->Fill(3 );}
426 
427 
428 }
429 */