]> git.uio.no Git - u/mrichter/AliRoot.git/blame - PHOS/AliPHOSRawFitterv2.cxx
updated for e-h analysis
[u/mrichter/AliRoot.git] / PHOS / AliPHOSRawFitterv2.cxx
CommitLineData
379c5c09 1/**************************************************************************
2 * Copyright(c) 2007, ALICE Experiment at CERN, All rights reserved. *
3 * *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
6 * *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
15
16/* $Id: $ */
17
6a265faf 18// This class extracts the signal parameters (energy, time, quality)
19// from ALTRO samples. Energy is in ADC counts, time is in time bin units.
20// Class uses FastFitting algorithm to fit sample and extract time and Amplitude
21// and evaluate sample quality = (chi^2/NDF)/some parameterization providing
22// efficiency close to 100%
379c5c09 23//
24// Typical use case:
25// AliPHOSRawFitter *fitter=new AliPHOSRawFitter();
379c5c09 26// fitter->SetChannelGeo(module,cellX,cellZ,caloFlag);
27// fitter->SetCalibData(fgCalibData) ;
1dfadc32 28// fitter->Eval(sig,sigStart,sigLength);
379c5c09 29// Double_t amplitude = fitter.GetEnergy();
30// Double_t time = fitter.GetTime();
31// Bool_t isLowGain = fitter.GetCaloFlag()==0;
32
6a265faf 33// Author: Dmitri Peressounko (after A.Pavlinov - see RAW/AliCaloFastAltroFitv0.cxx)
379c5c09 34
35// --- ROOT system ---
6a265faf 36#include "TArrayI.h"
379c5c09 37#include "TList.h"
38#include "TMath.h"
6a265faf 39#include "TH1I.h"
379c5c09 40#include "TF1.h"
6a265faf 41#include "TCanvas.h"
42#include "TFile.h"
379c5c09 43#include "TROOT.h"
44
45// --- AliRoot header files ---
46#include "AliLog.h"
47#include "AliPHOSCalibData.h"
48#include "AliPHOSRawFitterv2.h"
49#include "AliPHOSPulseGenerator.h"
50
51ClassImp(AliPHOSRawFitterv2)
52
53//-----------------------------------------------------------------------------
54AliPHOSRawFitterv2::AliPHOSRawFitterv2():
55 AliPHOSRawFitterv0(),
6a265faf 56 fAlpha(0.1),fBeta(0.035),fMax(0)
379c5c09 57{
58 //Default constructor.
379c5c09 59}
60
61//-----------------------------------------------------------------------------
62AliPHOSRawFitterv2::~AliPHOSRawFitterv2()
63{
64 //Destructor.
65}
66
67//-----------------------------------------------------------------------------
68AliPHOSRawFitterv2::AliPHOSRawFitterv2(const AliPHOSRawFitterv2 &phosFitter ):
6a265faf 69 AliPHOSRawFitterv0(phosFitter),
70 fAlpha(0.1),fBeta(0.035),fMax(0)
379c5c09 71{
72 //Copy constructor.
379c5c09 73}
74
75//-----------------------------------------------------------------------------
6a265faf 76AliPHOSRawFitterv2& AliPHOSRawFitterv2::operator = (const AliPHOSRawFitterv2 & /*phosFitter*/)
379c5c09 77{
78 //Assignment operator.
379c5c09 79 return *this;
80}
81
82//-----------------------------------------------------------------------------
92236b27 83Bool_t AliPHOSRawFitterv2::Eval(const UShort_t *signal, Int_t sigStart, Int_t sigLength)
379c5c09 84{
85 //Extract an energy deposited in the crystal,
86 //crystal' position (module,column,row),
87 //time and gain (high or low).
88 //First collects sample, then evaluates it and if it has
89 //reasonable shape, fits it with Gamma2 function and extracts
90 //energy and time.
91
6a265faf 92 const Float_t maxEtoFit=5 ; //fit only samples above this energy, accept all samples (with good aRMS) below it
379c5c09 93 const Float_t kBaseLine = 1.0;
94 const Int_t kPreSamples = 10;
95
6a265faf 96 fOverflow = kFALSE ;
97 fEnergy=0 ;
98 if (fCaloFlag == 2 || fNBunches > 1) {
99 fQuality = 150;
100 return kTRUE;
101 }
102 if(fCaloFlag!=0 && fCaloFlag!=1){//Corrupted sample
103 fQuality=200;
104 fEnergy=0 ;
105 return kTRUE;
106 }
379c5c09 107
6a265faf 108 //Evaluate pedestals
109 Float_t pedMean = 0;
110 Float_t pedRMS = 0;
111 Int_t nPed = 0;
112 for (Int_t i=sigLength-kPreSamples; i<sigLength; i++) {
113 nPed++;
114 pedMean += signal[i];
115 pedRMS += signal[i]*signal[i] ;
116 }
379c5c09 117
6a265faf 118 fEnergy = -111;
119 fQuality= 999. ;
379c5c09 120 Double_t pedestal = 0;
379c5c09 121
122 if (fPedSubtract) {
123 if (nPed > 0) {
124 fPedestalRMS=(pedRMS - pedMean*pedMean/nPed)/nPed ;
125 if(fPedestalRMS > 0.)
126 fPedestalRMS = TMath::Sqrt(fPedestalRMS) ;
6a265faf 127 pedestal = (Double_t)(pedMean/nPed); // pedestal subtraction
379c5c09 128 }
129 else
130 return kFALSE;
131 }
132 else {
133 //take pedestals from DB
134 pedestal = (Double_t) fAmpOffset ;
379c5c09 135 }
136
379c5c09 137
6a265faf 138 //calculate rough quality of the sample and check for overflow
6a265faf 139 Int_t maxAmp=0 ;
140 Int_t minAmp= signal[0] ;
141 Int_t nMax = 0 ; //number of points in plato
142 Double_t aMean =0. ;
143 Double_t aRMS =0. ;
144 Double_t wts =0 ;
145 Bool_t falling = kTRUE ; //Bad monotoneusly falling sample
146 Bool_t rising = kTRUE ; //Bad monotoneusly riging sample
147 for (Int_t i=0; i<sigLength; i++){
148 if(signal[i] > pedestal){
149 Double_t de = signal[i] - pedestal ;
150 if(de > 1.) {
151 aMean += de*i ;
152 aRMS += de*i*i ;
153 wts += de;
154 }
155 if(signal[i] > maxAmp){
156 maxAmp = signal[i];
157 nMax=0;
6a265faf 158 }
159 if(signal[i] == maxAmp){
160 nMax++;
161 }
162 if(signal[i] < minAmp)
163 minAmp=signal[i] ;
164 if(falling && i>0 && signal[i]<signal[i-1])
165 falling=kFALSE ;
166 if(rising && i>0 && signal[i]>signal[i-1])
167 rising=kFALSE ;
168 }
169 }
170
171 if(rising || falling){//bad "rising" or falling sample
172 fEnergy = 0. ;
173 fTime = 0. ; //-999. ;
174 fQuality= 250. ;
175 return kTRUE ;
379c5c09 176 }
6a265faf 177 if(maxAmp-minAmp<3 && maxAmp>7 && sigLength>20){ //bad flat sample
178 fEnergy = 0. ;
179 fTime = 0; //-999. ;
180 fQuality= 260. ;
181 return kTRUE ;
379c5c09 182 }
183
6a265faf 184 fEnergy=Double_t(maxAmp)-pedestal ;
185 if (fEnergy < kBaseLine) fEnergy = 0;
186 fTime = sigStart-sigLength-3;
187
188 //do not test quality of too soft samples
189 if (wts > 0) {
190 aMean /= wts;
191 aRMS = aRMS/wts - aMean*aMean;
192 }
193 if (fEnergy <= maxEtoFit){
194 if (aRMS < 2.) //sigle peak
195 fQuality = 299. ;
196 else
197 fQuality = 0. ;
198 //Evaluate time of signal arriving
199 return kTRUE ;
200 }
379c5c09 201
6a265faf 202 //look for plato on the top of sample
203 if (fEnergy>500 && //this is not fluctuation of soft sample
204 nMax>2){ //and there is a plato
205 fOverflow = kTRUE ;
206 }
379c5c09 207
6a265faf 208
209 //do not fit High Gain samples with overflow
210 if(fCaloFlag==1 && fOverflow){
211 fQuality = 99. ;
212 return kTRUE;
213
214 }
215
216 //----Now fit sample with reasonable shape------
217 TArrayD samples(sigLength); // array of sample amplitudes
218 TArrayD times(sigLength); // array of sample time stamps
219 for (Int_t i=0; i<sigLength; i++) {
220 samples.AddAt(signal[i]-pedestal,sigLength-i-1);
221 times.AddAt(double(i),i);
222 }
223
224 if(fMax==0)
225 FindMax() ;
226 if(!FindAmpT(samples,times)){
227 if(AliLog::GetDebugLevel("PHOS","AliPHOSRawFitterv2")>3){
228 goto plot ;
229 }
230 else{
231 return kFALSE ;
379c5c09 232 }
233 }
6a265faf 234 fEnergy*=fMax ;
235 fTime += sigStart-sigLength-3;
236
237
238 //Impose cut on quality
239// fQuality/=4. ;
240 fQuality/=1.+0.005*fEnergy ;
241
242 //Draw corrupted samples
243 if(AliLog::GetDebugLevel("PHOS","AliPHOSRawFitterv2")>3){
244 if(fEnergy > 50. ){
245 plot:
246 printf("Sample par: amp=%f, t0=%f, Quality=%f \n",fEnergy,fTime,fQuality) ;
247 TH1I * h = (TH1I*)gROOT->FindObjectAny("hSamples") ;
248 if(!h) h = new TH1I("hSamples","Samples",65,0.,65.) ;
249 h->Reset() ;
250 for (Int_t i=0; i<sigLength; i++) {
251 h->SetBinContent(i+1,float(samples.At(i))) ;
252 }
253// TF1 * fffit = new TF1("fffit","[0]+[1]*((x-[2])/[3])^2*exp(2.-2.*(x-[2])/[3])",0.,200.) ;
254 TF1 * fffit = new TF1("fffit","[0]*((x-[1])*(x-[1])*exp(-[2]*(x-[1]))+(x-[1])*exp(-[3]*(x-[1])))",0.,60.) ;
255 fffit->SetParameters(fEnergy/fMax,fTime-(sigStart-sigLength-3),fAlpha,fBeta) ;
256 fffit->SetLineColor(2) ;
257 TCanvas * can = (TCanvas*)gROOT->FindObjectAny("cSamples") ;
258 if(!can){
259 can = new TCanvas("cSamples","cSamples",10,10,600,600) ;
260 can->SetFillColor(0) ;
261 can->SetFillStyle(0) ;
262 can->Range(0,0,1,1);
263 can->SetBorderSize(0);
264 }
265 can->cd() ;
379c5c09 266
6a265faf 267 TPad * spectrum_1 = new TPad("spectrum_1", "spectrum_1",0.001,0.32,0.99,0.99);
268 spectrum_1->Draw();
269 spectrum_1->cd();
270 spectrum_1->Range(0,0,1,1);
271 spectrum_1->SetFillColor(0);
272 spectrum_1->SetFillStyle(4000);
273 spectrum_1->SetBorderSize(1);
274 spectrum_1->SetBottomMargin(0.012);
275 spectrum_1->SetTopMargin(0.03);
276 spectrum_1->SetLeftMargin(0.10);
277 spectrum_1->SetRightMargin(0.05);
278
279 char title[155] ;
3da0f212 280 snprintf(title,155,"Sample, mod=%d, x=%d, z=%d, Quality=%5.1f",fModule,fCellX,fCellZ,fQuality) ;
6a265faf 281 h->SetTitle(title) ;
282// h->Fit(fffit,"","",0.,51.) ;
283 h->Draw() ;
284 fffit->Draw("same") ;
285/*
286 sprintf(title,"mod%d_x%d_z%d_HG_qu%4.1f",fModule,fCellX,fCellZ,fQuality) ;
287 TFile fout("samples_bad.root","update") ;
288 h->Write(title);
289 fout.Close() ;
290*/
291 can->cd() ;
292 TPad *spectrum_2 = new TPad("spectrum_2", "spectrum_2",0.001,0.01,0.99,0.32);
293 spectrum_2->SetFillColor(0) ;
294 spectrum_2->SetFillStyle(0) ;
295 spectrum_2->SetGridy() ;
296 spectrum_2->Draw();
297 spectrum_2->Range(0,0,1,1);
298 spectrum_2->SetFillColor(0);
299 spectrum_2->SetBorderSize(1);
300 spectrum_2->SetTopMargin(0.01);
301 spectrum_2->SetBottomMargin(0.25);
302 spectrum_2->SetLeftMargin(0.10);
303 spectrum_2->SetRightMargin(0.05);
304 spectrum_2->cd() ;
305
306 TH1I * hd = (TH1I*)gROOT->FindObjectAny("hSamplesDif") ;
307 if(!hd) hd = new TH1I("hd","Samples",65,0.,65.) ;
308 hd->Reset() ;
309 for (Int_t i=0; i<sigLength; i++) {
310 hd->SetBinContent(i+1,TMath::Max(-1023.,TMath::Min(1023.,samples.At(i)+pedestal-fffit->Eval(i)))) ;
311 }
312 hd->Draw();
313
314 can->Update() ;
315 printf("Press <enter> to continue\n") ;
316 getchar();
317
318
319 delete fffit ;
320 delete spectrum_1 ;
321 delete spectrum_2 ;
322 }
379c5c09 323 }
324
379c5c09 325 return kTRUE;
326}
6a265faf 327//------------------------------------------------------------------
328Bool_t AliPHOSRawFitterv2::FindAmpT(TArrayD samples, TArrayD times){
329// makes fit
330
331 const Int_t nMaxIter=50 ; //Maximal number of iterations
332 const Double_t epsdt = 1.e-3 ; //expected precision of t0 calculation
333
334 Double_t dTime=times.At(0)-0.5 ; //Most probable Initial approximation
335//printf(" start fit... \n") ;
336
337 Int_t nPoints = samples.GetSize() ;
338 Double_t dea=TMath::Exp(-fAlpha) ;
339 Double_t deb=TMath::Exp(-fBeta) ;
340 Double_t dt=1.,timeOld=dTime,dfOld=0. ;
341 for(Int_t iter=0; iter<nMaxIter; iter++){
342 Double_t yy=0.;
343 Double_t yf=0. ;
344 Double_t ydf=0. ;
345 Double_t yddf=0. ;
346 Double_t ff=0. ;
347 Double_t fdf=0. ;
348 Double_t dfdf=0. ;
349 Double_t fddf=0. ;
350 Int_t nfit=0 ;
351 Double_t aexp=TMath::Exp(-fAlpha*(times.At(0)-1.-dTime)) ;
352 Double_t bexp=TMath::Exp(-fBeta*(times.At(0)-1.-dTime)) ;
353 for(Int_t i=0; i<nPoints; i++){
354 Double_t t= times.At(i)-dTime ;
355 aexp*=dea ;
356 bexp*=deb ;
357 if(t<0.) continue ;
358 Double_t y=samples.At(i) ;
359 if(y<=fAmpThreshold)
360 continue ;
361 nfit++ ;
362 Double_t at=fAlpha*t ;
363 Double_t bt = fBeta*t ;
364 Double_t phi=t*(t*aexp+bexp) ;
365 Double_t dphi=t*aexp*(2.-at)+(1.-bt)*bexp ;
366 Double_t ddphi=aexp*(2.-4.*at+at*at)+bexp*fBeta*(bt-2.) ;
367 yy+=y*y ;
368 yf+=y*phi ;
369 ydf+=y*dphi ;
370 yddf+=y*ddphi ;
371 ff+=phi*phi ;
372 fdf+=phi*dphi ;
373 dfdf+=dphi*dphi ;
374 fddf+=phi*ddphi ;
375 }
376
929af5d7 377 if(ff<1.e-09||nfit==0 ){
6a265faf 378 fQuality=199 ;
379 return kFALSE ;
380 }
381 Double_t f=ydf*ff-yf*fdf ; //d(chi2)/dt
382 Double_t df=yf*(dfdf+fddf)-yddf*ff-ydf*fdf;
383 if(df<=0.){ //we are too far from the root. In the wicinity of root df>0
384 if(iter!=0 && dfOld>0.){//If at previous step df was OK, just reduce step size
385 dt*=0.5 ;
386 dTime=timeOld+dt ;
387 continue ;
388 }
389 if(f<0){ //f<0 => dTime is too small and we still do not know root region
390 dTime+=2. ;
391 continue ;
392 }
393 else{ //dTime is too large, we are beyond the root region
394 dTime-=2. ;
395 continue ;
396 }
397 }
398 dt=-f/df ;
399 if(TMath::Abs(dt)<epsdt){
400 fQuality=(yy-yf*yf/ff)/nfit ;
401 fEnergy=yf/ff ; //ff!=0 already tested
402 fTime=dTime ;
403 return kTRUE ;
404 }
405 //In some cases time steps are huge (derivative ~0)
406 if(dt>10.) dt=10. ; //restrict step size
407 if(dt<-10.) dt=-5.3 ; //this restriction should be asimmetric to avoid jumping from one point to another
408 timeOld=dTime ; //remember current position for the case
409 dfOld=df ; //of reduction of dt step size
410 dTime+=dt ;
411
412 if(dTime>100. || dTime<-30.){ //this is corrupted sample, do not spend time improving accuracy.
413 fQuality=(yy-yf*yf/ff)/nfit ;
414 fEnergy=yf/ff ; //ff!=0 already tested
415 fTime=dTime ;
416 return kFALSE ;
417 }
418
419 }
420 //failed to find a root, too many iterations
421 fQuality=99.;
422 fEnergy=0 ;
423 return kFALSE ;
424}
425//_________________________________________
426void AliPHOSRawFitterv2::FindMax(){
427 //Finds maxumum of currecnt parameterization
428 Double_t t=2./fAlpha ;
429 fMax = t*t*TMath::Exp(-fAlpha*t)+t*TMath::Exp(-fBeta*t) ;
430 Double_t dt=15 ;
431 while(dt>0.01){
432 Double_t dfdt=(2.*t-fAlpha*t*t)*TMath::Exp(-fAlpha*t)+(1.-fBeta*t)*TMath::Exp(-fBeta*t) ;
433 if(dfdt>0.)
434 t+=dt ;
435 else
436 t-=dt ;
437 Double_t maxNew = t*t*TMath::Exp(-fAlpha*t)+t*TMath::Exp(-fBeta*t) ;
438 if(maxNew>fMax)
439 fMax=maxNew ;
440 else{
441 dt/=2 ;
442 if(dfdt<0.)
443 t+=dt ;
444 else
445 t-=dt ;
446 }
447 }
448}
449