source: trunk/MagicSoft/Mars/mhist/MHFindSignificance.cc@ 2550

Last change on this file since 2550 was 2357, checked in by wittek, 21 years ago
*** empty log message ***
File size: 53.3 KB
Line 
1/* ======================================================================== *\
2!
3! *
4! * This file is part of MARS, the MAGIC Analysis and Reconstruction
5! * Software. It is distributed to you in the hope that it can be a useful
6! * and timesaving tool in analysing Data of imaging Cerenkov telescopes.
7! * It is distributed WITHOUT ANY WARRANTY.
8! *
9! * Permission to use, copy, modify and distribute this software and its
10! * documentation for any purpose is hereby granted without fee,
11! * provided that the above copyright notice appear in all copies and
12! * that both that copyright notice and this permission notice appear
13! * in supporting documentation. It is provided "as is" without express
14! * or implied warranty.
15! *
16!
17!
18! Author(s): Wolfgang Wittek, July 2003 <mailto:wittek@mppmu.mpg.de>
19!
20! Copyright: MAGIC Software Development, 2000-2003
21!
22!
23\* ======================================================================== */
24
25/////////////////////////////////////////////////////////////////////////////
26//
27// MHFindSignificance
28//
29// determines the significance of a gamma signal in an |alpha| plot
30//
31//
32// Input : TH1 histogram of |alpha| : with 0 < |alpha| < 90 degrees
33// alphamin, alphamax : defining the background region
34// alphasig : defining the signal region for which
35// the significance is calculated
36// degree : the degree of the polynomial to be fitted to the background
37// ( a0 + a1*x + a2*x**2 + a3*x**3 + ...)
38//
39// Output :
40//
41// - polynomial which describes the background in the background region
42// - the number of events in the signal region (Non)
43// the number of background events in the signal region (Nbg)
44// - the number of excess events in the signal region (Nex = Non - Nbg)
45// - thew effective number of background events (Noff), and gamma :
46// Nbg = gamma * Noff
47// - the significance of the gamma signal according to Li & Ma
48//
49//
50// call member function 'FindSigma'
51// to fit the background and to determine the significance
52//
53// call the member function 'SigmaVsAlpha'
54// to determine the significance as a function of alphasig
55//
56/////////////////////////////////////////////////////////////////////////////
57#include "MHFindSignificance.h"
58
59#include <fstream>
60#include <math.h>
61
62#include <TArrayD.h>
63#include <TArrayI.h>
64#include <TH1.h>
65#include <TF1.h>
66#include <TCanvas.h>
67#include <TFitter.h>
68#include <TMinuit.h>
69#include <TPaveText.h>
70#include <TStyle.h>
71
72#include "MLog.h"
73#include "MLogManip.h"
74#include "MMinuitInterface.h"
75
76
77ClassImp(MHFindSignificance);
78
79using namespace std;
80
81const TString MHFindSignificance::gsDefName = "MHFindSignificance";
82const TString MHFindSignificance::gsDefTitle = "Find Significance in alpha plot";
83
84
85
86// --------------------------------------------------------------------------
87//
88// fcnpoly
89//
90// calculates the chi2 for the fit of the polynomial function 'poly'
91// to the histogram 'fhist'
92//
93// it is called by CallMinuit() (which is called in FitPolynomial())
94//
95// bins of fhist with huge errors are ignored in the calculation of the chi2
96// (the huge errors were set in 'FitPolynomial()')
97//
98
99static void fcnpoly(Int_t &npar, Double_t *gin, Double_t &f,
100 Double_t *par, Int_t iflag)
101{
102 TH1 *fhist = (TH1*)gMinuit->GetObjectFit();
103 TF1 *fpoly = fhist->GetFunction("Poly");
104
105
106 //-------------------------------------------
107
108 Double_t chi2 = 0.0;
109
110 Int_t nbins = fhist->GetNbinsX();
111 Int_t mbins = 0;
112 for (Int_t i=1; i<=nbins; i++)
113 {
114 Double_t content = fhist->GetBinContent(i);
115 Double_t error = fhist->GetBinError(i);
116 Double_t center = fhist->GetBinCenter(i);
117
118 //-----------------------------
119 // ignore unwanted points
120 if (error > 1.e19)
121 continue;
122
123 if (content <= 0.0)
124 {
125 gLog << "fcnpoly : bin with zero content; i, content, error = "
126 << i << ", " << content << ", " << error << endl;
127 continue;
128 }
129
130 if (error <= 0.0)
131 {
132 gLog << "fcnpoly : bin with zero error; i, content, error = "
133 << i << ", " << content << ", " << error << endl;
134 continue;
135 }
136
137 //-----------------------------
138 mbins++;
139
140 Double_t fu;
141 fu = fpoly->EvalPar(&center, par);
142
143 // the fitted function must not be negative
144 if (fu <= 0.0)
145 {
146 chi2 = 1.e10;
147 break;
148 }
149
150 Double_t temp = (content - fu) / error;
151 chi2 += temp*temp;
152 }
153
154 //-------------------------------------------
155
156 f = chi2;
157
158 //-------------------------------------------
159 // final calculations
160 //if (iflag == 3)
161 //{
162 //}
163
164 //-------------------------------------------------------------
165}
166
167
168// --------------------------------------------------------------------------
169//
170// fcnpolygauss
171//
172// calculates the chi2 for the fit of the (polynomial+Gauss) function
173// 'PolyGauss' to the histogram 'fhist'
174//
175// it is called by CallMinuit() (which is called in FitGaussPoly())
176//
177// bins of fhist with huge errors are ignored in the calculation of the chi2
178// (the huge errors were set in 'FitGaussPoly()')
179//
180
181static void fcnpolygauss(Int_t &npar, Double_t *gin, Double_t &f,
182 Double_t *par, Int_t iflag)
183{
184 TH1 *fhist = (TH1*)gMinuit->GetObjectFit();
185 TF1 *fpolygauss = fhist->GetFunction("PolyGauss");
186
187
188 //-------------------------------------------
189
190 Double_t chi2 = 0.0;
191
192 Int_t nbins = fhist->GetNbinsX();
193 Int_t mbins = 0;
194 for (Int_t i=1; i<=nbins; i++)
195 {
196 Double_t content = fhist->GetBinContent(i);
197 Double_t error = fhist->GetBinError(i);
198 Double_t center = fhist->GetBinCenter(i);
199
200 //-----------------------------
201 // ignore unwanted points
202 if (error > 1.e19)
203 continue;
204
205 if (content <= 0.0)
206 {
207 gLog << "fcnpolygauss : bin with zero content; i, content, error = "
208 << i << ", " << content << ", " << error << endl;
209 continue;
210 }
211
212 if (error <= 0.0)
213 {
214 gLog << "fcnpolygauss : bin with zero error; i, content, error = "
215 << i << ", " << content << ", " << error << endl;
216 continue;
217 }
218
219 //-----------------------------
220 mbins++;
221
222 Double_t fu;
223 fu = fpolygauss->EvalPar(&center, par);
224
225 // the fitted function must not be negative
226 if (fu <= 0.0)
227 {
228 chi2 = 1.e10;
229 break;
230 }
231
232 Double_t temp = (content - fu) / error;
233 chi2 += temp*temp;
234 }
235
236 //-------------------------------------------
237
238 f = chi2;
239
240 //-------------------------------------------
241 // final calculations
242 //if (iflag == 3)
243 //{
244 //}
245
246 //-------------------------------------------------------------
247}
248
249
250
251// --------------------------------------------------------------------------
252//
253// Constructor
254//
255MHFindSignificance::MHFindSignificance(const char *name, const char *title)
256{
257 fName = name ? name : gsDefName.Data();
258 fTitle = title ? title : gsDefTitle.Data();
259
260 fSigVsAlpha = NULL;
261
262 fPoly = NULL;
263 fGPoly = NULL;
264 fGBackg = NULL;
265
266 fHist = NULL;
267 fHistOrig = NULL;
268
269 // allow rebinning of the alpha plot
270 fRebin = kTRUE;
271
272 // allow reducing the degree of the polynomial
273 fReduceDegree = kTRUE;
274
275 fCanvas = NULL;
276}
277
278// --------------------------------------------------------------------------
279//
280// Destructor.
281//
282// =====> it is not clear why one obtains sometimes a segmentation violation
283// when the destructor is active <=======================
284//
285// therefore the 'return'statement
286//
287
288MHFindSignificance::~MHFindSignificance()
289{
290 return;
291
292 *fLog << "destructor of MHFindSignificance is called" << endl;
293
294 //delete fHist;
295
296 delete fSigVsAlpha;
297 delete fPoly;
298 delete fGPoly;
299 delete fGBackg;
300 //delete fCanvas;
301}
302
303// --------------------------------------------------------------------------
304//
305// Set flag fRebin
306//
307// if flag is kTRUE rebinning of the alpha plot is allowed
308//
309//
310void MHFindSignificance::SetRebin(Bool_t b)
311{
312 fRebin = b;
313
314 *fLog << "MHFindSignificance::SetRebin; flag fRebin set to "
315 << (b? "kTRUE" : "kFALSE") << endl;
316}
317
318// --------------------------------------------------------------------------
319//
320// Set flag fReduceDegree
321//
322// if flag is kTRUE reducing of the degree of the polynomial is allowed
323//
324//
325void MHFindSignificance::SetReduceDegree(Bool_t b)
326{
327 fReduceDegree = b;
328
329 *fLog << "MHFindSignificance::SetReduceDegree; flag fReduceDegree set to "
330 << (b? "kTRUE" : "kFALSE") << endl;
331}
332
333// --------------------------------------------------------------------------
334//
335// FindSigma
336//
337// calls FitPolynomial to fit the background in the background region
338// calls DetExcess to determine the number of excess events
339// using an extrapolation of the polynomial
340// into the signal region
341// calls SigmaLiMa to determine the significance of the gamma signal
342// in the range |alpha| < alphasig
343// calls FitGaussPoly to fit a (polynomial+Gauss) function in the
344// whole |alpha| region
345//
346//
347Bool_t MHFindSignificance::FindSigma(TH1 *fhist, Double_t alphamin,
348 Double_t alphamax, Int_t degree, Double_t alphasig,
349 Bool_t drawpoly, Bool_t fitgauss, Bool_t print)
350{
351 //*fLog << "MHFindSignificance::FindSigma;" << endl;
352
353 fHistOrig = fhist;
354
355 fHist = (TH1*)fHistOrig->Clone();
356 fHist->SetName(fhist->GetName());
357 if ( !fHist )
358 {
359 *fLog << "MHFindSignificance::FindSigma; Clone of histogram could not be generated"
360 << endl;
361 return kFALSE;
362 }
363
364 fHist->Sumw2();
365 //fHist->SetNameTitle("Alpha", "alpha plot");
366 fHist->SetXTitle("|alpha| [\\circ]");
367 fHist->SetYTitle("Counts");
368 fHist->UseCurrentStyle();
369
370 fAlphamin = alphamin;
371 fAlphamax = alphamax;
372 fAlphammm = (alphamin+alphamax)/2.0;
373 fDegree = degree;
374 fAlphasig = alphasig;
375
376 fDraw = drawpoly;
377 fFitGauss = fitgauss;
378
379
380 //--------------------------------------------
381 // fit a polynomial in the background region
382
383 //*fLog << "MHFindSignificance::FindSigma; calling FitPolynomial()" << endl;
384 if ( !FitPolynomial() )
385 {
386 *fLog << "MHFindSignificance::FindSigma; FitPolynomial failed"
387 << endl;
388 return kFALSE;
389 }
390
391
392 //--------------------------------------------
393 // calculate the number of excess events in the signal region
394
395 //*fLog << "MHFindSignificance::FindSigma; calling DetExcess()" << endl;
396 if ( !DetExcess() )
397 {
398 *fLog << "MHFindSignificance::FindSigma; DetExcess failed"
399 << endl;
400 return kFALSE;
401 }
402
403
404 //--------------------------------------------
405 // calculate the significance of the excess
406
407 //*fLog << "MHFindSignificance::FindSigma; calling SigmaLiMa()" << endl;
408 Double_t siglima = 0.0;
409 if ( !SigmaLiMa(fNon, fNoff, fGamma, &siglima) )
410 {
411 *fLog << "MHFindSignificance::FindSigma; SigmaLiMa failed"
412 << endl;
413 return kFALSE;
414 }
415 fSigLiMa = siglima;
416
417 //--------------------------------------------
418 // calculate the error of the number of excess events
419
420 fdNex = fNex / fSigLiMa;
421
422
423 //--------------------------------------------
424
425 //*fLog << "MHFindSignificance::FindSigma; calling PrintPoly()" << endl;
426 if (print)
427 PrintPoly();
428
429
430 //--------------------------------------------
431 // fit a (polynomial + Gauss) function
432
433 if (fFitGauss)
434 {
435 //--------------------------------------------------
436 // delete objects from this fit
437 // in order to have independent starting conditions for the next fit
438
439 delete gMinuit;
440 gMinuit = NULL;
441 //--------------------------------------------------
442
443 //*fLog << "MHFindSignificance::FindSigma; calling FitGaussPoly()"
444 // << endl;
445 if ( !FitGaussPoly() )
446 {
447 *fLog << "MHFindSignificance::FindSigma; FitGaussPoly failed"
448 << endl;
449 return kFALSE;
450 }
451
452 if (print)
453 {
454 //*fLog << "MHFindSignificance::FindSigma; calling PrintPolyGauss()"
455 // << endl;
456 PrintPolyGauss();
457 }
458 }
459
460 //--------------------------------------------------
461 // draw the histogram if requested
462
463 if (fDraw)
464 {
465 //*fLog << "MHFindSignificance::FindSigma; calling DrawFit()" << endl;
466 if ( !DrawFit() )
467 {
468 *fLog << "MHFindSignificance::FindSigma; DrawFit failed"
469 << endl;
470 return kFALSE;
471 }
472 }
473
474
475 //--------------------------------------------------
476 // delete objects from this fit
477 // in order to have independent starting conditions for the next fit
478
479 delete gMinuit;
480 gMinuit = NULL;
481 //--------------------------------------------------
482
483 return kTRUE;
484}
485
486// --------------------------------------------------------------------------
487//
488// SigmaVsAlpha (like FindSigma. However, alphasig is scanned and
489// the significance is plotted versus alphasig)
490//
491// calls FitPolynomial to fit the background in the background region
492//
493// scan alphasig; for a given alphasig :
494// calls DetExcess to determine the number of excess events
495// calls SigmaLiMa to determine the significance of the gamma signal
496// in the range fAlphalow < |alpha| < alphasig
497//
498
499Bool_t MHFindSignificance::SigmaVsAlpha(TH1 *fhist, Double_t alphamin,
500 Double_t alphamax, Int_t degree, Bool_t print)
501{
502 //*fLog << "MHFindSignificance::SigmaVsAlpha;" << endl;
503
504 fHistOrig = fhist;
505
506 fHist = (TH1*)fHistOrig->Clone();
507 fHist->SetName(fhist->GetName());
508 fHist->Sumw2();
509 //fHist->SetNameTitle("alpha", "alpha plot");
510 fHist->SetXTitle("|alpha| [\\circ]");
511 fHist->SetYTitle("Counts");
512 fHist->UseCurrentStyle();
513
514 fAlphamin = alphamin;
515 fAlphamax = alphamax;
516 fAlphammm = (alphamin+alphamax)/2.0;
517 fDegree = degree;
518
519
520 //--------------------------------------------
521 // fit a polynomial in the background region
522
523 //*fLog << "MHFindSignificance::SigmaVsAlpha calling FitPolynomial()"
524 // << endl;
525 if ( !FitPolynomial() )
526 {
527 *fLog << "MHFindSignificance::SigmaVsAlpha; FitPolynomial() failed"
528 << endl;
529 return kFALSE;
530 }
531
532
533 //--------------------------------------------
534 // loop over different signal regions
535
536 Int_t nsteps = 15;
537
538 fSigVsAlpha = new TH1D("SigVsAlpha","Sigma vs Alpha", nsteps, 0.0, alphamin);
539 fSigVsAlpha->SetXTitle("upper edge of signal region in |alpha| [\\circ]");
540 fSigVsAlpha->SetYTitle("Significance of gamma signal");
541
542 for (Int_t i=1; i<=nsteps; i++)
543 {
544 fAlphasig = fSigVsAlpha->GetBinCenter(i);
545
546 if ( !DetExcess() )
547 {
548 *fLog << "MHFindSignificance::SigmaVsAlpha; DetExcess() failed" << endl;
549 continue;
550 }
551
552 Double_t siglima = 0.0;
553 if ( !SigmaLiMa(fNon, fNoff, fGamma, &siglima) )
554 {
555 *fLog << "MHFindSignificance::SigmaVsAlpha; SigmaLiMa() failed" << endl;
556 continue;
557 }
558
559 fdNex = fNex / siglima;
560 fSigVsAlpha->SetBinContent(i, siglima);
561
562 if (print)
563 PrintPoly();
564 }
565
566 //--------------------------------------------
567 // plot significance versus alphasig
568
569 TCanvas *ccc = new TCanvas("SigVsAlpha", "Sigma vs Alpha", 600, 600);
570
571 gROOT->SetSelectedPad(NULL);
572 gStyle->SetPadLeftMargin(0.05);
573
574 ccc->cd();
575 fSigVsAlpha->DrawCopy();
576
577 ccc->Modified();
578 ccc->Update();
579
580 return kTRUE;
581}
582
583// --------------------------------------------------------------------------
584//
585// FitPolynomial
586//
587// - create a clone 'fHist' of the |alpha| distribution 'fHistOrig'
588// - fit a polynomial of degree 'fDegree' to the alpha distribution
589// 'fHist' in the region alphamin < |alpha| < alphamax
590//
591// in pathological cases the histogram is rebinned before fitting
592// (this is done only if fRebin is kTRUE)
593//
594// if the highest coefficient of the polynomial is compatible with zero
595// the fit is repeated with a polynomial of lower degree
596// (this is done only if fReduceDegree is kTRUE)
597//
598//
599Bool_t MHFindSignificance::FitPolynomial()
600{
601 //--------------------------------------------------
602 // check the histogram :
603 // - calculate initial values of the parameters
604 // - check for bins with zero entries
605 // - set minimum errors
606 // - save the original errors
607 // - set errors huge outside the fit range
608 // (in 'fcnpoly' points with huge errors will be ignored)
609
610
611 Double_t dummy = 1.e20;
612
613 Double_t mean;
614 Double_t rms;
615 Double_t nclose;
616 Double_t nfar;
617 Double_t a2init = 0.0;
618 TArrayD saveError;
619
620 Int_t nbins;
621 Int_t nrebin = 1;
622
623 //---------------- start while loop for rebinning -----------------
624 while(1)
625 {
626
627 fNzero = 0;
628 fMbins = 0;
629 fMlow = 0;
630 fNbgtot = 0.0;
631
632 fAlphami = 10000.0;
633 fAlphamm = 10000.0;
634 fAlphama = -10000.0;
635
636 mean = 0.0;
637 rms = 0.0;
638 nclose = 0.0;
639 nfar = 0.0;
640
641 nbins = fHist->GetNbinsX();
642 saveError.Set(nbins);
643
644 for (Int_t i=1; i<=nbins; i++)
645 {
646 saveError[i-1] = fHist->GetBinError(i);
647
648 // bin should be completely contained in the fit range
649 // (fAlphamin, fAlphamax)
650 Double_t xlo = fHist->GetBinLowEdge(i);
651 Double_t xup = fHist->GetBinLowEdge(i+1);
652
653 if ( xlo >= fAlphamin-fEps && xlo <= fAlphamax+fEps &&
654 xup >= fAlphamin-fEps && xup <= fAlphamax+fEps )
655 {
656 fMbins++;
657
658 if ( xlo < fAlphami )
659 fAlphami = xlo;
660
661 if ( xup > fAlphama )
662 fAlphama = xup;
663
664 Double_t content = fHist->GetBinContent(i);
665 fNbgtot += content;
666
667 mean += content;
668 rms += content*content;
669
670 // count events in low-alpha and high-alpha region
671 if ( xlo >= fAlphammm-fEps && xup >= fAlphammm-fEps)
672 {
673 nfar += content;
674 if ( xlo < fAlphamm )
675 fAlphamm = xlo;
676 if ( xup < fAlphamm )
677 fAlphamm = xup;
678 }
679 else
680 {
681 nclose += content;
682 if ( xlo > fAlphamm )
683 fAlphamm = xlo;
684 if ( xup > fAlphamm )
685 fAlphamm = xup;
686 }
687
688 // count bins with zero entry
689 if (content <= 0.0)
690 fNzero++;
691
692 // set minimum error
693 if (content < 9.0)
694 {
695 fMlow += 1;
696 fHist->SetBinError(i, 3.0);
697 }
698
699 //*fLog << "Take : i, content, error = " << i << ", "
700 // << fHist->GetBinContent(i) << ", "
701 // << fHist->GetBinError(i) << endl;
702
703 continue;
704 }
705 // bin is not completely contained in the fit range : set error huge
706
707 fHist->SetBinError(i, dummy);
708
709 //*fLog << "Omit : i, content, error = " << i << ", "
710 // << fHist->GetBinContent(i) << ", " << fHist->GetBinError(i)
711 // << endl;
712
713 }
714
715 // mean of entries/bin in the fit range
716 if (fMbins > 0)
717 {
718 mean /= ((Double_t) fMbins);
719 rms /= ((Double_t) fMbins);
720 }
721
722 rms = sqrt( rms - mean*mean );
723
724 // if there are no events in the background region
725 // there is no reason for rebinning
726 // and this is the condition for assuming a constant background (= 0)
727 if (mean <= 0.0)
728 break;
729
730 Double_t helpmi = fAlphami*fAlphami*fAlphami;
731 Double_t helpmm = fAlphamm*fAlphamm*fAlphamm;
732 Double_t helpma = fAlphama*fAlphama*fAlphama;
733 Double_t help = (helpma-helpmm) * (fAlphamm-fAlphami)
734 - (helpmm-helpmi) * (fAlphama-fAlphamm);
735 if (help != 0.0)
736 a2init = ( (fAlphamm-fAlphami)*nfar - (fAlphama-fAlphamm)*nclose )
737 * 1.5 * fHist->GetBinWidth(1) / help;
738 else
739 a2init = 0.0;
740
741
742 //--------------------------------------------
743 // rebin the histogram
744 // - if a bin has no entries
745 // - or if there are too many bins with too few entries
746 // - or if the new bin width would exceed half the size of the
747 // signal region
748
749 if ( !fRebin ||
750 ( fNzero <= 0 && (Double_t)fMlow<0.05*(Double_t)fMbins ) ||
751 (Double_t)(nrebin+1)/(Double_t)nrebin * fHist->GetBinWidth(1)
752 > fAlphasig/2.0 )
753 {
754 //*fLog << "before break" << endl;
755 break;
756 }
757
758 nrebin += 1;
759 TString histname = fHist->GetName();
760 delete fHist;
761 fHist = NULL;
762
763 *fLog << "MHFindSignificance::FitPolynomial; rebin the |alpha| plot, grouping "
764 << nrebin << " bins together" << endl;
765
766 // TH1::Rebin doesn't work properly
767 //fHist = fHistOrig->Rebin(nrebin, "Rebinned");
768 // use private routine RebinHistogram()
769 fHist = new TH1F;
770 fHist->Sumw2();
771 fHist->SetNameTitle(histname, histname);
772 fHist->UseCurrentStyle();
773
774 // do rebinning such that x0 remains a lower bin edge
775 Double_t x0 = 0.0;
776 if ( !RebinHistogram(x0, nrebin) )
777 {
778 *fLog << "MHFindSignificance::FitPolynomial; RebinHistgram() failed"
779 << endl;
780 return kFALSE;
781 }
782
783 fHist->SetXTitle("|alpha| [\\circ]");
784 fHist->SetYTitle("Counts");
785
786 }
787 //---------------- end of while loop for rebinning -----------------
788
789
790 // if there are still too many bins with too few entries don't fit
791 // and assume a constant background
792
793 fConstantBackg = kFALSE;
794 if ( fNzero > 0 || (Double_t)fMlow>0.05*(Double_t)fMbins )
795 {
796 *fLog << "MHFindSignificance::FitPolynomial; polynomial fit not possible, fNzero, fMlow, fMbins = "
797 << fNzero << ", " << fMlow << ", " << fMbins << endl;
798 *fLog << " assume a constant background" << endl;
799
800 fConstantBackg = kTRUE;
801 fDegree = 0;
802
803 TString funcname = "Poly";
804 Double_t xmin = 0.0;
805 Double_t xmax = 90.0;
806
807 TString formula = "[0]";
808
809 fPoly = new TF1(funcname, formula, xmin, xmax);
810 TList *funclist = fHist->GetListOfFunctions();
811 funclist->Add(fPoly);
812
813 //--------------------
814 Int_t nparfree = 1;
815 fChisq = 0.0;
816 fNdf = fMbins - nparfree;
817 fProb = 0.0;
818 fIstat = 0;
819
820 fValues.Set(1);
821 fErrors.Set(1);
822
823 Double_t val, err;
824 val = mean;
825 err = sqrt( mean / (Double_t)fMbins );
826
827 fPoly->SetParameter(0, val);
828 fPoly->SetParError (0, err);
829
830 fValues[0] = val;
831 fErrors[0] = err;
832
833 fEma[0][0] = err*err;
834 fCorr[0][0] = 1.0;
835 //--------------------
836
837 //--------------------------------------------------
838 // reset the errors of the points in the histogram
839 for (Int_t i=1; i<=nbins; i++)
840 {
841 fHist->SetBinError(i, saveError[i-1]);
842 }
843
844
845 return kTRUE;
846 }
847
848
849 //=========== start loop for reducing the degree ==================
850 // of the polynomial
851 while (1)
852 {
853 //--------------------------------------------------
854 // prepare fit of a polynomial : (a0 + a1*x + a2*x**2 + a3*x**3 + ...)
855
856 TString funcname = "Poly";
857 Double_t xmin = 0.0;
858 Double_t xmax = 90.0;
859
860 TString formula = "[0]";
861 TString bra1 = "+[";
862 TString bra2 = "]";
863 TString xpower = "*x";
864 TString newpower = "*x";
865 for (Int_t i=1; i<=fDegree; i++)
866 {
867 formula += bra1;
868 formula += i;
869 formula += bra2;
870 formula += xpower;
871
872 xpower += newpower;
873 }
874
875 //*fLog << "FitPolynomial : formula = " << formula << endl;
876
877 fPoly = new TF1(funcname, formula, xmin, xmax);
878 TList *funclist = fHist->GetListOfFunctions();
879 funclist->Add(fPoly);
880
881 //------------------------
882 // attention : the dimensions must agree with those in CallMinuit()
883 const UInt_t npar = fDegree+1;
884
885 TString parname[npar];
886 TArrayD vinit(npar);
887 TArrayD step(npar);
888 TArrayD limlo(npar);
889 TArrayD limup(npar);
890 TArrayI fix(npar);
891
892 vinit[0] = mean;
893 vinit[2] = a2init;
894
895 for (UInt_t j=0; j<npar; j++)
896 {
897 parname[j] = "p";
898 parname[j] += j+1;
899
900 step[j] = vinit[j] != 0.0 ? TMath::Abs(vinit[j]) / 10.0 : 0.000001;
901 }
902
903 // limit the first coefficient of the polynomial to positive values
904 // because the background must not be negative
905 limup[0] = fHist->GetEntries();
906
907 // use the subsequernt loop if you want to apply the
908 // constraint : uneven derivatives (at alpha=0) = zero
909 for (UInt_t j=1; j<npar; j+=2)
910 {
911 vinit[j] = 0;
912 step[j] = 0;
913 fix[j] = 1;
914 }
915
916 //*fLog << "FitPolynomial : before CallMinuit()" << endl;
917
918 MMinuitInterface inter;
919 const Bool_t rc = inter.CallMinuit(fcnpoly, parname, vinit, step,
920 limlo, limup, fix, fHist, "Migrad",
921 kFALSE);
922
923 //*fLog << "FitPolynomial : after CallMinuit()" << endl;
924
925 if (rc != 0)
926 {
927 // *fLog << "MHFindSignificance::FitPolynomial; polynomial fit failed"
928 // << endl;
929 // return kFALSE;
930 }
931
932
933 //-------------------
934 // get status of minimization
935 Double_t fmin = 0;
936 Double_t fedm = 0;
937 Double_t errdef = 0;
938 Int_t npari = 0;
939 Int_t nparx = 0;
940
941 if (gMinuit)
942 gMinuit->mnstat(fmin, fedm, errdef, npari, nparx, fIstat);
943
944 *fLog << "MHFindSignificance::FitPolynomial; fmin, fedm, errdef, npari, nparx, fIstat = "
945 << fmin << ", " << fedm << ", " << errdef << ", " << npari
946 << ", " << nparx << ", " << fIstat << endl;
947
948
949 //-------------------
950 // store the results
951
952 Int_t nparfree = gMinuit!=NULL ? gMinuit->GetNumFreePars() : 0;
953 fChisq = fmin;
954 fNdf = fMbins - nparfree;
955 fProb = TMath::Prob(fChisq, fNdf);
956
957
958 // get fitted parameter values and errors
959 fValues.Set(npar);
960 fErrors.Set(npar);
961
962 for (Int_t j=0; j<=fDegree; j++)
963 {
964 Double_t val, err;
965 if (gMinuit)
966 gMinuit->GetParameter(j, val, err);
967
968 fPoly->SetParameter(j, val);
969 fPoly->SetParError(j, err);
970
971 fValues[j] = val;
972 fErrors[j] = err;
973 }
974
975
976 //--------------------------------------------------
977 // if the highest coefficient (j0) of the polynomial
978 // is consistent with zero reduce the degree of the polynomial
979
980 Int_t j0 = 0;
981 for (Int_t j=fDegree; j>1; j--)
982 {
983 // ignore fixed parameters
984 if (fErrors[j] == 0)
985 continue;
986
987 // this is the highest coefficient
988 j0 = j;
989 break;
990 }
991
992 if (!fReduceDegree || j0==0 || TMath::Abs(fValues[j0]) > fErrors[j0])
993 break;
994
995 // reduce the degree of the polynomial
996 *fLog << "MHFindSignificance::FitPolynomial; reduce the degree of the polynomial from "
997 << fDegree << " to " << (j0-2) << endl;
998 fDegree = j0 - 2;
999
1000 funclist->Remove(fPoly);
1001 //if (fPoly)
1002 delete fPoly;
1003 fPoly = NULL;
1004
1005 // delete the Minuit object in order to have independent starting
1006 // conditions for the next minimization
1007 //if (gMinuit)
1008 delete gMinuit;
1009 gMinuit = NULL;
1010 }
1011 //=========== end of loop for reducing the degree ==================
1012 // of the polynomial
1013
1014
1015 //--------------------------------------------------
1016 // get the error matrix of the fitted parameters
1017
1018
1019 if (fIstat >= 1)
1020 {
1021 // error matrix was calculated
1022 if (gMinuit)
1023 gMinuit->mnemat(&fEmat[0][0], fNdim);
1024
1025 // copy covariance matrix into a matrix which includes also the fixed
1026 // parameters
1027 TString name;
1028 Double_t bnd1, bnd2, val, err;
1029 Int_t jvarbl;
1030 Int_t kvarbl;
1031 for (Int_t j=0; j<=fDegree; j++)
1032 {
1033 if (gMinuit)
1034 gMinuit->mnpout(j, name, val, err, bnd1, bnd2, jvarbl);
1035
1036 for (Int_t k=0; k<=fDegree; k++)
1037 {
1038 if (gMinuit)
1039 gMinuit->mnpout(k, name, val, err, bnd1, bnd2, kvarbl);
1040
1041 fEma[j][k] = jvarbl==0 || kvarbl==0 ? 0 : fEmat[jvarbl-1][kvarbl-1];
1042 }
1043 }
1044 }
1045 else
1046 {
1047 // error matrix was not calculated, construct it
1048 *fLog << "MHFindSignificance::FitPolynomial; error matrix not defined"
1049 << endl;
1050 for (Int_t j=0; j<=fDegree; j++)
1051 {
1052 for (Int_t k=0; k<=fDegree; k++)
1053 fEma[j][k] = 0;
1054
1055 fEma[j][j] = fErrors[j]*fErrors[j];
1056 }
1057 }
1058
1059
1060 //--------------------------------------------------
1061 // calculate correlation matrix
1062 for (Int_t j=0; j<=fDegree; j++)
1063 for (Int_t k=0; k<=fDegree; k++)
1064 {
1065 const Double_t sq = fEma[j][j]*fEma[k][k];
1066 fCorr[j][k] = sq==0 ? 0 : fEma[j][k] / TMath::Sqrt(fEma[j][j]*fEma[k][k]);
1067 }
1068
1069
1070 //--------------------------------------------------
1071 // reset the errors of the points in the histogram
1072 for (Int_t i=1; i<=nbins; i++)
1073 fHist->SetBinError(i, saveError[i-1]);
1074
1075
1076 return kTRUE;
1077}
1078
1079// --------------------------------------------------------------------------
1080//
1081// ReBinHistogram
1082//
1083// rebin the histogram 'fHistOrig' by grouping 'nrebin' bins together
1084// put the result into the histogram 'fHist'
1085// the rebinning is made such that 'x0' remains a lower bound of a bin
1086//
1087
1088Bool_t MHFindSignificance::RebinHistogram(Double_t x0, Int_t nrebin)
1089{
1090 //-----------------------------------------
1091 // search bin i0 which has x0 as lower edge
1092
1093 Int_t i0 = -1;
1094 Int_t nbold = fHistOrig->GetNbinsX();
1095 for (Int_t i=1; i<=nbold; i++)
1096 {
1097 if (TMath::Abs(fHistOrig->GetBinLowEdge(i) - x0) < 1.e-4 )
1098 {
1099 i0 = i;
1100 break;
1101 }
1102 }
1103
1104 if (i0 == -1)
1105 {
1106 i0 = 1;
1107 *fLog << "MHFindsignificance::Rebin; no bin found with " << x0
1108 << " as lower edge, start rebinning with bin 1" << endl;
1109 }
1110
1111 Int_t istart = i0 - nrebin * ( (i0-1)/nrebin );
1112
1113 //-----------------------------------------
1114 // get new bin edges
1115
1116 const Int_t nbnew = (nbold-istart+1) / nrebin;
1117 const Double_t xmin = fHistOrig->GetBinLowEdge(istart);
1118 const Double_t xmax = xmin + (Double_t)nbnew * nrebin * fHistOrig->GetBinWidth(1);
1119 fHist->SetBins(nbnew, xmin, xmax);
1120
1121 *fLog << "MHFindSignificance::ReBin; x0, i0, nbold, nbnew, xmin, xmax = "
1122 << x0 << ", " << i0 << ", " << nbold << ", " << nbnew << ", "
1123 << xmin << ", " << xmax << endl;
1124
1125 //-----------------------------------------
1126 // get new bin entries
1127
1128 for (Int_t i=1; i<=nbnew; i++)
1129 {
1130 Int_t j = nrebin*(i-1) + istart;
1131
1132 Double_t content = 0;
1133 Double_t error2 = 0;
1134 for (Int_t k=0; k<nrebin; k++)
1135 {
1136 content += fHistOrig->GetBinContent(j+k);
1137 error2 += fHistOrig->GetBinError(j+k) * fHistOrig->GetBinError(j+k);
1138 }
1139 fHist->SetBinContent(i, content);
1140 fHist->SetBinError (i, sqrt(error2));
1141 }
1142 fHist->SetEntries( fHistOrig->GetEntries() );
1143
1144 return kTRUE;
1145}
1146
1147// --------------------------------------------------------------------------
1148//
1149// FitGaussPoly
1150//
1151// fits a (Gauss + polynomial function) to the alpha distribution 'fhist'
1152//
1153//
1154Bool_t MHFindSignificance::FitGaussPoly()
1155{
1156 *fLog << "Entry FitGaussPoly" << endl;
1157
1158 //--------------------------------------------------
1159 // check the histogram :
1160 // - calculate initial values of the parameters
1161 // - check for bins with zero entries
1162 // - set minimum errors
1163 // - save the original errors
1164 // - set errors huge outside the fit range
1165 // (in 'fcnpoly' points with huge errors will be ignored)
1166
1167
1168 Double_t dummy = 1.e20;
1169
1170 fGNzero = 0;
1171 fGMbins = 0;
1172
1173 //------------------------------------------
1174 // if a constant background has been assumed (due to low statistics)
1175 // fit only in the signal region
1176 if ( !fConstantBackg )
1177 {
1178 fAlphalow = 0.0;
1179 fAlphahig = fAlphamax;
1180 }
1181 else
1182 {
1183 fAlphalow = 0.0;
1184 fAlphahig = 2.0*fAlphasig>25.0 ? 25.0 : 2.0*fAlphasig;
1185 }
1186 //------------------------------------------
1187
1188
1189 fAlphalo = 10000.0;
1190 fAlphahi = -10000.0;
1191
1192
1193 Int_t nbins = fHist->GetNbinsX();
1194 TArrayD saveError(nbins);
1195
1196 for (Int_t i=1; i<=nbins; i++)
1197 {
1198 saveError[i-1] = fHist->GetBinError(i);
1199
1200 // bin should be completely contained in the fit range
1201 // (fAlphalow, fAlphahig)
1202 Double_t xlo = fHist->GetBinLowEdge(i);
1203 Double_t xup = fHist->GetBinLowEdge(i+1);
1204
1205 if ( xlo >= fAlphalow-fEps && xlo <= fAlphahig+fEps &&
1206 xup >= fAlphalow-fEps && xup <= fAlphahig+fEps )
1207 {
1208 fGMbins++;
1209
1210 if ( xlo < fAlphalo )
1211 fAlphalo = xlo;
1212
1213 if ( xup > fAlphahi )
1214 fAlphahi = xup;
1215
1216 Double_t content = fHist->GetBinContent(i);
1217
1218
1219 // count bins with zero entry
1220 if (content <= 0.0)
1221 fGNzero++;
1222
1223 // set minimum error
1224 if (content < 9.0)
1225 fHist->SetBinError(i, 3.0);
1226
1227 //*fLog << "Take : i, content, error = " << i << ", "
1228 // << fHist->GetBinContent(i) << ", "
1229 // << fHist->GetBinError(i) << endl;
1230
1231 continue;
1232 }
1233 // bin is not completely contained in the fit range : set error huge
1234
1235 fHist->SetBinError(i, dummy);
1236
1237 //*fLog << "Omit : i, content, error = " << i << ", "
1238 // << fHist->GetBinContent(i) << ", " << fHist->GetBinError(i)
1239 // << endl;
1240
1241 }
1242
1243
1244 // if a bin has no entries don't fit
1245 if (fGNzero > 0)
1246 {
1247 *fLog << "MHFindSignificance::FitGaussPoly; out of " << fGMbins
1248 << " bins there are " << fGNzero
1249 << " bins with zero entry" << endl;
1250
1251 fGPoly = NULL;
1252 return kFALSE;
1253 }
1254
1255
1256 //--------------------------------------------------
1257 // prepare fit of a (polynomial+Gauss) :
1258 // (a0 + a1*x + a2*x**2 + a3*x**3 + ...) + A*exp( -0.5*((x-x0)/sigma)**2 )
1259
1260 TString funcname = "PolyGauss";
1261 Double_t xmin = 0.0;
1262 Double_t xmax = 90.0;
1263
1264 TString xpower = "*x";
1265 TString newpower = "*x";
1266
1267 TString formulaBackg = "[0]";
1268 for (Int_t i=1; i<=fDegree; i++)
1269 formulaBackg += Form("+[%d]*x^%d", i, i);
1270
1271 const TString formulaGauss =
1272 Form("[%d]/[%d]*exp(-0.5*((x-[%d])/[%d])^2)",
1273 fDegree+1, fDegree+3, fDegree+2, fDegree+3);
1274
1275 TString formula = formulaBackg;
1276 formula += "+";
1277 formula += formulaGauss;
1278
1279 *fLog << "FitGaussPoly : formulaBackg = " << formulaBackg << endl;
1280 *fLog << "FitGaussPoly : formulaGauss = " << formulaGauss << endl;
1281 *fLog << "FitGaussPoly : formula = " << formula << endl;
1282
1283 fGPoly = new TF1(funcname, formula, xmin, xmax);
1284 TList *funclist = fHist->GetListOfFunctions();
1285 funclist->Add(fGPoly);
1286
1287 fGBackg = new TF1("Backg", formulaBackg, xmin, xmax);
1288 funclist->Add(fGBackg);
1289
1290 //------------------------
1291 // attention : the dimensions must agree with those in CallMinuit()
1292 Int_t npar = fDegree+1 + 3;
1293
1294 TString parname[npar];
1295 TArrayD vinit(npar);
1296 TArrayD step(npar);
1297 TArrayD limlo(npar);
1298 TArrayD limup(npar);
1299 TArrayI fix(npar);
1300
1301
1302 // take as initial values for the polynomial
1303 // the result from the polynomial fit
1304 for (Int_t j=0; j<=fDegree; j++)
1305 vinit[j] = fPoly->GetParameter(j);
1306
1307 Double_t sigma = 8;
1308 vinit[fDegree+1] = 2.0 * fNex * fHist->GetBinWidth(1) / TMath::Sqrt(TMath::Pi()*2);
1309 vinit[fDegree+2] = 0;
1310 vinit[fDegree+3] = sigma;
1311
1312 *fLog << "FitGaussPoly : starting value for Gauss-amplitude = "
1313 << vinit[fDegree+1] << endl;
1314
1315 for (Int_t j=0; j<npar; j++)
1316 {
1317 parname[j] = "p";
1318 parname[j] += j+1;
1319
1320 step[j] = vinit[j]!=0 ? TMath::Abs(vinit[j]) / 10.0 : 0.000001;
1321 }
1322
1323 // limit the first coefficient of the polynomial to positive values
1324 // because the background must not be negative
1325 limup[0] = fHist->GetEntries()*10;
1326
1327 // limit the sigma of the Gauss function
1328 limup[fDegree+3] = 20;
1329
1330
1331 // use the subsequernt loop if you want to apply the
1332 // constraint : uneven derivatives (at alpha=0) = zero
1333 for (Int_t j=1; j<=fDegree; j+=2)
1334 {
1335 vinit[j] = 0;
1336 step[j] = 0;
1337 fix[j] = 1;
1338 }
1339
1340 // fix position of Gauss function
1341 vinit[fDegree+2] = 0;
1342 step[fDegree+2] = 0;
1343 fix[fDegree+2] = 1;
1344
1345 // if a constant background has been assumed (due to low statistics)
1346 // fix the background
1347 if (fConstantBackg)
1348 {
1349 step[0] = 0;
1350 fix[0] = 1;
1351 }
1352
1353 MMinuitInterface inter;
1354 const Bool_t rc = inter.CallMinuit(fcnpolygauss, parname, vinit, step,
1355 limlo, limup, fix, fHist, "Migrad",
1356 kFALSE);
1357
1358 if (rc != 0)
1359 {
1360 // *fLog << "MHFindSignificance::FitGaussPoly; (polynomial+Gauss) fit failed"
1361 // << endl;
1362 // return kFALSE;
1363 }
1364
1365
1366 //-------------------
1367 // get status of the minimization
1368 Double_t fmin;
1369 Double_t fedm;
1370 Double_t errdef;
1371 Int_t npari;
1372 Int_t nparx;
1373
1374 if (gMinuit)
1375 gMinuit->mnstat(fmin, fedm, errdef, npari, nparx, fGIstat);
1376
1377 *fLog << "MHFindSignificance::FitGaussPoly; fmin, fedm, errdef, npari, nparx, fGIstat = "
1378 << fmin << ", " << fedm << ", " << errdef << ", " << npari
1379 << ", " << nparx << ", " << fGIstat << endl;
1380
1381
1382 //-------------------
1383 // store the results
1384
1385 Int_t nparfree = gMinuit!=NULL ? gMinuit->GetNumFreePars() : 0;
1386 fGChisq = fmin;
1387 fGNdf = fGMbins - nparfree;
1388 fGProb = TMath::Prob(fGChisq, fGNdf);
1389
1390
1391 // get fitted parameter values and errors
1392 fGValues.Set(npar);
1393 fGErrors.Set(npar);
1394
1395 for (Int_t j=0; j<npar; j++)
1396 {
1397 Double_t val, err;
1398 if (gMinuit)
1399 gMinuit->GetParameter(j, val, err);
1400
1401 fGPoly->SetParameter(j, val);
1402 fGPoly->SetParError(j, err);
1403
1404 fGValues[j] = val;
1405 fGErrors[j] = err;
1406
1407 if (j <=fDegree)
1408 {
1409 fGBackg->SetParameter(j, val);
1410 fGBackg->SetParError(j, err);
1411 }
1412 }
1413
1414 fSigmaGauss = fGValues[fDegree+3];
1415 fdSigmaGauss = fGErrors[fDegree+3];
1416 // fitted total number of excess events
1417 fNexGauss = fGValues[fDegree+1] * TMath::Sqrt(TMath::Pi()*2) /
1418 (fHist->GetBinWidth(1)*2 );
1419 fdNexGauss = fNexGauss * fGErrors[fDegree+1]/fGValues[fDegree+1];
1420
1421 //--------------------------------------------------
1422 // get the error matrix of the fitted parameters
1423
1424
1425 if (fGIstat >= 1)
1426 {
1427 // error matrix was calculated
1428 if (gMinuit)
1429 gMinuit->mnemat(&fGEmat[0][0], fGNdim);
1430
1431 // copy covariance matrix into a matrix which includes also the fixed
1432 // parameters
1433 TString name;
1434 Double_t bnd1, bnd2, val, err;
1435 Int_t jvarbl;
1436 Int_t kvarbl;
1437 for (Int_t j=0; j<npar; j++)
1438 {
1439 if (gMinuit)
1440 gMinuit->mnpout(j, name, val, err, bnd1, bnd2, jvarbl);
1441
1442 for (Int_t k=0; k<npar; k++)
1443 {
1444 if (gMinuit)
1445 gMinuit->mnpout(k, name, val, err, bnd1, bnd2, kvarbl);
1446
1447 fGEma[j][k] = jvarbl==0 || kvarbl==0 ? 0 : fGEmat[jvarbl-1][kvarbl-1];
1448 }
1449 }
1450 }
1451 else
1452 {
1453 // error matrix was not calculated, construct it
1454 *fLog << "MHFindSignificance::FitPolynomial; error matrix not defined"
1455 << endl;
1456 for (Int_t j=0; j<npar; j++)
1457 {
1458 for (Int_t k=0; k<npar; k++)
1459 fGEma[j][k] = 0;
1460
1461 fGEma[j][j] = fGErrors[j]*fGErrors[j];
1462 }
1463 }
1464
1465
1466 //--------------------------------------------------
1467 // calculate correlation matrix
1468 for (Int_t j=0; j<npar; j++)
1469 {
1470 for (Int_t k=0; k<npar; k++)
1471 {
1472 const Double_t sq = fGEma[j][j]*fGEma[k][k];
1473 fGCorr[j][k] = sq==0 ? 0 : fGEma[j][k] / sqrt( fGEma[j][j]*fGEma[k][k] );
1474 }
1475 }
1476
1477
1478 //--------------------------------------------------
1479 // reset the errors of the points in the histogram
1480 for (Int_t i=1; i<=nbins; i++)
1481 fHist->SetBinError(i, saveError[i-1]);
1482
1483 return kTRUE;
1484
1485}
1486
1487// --------------------------------------------------------------------------
1488//
1489// DetExcess
1490//
1491// using the result of the polynomial fit (fValues), DetExcess determines
1492//
1493// - the total number of events in the signal region (fNon)
1494// - the number of backgound events in the signal region (fNbg)
1495// - the number of excess events (fNex)
1496// - the effective number of background events (fNoff), and fGamma :
1497// fNbg = fGamma * fNoff; fdNbg = fGamma * sqrt(fNoff);
1498//
1499// It assumed that the polynomial is defined as
1500// a0 + a1*x + a2*x**2 + a3*x**3 + ..
1501//
1502// and that the alpha distribution has the range 0 < alpha < 90 degrees
1503//
1504
1505Bool_t MHFindSignificance::DetExcess()
1506{
1507 //*fLog << "MHFindSignificance::DetExcess;" << endl;
1508
1509 //--------------------------------------------
1510 // calculate the total number of events (fNon) in the signal region
1511
1512 fNon = 0.0;
1513 fdNon = 0.0;
1514
1515 Double_t alphaup = -1000.0;
1516 Double_t binwidth = fHist->GetBinWidth(1);
1517
1518 Int_t nbins = fHist->GetNbinsX();
1519 for (Int_t i=1; i<=nbins; i++)
1520 {
1521 Double_t xlo = fHist->GetBinLowEdge(i);
1522 Double_t xup = fHist->GetBinLowEdge(i+1);
1523
1524 // bin must be completely contained in the signal region
1525 if ( xlo <= (fAlphasig+fEps) && xup <= (fAlphasig+fEps) )
1526 {
1527 Double_t width = fabs(xup-xlo);
1528 if (fabs(width-binwidth) > fEps)
1529 {
1530 *fLog << "MHFindSignificance::DetExcess; alpha plot has variable binning, which is not allowed"
1531 << endl;
1532 return kFALSE;
1533 }
1534
1535 if (xup > alphaup)
1536 alphaup = xup;
1537
1538 fNon += fHist->GetBinContent(i);
1539 fdNon += fHist->GetBinError(i) * fHist->GetBinError(i);
1540 }
1541 }
1542 fdNon = sqrt(fdNon);
1543
1544 // the actual signal range is :
1545 if (alphaup == -1000.0)
1546 return kFALSE;
1547
1548 fAlphasi = alphaup;
1549
1550 //*fLog << "fAlphasi, fNon, fdNon, binwidth, fDegree = " << fAlphasi << ", "
1551 // << fNon << ", " << fdNon << ", " << binwidth << ", "
1552 // << fDegree << endl;
1553
1554 //--------------------------------------------
1555 // calculate the number of background events (fNbg) in the signal region
1556 // and its error (fdNbg)
1557
1558 Double_t fac = 1.0/binwidth;
1559
1560 fNbg = 0.0;
1561 Double_t altothejplus1 = fAlphasi;
1562 for (Int_t j=0; j<=fDegree; j++)
1563 {
1564 fNbg += fValues[j] * altothejplus1 / ((Double_t)(j+1));
1565 altothejplus1 *= fAlphasi;
1566 }
1567 fNbg *= fac;
1568
1569 // derivative of Nbg
1570 Double_t facj;
1571 Double_t fack;
1572
1573 Double_t sum = 0.0;
1574 altothejplus1 = fAlphasi;
1575 for (Int_t j=0; j<=fDegree; j++)
1576 {
1577 facj = altothejplus1 / ((Double_t)(j+1));
1578
1579 Double_t altothekplus1 = fAlphasi;
1580 for (Int_t k=0; k<=fDegree; k++)
1581 {
1582 fack = altothekplus1 / ((Double_t)(k+1));
1583
1584 sum += facj * fack * fEma[j][k];
1585 altothekplus1 *= fAlphasi;
1586 }
1587 altothejplus1 *= fAlphasi;
1588 }
1589 sum *= fac*fac;
1590
1591 if (sum < 0.0)
1592 {
1593 *fLog << "MHFindsignificance::DetExcess; error squared is negative"
1594 << endl;
1595 return kFALSE;
1596 }
1597
1598 fdNbg = sqrt(sum);
1599
1600
1601 //--------------------------------------------
1602 // AS A CHECK :
1603 // calculate the number of background events (fNbgtotFitted) in the
1604 // background region, and its error (fdNbgtotFitted)
1605 // expect fdnbg to be approximately equal to sqrt(fNbgtotFitted)
1606
1607 Double_t fNmi = 0.0;
1608 altothejplus1 = fAlphami;
1609 for (Int_t j=0; j<=fDegree; j++)
1610 {
1611 fNmi += fValues[j] * altothejplus1 / ((Double_t)(j+1));
1612 altothejplus1 *= fAlphami;
1613 }
1614 fNmi *= fac;
1615
1616 Double_t fNma = 0.0;
1617 altothejplus1 = fAlphama;
1618 for (Int_t j=0; j<=fDegree; j++)
1619 {
1620 fNma += fValues[j] * altothejplus1 / ((Double_t)(j+1));
1621 altothejplus1 *= fAlphama;
1622 }
1623 fNma *= fac;
1624
1625 fNbgtotFitted = fNma - fNmi;
1626
1627 //----------------------
1628
1629 sum = 0.0;
1630 Double_t altothejma = fAlphama;
1631 Double_t altothejmi = fAlphami;
1632 for (Int_t j=0; j<=fDegree; j++)
1633 {
1634 facj = (altothejma-altothejmi) / ((Double_t)(j+1));
1635
1636 Double_t altothekma = fAlphama;
1637 Double_t altothekmi = fAlphami;
1638 for (Int_t k=0; k<=fDegree; k++)
1639 {
1640 fack = (altothekma-altothekmi) / ((Double_t)(k+1));
1641
1642 sum += facj * fack * fEma[j][k];
1643 altothekma *= fAlphama;
1644 altothekmi *= fAlphami;
1645 }
1646 altothejma *= fAlphama;
1647 altothejmi *= fAlphami;
1648 }
1649 sum *= fac*fac;
1650
1651 fdNbgtotFitted = sqrt(sum);
1652 if ( fabs(fdNbgtotFitted - sqrt(fNbgtotFitted)) > 0.2 * sqrt(fNbgtotFitted) )
1653 {
1654 *fLog << "MHFindSignificance::DetExcess; error of calculated number of background events (in the background region) does not agree with the expectation :"
1655 << endl;
1656 *fLog << " fNbgtotFitted, fdNbgtotFitted = "
1657 << fNbgtotFitted << ", " << fdNbgtotFitted
1658 << ", expected : " << sqrt(fNbgtotFitted) << endl;
1659 }
1660
1661
1662 //--------------------------------------------
1663 // calculate the number of excess events in the signal region
1664
1665 fNex = fNon - fNbg;
1666
1667 //--------------------------------------------
1668 // calculate the effective number of background events (fNoff) , and fGamma :
1669 // fNbg = fGamma * fNoff; dfNbg = fGamma * sqrt(fNoff);
1670
1671 if (fNbg < 0.0)
1672 {
1673 *fLog << "MHFindSignificamce::DetExcess; number of background events is negative, fNbg, fdNbg = "
1674 << fNbg << ", " << fdNbg << endl;
1675
1676 fGamma = 1.0;
1677 fNoff = 0.0;
1678 return kFALSE;
1679 }
1680
1681 if (fNbg > 0.0)
1682 {
1683 fGamma = fdNbg*fdNbg / fNbg;
1684 fNoff = fNbg*fNbg / (fdNbg*fdNbg);
1685 }
1686 else
1687 {
1688 fGamma = 1.0;
1689 fNoff = 0.0;
1690 }
1691
1692 //*fLog << "Exit DetExcess()" << endl;
1693
1694 return kTRUE;
1695}
1696
1697// --------------------------------------------------------------------------
1698//
1699// SigmaLiMa
1700//
1701// calculates the significance according to Li & Ma
1702// ApJ 272 (1983) 317
1703//
1704Bool_t MHFindSignificance::SigmaLiMa(Double_t non, Double_t noff,
1705 Double_t gamma, Double_t *siglima)
1706{
1707 if (gamma <= 0.0 || non <= 0.0 || noff <= 0.0)
1708 {
1709 *siglima = 0.0;
1710 return kFALSE;
1711 }
1712
1713 Double_t help1 = non * log( (1.0+gamma)*non / (gamma*(non+noff)) );
1714 Double_t help2 = noff * log( (1.0+gamma)*noff / ( non+noff ) );
1715 *siglima = sqrt( 2.0 * (help1+help2) );
1716
1717 Double_t nex = non - gamma*noff;
1718 if (nex < 0.0)
1719 *siglima = - *siglima;
1720
1721 //*fLog << "MHFindSignificance::SigmaLiMa; non, noff, gamma, *siglima = "
1722 // << non << ", " << noff << ", " << gamma << ", " << *siglima << endl;
1723
1724 return kTRUE;
1725}
1726
1727// --------------------------------------------------------------------------
1728//
1729Bool_t MHFindSignificance::DrawFit(const Option_t *opt)
1730{
1731 if (fHist == NULL)
1732 *fLog << "MHFindSignificance::DrawFit; fHist = NULL" << endl;
1733
1734
1735 //TCanvas *fCanvas = new TCanvas("Alpha", "Alpha plot", 600, 600);
1736 fCanvas = new TCanvas(fHist->GetName(), "Alpha plot", 600, 600);
1737
1738 //gStyle->SetOptFit(1011);
1739
1740 gROOT->SetSelectedPad(NULL);
1741 gStyle->SetPadLeftMargin(0.1);
1742
1743 fCanvas->cd();
1744
1745
1746 if (fHist)
1747 {
1748 fHist->DrawCopy();
1749 }
1750
1751 TF1 *fpoly = fHist->GetFunction("Poly");
1752 if (fpoly == NULL)
1753 *fLog << "MHFindSignificance::DrawFit; fpoly = NULL" << endl;
1754
1755 if (fpoly)
1756 {
1757 // 2, 1 is red and solid
1758 fpoly->SetLineColor(2);
1759 fpoly->SetLineStyle(1);
1760 fpoly->SetLineWidth(2);
1761 fpoly->DrawCopy("same");
1762 }
1763
1764 if (fFitGauss)
1765 {
1766 TF1 *fpolygauss = fHist->GetFunction("PolyGauss");
1767 if (fpolygauss == NULL)
1768 *fLog << "MHFindSignificance::DrawFit; fpolygauss = NULL" << endl;
1769
1770 if (fpolygauss)
1771 {
1772 // 4, 1 is blue and solid
1773 fpolygauss->SetLineColor(4);
1774 fpolygauss->SetLineStyle(1);
1775 fpolygauss->SetLineWidth(4);
1776 fpolygauss->DrawCopy("same");
1777 }
1778
1779 TF1 *fbackg = fHist->GetFunction("Backg");
1780 if (fbackg == NULL)
1781 *fLog << "MHFindSignificance::DrawFit; fbackg = NULL" << endl;
1782
1783 if (fbackg)
1784 {
1785 // 6, 4 is pink and dotted
1786 fbackg->SetLineColor(4);
1787 fbackg->SetLineStyle(4);
1788 fbackg->SetLineWidth(4);
1789 fbackg->DrawCopy("same");
1790 }
1791 }
1792
1793
1794 //-------------------------------
1795 // print results onto the figure
1796 TPaveText *pt = new TPaveText(0.30, 0.35, 0.70, 0.90, "NDC");
1797 char tx[100];
1798
1799 sprintf(tx, "Results of polynomial fit (order %2d) :", fDegree);
1800 TText *t1 = pt->AddText(tx);
1801 t1->SetTextSize(0.03);
1802 t1->SetTextColor(2);
1803
1804 sprintf(tx, " (%6.2f< |alpha| <%6.2f [\\circ])", fAlphami, fAlphama);
1805 pt->AddText(tx);
1806
1807 sprintf(tx, " chi2 = %8.2f, Ndof = %4d, Prob = %6.2f",
1808 fChisq, fNdf, fProb);
1809 pt->AddText(tx);
1810
1811 sprintf(tx, " Nbgtot(fit) = %8.1f #pm %8.1f",
1812 fNbgtotFitted, fdNbgtotFitted);
1813 pt->AddText(tx);
1814
1815 sprintf(tx, " Nbgtot(meas) = %8.1f", fNbgtot);
1816 pt->AddText(tx);
1817
1818
1819 //sprintf(tx, " ");
1820 //pt->AddText(tx);
1821
1822 //--------------
1823 sprintf(tx, "Results for |alpha|< %6.2f [\\circ] :", fAlphasi);
1824 TText *t6 = pt->AddText(tx);
1825 t6->SetTextSize(0.03);
1826 t6->SetTextColor(8);
1827
1828 sprintf(tx, " Non = %8.1f #pm %8.1f", fNon, fdNon);
1829 pt->AddText(tx);
1830
1831 sprintf(tx, " Nex = %8.1f #pm %8.1f", fNex, fdNex);
1832 pt->AddText(tx);
1833
1834 sprintf(tx, " Nbg = %8.1f #pm %8.1f, gamma = %6.1f",
1835 fNbg, fdNbg, fGamma);
1836 pt->AddText(tx);
1837
1838 Double_t ratio = fNbg>0.0 ? fNex/fNbg : 0.0;
1839 sprintf(tx, " Significance = %6.2f, Nex/Nbg = %6.2f",
1840 fSigLiMa, ratio);
1841 pt->AddText(tx);
1842
1843 //sprintf(tx, " ");
1844 //pt->AddText(tx);
1845
1846 //--------------
1847 if (fFitGauss)
1848 {
1849 sprintf(tx, "Results of (polynomial+Gauss) fit :");
1850 TText *t7 = pt->AddText(tx);
1851 t7->SetTextSize(0.03);
1852 t7->SetTextColor(4);
1853
1854 sprintf(tx, " chi2 = %8.2f, Ndof = %4d, Prob = %6.2f",
1855 fGChisq, fGNdf, fGProb);
1856 pt->AddText(tx);
1857
1858 sprintf(tx, " Sigma of Gauss = %8.1f #pm %8.1f [\\circ]",
1859 fSigmaGauss, fdSigmaGauss);
1860 pt->AddText(tx);
1861
1862 sprintf(tx, " total no.of excess events = %8.1f #pm %8.1f",
1863 fNexGauss, fdNexGauss);
1864 pt->AddText(tx);
1865 }
1866 //--------------
1867
1868 pt->SetFillStyle(0);
1869 pt->SetBorderSize(0);
1870 pt->SetTextAlign(12);
1871
1872 pt->Draw();
1873
1874 fCanvas->Modified();
1875 fCanvas->Update();
1876
1877 return kTRUE;
1878}
1879
1880
1881
1882// --------------------------------------------------------------------------
1883//
1884// Print the results of the polynomial fit to the alpha distribution
1885//
1886//
1887void MHFindSignificance::PrintPoly(Option_t *o)
1888{
1889 *fLog << "---------------------------" << endl;
1890 *fLog << "MHFindSignificance::PrintPoly :" << endl;
1891
1892 *fLog << "fAlphami, fAlphama, fDegree, fAlphasi = "
1893 << fAlphami << ", " << fAlphama << ", " << fDegree << ", "
1894 << fAlphasi << endl;
1895
1896 *fLog << "fMbins, fNzero, fIstat = " << fMbins << ", "
1897 << fNzero << ", " << fIstat << endl;
1898
1899 *fLog << "fChisq, fNdf, fProb = " << fChisq << ", "
1900 << fNdf << ", " << fProb << endl;
1901
1902 *fLog << "fNon, fNbg, fdNbg, fNbgtot, fNbgtotFitted, fdNbgtotFitted = "
1903 << fNon << ", " << fNbg << ", " << fdNbg << ", " << fNbgtot
1904 << ", " << fNbgtotFitted << ", " << fdNbgtotFitted << endl;
1905
1906 Double_t sigtoback = fNbg>0.0 ? fNex/fNbg : 0.0;
1907 *fLog << "fNex, fdNex, fGamma, fNoff, fSigLiMa, sigtoback = "
1908 << fNex << ", " << fdNex << ", " << fGamma << ", " << fNoff
1909 << ", " << fSigLiMa << ", " << sigtoback << endl;
1910
1911 //------------------------------------
1912 // get errors
1913
1914 /*
1915 Double_t eplus;
1916 Double_t eminus;
1917 Double_t eparab;
1918 Double_t gcc;
1919 Double_t errdiag;
1920
1921
1922 if ( !fConstantBackg )
1923 {
1924 *fLog << "parameter value error eplus eminus eparab errdiag gcc"
1925 << endl;
1926
1927 for (Int_t j=0; j<=fDegree; j++)
1928 {
1929 if (gMinuit)
1930 gMinuit->mnerrs(j, eplus, eminus, eparab, gcc);
1931 errdiag = sqrt(fEma[j][j]);
1932 *fLog << j << " " << fValues[j] << " " << fErrors[j] << " "
1933 << eplus << " " << eminus << " " << eparab << " "
1934 << errdiag << " " << gcc << endl;
1935 }
1936 }
1937 else
1938 {
1939 *fLog << "parameter value error errdiag "
1940 << endl;
1941
1942 for (Int_t j=0; j<=fDegree; j++)
1943 {
1944 errdiag = sqrt(fEma[j][j]);
1945 *fLog << j << " " << fValues[j] << " " << fErrors[j] << " "
1946 << errdiag << endl;
1947 }
1948 }
1949 */
1950
1951 //----------------------------------------
1952 /*
1953 *fLog << "Covariance matrix :" << endl;
1954 for (Int_t j=0; j<=fDegree; j++)
1955 {
1956 *fLog << "j = " << j << " : ";
1957 for (Int_t k=0; k<=fDegree; k++)
1958 {
1959 *fLog << fEma[j][k] << " ";
1960 }
1961 *fLog << endl;
1962 }
1963
1964 *fLog << "Correlation matrix :" << endl;
1965 for (Int_t j=0; j<=fDegree; j++)
1966 {
1967 *fLog << "j = " << j << " : ";
1968 for (Int_t k=0; k<=fDegree; k++)
1969 {
1970 *fLog << fCorr[j][k] << " ";
1971 }
1972 *fLog << endl;
1973 }
1974 */
1975
1976 *fLog << "---------------------------" << endl;
1977}
1978
1979// --------------------------------------------------------------------------
1980//
1981// Print the results of the (polynomial+Gauss) fit to the alpha distribution
1982//
1983//
1984void MHFindSignificance::PrintPolyGauss(Option_t *o)
1985{
1986 *fLog << "---------------------------" << endl;
1987 *fLog << "MHFindSignificance::PrintPolyGauss :" << endl;
1988
1989 *fLog << "fAlphalo, fAlphahi = "
1990 << fAlphalo << ", " << fAlphahi << endl;
1991
1992 *fLog << "fGMbins, fGNzero, fGIstat = " << fGMbins << ", "
1993 << fGNzero << ", " << fGIstat << endl;
1994
1995 *fLog << "fGChisq, fGNdf, fGProb = " << fGChisq << ", "
1996 << fGNdf << ", " << fGProb << endl;
1997
1998
1999 //------------------------------------
2000 // get errors
2001
2002 Double_t eplus;
2003 Double_t eminus;
2004 Double_t eparab;
2005 Double_t gcc;
2006 Double_t errdiag;
2007
2008 *fLog << "parameter value error eplus eminus eparab errdiag gcc"
2009 << endl;
2010 for (Int_t j=0; j<=(fDegree+3); j++)
2011 {
2012 if (gMinuit)
2013 gMinuit->mnerrs(j, eplus, eminus, eparab, gcc);
2014 errdiag = sqrt(fGEma[j][j]);
2015 *fLog << j << " " << fGValues[j] << " " << fGErrors[j] << " "
2016 << eplus << " " << eminus << " " << eparab << " "
2017 << errdiag << " " << gcc << endl;
2018 }
2019
2020
2021 *fLog << "Covariance matrix :" << endl;
2022 for (Int_t j=0; j<=(fDegree+3); j++)
2023 {
2024 *fLog << "j = " << j << " : ";
2025 for (Int_t k=0; k<=(fDegree+3); k++)
2026 {
2027 *fLog << fGEma[j][k] << " ";
2028 }
2029 *fLog << endl;
2030 }
2031
2032 *fLog << "Correlation matrix :" << endl;
2033 for (Int_t j=0; j<=(fDegree+3); j++)
2034 {
2035 *fLog << "j = " << j << " : ";
2036 for (Int_t k=0; k<=(fDegree+3); k++)
2037 {
2038 *fLog << fGCorr[j][k] << " ";
2039 }
2040 *fLog << endl;
2041 }
2042
2043 *fLog << "---------------------------" << endl;
2044}
2045
2046//============================================================================
2047
Note: See TracBrowser for help on using the repository browser.