1 /*************************************************************************
2 * Copyright(c) 1998-2009, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
16 ///////////////////////////////////////////////////////////////////////////
17 // Dielectron SignalFunc //
21 Dielectron signal extraction class using functions as input.
23 A function to describe the signal as well as one to describe the background
24 has to be deployed by the user. Alternatively on of the default implementaions
29 ///////////////////////////////////////////////////////////////////////////
36 #include <TPaveText.h>
38 #include <TFitResult.h>
39 //#include <../hist/hist/src/TF1Helper.h>
43 #include "AliDielectronSignalFunc.h"
45 ClassImp(AliDielectronSignalFunc)
47 TH1F* AliDielectronSignalFunc::fgHistSimPM=0x0;
48 TF1* AliDielectronSignalFunc::fFuncSignal=0x0;
49 TF1* AliDielectronSignalFunc::fFuncBackground=0x0;
50 Int_t AliDielectronSignalFunc::fNparPeak=0;
51 Int_t AliDielectronSignalFunc::fNparBgnd=0;
54 AliDielectronSignalFunc::AliDielectronSignalFunc() :
55 AliDielectronSignalBase(),
66 // Default Constructor
71 //______________________________________________
72 AliDielectronSignalFunc::AliDielectronSignalFunc(const char* name, const char* title) :
73 AliDielectronSignalBase(name, title),
88 //______________________________________________
89 AliDielectronSignalFunc::~AliDielectronSignalFunc()
94 if(fFuncSigBack) delete fFuncSigBack;
98 //______________________________________________
99 void AliDielectronSignalFunc::Process(TObjArray * const arrhist)
102 // Fit the invariant mass histograms and retrieve the signal and background
118 AliError("Background substraction method not known!");
121 //______________________________________________________________________________
122 Double_t AliDielectronSignalFunc::PeakFunMC(const Double_t *x, const Double_t *par) {
123 // Fit MC signal shape
125 // [0]: scale for simpeak
129 TH1F *hPeak = fgHistSimPM;
131 printf("E-AliDielectronSignalFunc::PeakFun: No histogram for peak fit defined!\n");
135 Int_t idx = hPeak->FindBin(xx);
137 (idx >= hPeak->GetNbinsX())) {
141 return (par[0+fNparBgnd] * hPeak->GetBinContent(idx));
145 //______________________________________________________________________________
146 Double_t AliDielectronSignalFunc::PeakFunCB(const Double_t *x, const Double_t *par) {
147 // Crystal Ball fit function
149 Double_t alpha = par[0+fNparBgnd];
150 Double_t n = par[1+fNparBgnd];
151 Double_t meanx = par[2+fNparBgnd];
152 Double_t sigma = par[3+fNparBgnd];
153 Double_t nn = par[4+fNparBgnd];
155 Double_t a = TMath::Power((n/TMath::Abs(alpha)), n) * TMath::Exp(-.5*alpha*alpha);
156 Double_t b = n/TMath::Abs(alpha) - TMath::Abs(alpha);
158 Double_t arg = (x[0] - meanx)/sigma;
161 if (arg > -1.*alpha) {
162 fitval = nn * TMath::Exp(-.5*arg*arg);
164 fitval = nn * a * TMath::Power((b-arg), (-1*n));
170 //______________________________________________________________________________
171 Double_t AliDielectronSignalFunc::PeakFunGaus(const Double_t *x, const Double_t *par) {
172 // Gaussian fit function
174 Double_t n = par[0+fNparBgnd];
175 Double_t mean = par[1+fNparBgnd];
176 Double_t sigma = par[2+fNparBgnd];
179 return ( n*exp(-0.5*TMath::Power((xx-mean)/sigma,2)) );
182 //______________________________________________
183 void AliDielectronSignalFunc::ProcessFit(TObjArray * const arrhist) {
185 // Fit the +- invariant mass distribution only
186 // Here we assume that the combined fit function is a sum of the signal and background functions
187 // and that the signal function is always the first term of this sum
190 fHistDataPM = (TH1F*)(arrhist->At(1))->Clone("histPM"); // +- SE
191 fHistDataPM->Sumw2();
193 fHistDataPM->Rebin(fRebin);
195 fHistSignal = new TH1F("HistSignal", "Fit substracted signal",
196 fHistDataPM->GetXaxis()->GetNbins(),
197 fHistDataPM->GetXaxis()->GetXmin(), fHistDataPM->GetXaxis()->GetXmax());
198 fHistBackground = new TH1F("HistBackground", "Fit contribution",
199 fHistDataPM->GetXaxis()->GetNbins(),
200 fHistDataPM->GetXaxis()->GetXmin(), fHistDataPM->GetXaxis()->GetXmax());
202 // the starting parameters of the fit function and their limits can be tuned
203 // by the user in its macro
204 fHistDataPM->Fit(fFuncSigBack, fFitOpt.Data(), "", fFitMin, fFitMax);
205 TFitResultPtr pmFitPtr = fHistDataPM->Fit(fFuncSigBack, fFitOpt.Data(), "", fFitMin, fFitMax);
206 //TFitResult *pmFitResult = pmFitPtr.Get(); // used only with TF1Helper
207 fFuncBackground->SetParameters(fFuncSigBack->GetParameters());
208 fFuncSignal->SetParameters(fFuncSigBack->GetParameters()+fFuncBackground->GetNpar());
209 // fFuncBackground->SetParameters(fFuncSigBack->GetParameters()+fFuncSignal->GetNpar());
211 for(Int_t iBin=1; iBin<=fHistDataPM->GetXaxis()->GetNbins(); iBin++) {
212 Double_t m = fHistDataPM->GetBinCenter(iBin);
213 Double_t pm = fHistDataPM->GetBinContent(iBin);
214 Double_t epm = fHistDataPM->GetBinError(iBin);
215 Double_t bknd = fFuncBackground->Eval(m);
217 for(Int_t iPar=fFuncSignal->GetNpar(); iPar<fFuncSigBack->GetNpar(); iPar++) {
218 /* TF1Helper problem on alien compilation
219 for(Int_t jPar=iPar; jPar<fFuncSigBack->GetNpar(); jPar++) {
220 TF1 gradientIpar("gradientIpar",
221 ROOT::TF1Helper::TGradientParFunction(iPar-fFuncSignal->GetNpar(),fFuncBackground),0,0,0);
222 TF1 gradientJpar("gradientJpar",
223 ROOT::TF1Helper::TGradientParFunction(jPar-fFuncSignal->GetNpar(),fFuncBackground),0,0,0);
224 ebknd += pmFitResult->CovMatrix(iPar,jPar)*
225 gradientIpar.Eval(m)*gradientJpar.Eval(m)*
226 (iPar==jPar ? 1.0 : 2.0);
230 Double_t signal = pm-bknd;
231 Double_t error = TMath::Sqrt(epm*epm+ebknd);
232 fHistSignal->SetBinContent(iBin, signal);
233 fHistSignal->SetBinError(iBin, error);
234 fHistBackground->SetBinContent(iBin, bknd);
235 fHistBackground->SetBinError(iBin, TMath::Sqrt(ebknd));
240 fValues(0) = fFuncSignal->Integral(fIntMin, fIntMax)/fHistDataPM->GetBinWidth(1);
242 for(Int_t iPar=0; iPar<fFuncSignal->GetNpar(); iPar++) {
243 /* TF1Helper problem on alien compilation
244 for(Int_t jPar=iPar; jPar<fFuncSignal->GetNpar(); jPar++) {
245 TF1 gradientIpar("gradientIpar",
246 ROOT::TF1Helper::TGradientParFunction(iPar,fFuncSignal),0,0,0);
247 TF1 gradientJpar("gradientJpar",
248 ROOT::TF1Helper::TGradientParFunction(jPar,fFuncSignal),0,0,0);
249 fErrors(0) += pmFitResult->CovMatrix(iPar,jPar)*
250 gradientIpar.Integral(fIntMin,fIntMax)*gradientJpar.Integral(fIntMin,fIntMax)*
251 (iPar==jPar ? 1.0 : 2.0);
256 fValues(1) = fFuncBackground->Integral(fIntMin, fIntMax)/fHistDataPM->GetBinWidth(1);
258 for(Int_t iPar=fFuncSignal->GetNpar(); iPar<fFuncSigBack->GetNpar(); iPar++) {
259 /* TF1Helper problem on alien compilation
260 for(Int_t jPar=iPar; jPar<fFuncSigBack->GetNpar(); jPar++) {
261 TF1 gradientIpar("gradientIpar",
262 ROOT::TF1Helper::TGradientParFunction(iPar-fFuncSignal->GetNpar(),fFuncBackground),0,0,0);
263 TF1 gradientJpar("gradientJpar",
264 ROOT::TF1Helper::TGradientParFunction(jPar-fFuncSignal->GetNpar(),fFuncBackground),0,0,0);
265 fErrors(1) += pmFitResult->CovMatrix(iPar,jPar)*
266 gradientIpar.Integral(fIntMin, fIntMax)*gradientJpar.Integral(fIntMin, fIntMax)*
267 (iPar==jPar ? 1.0 : 2.0);
274 fValues(0) = fHistSignal->IntegralAndError(fHistSignal->FindBin(fIntMin),
275 fHistSignal->FindBin(fIntMax), fErrors(0));
277 fValues(1) = fHistBackground->IntegralAndError(fHistBackground->FindBin(fIntMin),
278 fHistBackground->FindBin(fIntMax),
281 // S/B and significance
282 SetSignificanceAndSOB();
283 fValues(4) = fFuncSigBack->GetParameter(fParMass);
284 fErrors(4) = fFuncSigBack->GetParError(fParMass);
285 fValues(5) = fFuncSigBack->GetParameter(fParMassWidth);
286 fErrors(5) = fFuncSigBack->GetParError(fParMassWidth);
290 fHistBackground->GetListOfFunctions()->Add(fFuncBackground);
294 //______________________________________________
295 void AliDielectronSignalFunc::ProcessLS(TObjArray * const arrhist) {
297 // Substract background using the like-sign spectrum
299 fHistDataPP = (TH1F*)(arrhist->At(0))->Clone("histPP"); // ++ SE
300 fHistDataPM = (TH1F*)(arrhist->At(1))->Clone("histPM"); // +- SE
301 fHistDataMM = (TH1F*)(arrhist->At(2))->Clone("histMM"); // -- SE
303 fHistDataPP->Rebin(fRebin);
304 fHistDataPM->Rebin(fRebin);
305 fHistDataMM->Rebin(fRebin);
307 fHistDataPP->Sumw2();
308 fHistDataPM->Sumw2();
309 fHistDataMM->Sumw2();
311 fHistSignal = new TH1F("HistSignal", "Like-Sign substracted signal",
312 fHistDataPM->GetXaxis()->GetNbins(),
313 fHistDataPM->GetXaxis()->GetXmin(), fHistDataPM->GetXaxis()->GetXmax());
314 fHistBackground = new TH1F("HistBackground", "Like-sign contribution",
315 fHistDataPM->GetXaxis()->GetNbins(),
316 fHistDataPM->GetXaxis()->GetXmin(), fHistDataPM->GetXaxis()->GetXmax());
318 // fit the +- mass distribution
319 fHistDataPM->Fit(fFuncSigBack, fFitOpt.Data(), "", fFitMin, fFitMax);
320 fHistDataPM->Fit(fFuncSigBack, fFitOpt.Data(), "", fFitMin, fFitMax);
321 // declare the variables where the like-sign fit results will be stored
322 // TFitResult *ppFitResult = 0x0;
323 // TFitResult *mmFitResult = 0x0;
324 // fit the like sign background
325 TF1 *funcClonePP = (TF1*)fFuncBackground->Clone("funcClonePP");
326 TF1 *funcCloneMM = (TF1*)fFuncBackground->Clone("funcCloneMM");
327 fHistDataPP->Fit(funcClonePP, fFitOpt.Data(), "", fFitMin, fFitMax);
328 fHistDataPP->Fit(funcClonePP, fFitOpt.Data(), "", fFitMin, fFitMax);
329 // TFitResultPtr ppFitPtr = fHistDataPP->Fit(funcClonePP, fFitOpt.Data(), "", fFitMin, fFitMax);
330 // ppFitResult = ppFitPtr.Get();
331 fHistDataMM->Fit(funcCloneMM, fFitOpt.Data(), "", fFitMin, fFitMax);
332 fHistDataMM->Fit(funcCloneMM, fFitOpt.Data(), "", fFitMin, fFitMax);
333 // TFitResultPtr mmFitPtr = fHistDataMM->Fit(funcCloneMM, fFitOpt.Data(), "", fFitMin, fFitMax);
334 // mmFitResult = mmFitPtr.Get();
336 for(Int_t iBin=1; iBin<=fHistDataPM->GetXaxis()->GetNbins(); iBin++) {
337 Double_t m = fHistDataPM->GetBinCenter(iBin);
338 Double_t pm = fHistDataPM->GetBinContent(iBin);
339 Double_t pp = funcClonePP->Eval(m);
340 Double_t mm = funcCloneMM->Eval(m);
341 Double_t epm = fHistDataPM->GetBinError(iBin);
343 for(Int_t iPar=0; iPar<funcClonePP->GetNpar(); iPar++) {
344 /* TF1Helper problem on alien compilation
345 for(Int_t jPar=iPar; jPar<funcClonePP->GetNpar(); jPar++) {
346 TF1 gradientIpar("gradientIpar",
347 ROOT::TF1Helper::TGradientParFunction(iPar,funcClonePP),0,0,0);
348 TF1 gradientJpar("gradientJpar",
349 ROOT::TF1Helper::TGradientParFunction(jPar,funcClonePP),0,0,0);
350 epp += ppFitResult->CovMatrix(iPar,jPar)*
351 gradientIpar.Eval(m)*gradientJpar.Eval(m)*
352 (iPar==jPar ? 1.0 : 2.0);
357 for(Int_t iPar=0; iPar<funcCloneMM->GetNpar(); iPar++) {
358 /* TF1Helper problem on alien compilation
359 for(Int_t jPar=iPar; jPar<funcCloneMM->GetNpar(); jPar++) {
360 TF1 gradientIpar("gradientIpar",
361 ROOT::TF1Helper::TGradientParFunction(iPar,funcCloneMM),0,0,0);
362 TF1 gradientJpar("gradientJpar",
363 ROOT::TF1Helper::TGradientParFunction(jPar,funcCloneMM),0,0,0);
364 emm += mmFitResult->CovMatrix(iPar,jPar)*
365 gradientIpar.Eval(m)*gradientJpar.Eval(m)*
366 (iPar==jPar ? 1.0 : 2.0);
371 Double_t signal = pm-2.0*TMath::Sqrt(pp*mm);
372 Double_t background = 2.0*TMath::Sqrt(pp*mm);
373 // error propagation on the signal calculation above
374 Double_t esignal = TMath::Sqrt(epm*epm+(mm/pp)*epp+(pp/mm)*emm);
375 Double_t ebackground = TMath::Sqrt((mm/pp)*epp+(pp/mm)*emm);
376 fHistSignal->SetBinContent(iBin, signal);
377 fHistSignal->SetBinError(iBin, esignal);
378 fHistBackground->SetBinContent(iBin, background);
379 fHistBackground->SetBinError(iBin, ebackground);
383 fValues(0) = fHistSignal->IntegralAndError(fHistSignal->FindBin(fIntMin),
384 fHistSignal->FindBin(fIntMax), fErrors(0));
386 fValues(1) = fHistBackground->IntegralAndError(fHistBackground->FindBin(fIntMin),
387 fHistBackground->FindBin(fIntMax),
389 // S/B and significance
390 SetSignificanceAndSOB();
391 fValues(4) = fFuncSigBack->GetParameter(fParMass);
392 fErrors(4) = fFuncSigBack->GetParError(fParMass);
393 fValues(5) = fFuncSigBack->GetParameter(fParMassWidth);
394 fErrors(5) = fFuncSigBack->GetParError(fParMassWidth);
399 //______________________________________________
400 void AliDielectronSignalFunc::ProcessEM(TObjArray * const arrhist) {
402 // Substract background with the event mixing technique
404 arrhist->GetEntries(); // just to avoid the unused parameter warning
405 AliError("Event mixing for background substraction method not implemented!");
408 //______________________________________________
409 void AliDielectronSignalFunc::SetFunctions(TF1 * const combined, TF1 * const sig, TF1 * const back,
410 Int_t parM, Int_t parMres)
413 // Set the signal, background functions and combined fit function
414 // Note: The process method assumes that the first n parameters in the
415 // combined fit function correspond to the n parameters of the signal function
416 // and the n+1 to n+m parameters to the m parameters of the background function!!!
418 if (!sig||!back||!combined) {
419 AliError("Both, signal and background function need to be set!");
423 fFuncBackground=back;
424 fFuncSigBack=combined;
426 fParMassWidth=parMres;
430 //______________________________________________
431 void AliDielectronSignalFunc::SetDefaults(Int_t type)
434 // Setup some default functions:
435 // type = 0: gaus signal + linear background in 2.5 - 4 GeV inv. mass
436 // type = 1: gaus signal + exponential background in 2.5 - 4 GeV inv. mass
437 // type = 2: half gaussian, half exponential signal function
438 // type = 3: Crystal-Ball function
439 // type = 4: Crystal-Ball signal + exponential background
443 fFuncSignal=new TF1("DieleSignal","gaus",2.5,4);
444 fFuncBackground=new TF1("DieleBackground","pol1",2.5,4);
445 fFuncSigBack=new TF1("DieleCombined","gaus+pol1(3)",2.5,4);
447 fFuncSigBack->SetParameters(1,3.1,.05,2.5,1);
448 fFuncSigBack->SetParLimits(0,0,10000000);
449 fFuncSigBack->SetParLimits(1,3.05,3.15);
450 fFuncSigBack->SetParLimits(2,.02,.1);
453 fFuncSignal=new TF1("DieleSignal","gaus",2.5,4);
454 fFuncBackground=new TF1("DieleBackground","[0]*exp(-(x-[1])/[2])",2.5,4);
455 fFuncSigBack=new TF1("DieleCombined","gaus+[3]*exp(-(x-[4])/[5])",2.5,4);
457 fFuncSigBack->SetParameters(1,3.1,.05,1,2.5,1);
458 fFuncSigBack->SetParLimits(0,0,10000000);
459 fFuncSigBack->SetParLimits(1,3.05,3.15);
460 fFuncSigBack->SetParLimits(2,.02,.1);
463 // half gaussian, half exponential signal function
464 // exponential background
465 fFuncSignal = new TF1("DieleSignal","(x<[1])*([0]*(exp(-0.5*((x-[1])/[2])^2)+exp((x-[1])/[3])*(1-exp(-0.5*((x-[1])/[2])^2))))+(x>=[1])*([0]*exp(-0.5*((x-[1])/[2])^2))",2.5,4);
466 fFuncBackground = new TF1("DieleBackground","[0]*exp(-(x-[1])/[2])+[3]",2.5,4);
467 fFuncSigBack = new TF1("DieleCombined","(x<[1])*([0]*(exp(-0.5*((x-[1])/[2])^2)+exp((x-[1])/[3])*(1-exp(-0.5*((x-[1])/[2])^2))))+(x>=[1])*([0]*exp(-0.5*((x-[1])/[2])^2))+[4]*exp(-(x-[5])/[6])+[7]",2.5,4);
468 fFuncSigBack->SetParameters(1.,3.1,.05,.1,1,2.5,1,0);
470 fFuncSigBack->SetParLimits(0,0,10000000);
471 fFuncSigBack->SetParLimits(1,3.05,3.15);
472 fFuncSigBack->SetParLimits(2,.02,.1);
473 fFuncSigBack->FixParameter(6,2.5);
474 fFuncSigBack->FixParameter(7,0);
479 //______________________________________________
480 void AliDielectronSignalFunc::Draw(const Option_t* option)
483 // Draw the fitted function
486 TString drawOpt(option);
489 Bool_t optStat=drawOpt.Contains("stat");
491 fFuncSigBack->SetNpx(200);
492 fFuncSigBack->SetRange(fIntMin,fIntMax);
493 fFuncBackground->SetNpx(200);
494 fFuncBackground->SetRange(fIntMin,fIntMax);
496 TGraph *grSig=new TGraph(fFuncSigBack);
497 grSig->SetFillColor(kGreen);
498 grSig->SetFillStyle(3001);
500 TGraph *grBack=new TGraph(fFuncBackground);
501 grBack->SetFillColor(kRed);
502 grBack->SetFillStyle(3001);
504 grSig->SetPoint(0,grBack->GetX()[0],grBack->GetY()[0]);
505 grSig->SetPoint(grSig->GetN()-1,grBack->GetX()[grBack->GetN()-1],grBack->GetY()[grBack->GetN()-1]);
507 grBack->SetPoint(0,grBack->GetX()[0],0.);
508 grBack->SetPoint(grBack->GetN()-1,grBack->GetX()[grBack->GetN()-1],0.);
510 fFuncSigBack->SetRange(fFitMin,fFitMax);
511 fFuncBackground->SetRange(fFitMin,fFitMax);
513 if (!drawOpt.Contains("same")){
523 if(fMethod==kFitted || fMethod==kFittedMC) grBack->Draw("f");
524 fFuncSigBack->Draw("same");
525 fFuncSigBack->SetLineWidth(2);
526 if(fMethod==kLikeSign) {
527 fHistDataPP->SetLineWidth(2);
528 fHistDataPP->SetLineColor(6);
529 fHistDataPP->Draw("same");
530 fHistDataMM->SetLineWidth(2);
531 fHistDataMM->SetLineColor(8);
532 fHistDataMM->Draw("same");
535 if(fMethod==kFitted || fMethod==kFittedMC)
536 fFuncBackground->Draw("same");
538 if (optStat) DrawStats();
543 //______________________________________________________________________________
544 void AliDielectronSignalFunc::CombineFunc(TF1 * const peak, TF1 * const bgnd) {
546 // combine the bgnd and the peak function
550 AliError("Both, signal and background function need to be set!");
554 fFuncBackground=bgnd;
556 fNparPeak = fFuncSignal->GetNpar();
557 fNparBgnd = fFuncBackground->GetNpar();
559 fFuncSigBack = new TF1("BgndPeak",AliDielectronSignalFunc::PeakBgndFun, 0.,5.,fNparPeak+fNparBgnd);
563 //______________________________________________________________________________
564 Double_t AliDielectronSignalFunc::PeakBgndFun(const Double_t *x, const Double_t *par) {
566 // merge peak and bgnd functions
568 return (fFuncBackground->EvalPar(x,par) + fFuncSignal->EvalPar(x,par));