Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
OnlBbcSig.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file OnlBbcSig.cc
1 #include "OnlBbcSig.h"
2 //#include "RunningStats.h"
3 
4 #include <TFile.h>
5 #include <TTree.h>
6 #include <TF1.h>
7 #include <TH2.h>
8 //#include <THnSparse.h>
9 #include <TSpline.h>
10 #include <TPad.h>
11 #include <TMath.h>
12 #include <TGraphErrors.h>
13 #include <TSpectrum.h>
14 
15 #include <iostream>
16 #include <fstream>
17 #include <limits>
18 
19 using namespace std;
20 
21 
22 OnlBbcSig::OnlBbcSig(const int chnum, const int nsamp) :
23  ch{chnum},
24  nsamples{nsamp},
25  f_ampl{0},
26  f_time{0},
27  f_time_offset{4.0}, // time shift from fit
28  f_integral{0.}, // time shift from fit
29  hRawPulse{nullptr},
30  hSubPulse{nullptr},
31  hpulse{nullptr},
32  gRawPulse{nullptr},
33  gSubPulse{nullptr},
34  gpulse{nullptr},
35  hPed0{nullptr},
36  ped0{0}, // ped average
37  ped0rms{0},
39  minped0samp{-9999},
40  maxped0samp{-9999},
41  minped0x{0.},
42  maxped0x{0.},
44  h2Template{nullptr},
45  h2Residuals{nullptr},
46  // range of good amplitudes for templates
47  // units are usually in ADC counts
48  hAmpl{nullptr},
49  hTime{nullptr},
58  template_fcn{nullptr},
59  verbose{0}
60 {
61  //cout << "In OnlBbcSig::OnlBbcSig(" << ch << "," << nsamples << ")" << endl;
62 
63 }
64 
65 
66 void OnlBbcSig::Init()
67 {
68  TString name;
69 
70  name = "hrawpulse"; name += ch;
71  hRawPulse = new TH1F(name,name,nsamples,-0.5,nsamples-0.5);
72  name = "hsubpulse"; name += ch;
73  hSubPulse = new TH1F(name,name,nsamples,-0.5,nsamples-0.5);
74 
75  //gRawPulse = new TGraphErrors(nsamples);
76  gRawPulse = new TGraphErrors();
77  name = "grawpulse"; name += ch;
78  gRawPulse->SetName(name);
79  //gSubPulse = new TGraphErrors(nsamples);
80  gSubPulse = new TGraphErrors();
81  name = "gsubpulse"; name += ch;
82  gSubPulse->SetName(name);
83 
84  hpulse = hRawPulse; // hpulse,gpulse point to raw by default
85  gpulse = gRawPulse; // we switch to sub for default if ped is applied
86 
87  //ped0stats = new RunningStats();
88  name = "hPed0_"; name += ch;
89  hPed0 = new TH1F(name,name,16384,-0.5,16383.5);
90  //hPed0 = new TH1F(name,name,10000,1,0); // automatically determine the range
91 
92  SetTemplateSize(120,2048,-2,9.9);
93 }
94 
95 void OnlBbcSig::SetTemplateSize(const Int_t nptsx, const Int_t nptsy, const Double_t begt, const Double_t endt)
96 {
97  template_npointsx = nptsx;
98  template_npointsy = nptsy;
99  template_begintime = begt;
100  template_endtime = endt;
101 
104 
105  Double_t xbinwid = (template_endtime - template_begintime)/(template_npointsx-1);
106  Double_t ybinwid = (1.1+0.1)/template_npointsy; // yscale... should we vary this?
107  if ( h2Template ) delete h2Template;
108  if ( h2Residuals ) delete h2Residuals;
109 
110  TString name = "h2Template"; name += ch;
111  h2Template = new TH2F(name,name,template_npointsx,template_begintime-xbinwid/2.,template_endtime+xbinwid/2,
112  template_npointsy,-0.1+ybinwid/2.0,1.1+ybinwid/2.0);
113 
114  name = "h2Residuals"; name += ch;
115  h2Residuals = new TH2F(name,name,template_npointsx,template_begintime-xbinwid/2.,template_endtime+xbinwid/2,
116  80,-20,20);
117 
118  /*
119  int nbins[] = { template_npointsx, nbinsy };
120  Double_t lowrange[] = { template_begintime-xbinwid/2.0, -0.1+ybinwid/2.0 };
121  Double_t highrange[] = { template_endtime+xbinwid/2.0, 1.1+ybinwid/2.0 };
122  h2Template = new THnSparseF(name,name,2,nbins,lowrange,highrange);
123  */
124  //h2Template->cd( gDirectory );
125 
126 }
127 
129 {
130  delete hRawPulse;
131  delete hSubPulse;
132  delete gRawPulse;
133  delete gSubPulse;
134  //delete ped0stats;
135  delete hPed0;
136  //h2Template->Write();
137  delete h2Template;
138  delete h2Residuals;
139  delete hAmpl;
140  delete hTime;
141  delete template_fcn;
142 
143 }
144 
145 void OnlBbcSig::SetTemplateMinMaxGoodADC(const Double_t min, const Double_t max)
146 {
149 }
150 
151 void OnlBbcSig::SetTemplateMinMaxFitRange(const Double_t min, const Double_t max)
152 {
154  template_max_xrange = max;
155 }
156 
157 // This sets y, and x to sample number (starts at 0)
158 void OnlBbcSig::SetY(const Float_t *y, const int invert)
159 {
160  if ( hRawPulse == nullptr )
161  {
162  Init();
163  }
164 
165  hpulse->Reset();
166  f_ampl = -9999.;
167  f_time = -9999.;
168 
169  for (int isamp=0; isamp<nsamples; isamp++)
170  {
171  hRawPulse->SetBinContent( isamp+1, y[isamp] );
172  gRawPulse->SetPoint( isamp, Double_t(isamp), y[isamp] );
173  }
174 
175  // Apply pedestal
176  if ( use_ped0 != 0 || minped0samp >= 0 || minped0x != maxped0x )
177  {
178  //cout << "sub" << endl;
179 
180  if ( minped0samp >= 0 )
181  {
183  }
184  else if ( minped0x != maxped0x )
185  {
187  }
188 
189  for (int isamp=0; isamp<nsamples; isamp++)
190  {
191  hSubPulse->SetBinContent( isamp+1, invert*(y[isamp]-ped0) );
192  hSubPulse->SetBinError( isamp+1, ped0rms );
193  gSubPulse->SetPoint( isamp, (Double_t)isamp, invert*(y[isamp]-ped0) );
194  gSubPulse->SetPointError( isamp, 0., ped0rms );
195  }
196  }
197 }
198 
199 void OnlBbcSig::SetXY(const Float_t *x, const Float_t *y, const int invert)
200 {
201  if ( hRawPulse == nullptr )
202  {
203  Init();
204  }
205 
206  hRawPulse->Reset();
207  hSubPulse->Reset();
208 
209  f_ampl = -9999.;
210  f_time = -9999.;
211 
212  //cout << "nsamples " << nsamples << endl;
213  //cout << "use_ped0 " << use_ped0 << "\t" << ped0 << endl;
214 
215  for( int isamp=0; isamp<nsamples; isamp++ )
216  {
217  //cout << "aaa\t" << isamp << "\t" << x[isamp] << "\t" << y[isamp] << endl;
218  hRawPulse->SetBinContent( isamp+1, y[isamp] );
219  gRawPulse->SetPoint( isamp, x[isamp], y[isamp] );
220  }
221 
222  if ( use_ped0 != 0 || minped0samp >= 0 || minped0x != maxped0x )
223  {
224  if ( minped0samp >= 0 )
225  {
227  }
228  else if ( minped0x != maxped0x )
229  {
231  }
232 
233  for (int isamp=0; isamp<nsamples; isamp++)
234  {
235  {
236  // How do we handle data which is not in samples, but is in time,
237  // such as DRS4 data
238  //cout << "bbb\t" << isamp << "\t" << x[isamp] << "\t" << invert*(y[isamp]-ped0) << endl;
239  hSubPulse->SetBinContent( isamp+1, invert*(y[isamp]-ped0) );
240  hSubPulse->SetBinError( isamp+1, ped0rms );
241  gSubPulse->SetPoint( isamp, x[isamp], invert*(y[isamp]-ped0) );
242  gSubPulse->SetPointError( isamp, 0., ped0rms );
243  }
244  }
245  }
246 }
247 
248 Double_t OnlBbcSig::GetSplineAmpl()
249 {
250  TSpline3 s3("s3",gSubPulse);
251 
252  // First find maximum, to rescale
253  f_ampl = -999999.;
254  double step_size = 0.01;
255  //cout << "step size " << step_size << endl;
256  for (double ix=0; ix<nsamples; ix += step_size)
257  {
258  Double_t val = s3.Eval(ix);
259  if ( val > f_ampl )
260  {
261  f_ampl = val;
262  }
263  }
264 
265  return f_ampl;
266 }
267 
268 // This does a straight line fit for now...
269 /*
270 Double_t OnlBbcSig::FitPulse()
271 {
272  const Double_t pedcut[] = {1650,1560};
273  const Double_t maxcut[] = {12000,12600};
274 
275  TF1 f("f","pol1",0,31);
276  f.SetParameter(0,0);
277  f.SetParameter(1,3000.);
278 
279  Double_t start = 0;
280  Double_t stop = 31;
281  Double_t x, y;
282  for (int isamp=0; isamp<nsamples; isamp++)
283  {
284  gpulse->GetPoint(isamp,x,y);
285  if ( y>pedcut[ch] )
286  {
287  start = x;
288  break;
289  }
290  }
291 
292  for (int isamp=(int)start; isamp<nsamples; isamp++)
293  {
294  gpulse->GetPoint(isamp,x,y);
295  if ( y>maxcut[ch] )
296  {
297  stop = x-1;
298  break;
299  }
300  }
301 
302  f.SetRange(start,stop);
303  gpulse->Fit(&f,"R");
304 
305  Double_t slope = f.GetParameter(1);
306 
307  //cout << "xxx " << slope << endl;
308  return slope;
309 }
310 */
311 
312 void OnlBbcSig::FillPed0(const Int_t sampmin, const Int_t sampmax)
313 {
314  Double_t x, y;
315  for (int isamp=sampmin; isamp<=sampmax; isamp++)
316  {
317  gRawPulse->GetPoint(isamp,x,y);
318  //gRawPulse->Print("all");
319  hPed0->Fill( y );
320 
321  /*
322 // chiu taken out
323  ped0stats->Push( y );
324  ped0 = ped0stats->Mean();
325  ped0rms = ped0stats->RMS();
326  */
327 
328  //cout << "ped0 " << ch << " " << n << "\t" << ped0 << endl;
329  //cout << "ped0 " << ch << "\t" << ped0 << endl;
330  }
331 
332 }
333 
334 
335 void OnlBbcSig::FillPed0(const Double_t begin, const Double_t end)
336 {
337  Double_t x, y;
338  Int_t n = gRawPulse->GetN();
339  for (int isamp=0; isamp<n; isamp++)
340  {
341  gRawPulse->GetPoint(isamp,x,y);
342  if ( x>=begin && x<=end )
343  {
344  hPed0->Fill( y );
345 
346  /*
347  ped0stats->Push( y );
348  ped0 = ped0stats->Mean();
349  ped0rms = ped0stats->RMS();
350  */
351 
352  //cout << "ped0 " << ch << " " << n << "\t" << x << "\t" << y << endl;
353  }
354 
355  // quit if we are past the ped region
356  if ( x>end ) break;
357  }
358 
359 }
360 
361 
362 void OnlBbcSig::SetPed0(const Double_t mean, const Double_t rms)
363 {
364  ped0 = mean;
365  ped0rms = rms;
366  use_ped0 = 1;
367  hpulse = hSubPulse;
368  gpulse = gSubPulse;
369  //if ( ch==8 ) cout << "ch " << ch << " Ped = " << ped0 << endl;
370 }
371 
372 // Get Event by Event Ped0 if requested
373 void OnlBbcSig::CalcEventPed0(const Int_t minpedsamp, const Int_t maxpedsamp)
374 {
375  //if (ch==8) cout << "In OnlBbcSig::CalcEventPed0(int,int)" << endl;
376  hPed0->Reset();
377  //ped0stats->Clear();
378 
379  Double_t x, y;
380  for (int isamp=minpedsamp; isamp<=maxpedsamp; isamp++)
381  {
382  gRawPulse->GetPoint(isamp,x,y);
383 
384  hPed0->Fill(y);
385  //ped0stats->Push( y );
386  //if ( ch==8 ) cout << "ped0stats " << isamp << "\t" << y << endl;
387  }
388 
389 
390  // use straight mean for pedestal
391  // Could consider using fit to hPed0 to remove outliers
392  float mean = hPed0->GetMean();
393  float rms = hPed0->GetRMS();
394 
395  //SetPed0( ped0stats->Mean(), ped0stats->RMS() );
396 
397  SetPed0( mean, rms );
398  //if (ch==8) cout << "ped0stats mean, rms " << mean << "\t" << rms << endl;
399 }
400 
401 // Get Event by Event Ped0 if requested
402 void OnlBbcSig::CalcEventPed0(const Double_t minpedx, const Double_t maxpedx)
403 {
404  hPed0->Reset();
405  //ped0stats->Clear();
406 
407  Double_t x, y;
408  Int_t n = gRawPulse->GetN();
409 
410  for (int isamp=0; isamp<n; isamp++)
411  {
412  gRawPulse->GetPoint(isamp,x,y);
413 
414  if ( x>= minpedx && x<= maxpedx)
415  {
416  hPed0->Fill(y);
417  //ped0stats->Push( y );
418  }
419  }
420 
421  // use straight mean for pedestal
422  // Could consider using fit to hPed0 to remove outliers
423  SetPed0( hPed0->GetMean(), hPed0->GetRMS() );
424  /*
425  Double_t mean = ped0stats->Mean();
426  Double_t rms = ped0stats->RMS();
427  SetPed0( mean, rms );
428  */
429  //cout << "ped0stats " << mean << "\t" << rms << endl;
430 }
431 
432 Double_t OnlBbcSig::LeadingEdge(const Double_t threshold)
433 {
434  // Find first point above threshold
435  // We also make sure the next point is above threshold
436  // to get rid of a high fluctuation
437  int n = gSubPulse->GetN();
438  Double_t *x = gSubPulse->GetX();
439  Double_t *y = gSubPulse->GetY();
440 
441  int sample = -1;
442  for (int isamp=0; isamp<n; isamp++)
443  {
444  if ( y[isamp] > threshold )
445  {
446  if ( isamp==(n-1) || y[isamp+1] > threshold )
447  {
448  sample = isamp;
449  break;
450  }
451  }
452  }
453  if ( sample == -1 ) return -9999.; // no signal above threshold
454 
455  // Linear Interpolation of start time
456  Double_t dx = x[sample] - x[sample-1];
457  Double_t dy = y[sample] - y[sample-1];
458  Double_t dt1 = y[sample] - threshold;
459 
460  Double_t t0 = x[sample] - dt1*(dx/dy);
461 
462  return t0;
463 }
464 
465 Double_t OnlBbcSig::dCFD(const Double_t fraction_threshold)
466 {
467  // Find first point above threshold
468  // We also make sure the next point is above threshold
469  // to get rid of a high fluctuation
470  int n = gSubPulse->GetN();
471  Double_t *x = gSubPulse->GetX();
472  Double_t *y = gSubPulse->GetY();
473 
474  // Get max amplitude
475  Double_t ymax = TMath::MaxElement(n,y);
476  if ( f_ampl == -9999. ) f_ampl = ymax;
477 
478  Double_t threshold = fraction_threshold * ymax; // get fraction of amplitude
479  //cout << "threshold = " << threshold << "\tymax = " << ymax <<endl;
480 
481  int sample = -1;
482  for (int isamp=0; isamp<n; isamp++)
483  {
484  if ( y[isamp] > threshold )
485  {
486  if ( isamp==(n-1) || y[isamp+1] > threshold )
487  {
488  sample = isamp;
489  break;
490  }
491  }
492  }
493  if ( sample == -1 ) return -9999.; // no signal above threshold
494 
495  // Linear Interpolation of start time
496  Double_t dx = x[sample] - x[sample-1];
497  Double_t dy = y[sample] - y[sample-1];
498  Double_t dt1 = y[sample] - threshold;
499 
500  Double_t t0 = x[sample] - dt1*(dx/dy);
501 
502  return t0;
503 }
504 
505 Double_t OnlBbcSig::MBD(const Int_t max_samp)
506 {
507  // Get the amplitude of the sample number to get time
508  Double_t *y = gSubPulse->GetY();
509 
510  if ( y==0 ) {
511  cout << "ERROR y == 0" << endl;
512  return 0;
513  }
514 
515  // SHOULD INCLUDE TIME CALIBRATION HERE
516  Double_t t0 = y[max_samp];
517 
518  // Get max amplitude, and set it if it hasn't already been set
519  int n = gSubPulse->GetN();
520  Double_t ymax = TMath::MaxElement(n,y);
521  if ( f_ampl == -9999. ) f_ampl = ymax;
522 
523  return t0;
524 }
525 
526 Double_t OnlBbcSig::Integral(const Double_t xmin, const Double_t xmax)
527 {
528  Int_t n = gSubPulse->GetN();
529  Double_t* x = gSubPulse->GetX();
530  Double_t* y = gSubPulse->GetY();
531 
532  f_integral = 0.;
533  for (int ix=0; ix<n; ix++)
534  {
535  if (x[ix]>=xmin && x[ix]<=xmax)
536  {
537  // Get dx
538  Double_t dx = (x[ix+1]-x[ix-1])/2.0;
539  f_integral += (y[ix]*dx);
540  }
541  }
542 
543  return f_integral;
544 }
545 
546 void OnlBbcSig::LocMax(Double_t& x_at_max, Double_t& ymax, Double_t xminrange, Double_t xmaxrange)
547 {
548  // Find index of maximum peak
549  Int_t n = gSubPulse->GetN();
550  Double_t* x = gSubPulse->GetX();
551  Double_t* y = gSubPulse->GetY();
552 
553  // if flipped or equal, we search the whole range
554  if ( xmaxrange <= xminrange )
555  {
556  xminrange = -DBL_MAX;
557  xmaxrange = DBL_MAX;
558  }
559 
560  ymax = -DBL_MAX;
561 
562  for (int i=0; i<n; i++)
563  {
564  // Skip if out of range
565  if ( x[i] < xminrange ) continue;
566  if ( x[i] > xmaxrange ) break;
567 
568  if ( y[i] > ymax )
569  {
570  ymax = y[i];
571  x_at_max = x[i];
572  }
573  }
574 
575 }
576 
577 void OnlBbcSig::LocMin(Double_t& x_at_max, Double_t& ymin, Double_t xminrange, Double_t xmaxrange)
578 {
579  // Find index of minimum peak (for neg signals)
580  Int_t n = gSubPulse->GetN();
581  Double_t* x = gSubPulse->GetX();
582  Double_t* y = gSubPulse->GetY();
583 
584  // if flipped or equal, we search the whole range
585  if ( xmaxrange <= xminrange )
586  {
587  xminrange = -DBL_MAX;
588  xmaxrange = DBL_MAX;
589  }
590 
591  ymin = DBL_MAX;
592 
593  for (int i=0; i<n; i++)
594  {
595  // Skip if out of range
596  if ( x[i] < xminrange ) continue;
597  if ( x[i] > xmaxrange ) break;
598 
599  if ( y[i] < ymin )
600  {
601  ymin = y[i];
602  x_at_max = x[i];
603  }
604  }
605 
606  // old way of getting locmax
607  //int locmax = TMath::LocMin(n,y);
608 }
609 
610 void OnlBbcSig::Print()
611 {
612  Double_t x, y;
613  cout << "CH " << ch << endl;
614  for (int isamp=0; isamp<nsamples; isamp++)
615  {
616  gpulse->GetPoint(isamp,x,y);
617  cout << isamp << "\t" << x << "\t" << y << endl;
618  }
619 }
620 
622 {
623  // Make sure TCanvas is created externally!
624  gPad->Modified();
625  gPad->Update();
626  cout << ch << " ? ";
627  TString junk;
628  cin >> junk;
629 
630  if (junk[0] == 'w' || junk[0] == 's')
631  {
632  TString name = "ch"; name += ch; name += ".png";
633  gPad->SaveAs( name );
634  }
635 }
636 
637 Double_t OnlBbcSig::TemplateFcn(const Double_t *x, const Double_t *par)
638 {
639  // par[0] is the amplitude (relative to the spline amplitude)
640  // par[1] is the start time (in sample number)
641  // x[0] units are in sample number
642  Double_t xx = x[0]-par[1];
643  Double_t f = 0.;
644 
645  //verbose = 100;
646 
647  // When fit is out of limits of good part of spline, ignore fit
648  if ( xx<template_begintime || xx>template_endtime )
649  {
650  TF1::RejectPoint();
651  if ( xx < template_begintime )
652  {
653  //Double_t x0,y0;
654  Double_t y0 = template_y[0];
655  return par[0]*y0;
656  }
657  else if ( xx > template_endtime )
658  {
659  //Double_t x0,y0;
660  Double_t y0 = template_y[template_npointsx-1];
661  return par[0]*y0;
662  }
663  }
664 
665  // Linear Interpolation of template
666  Double_t x0 = 0.;
667  Double_t y0 = 0.;
668  Double_t x1 = 0.;
669  Double_t y1 = 0.;
670 
671  // find the index in the vector which is closest to xx
672  Double_t step = (template_endtime - template_begintime) / (template_npointsx-1);
673  Double_t index = (xx - template_begintime)/step;
674 
675  int ilow = TMath::FloorNint( index );
676  int ihigh = TMath::CeilNint( index );
677  if ( ilow < 0 || ihigh >= template_npointsx )
678  {
679  if ( verbose>0 )
680  {
681  cout << "ERROR, ilow ihigh " << ilow << "\t" << ihigh << endl;
682  cout << " " << xx << " " << x[0] << " " << par[1] << endl;
683  }
684 
685  if ( ilow<0 )
686  {
687  ilow = 0;
688  }
689  else if ( ihigh >= template_npointsx )
690  {
691  ihigh = template_npointsx - 1;
692  }
693  }
694 
695  if ( ilow==ihigh )
696  {
697  f = par[0]*template_y[ilow];
698  }
699  else
700  {
701  x0 = template_begintime + ilow*step;
702  y0 = template_y[ilow];
703  x1 = template_begintime + ihigh*step;
704  y1 = template_y[ihigh];
705  f = par[0]*(y0+((y1-y0)/(x1-x0))*(xx-x0)); // linear interpolation
706  }
707 
708  return f;
709 }
710 
712 {
713  //verbose = 100; // uncomment to see fits
714  if ( verbose>0 ) cout << "Fitting ch " << ch << endl;
715 
716  /*
717  Int_t maxadc = -1;
718  Int_t peak_samp = -1;
719  for (int isamp=0; isamp<NSAMPLES; isamp++)
720  {
721  x[isamp] = (Float_t)isamp;
722  adcsub[isamp] = adc[isamp] - ped;
723  adcerr[isamp] = pedrms;
724  if ( adcsub[isamp]>maxadc )
725  {
726  maxadc = adcsub[isamp];
727  peak_samp = isamp;
728  }
729  }
730 
731  TGraphErrors gSubpulse(NSAMPLES,x,adcsub,0,adcerr);
732  if ( verbose>10 )
733  {
734  gSubPulse->SetMarkerStyle(20);
735  gSubPulse->SetMarkerColor(2);
736  gSubPulse->SetLineColor(2);
737  }
738 
739  fit_shape = fit_pshape[ch];
740  fit_sherr = fit_psherr[ch];
741  //if ( verbose>10 ) cout << "CH is " << ch << "\t" << fit_shape << endl;
742  */
743 
744  // Check if channel is empty
745  if ( gSubPulse->GetN() == 0 )
746  {
747  f_ampl = -9999.;
748  f_time = -9999.;
749  //cout << "gSubPulse empty" << endl;
750  return 1;
751  }
752 
753  // Get x-position of maximum
754  Double_t x_at_max, ymax;
755  LocMax(x_at_max, ymax);
756 
757  template_fcn->SetParameters(ymax, x_at_max);
758 
759  //template_fcn->SetParLimits(1,-5.,4.);
761  if ( verbose==0 ) gSubPulse->Fit(template_fcn,"RNQ");
762  else gSubPulse->Fit(template_fcn,"R");
763 
764  // Get fit parameters
765  f_ampl = template_fcn->GetParameter(0);
766  f_time = template_fcn->GetParameter(1);
767 
768  if ( verbose>0 && fabs(f_ampl) > 0. )
769  {
770  cout << "FitTemplate " << f_ampl << "\t" << f_time << endl;
771  gSubPulse->Draw("ap");
772  template_fcn->SetLineColor(4);
773  template_fcn->Draw("same");
774  PadUpdate();
775  }
776 
777  /*
778  Double_t chi2ndf = template_fcn->GetChisquare()/template_fcn->GetNDF();
779  // Store fit values
780  amp = static_cast<Float_t>( template_fcn->GetParameter(0) );
781  fquality = (Short_t)chi2ndf; // Need to define this still
782 
783  // For the tdc, we choose 360 tdc ticks per sample
784  Float_t samp_number = 7.0+template_fcn->GetParameter(1);
785  if ( samp_number<0. )
786  {
787  samp_number = 0.;
788  amp = 0; // for now, if the time is bad, we zero out the channel
789  }
790  else if ( samp_number>18.0 )
791  {
792  samp_number = 18.0;
793  amp = 0;
794  }
795  tdc = static_cast<Short_t>( samp_number*360. );
796  */
797 
798  return 1;
799 }
800 
802 {
803  //verbose = 100;
804 
805  if ( ! hAmpl )
806  {
807  TString name = "hAmpl"; name += ch;
808  hAmpl = new TH1F(name,name,17100,-100,17000);
809  }
810  if ( ! hTime )
811  {
812  TString name = "hTime"; name += ch;
813  hTime = new TH1F(name,name,3100,0,31);
814  }
815 
816 
817  Double_t max = TMath::MaxElement(gSubPulse->GetN(),gSubPulse->GetY());
818 
819  if ( max < template_min_good_amplitude ) return 0;
820 
821  if ( verbose ) gSubPulse->Draw("ap");
822  TSpline3 s3("s3",gSubPulse);
823 
824  // First find maximum, to rescale
825  f_ampl = -999999.;
826  double step_size = h2Template->GetXaxis()->GetBinWidth(1);
827  //cout << "step size " << step_size << endl;
828  for (double ix=0; ix<nsamples; ix += step_size)
829  {
830  Double_t val = s3.Eval(ix);
831  if ( val > f_ampl )
832  {
833  f_ampl = val;
834  }
835  }
836 
837  //cout << f_ampl << endl;
838  if ( f_ampl<template_min_good_amplitude || f_ampl>template_max_good_amplitude ) return 0;
839 
840  if ( verbose>0 )
841  {
842  //cout << ch << endl;
843  s3.SetLineColor(2);
844  s3.Draw("same");
845  gSubPulse->Draw("p");
846  PadUpdate();
847  }
848 
849 
850  // Now go back to find the time by finding x at midpoint of rise
851  for (double ix=0; ix<nsamples; ix += step_size)
852  {
853  Double_t val = s3.Eval(ix);
854  if ( val > 0.5*f_ampl )
855  {
856  // interpolate midpoint
857  Double_t dy_mid = val - 0.5*f_ampl;
858  Double_t dy_prev = val - s3.Eval(ix-step_size);
859  Double_t dx_prev = step_size;
860 
861  f_time = ix - (dy_mid/dy_prev)*dx_prev;
862  break;
863  }
864  }
865 
866  // correct the pulse back
868 
869  // Get Time and Max of spline to rescale
870  //cout << f_ampl << "\t" << time << endl;
871  hAmpl->Fill( f_ampl );
872  hTime->Fill( f_time );
873 
874  //cout << "nsamples " << nsamples << endl;
875  for (int isamp=0; isamp<nsamples; isamp++)
876  {
877  Double_t x, y;
878  gSubPulse->GetPoint(isamp,x,y);
879 
880  Double_t fillvalues[2] = {0.};
881  fillvalues[0] = x - f_time; //corr_time
882  if ( f_ampl != 0. )
883  {
884  fillvalues[1] = y/f_ampl; //scaled_ampl
885  }
886 
887  h2Template->Fill(fillvalues[0],fillvalues[1]);
888  //h2Template->Fill( fillvalues );
889 
890  // For splines, by defn they go through the data pts so residuals = 0
891  //h2Residuals->Fill( fillvalues[0], y - s3.Eval(x) );
892  }
893 
894  return 1;
895 }
896 
897 
898 void OnlBbcSig::MakeAndWriteTemplate(ostream& out, ostream& oerr)
899 {
900  //verbose = 100;
901  if ( verbose ) cout << "In OnlBbcSig::MakeAndWriteTemplate" << endl;
902 
903  //Int_t nbinsy = h2Template->GetNbinsX();
904 
905  TString name = h2Template->GetName(); name += "_py";
906  TH1 *hprojy = h2Template->ProjectionY(name,1,1,"e");
907  TF1 *gaus = new TF1("gaussian","gaus",template_begintime,template_endtime);
908  gaus->SetLineColor(2);
909 
910  if ( verbose )
911  {
912  h2Template->Draw("colz");
913  //TH2 *h = h2Template->Projection(1,0);
914  //h->Draw("colz");
915  PadUpdate();
916  //delete h;
917  }
918 
919  TString fitarg = "R";
920  if ( verbose==0 ) fitarg += "NQ";
921 
922  for (int ibin=0; ibin<template_npointsx; ibin++)
923  {
924  hprojy = h2Template->ProjectionY(name,ibin+1,ibin+1,"e");
925 
926  //h2Template->GetAxis(0)->SetRange(ibin+1,ibin+1);
927  //TH1 *hprojy = h2Template->Projection(1,"e");
928  //hprojy->Sumw2();
929 
930  Double_t ncounts = hprojy->Integral();
931  if ( ncounts < 10. )
932  {
933  //cout << "ERROR, " << ch << "\t" << ibin << "\tToo few entries " << hprojy->Integral() << endl;
934  fitarg += "WLL";
935  }
936  else if ( ncounts<100. )
937  {
938  fitarg += "WLL";
939  }
940 
941  Double_t peak = hprojy->GetBinContent( hprojy->GetMaximumBin() );
942  Double_t mean = hprojy->GetBinCenter( hprojy->GetMaximumBin() );
943  Double_t rms = hprojy->GetRMS();
944  //cout << ch << "\t" << ibin << "\t" << peak << "\t" << mean << endl;
945  //gaus->SetParameters(peak,mean,0.01);
946  gaus->SetParameters(peak,mean,rms);
947 
948  if ( ncounts>=10 ) hprojy->Fit(gaus,fitarg);
949 
950  // See the fits
951  if ( verbose )
952  {
953  hprojy->Draw();
954  PadUpdate();
955  }
956 
957  /*
958  template_y[ibin] = gaus->GetParameter(1);
959  template_yrms[ibin] = gaus->GetParameter(2);
960  */
961 
962  template_y[ibin] = hprojy->GetMean();
963  template_yrms[ibin] = hprojy->GetRMS();
964 
965  if ( verbose ) cout << "ibin " << ibin << "\t" << template_y[ibin] << "\t" << template_yrms[ibin] << endl;
966  //delete hprojy;
967 
968  }
969  delete hprojy;
970  delete gaus;
971 
972  /* //thnsparse
973  h2Template->GetAxis(0)->SetRange(1,template_npointsx);
974  h2Template->Write();
975  */
976 
977  out << ch << "\t" << template_npointsx << "\t" << template_begintime << "\t" << template_endtime << endl;
978  oerr << ch << "\t" << template_npointsx << "\t" << template_begintime << "\t" << template_endtime << endl;
979  for (int ibin=0; ibin<template_npointsx; ibin++)
980  {
981  // Write out the template value for bin i
982  out << template_y[ibin] << "\t";
983  if (ibin%10==9) out << endl;
984 
985  // Now write out the rms
986  oerr << template_yrms[ibin] << "\t";
987  if (ibin%10==9) oerr << endl;
988  }
989  out << endl;
990  oerr << endl;
991 
992 }
993 
995 {
996  //verbose = 100;
997  if ( ! hAmpl )
998  {
999  TString name = "hAmpl"; name += ch;
1000  hAmpl = new TH1F(name,name,17100,-100,17000);
1001  }
1002  if ( ! hTime )
1003  {
1004  TString name = "hTime"; name += ch;
1005  hTime = new TH1F(name,name,3100,0,31);
1006  }
1007 
1008 
1009  FitTemplate();
1010 
1011  if ( f_ampl<template_min_good_amplitude || f_ampl>template_max_good_amplitude ) return;
1012 
1013  // Get Time and Max of spline to rescale
1014  if ( verbose ) cout << "ampl time " << ch << "\t" << f_ampl << "\t" << f_time << endl;
1015  hAmpl->Fill( f_ampl );
1016  hTime->Fill( f_time );
1017 
1018  // Rescale and shift time using template fit
1019  for (int isamp=0; isamp<nsamples; isamp++)
1020  {
1021  Double_t x, y;
1022  gSubPulse->GetPoint(isamp,x,y);
1023 
1024  Double_t fillvalues[2] = {0};
1025  fillvalues[0] = x - f_time; //corr_time
1026  //Double_t scaled_ampl = 0.;
1027  if ( f_ampl != 0 )
1028  {
1029  fillvalues[1] = y/f_ampl; //scaled_ampl
1030  }
1031  h2Template->Fill( fillvalues[0], fillvalues[1] );
1032  //h2Template->Fill( fillvalues );
1033  }
1034 }
1035 
1036 
1037 int OnlBbcSig::ReadTemplate(ifstream& shapefile, ifstream& sherrfile)
1038 {
1039  //verbose = 100;
1040  Int_t temp_ch = -9999;
1041  Int_t temp_nsamples;
1042  Double_t temp_begintime;
1043  Double_t temp_endtime;
1044 
1045  template_y.clear();
1046  template_yrms.clear();
1047 
1048  // Template
1049  while ( shapefile >> temp_ch >> temp_nsamples >> temp_begintime >> temp_endtime )
1050  {
1051  if ( verbose ) cout << "shape " << temp_ch << "\t" << temp_nsamples << "\t" << temp_begintime << "\t" << temp_endtime << endl;
1052  if ( temp_ch != ch )
1053  {
1054  cerr << "ERROR in shape: ch is " << temp_ch << "but should be " << ch << endl;
1055  return -1;
1056  }
1057 
1058  Double_t temp_val;
1059  for (int isamp=0; isamp<temp_nsamples; isamp++)
1060  {
1061  shapefile >> temp_val;
1062  template_y.push_back( temp_val );
1063  if ( verbose )
1064  {
1065  cout << template_y[isamp] << " ";
1066  if ( isamp%10==9 ) cout << endl;
1067  }
1068  }
1069  if ( verbose ) cout << endl;
1070  break;
1071  }
1072 
1073  // Now get the errors
1074  while ( sherrfile >> temp_ch >> temp_nsamples >> temp_begintime >> temp_endtime )
1075  {
1076  if ( verbose ) cout << "sherr " << temp_ch << "\t" << temp_nsamples << "\t" << temp_begintime << "\t" << temp_endtime << endl;
1077  if ( temp_ch != ch )
1078  {
1079  cerr << "ERROR in sherr: ch is " << temp_ch << " but should be " << ch << endl;
1080  return -1;
1081  }
1082 
1083  Double_t temp_val;
1084  for (int isamp=0; isamp<temp_nsamples; isamp++)
1085  {
1086  sherrfile >> temp_val;
1087  template_yrms.push_back( temp_val );
1088  if ( verbose )
1089  {
1090  cout << template_yrms[isamp] << " ";
1091  if ( isamp%10==9 ) cout << endl;
1092  }
1093  }
1094  if ( verbose ) cout << endl;
1095  break;
1096  }
1097 
1098  TString name = "template_fcn"; name += ch;
1099  template_fcn = new TF1(name,this,&OnlBbcSig::TemplateFcn,0,nsamples,2,"OnlBbcSig","TemplateFcn");
1100  template_fcn->SetParameters(1,8);
1101 
1102  return 1;
1103 }
1104