Jpp
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
NBPulse.hh
Go to the documentation of this file.
1 #ifndef __NBPULSE__
2 #define __NBPULSE__
3 
4 
5 #include "RooRealVar.h"
6 #include "RooWorkspace.h"
7 #include "RooGaussModel.h"
8 #include "RooArgList.h"
9 #include "RooLandau.h"
10 #include "RooDataSet.h"
11 #include "RooDataHist.h"
12 #include "RooAddPdf.h"
13 #include "RooGaussian.h"
14 #include "RooMsgService.h"
15 
16 #include "TH1D.h"
17 #include "TH2D.h"
18 #include "TRandom3.h"
19 
20 
21 
22 /**
23  * \author rgruiz
24  */
25 
26 using namespace RooFit;
27 using namespace std;
28 
29 
30 /**
31  * Analyzes the signal of a nanobeacon in a PMT
32  */
33 class NBPulse {
34 
35  TH2D* time_vs_tot ;
36 
37  TH1D *htime_full , *htime_peak , *tot_peak ;
38 
39  RooWorkspace w ;
40 
42 
43  double tlow , thigh , tpeak , nhits , meanToT , sigmaToT , max_ToT ;
44 
45  int n_bins_right , n_bins_left , n_bins_before_peak , n_bins_afterpulse , max_n_bins_baseline , min_n_bins_baseline , n_sigma_peak , n_sigma_before_peak ;
46 
47  double fit_region_min , fit_region_max , fit_range_min , fit_range_max , landau_m_min , landau_m_max , landau_s_min , landau_s_max , gaus_m_min , gaus_m_max , gaus_s_min , gaus_s_max , l_g_ratio_min , l_g_ratio_max , KS_threshold;
48 
49  bool analyzed ;
50 
51  bool fitted ;
52 
53  bool is_good ;
54 
56 
57  bool saturated_tot ;
58 
59  bool weak ;
60 
61  public :
62 
63  /**
64  * Default constructor.
65  */
66  NBPulse(){}
67 
68 
69  /**
70  * Constructor.
71  * This constructor initializes the nanobeacon pulse from a 2D histogram containing the
72  * time vs ToT hit distribution.
73  *
74  * \param h time vs ToT histogram
75  */
76  NBPulse(TH2D* h) :
77  max_ToT (26.4) ,
78  n_bins_right (5) ,
79  n_bins_left (5) ,
80  n_bins_before_peak(2) ,
81  n_bins_afterpulse (10),
82  max_n_bins_baseline (50),
83  min_n_bins_baseline (10),
84  n_sigma_peak (5) ,
85  n_sigma_before_peak (4) ,
86  fit_region_min (20.0),
87  fit_region_max (20.0) ,
88  fit_range_min (6.0) ,
89  fit_range_max (15.0) ,
90  landau_m_min (2.0) ,
91  landau_m_max (2.0) ,
92  landau_s_min (1.0) ,
93  landau_s_max (9.0) ,
94  gaus_m_min (2.0) ,
95  gaus_m_max (2.0) ,
96  gaus_s_min (1.0) ,
97  gaus_s_max (9.0) ,
98  l_g_ratio_min (0.0) ,
99  l_g_ratio_max (1.0) ,
100  KS_threshold(1e-3) ,
101  analyzed (false) ,
102  fitted (false) ,
103  is_good (false) ,
104  saturated_hit (false) ,
105  saturated_tot (false) ,
106  weak (false)
107 
108  {
109 
110  time_vs_tot = h ;
111 
112  initialize() ;
113 
114  }
115 
116 
117  /**
118  * Destructor.
119  */
121 
122  delete(htime_full) ;
123 
124  if (analyzed == true){
125 
126  delete(tot_peak) ;
127 
128  delete(htime_peak) ;
129 
130  }
131 
132  }
133 
134 
135  /**
136  * Performs a Kolmogorov-Smirnov compatibility test between the hit time distribution and a uniform distribution
137  *
138  * \param h The hit time distribution
139  * \return The probability that the hit time distribution is compatible with a uniform distribution.
140  */
141  double Kolmogorov_Smirnov_uniform(TH1D* h){
142 
143  TRandom3* r = new TRandom3() ;
144 
145  double low_x = 0 ;
146 
147  double high_x = h->GetBinCenter(h->GetNbinsX() - 1) ;
148 
149  int nentries = h->Integral(1 , h->GetNbinsX() - 1) ;
150 
151  if (h->GetBinCenter(1)>=0){
152 
153  low_x = h->GetBinCenter(1) ;
154 
155  }
156 
157  TH1D* u = (TH1D*)h->Clone("uniform") ;
158 
159  u->Reset() ;
160 
161  for (int i = 0 ; i<nentries ; i++){
162 
163  u->Fill(r->Uniform(low_x, high_x));
164 
165  }
166 
167  double proba = h->KolmogorovTest(u) ;
168 
169  delete(r) ;
170 
171  delete(u) ;
172 
173  return proba ;
174 
175  } ;
176 
177 
178 
179 
180  /**
181  * Leaves the pulse ready for analysis by projecting the time vs ToT distribution to
182  * the time axis and moving it out of the Root file directory.
183  */
184  void initialize(){
185 
186  htime_full = time_vs_tot->ProjectionX(time_vs_tot->GetName() , 1 , time_vs_tot->GetNbinsY());
187 
188  htime_full->SetDirectory(0) ;
189 
190  RooMsgService::instance().setGlobalKillBelow(RooFit::WARNING);
191 
192  }
193 
194 
195  /**
196  * Performs a fast analysis of the hit time distribution.
197  */
198  void analyzeFast(){
199 
200  if (analyzed == true) return ;
201 
202  computeBaseline(htime_full) ;
203 
204  int peakbin = htime_full->GetMaximumBin() ;
205 
206  double height = htime_full->GetBinContent(peakbin) ;
207 
208  int leftbin = peakbin - n_bins_left ;
209 
210  int rightbin = peakbin + n_bins_right ;
211 
212  tpeak = htime_full->GetBinCenter(peakbin) ;
213 
214  tlow = htime_full->GetBinCenter(leftbin) ;
215 
216  thigh = htime_full->GetBinCenter(rightbin) ;
217 
218  htime_peak = (TH1D*)htime_full->Clone();
219 
220  for (int i=0 ; i<htime_peak->GetNbinsX() ; i++){
221 
222  if (i<leftbin || i>rightbin){
223 
224  htime_peak->SetBinContent(i,0);
225 
226  }
227 
228  }
229 
230  htime_peak->SetName((std::string("htime_")+htime_peak->GetName()).c_str());
231 
232  htime_peak->SetDirectory(0) ;
233 
234  tot_peak = (TH1D*)time_vs_tot->ProjectionY((std::string("ToT_") + time_vs_tot->GetName()).c_str() , leftbin , rightbin) ;
235 
236  tot_peak->SetDirectory(0);
237 
238  meanToT = tot_peak->GetMean() ;
239 
240  if (meanToT > max_ToT){
241 
242  saturated_tot = true ;
243 
244  }
245 
246  sigmaToT = tot_peak->GetStdDev() ;
247 
248  double p_KS = Kolmogorov_Smirnov_uniform(htime_full) ;
249 
250  if (baseline.first==0 && baseline.second==0) weak = true ;
251 
252  if (p_KS > KS_threshold) weak = true ;
253 
254  if (height < (baseline.first + n_sigma_peak * baseline.second)) weak = true ;
255 
256  for (int i = 1 ; i<=n_bins_before_peak ; i++){
257 
258  if (htime_full->GetBinContent(peakbin - n_bins_before_peak) < (baseline.first + n_sigma_before_peak * baseline.second)) weak = true ;
259 
260  }
261 
262  if (weak == false && htime_full->GetBinContent(peakbin + n_bins_afterpulse) == 0) saturated_hit = true ;
263 
264  if (weak == false && saturated_hit == false) is_good = true ;
265 
266  nhits = htime_peak->Integral() ;
267 
268  analyzed = true ;
269 
270  }
271 
272 
273 
274  /**
275  * Computes baseline of the hit time distribution measured by the PMT. For this the first bins of the distribution (where the nanobeacon pulse is absent) are used.
276  *
277  * \param h Histogram with the hit time distribution
278  */
279  void computeBaseline(TH1* h){
280 
281  int N = 0;
282 
283  double sum = 0 ;
284 
285  vector<double> bins ;
286 
287  for (int i=1 ; i<max_n_bins_baseline + 1 ; i++){
288 
289  if(h->GetBinContent(i) > 0 ){
290 
291  sum += h->GetBinContent(i);
292 
293  bins.push_back(h->GetBinContent(i));
294 
295  N += 1 ;
296 
297  }
298 
299  }
300 
301  if(N < min_n_bins_baseline){
302 
303  bins.clear();
304 
305  sum = 0 ;
306 
307  N = 0 ;
308 
309  for (int i=1 ; i<max_n_bins_baseline + 1 ; i++){
310 
311  if(h->GetBinContent(h->GetNbinsX() - i)>0){
312 
313  sum += h->GetBinContent(h->GetNbinsX() - i);
314 
315  bins.push_back(h->GetBinContent(h->GetNbinsX() - i));
316 
317  N += 1 ;
318 
319  }
320 
321  }
322 
323  }
324 
325  if(N < min_n_bins_baseline){
326 
327  baseline.first = 0 ;
328 
329  baseline.second = 0 ;
330 
331  return ;
332 
333  }
334 
335  double bg_mean = sum/N ;
336 
337  baseline.first = bg_mean ;
338 
339  double sdev = 0;
340 
341  for (int i=0 ; i<N ; i++){
342 
343  sdev += pow((bins[i] - bg_mean) , 2) ;
344 
345  }
346 
347  baseline.second = sqrt(sdev/N);
348 
349  }
350 
351 
352  /**
353  * Fits the hit nanobeacon signal to a model composed by a Landau and a Gauss functions.
354  */
355  void fit(){
356 
357  if (fitted==true) return ;
358 
359  if (analyzed==false) analyzeFast() ;
360 
361  w.SetName((std::string("W_") + htime_full->GetName()).c_str());
362 
363  double tpeak = htime_full->GetBinCenter(htime_full->GetMaximumBin()) ;
364 
365  RooRealVar x("time" , "hit time" , tpeak - fit_region_min , tpeak + fit_region_max) ;
366 
367  RooRealVar ml("mean landau" , "mean landau" , tpeak - landau_m_min , tpeak + landau_m_max);
368 
369  RooRealVar sl("sigma landau" , "sigma landau" , landau_s_min , landau_s_max);
370 
371  RooLandau L1("L1" , "Main_Landau" , x , ml , sl) ;
372 
373  RooRealVar mg("mean Gauss" , "mean Gauss" , tpeak - gaus_m_min , tpeak + gaus_m_max);
374 
375  RooRealVar sg("sigma Gauss" , "sigma Gauss" , gaus_s_min , gaus_s_max);
376 
377  RooGaussian G1("G1" , "Main_Gaussian" , x , mg , sg) ;
378 
379  RooRealVar c1("c1" , "c1" , l_g_ratio_min , l_g_ratio_max);
380 
381  RooAddPdf M("Model" , "Model" , RooArgList(G1,L1) , RooArgList(c1));
382 
383  w.import(M) ;
384 
385  RooDataHist Data ("data" , "data" , *w.var("time") , Import(*htime_full));
386 
387  w.pdf("Model")->fitTo(Data , Range(tpeak - fit_range_min , tpeak + fit_range_max) , RooFit::PrintLevel(-1000) , RooFit::PrintEvalErrors(-1000)) ;
388 
389  RooRealVar Tmin ("tmin" , "tmin" , tpeak - fit_range_min) ;
390 
391  RooRealVar Tmax ("tmax" , "tmax" , tpeak + fit_range_max) ;
392 
393  RooRealVar Tpeak ("tpeak" , "tpeak" , tpeak) ;
394 
395  RooRealVar Mpv("mpv" , "mpv" , Tmin.getVal()) ;
396 
397  RooRealVar Diff("peak-mpv" , "peak-mpv" , Tpeak.getVal() - Tmin.getVal()) ;
398 
399  double max_pdfval = 0 ;
400 
401  RooRealVar *var = (RooRealVar*)w.function("Model")->getObservables(RooArgSet(*w.var("time")))->first();
402 
403  for(double x = Tmin.getVal() ; x<Tmax.getVal() ; x+=0.1){
404 
405  var->setVal(x) ;
406 
407  double pdfval = w.function("Model")->getVal(RooArgSet(*var)) ;
408 
409  if (pdfval>max_pdfval){
410 
411  max_pdfval = pdfval ;
412 
413  Mpv.setVal(x) ;
414 
415  }
416 
417  }
418 
419  w.import(Mpv) ;
420 
421  w.import(Tmin) ;
422 
423  w.import(Tmax) ;
424 
425  w.import(Tpeak) ;
426 
427  w.import(Diff) ;
428 
429  fitted = true ;
430 
431  }
432 
433 
434  /**
435  * Check if the peak is good.
436  *
437  * \result true if the peak is classified as good.
438  */
439  bool IsGood() {
440 
441  return is_good ;
442 
443  }
444 
445 
446  /**
447  * Check if the peak is fitted.
448  *
449  * \result true if the peak has been fitted.
450  */
451  bool IsFitted() {
452 
453  return fitted ;
454 
455  }
456 
457 
458  /**
459  * Check if the hit time distribution is saturated.
460  *
461  * \result true if the hit time distributon is classified as saturated.
462  */
464 
465  return saturated_hit ;
466 
467  }
468 
469 
470  /**
471  * Check if the hit time distribution is weak.
472  *
473  * \result true if the hit time distributon is classified as weak.
474  */
475  bool IsWeak(){
476 
477  return weak ;
478 
479  }
480 
481 
482 
483  /**
484  * Get the hit time distribution.
485  *
486  * \return histogram with hit time distribution
487  */
488  TH1D* getHtime_full(){
489 
490  return htime_full ;
491 
492  }
493 
494 
495 
496  /**
497  * Get the hit time distribution.
498  *
499  * \return histogram with hit time distribution
500  */
501  TH1D* gettime_peak(){
502 
503  return htime_peak ;
504 
505  }
506 
507 
508 
509  /**
510  * Get the hit time distribution.
511  *
512  * \return histogram with hit time distribution
513  */
514  TH1D* gettot_peak(){
515 
516  return tot_peak ;
517 
518  }
519 
520 
521 
522 
523  /**
524  * Get the hit time vs ToT distribution.
525  *
526  * \return a 2d histogram with hit time vs ToT distribution
527  */
528  TH2D* gettime_vs_tot(){
529 
530  return time_vs_tot ;
531 
532  }
533 
534 
535 
536  /**
537  * Get all the information from the fit.
538  *
539  * \return Roofit Workspace with all the information and parameters from the fit
540  */
541  RooWorkspace getWorkspace(){
542 
543  return w ;
544 
545  }
546 
547 
548 
549  /**
550  * Get the arrival time of the nanobeacon pulse.
551  *
552  * \return pulse arrival time
553  */
554  double getPeakTime() {
555 
556  return tpeak ;
557 
558  }
559 
560 
561 
562  /**
563  * Get the mean of the ToT distribution of the hits produced by the nanobeacon.
564  *
565  * \return mean ToT value
566  */
567  double getMeanToT() {
568 
569  return meanToT ;
570 
571  }
572 
573 
574 
575  /**
576  * Get the standard deviation of the ToT distribution of the hits produced by the nanobeacon.
577  *
578  * \return standard deviation from ToT distribution
579  */
580  double getSigmaToT() {
581 
582  return sigmaToT ;
583 
584  }
585 
586 
587 
588  /**
589  * Get name of the hit time vs ToT histogram.
590  *
591  * \return The name of the histogram.
592  */
593  string getName() {
594 
595  return time_vs_tot->GetName();
596 
597  }
598 
599 
600 };
601 
602 
603 
604 #endif
bool IsGood()
Check if the peak is good.
Definition: NBPulse.hh:439
#define WARNING(A)
Definition: JMessage.hh:63
double landau_s_min
Definition: NBPulse.hh:47
NBPulse(TH2D *h)
Constructor.
Definition: NBPulse.hh:76
string getName()
Get name of the hit time vs ToT histogram.
Definition: NBPulse.hh:593
TH2D * gettime_vs_tot()
Get the hit time vs ToT distribution.
Definition: NBPulse.hh:528
int n_sigma_peak
Definition: NBPulse.hh:45
Analyzes the signal of a nanobeacon in a PMT.
Definition: NBPulse.hh:33
void computeBaseline(TH1 *h)
Computes baseline of the hit time distribution measured by the PMT.
Definition: NBPulse.hh:279
RooWorkspace getWorkspace()
Get all the information from the fit.
Definition: NBPulse.hh:541
double getMeanToT()
Get the mean of the ToT distribution of the hits produced by the nanobeacon.
Definition: NBPulse.hh:567
NBPulse()
Default constructor.
Definition: NBPulse.hh:66
bool saturated_hit
Definition: NBPulse.hh:55
TH1D * tot_peak
Definition: NBPulse.hh:37
void fit()
Fits the hit nanobeacon signal to a model composed by a Landau and a Gauss functions.
Definition: NBPulse.hh:355
void initialize()
Leaves the pulse ready for analysis by projecting the time vs ToT distribution to the time axis and m...
Definition: NBPulse.hh:184
TH2D * time_vs_tot
Definition: NBPulse.hh:35
bool weak
Definition: NBPulse.hh:59
void analyzeFast()
Performs a fast analysis of the hit time distribution.
Definition: NBPulse.hh:198
Double_t G1(const Double_t x)
Integral of method g1.
Definition: JQuantiles.cc:37
bool analyzed
Definition: NBPulse.hh:49
~NBPulse()
Destructor.
Definition: NBPulse.hh:120
TH1D * gettot_peak()
Get the hit time distribution.
Definition: NBPulse.hh:514
double Kolmogorov_Smirnov_uniform(TH1D *h)
Performs a Kolmogorov-Smirnov compatibility test between the hit time distribution and a uniform dist...
Definition: NBPulse.hh:141
TH1D * getHtime_full()
Get the hit time distribution.
Definition: NBPulse.hh:488
bool IsFitted()
Check if the peak is fitted.
Definition: NBPulse.hh:451
bool IsWeak()
Check if the hit time distribution is weak.
Definition: NBPulse.hh:475
bool fitted
Definition: NBPulse.hh:51
TCanvas * c1
Global variables to handle mouse events.
double tpeak
Definition: NBPulse.hh:43
TH1D * gettime_peak()
Get the hit time distribution.
Definition: NBPulse.hh:501
bool is_good
Definition: NBPulse.hh:53
pair< double, double > baseline
Definition: NBPulse.hh:41
double getPeakTime()
Get the arrival time of the nanobeacon pulse.
Definition: NBPulse.hh:554
bool saturated_tot
Definition: NBPulse.hh:57
bool IsSaturatedHit()
Check if the hit time distribution is saturated.
Definition: NBPulse.hh:463
RooWorkspace w
Definition: NBPulse.hh:39
double getSigmaToT()
Get the standard deviation of the ToT distribution of the hits produced by the nanobeacon.
Definition: NBPulse.hh:580