source: trunk/MagicSoft/Mars/mcalib/MHGausEvents.cc@ 4231

Last change on this file since 4231 was 4198, checked in by gaug, 21 years ago
*** empty log message ***
File size: 27.2 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): Markus Gaug 02/2004 <mailto:markus@ifae.es>
19!
20! Copyright: MAGIC Software Development, 2000-2004
21!
22!
23\* ======================================================================== */
24
25//////////////////////////////////////////////////////////////////////////////
26//
27// MHGausEvents
28//
29// A base class for events which are believed to follow a Gaussian distribution
30// with time, e.g. calibration events, observables containing white noise, ...
31//
32// MHGausEvents derives from MH, thus all features of MH can be used by a class
33// deriving from MHGausEvents, especially the filling functions.
34//
35// The central objects are:
36//
37// 1) The TH1F fHGausHist:
38// ====================
39//
40// It is created with a default name and title and resides in directory NULL.
41// - Any class deriving from MHGausEvents needs to apply a binning to fHGausHist
42// (e.g. by setting the variables fNbins, fFirst, fLast and calling the function
43// InitBins() or by directly calling fHGausHist.SetBins(..) )
44// - The histogram is filled with the functions FillHist() or FillHistAndArray().
45// - The histogram can be fitted with the function FitGaus(). This involves stripping
46// of all zeros at the lower and upper end of the histogram and re-binning to
47// a new number of bins, specified in the variable fBinsAfterStripping.
48// - The fit result's probability is compared to a reference probability fProbLimit
49// The NDF is compared to fNDFLimit and a check is made whether results are NaNs.
50// Accordingly, a flag IsGausFitOK() is set.
51// - One can repeat the fit within a given amount of sigmas from the previous mean
52// (specified by the variables fPickupLimit and fBlackoutLimit) with the function RepeatFit()
53// - One can completely skip the fitting to set mean, sigma and its errors directly
54// from the histograms with the function BypassFit()
55//
56// 2) The TArrayF fEvents:
57// ==========================
58//
59// It is created with 0 entries and not expanded unless FillArray() or FillHistAndArray()
60// are called.
61// - A first call to FillArray() or FillHistAndArray() initializes fEvents by default
62// to 512 entries.
63// - Any later call to FillArray() or FillHistAndArray() fills up the array.
64// Reaching the limit, the array is expanded by a factor 2.
65// - The array can be fourier-transformed into the array fPowerSpectrum.
66// Note that any FFT accepts only number of events which are a power of 2.
67// Thus, fEvents is cut to the next power of 2 smaller than its actual number of entries.
68// Be aware that you might lose information at the end of your analysis.
69// - Calling the function CreateFourierSpectrum() creates the array fPowerSpectrum
70// and its projection fHPowerProbability which in turn is fit to an exponential.
71// - The fit result's probability is compared to a referenc probability fProbLimit
72// and accordingly the flag IsExpFitOK() is set.
73// - The flag IsFourierSpectrumOK() is set accordingly to IsExpFitOK().
74// Later, a closer check will be installed.
75// - You can display all arrays by calls to: CreateGraphEvents() and
76// CreateGraphPowerSpectrum() and successive calls to the corresponding Getters.
77//
78// To see an example, have a look at: Draw()
79//
80//////////////////////////////////////////////////////////////////////////////
81#include "MHGausEvents.h"
82
83#include <TH1.h>
84#include <TF1.h>
85#include <TGraph.h>
86#include <TPad.h>
87#include <TVirtualPad.h>
88#include <TCanvas.h>
89#include <TStyle.h>
90
91#include "MFFT.h"
92#include "MArray.h"
93
94#include "MH.h"
95
96#include "MLog.h"
97#include "MLogManip.h"
98
99ClassImp(MHGausEvents);
100
101using namespace std;
102
103const Int_t MHGausEvents::fgBinsAfterStripping = 40;
104const Float_t MHGausEvents::fgBlackoutLimit = 5.;
105const Int_t MHGausEvents::fgNDFLimit = 2;
106const Float_t MHGausEvents::fgPickupLimit = 5.;
107const Float_t MHGausEvents::fgProbLimit = 0.001;
108const Int_t MHGausEvents::fgPowerProbabilityBins = 20;
109// --------------------------------------------------------------------------
110//
111// Default Constructor.
112// Sets:
113// - the default Probability Bins for fPowerProbabilityBins (fgPowerProbabilityBins)
114// - the default Probability Limit for fProbLimit (fgProbLimit)
115// - the default NDF Limit for fNDFLimit (fgNDFLimit)
116// - the default number for fPickupLimit (fgPickupLimit)
117// - the default number for fBlackoutLimit (fgBlackoutLimit)
118// - the default number of bins after stripping for fBinsAfterStipping (fgBinsAfterStipping)
119// - the default name of the fHGausHist ("HGausHist")
120// - the default title of the fHGausHist ("Histogram of Events with Gaussian Distribution")
121// - the default directory of the fHGausHist (NULL)
122// - the default for fNbins (100)
123// - the default for fFirst (0.)
124// - the default for fLast (100.)
125//
126// Initializes:
127// - fEvents to 0 entries
128// - fHGausHist()
129// - all other pointers to NULL
130// - all variables to 0.
131// - all flags to kFALSE
132//
133MHGausEvents::MHGausEvents(const char *name, const char *title)
134 : fEventFrequency(0), fHPowerProbability(NULL),
135 fPowerSpectrum(NULL),
136 fGraphEvents(NULL), fGraphPowerSpectrum(NULL),
137 fFGausFit(NULL), fFExpFit(NULL),
138 fFirst(0.), fLast(100.),
139 fNbins(100), fPixId(-1)
140{
141
142 fName = name ? name : "MHGausEvents";
143 fTitle = title ? title : "Events with expected Gaussian distributions";
144
145 Clear();
146
147 SetBinsAfterStripping();
148 SetBlackoutLimit();
149 SetNDFLimit();
150 SetPickupLimit();
151 SetPowerProbabilityBins();
152 SetProbLimit();
153
154 fHGausHist.SetName("HGausHist");
155 fHGausHist.SetTitle("Histogram of Events with Gaussian Distribution");
156 // important, other ROOT will not draw the axes:
157 fHGausHist.UseCurrentStyle();
158 fHGausHist.SetDirectory(NULL);
159}
160
161
162
163// --------------------------------------------------------------------------
164//
165// Default Destructor.
166//
167// Deletes (if Pointer is not NULL):
168//
169// - fHPowerProbability
170// - fFGausFit
171// - fFExpFit
172// - fPowerSpectrum
173// - fGraphEvents
174// - fGraphPowerSpectrum
175//
176MHGausEvents::~MHGausEvents()
177{
178
179 // delete histograms
180 if (fHPowerProbability)
181 delete fHPowerProbability;
182
183 // delete fits
184 if (fFGausFit)
185 delete fFGausFit;
186 if (fFExpFit)
187 delete fFExpFit;
188
189 // delete arrays
190 if (fPowerSpectrum)
191 delete fPowerSpectrum;
192
193 // delete graphs
194 if (fGraphEvents)
195 delete fGraphEvents;
196 if (fGraphPowerSpectrum)
197 delete fGraphPowerSpectrum;
198}
199
200// --------------------------------------------------------------------------
201//
202// Default Clear(), can be overloaded.
203//
204// Sets:
205// - all other pointers to NULL
206// - all variables to 0., except fPixId to -1 and keep fEventFrequency
207// - all flags to kFALSE
208//
209// Deletes (if not NULL):
210// - all pointers
211//
212void MHGausEvents::Clear(Option_t *o)
213{
214
215 SetGausFitOK ( kFALSE );
216 SetExpFitOK ( kFALSE );
217 SetFourierSpectrumOK( kFALSE );
218 SetExcluded ( kFALSE );
219
220 fMean = 0.;
221 fSigma = 0.;
222 fMeanErr = 0.;
223 fSigmaErr = 0.;
224 fProb = 0.;
225
226 fCurrentSize = 0;
227 fPixId = -1;
228
229 if (fHPowerProbability)
230 {
231 delete fHPowerProbability;
232 fHPowerProbability = NULL;
233 }
234
235 // delete fits
236 if (fFGausFit)
237 {
238 delete fFGausFit;
239 fFGausFit = NULL;
240 }
241
242 if (fFExpFit)
243 {
244 delete fFExpFit;
245 fFExpFit = NULL;
246 }
247
248 // delete arrays
249 if (fPowerSpectrum)
250 {
251 delete fPowerSpectrum;
252 fPowerSpectrum = NULL;
253 }
254
255 // delete graphs
256 if (fGraphEvents)
257 {
258 delete fGraphEvents;
259 fGraphEvents = NULL;
260 }
261
262 if (fGraphPowerSpectrum)
263 {
264 delete fGraphPowerSpectrum;
265 fGraphPowerSpectrum = NULL;
266 }
267}
268
269
270// -----------------------------------------------------------------------------
271//
272// Bypasses the Gauss fit by taking mean and RMS from the histogram
273//
274// Errors are determined in the following way:
275// MeanErr = RMS / Sqrt(entries)
276// SigmaErr = RMS / (2.*Sqrt(entries) )
277//
278void MHGausEvents::BypassFit()
279{
280
281 const Stat_t entries = fHGausHist.GetEntries();
282
283 if (entries <= 0.)
284 {
285 *fLog << warn << GetDescriptor()
286 << ": Cannot bypass fit. Number of entries smaller or equal 0 in pixel: " << fPixId << endl;
287 return;
288 }
289
290 fMean = fHGausHist.GetMean();
291 fMeanErr = fHGausHist.GetRMS() / TMath::Sqrt(entries);
292 fSigma = fHGausHist.GetRMS() ;
293 fSigmaErr = fHGausHist.GetRMS() / TMath::Sqrt(entries) / 2.;
294}
295
296
297
298// --------------------------------------------------------------------------
299//
300// - Set fPixId to id
301//
302// Add id to names and titles of:
303// - fHGausHist
304//
305void MHGausEvents::ChangeHistId(const Int_t id)
306{
307
308 fPixId = id;
309
310 fHGausHist.SetName( Form("%s%d", fHGausHist.GetName(), id));
311 fHGausHist.SetTitle( Form("%s%d", fHGausHist.GetTitle(), id));
312
313 fName = Form("%s%d", fName.Data(), id);
314 fTitle = Form("%s%d", fTitle.Data(), id);
315
316}
317
318// -----------------------------------------------------------------------------
319//
320// Create the x-axis for the event graph
321//
322Float_t *MHGausEvents::CreateEventXaxis(Int_t n)
323{
324
325 Float_t *xaxis = new Float_t[n];
326
327 if (fEventFrequency)
328 for (Int_t i=0;i<n;i++)
329 xaxis[i] = (Float_t)i/fEventFrequency;
330 else
331 for (Int_t i=0;i<n;i++)
332 xaxis[i] = (Float_t)i;
333
334 return xaxis;
335
336}
337
338
339// -------------------------------------------------------------------
340//
341// Create the fourier spectrum using the class MFFT.
342// The result is projected into a histogram and fitted by an exponential
343//
344void MHGausEvents::CreateFourierSpectrum()
345{
346
347 if (fFExpFit)
348 return;
349
350 if (fEvents.GetSize() < 8)
351 {
352 *fLog << warn << "Cannot create Fourier spectrum in pixel: " << fPixId
353 << ". Number of events smaller than 8 " << endl;
354 return;
355 }
356
357
358 //
359 // The number of entries HAS to be a potence of 2,
360 // so we can only cut out from the last potence of 2 to the rest.
361 // Another possibility would be to fill everything with
362 // zeros, but that gives a low frequency peak, which we would
363 // have to cut out later again.
364 //
365 // So, we have to live with the possibility that at the end
366 // of the calibration run, something has happened without noticing
367 // it...
368 //
369
370 // This cuts only the non-used zero's, but MFFT will later cut the rest
371 MArray::StripZeros(fEvents);
372
373 if (fEvents.GetSize() < 8)
374 {
375 /*
376 *fLog << warn << "Cannot create Fourier spectrum. " << endl;
377 *fLog << warn << "Number of events (after stripping of zeros) is smaller than 8 "
378 << "in pixel: " << fPixId << endl;
379 */
380 return;
381 }
382
383 MFFT fourier;
384
385 fPowerSpectrum = fourier.PowerSpectrumDensity(&fEvents);
386 fHPowerProbability = ProjectArray(*fPowerSpectrum, fPowerProbabilityBins,
387 "PowerProbability",
388 "Probability of Power occurrance");
389 fHPowerProbability->SetXTitle("P(f)");
390 fHPowerProbability->SetDirectory(NULL);
391 //
392 // First guesses for the fit (should be as close to reality as possible,
393 //
394 const Double_t xmax = fHPowerProbability->GetXaxis()->GetXmax();
395
396 fFExpFit = new TF1("FExpFit","exp([0]-[1]*x)",0.,xmax);
397
398 const Double_t slope_guess = (TMath::Log(fHPowerProbability->GetEntries())+1.)/xmax;
399 const Double_t offset_guess = slope_guess*xmax;
400
401 fFExpFit->SetParameters(offset_guess, slope_guess);
402 fFExpFit->SetParNames("Offset","Slope");
403 fFExpFit->SetParLimits(0,offset_guess/2.,2.*offset_guess);
404 fFExpFit->SetParLimits(1,slope_guess/1.5,1.5*slope_guess);
405 fFExpFit->SetRange(0.,xmax);
406
407 fHPowerProbability->Fit(fFExpFit,"RQL0");
408
409 if (GetExpProb() > fProbLimit)
410 SetExpFitOK(kTRUE);
411
412 //
413 // For the moment, this is the only check, later we can add more...
414 //
415 SetFourierSpectrumOK(IsExpFitOK());
416
417 return;
418}
419
420// ----------------------------------------------------------------------------------
421//
422// Create a graph to display the array fEvents
423// If the variable fEventFrequency is set, the x-axis is transformed into real time.
424//
425void MHGausEvents::CreateGraphEvents()
426{
427
428 MArray::StripZeros(fEvents);
429
430 const Int_t n = fEvents.GetSize();
431
432 fGraphEvents = new TGraph(n,CreateEventXaxis(n),fEvents.GetArray());
433 fGraphEvents->SetTitle("Evolution of Events with time");
434 fGraphEvents->GetXaxis()->SetTitle((fEventFrequency) ? "Time [s]" : "Event Nr.");
435}
436
437// ----------------------------------------------------------------------------------
438//
439// Create a graph to display the array fPowerSpectrum
440// If the variable fEventFrequency is set, the x-axis is transformed into real frequency.
441//
442void MHGausEvents::CreateGraphPowerSpectrum()
443{
444
445 MArray::StripZeros(*fPowerSpectrum);
446
447 const Int_t n = fPowerSpectrum->GetSize();
448
449 fGraphPowerSpectrum = new TGraph(n,CreatePSDXaxis(n),fPowerSpectrum->GetArray());
450 fGraphPowerSpectrum->SetTitle("Power Spectrum Density");
451 fGraphPowerSpectrum->GetXaxis()->SetTitle((fEventFrequency) ? "Frequency [Hz]" : "Frequency");
452 fGraphPowerSpectrum->GetYaxis()->SetTitle("P(f)");
453}
454
455
456// -----------------------------------------------------------------------------
457//
458// Create the x-axis for the event graph
459//
460Float_t *MHGausEvents::CreatePSDXaxis(Int_t n)
461{
462
463 Float_t *xaxis = new Float_t[n];
464
465 if (fEventFrequency)
466 for (Int_t i=0;i<n;i++)
467 xaxis[i] = 0.5*(Float_t)i*fEventFrequency/n;
468 else
469 for (Int_t i=0;i<n;i++)
470 xaxis[i] = 0.5*(Float_t)i/n;
471
472 return xaxis;
473
474}
475
476// -----------------------------------------------------------------------------
477//
478// Default draw:
479//
480// The following options can be chosen:
481//
482// "EVENTS": displays a TGraph of the array fEvents
483// "FOURIER": display a TGraph of the fourier transform of fEvents
484// displays the projection of the fourier transform with the fit
485//
486// The following picture shows a typical outcome of call to Draw("fourierevents"):
487// - The first plot shows the distribution of the values with the Gauss fit
488// (which did not succeed, in this case, for obvious reasons)
489// - The second plot shows the TGraph with the events vs. time
490// - The third plot shows the fourier transform and a small peak at about 85 Hz.
491// - The fourth plot shows the projection of the fourier components and an exponential
492// fit, with the result that the observed deviation is still statistical with a
493// probability of 0.5%.
494//
495//Begin_Html
496/*
497<img src="images/MHGausEventsDraw.gif">
498*/
499//End_Html
500//
501void MHGausEvents::Draw(const Option_t *opt)
502{
503
504 TVirtualPad *pad = gPad ? gPad : MH::MakeDefCanvas(this,600, 900);
505
506 TString option(opt);
507 option.ToLower();
508
509 Int_t win = 1;
510
511 if (option.Contains("events"))
512 {
513 option.ReplaceAll("events","");
514 win += 1;
515 }
516 if (option.Contains("fourier"))
517 {
518 option.ReplaceAll("fourier","");
519 win += 2;
520 }
521
522 pad->SetTicks();
523 pad->SetBorderMode(0);
524 pad->Divide(1,win);
525 pad->cd(1);
526
527 if (!IsEmpty())
528 gPad->SetLogy();
529
530 fHGausHist.Draw(opt);
531
532 if (fFGausFit)
533 {
534 fFGausFit->SetLineColor(IsGausFitOK() ? kGreen : kRed);
535 fFGausFit->Draw("same");
536 }
537 switch (win)
538 {
539 case 2:
540 pad->cd(2);
541 DrawEvents();
542 break;
543 case 3:
544 pad->cd(2);
545 DrawPowerSpectrum(*pad,3);
546 break;
547 case 4:
548 pad->cd(2);
549 DrawEvents();
550 pad->cd(3);
551 DrawPowerSpectrum(*pad,4);
552 break;
553 }
554}
555
556void MHGausEvents::DrawEvents()
557{
558
559 if (!fGraphEvents)
560 CreateGraphEvents();
561
562 fGraphEvents->SetBit(kCanDelete);
563 fGraphEvents->SetTitle("Events with time");
564 fGraphEvents->Draw("AL");
565
566}
567
568
569void MHGausEvents::DrawPowerSpectrum(TVirtualPad &pad, Int_t i)
570{
571
572 if (fPowerSpectrum)
573 {
574 if (!fGraphPowerSpectrum)
575 CreateGraphPowerSpectrum();
576
577 fGraphPowerSpectrum->Draw("AL");
578 fGraphPowerSpectrum->SetBit(kCanDelete);
579 }
580
581 pad.cd(i);
582
583 if (fHPowerProbability && fHPowerProbability->GetEntries() > 0)
584 {
585 gPad->SetLogy();
586 fHPowerProbability->Draw();
587 if (fFExpFit)
588 {
589 fFExpFit->SetLineColor(IsExpFitOK() ? kGreen : kRed);
590 fFExpFit->Draw("same");
591 }
592 }
593}
594
595
596// --------------------------------------------------------------------------
597//
598// Fill fEvents with f
599// If size of fEvents is 0, initializes it to 512
600// If size of fEvents is smaller than fCurrentSize, double the size
601// Increase fCurrentSize by 1
602//
603void MHGausEvents::FillArray(const Float_t f)
604{
605 if (fEvents.GetSize() == 0)
606 fEvents.Set(512);
607
608 if (fCurrentSize >= fEvents.GetSize())
609 fEvents.Set(fEvents.GetSize()*2);
610
611 fEvents.AddAt(f,fCurrentSize++);
612}
613
614
615// --------------------------------------------------------------------------
616//
617// Fills fHGausHist with f
618// Returns kFALSE, if overflow or underflow occurred, else kTRUE
619//
620Bool_t MHGausEvents::FillHist(const Float_t f)
621{
622 return fHGausHist.Fill(f) > -1;
623}
624
625// --------------------------------------------------------------------------
626//
627// Executes:
628// - FillArray()
629// - FillHist()
630//
631Bool_t MHGausEvents::FillHistAndArray(const Float_t f)
632{
633
634 FillArray(f);
635 return FillHist(f);
636}
637
638// -------------------------------------------------------------------
639//
640// Fit fGausHist with a Gaussian after stripping zeros from both ends
641// and rebinned to the number of bins specified in fBinsAfterStripping
642//
643// The fit results are retrieved and stored in class-own variables.
644//
645// A flag IsGausFitOK() is set according to whether the fit probability
646// is smaller or bigger than fProbLimit, whether the NDF is bigger than
647// fNDFLimit and whether results are NaNs.
648//
649Bool_t MHGausEvents::FitGaus(Option_t *option, const Double_t xmin, const Double_t xmax)
650{
651
652 if (IsGausFitOK())
653 return kTRUE;
654
655 //
656 // First, strip the zeros from the edges which contain only zeros and rebin
657 // to about fBinsAfterStripping bins.
658 //
659 // (ATTENTION: The Chisquare method is more sensitive,
660 // the _less_ bins, you have!)
661 //
662 StripZeros(&fHGausHist,fBinsAfterStripping);
663
664 TAxis *axe = fHGausHist.GetXaxis();
665 //
666 // Get the fitting ranges
667 //
668 Axis_t rmin = ((xmin==0.) && (xmax==0.)) ? fHGausHist.GetBinCenter(axe->GetFirst()) : xmin;
669 Axis_t rmax = ((xmin==0.) && (xmax==0.)) ? fHGausHist.GetBinCenter(axe->GetLast()) : xmax;
670
671 //
672 // First guesses for the fit (should be as close to reality as possible,
673 //
674 const Stat_t entries = fHGausHist.Integral(axe->FindBin(rmin),axe->FindBin(rmax),"width");
675 const Double_t mu_guess = fHGausHist.GetBinCenter(fHGausHist.GetMaximumBin());
676 const Double_t sigma_guess = fHGausHist.GetRMS();
677 const Double_t area_guess = entries/TMath::Sqrt(TMath::TwoPi())/sigma_guess;
678
679 fFGausFit = new TF1("GausFit","gaus",rmin,rmax);
680
681 if (!fFGausFit)
682 {
683 *fLog << warn << dbginf << "WARNING: Could not create fit function for Gauss fit "
684 << "in pixel: " << fPixId << endl;
685 return kFALSE;
686 }
687
688 fFGausFit->SetParameters(area_guess,mu_guess,sigma_guess);
689 fFGausFit->SetParNames("Area","#mu","#sigma");
690 fFGausFit->SetParLimits(0,0.,area_guess*25.);
691 fFGausFit->SetParLimits(1,rmin,rmax);
692 fFGausFit->SetParLimits(2,0.,rmax-rmin);
693 fFGausFit->SetRange(rmin,rmax);
694
695 fHGausHist.Fit(fFGausFit,option);
696
697
698 fMean = fFGausFit->GetParameter(1);
699 fSigma = fFGausFit->GetParameter(2);
700 fMeanErr = fFGausFit->GetParError(1);
701 fSigmaErr = fFGausFit->GetParError(2);
702 fProb = fFGausFit->GetProb();
703 //
704 // The fit result is accepted under condition:
705 // 1) The results are not nan's
706 // 2) The NDF is not smaller than fNDFLimit (default: fgNDFLimit)
707 // 3) The Probability is greater than fProbLimit (default: fgProbLimit)
708 //
709 if ( TMath::IsNaN(fMean)
710 || TMath::IsNaN(fMeanErr)
711 || TMath::IsNaN(fProb)
712 || TMath::IsNaN(fSigma)
713 || TMath::IsNaN(fSigmaErr)
714 || fFGausFit->GetNDF() < fNDFLimit
715 || fProb < fProbLimit )
716 return kFALSE;
717
718 SetGausFitOK(kTRUE);
719 return kTRUE;
720}
721
722// -------------------------------------------------------------------------------
723//
724// Return the number of "blackout" events, which are events with values higher
725// than fBlackoutLimit sigmas from the mean
726//
727//
728const Double_t MHGausEvents::GetBlackout() const
729{
730
731 if ((fMean == 0.) && (fSigma == 0.))
732 return -1.;
733
734 const Int_t first = fHGausHist.GetXaxis()->GetFirst();
735 const Int_t last = fHGausHist.GetXaxis()->FindBin(fMean-fBlackoutLimit*fSigma);
736
737 if (first >= last)
738 return 0.;
739
740 return fHGausHist.Integral(first, last, "width");
741}
742
743const Double_t MHGausEvents::GetChiSquare() const
744{
745 return ( fFGausFit ? fFGausFit->GetChisquare() : 0.);
746}
747
748
749const Double_t MHGausEvents::GetExpChiSquare() const
750{
751 return ( fFExpFit ? fFExpFit->GetChisquare() : 0.);
752}
753
754
755const Int_t MHGausEvents::GetExpNdf() const
756{
757 return ( fFExpFit ? fFExpFit->GetNDF() : 0);
758}
759
760
761const Double_t MHGausEvents::GetExpProb() const
762{
763 return ( fFExpFit ? fFExpFit->GetProb() : 0.);
764}
765
766
767const Int_t MHGausEvents::GetNdf() const
768{
769 return ( fFGausFit ? fFGausFit->GetNDF() : 0);
770}
771
772const Double_t MHGausEvents::GetOffset() const
773{
774 return ( fFExpFit ? fFExpFit->GetParameter(0) : 0.);
775}
776
777
778// -------------------------------------------------------------------------------
779//
780// Return the number of "pickup" events, which are events with values higher
781// than fPickupLimit sigmas from the mean
782//
783//
784const Double_t MHGausEvents::GetPickup() const
785{
786
787 if ((fMean == 0.) && (fSigma == 0.))
788 return -1.;
789
790 const Int_t first = fHGausHist.GetXaxis()->FindBin(fMean+fPickupLimit*fSigma);
791 const Int_t last = fHGausHist.GetXaxis()->GetLast();
792
793 if (first >= last)
794 return 0.;
795
796 return fHGausHist.Integral(first, last, "width");
797}
798
799
800const Double_t MHGausEvents::GetSlope() const
801{
802 return ( fFExpFit ? fFExpFit->GetParameter(1) : 0.);
803}
804
805// --------------------------------------------------------------------------
806//
807// Default InitBins, can be overloaded.
808//
809// Executes:
810// - fHGausHist.SetBins(fNbins,fFirst,fLast)
811//
812void MHGausEvents::InitBins()
813{
814 fHGausHist.SetBins(fNbins,fFirst,fLast);
815}
816
817const Bool_t MHGausEvents::IsEmpty() const
818{
819 return !(fHGausHist.GetEntries());
820}
821
822
823const Bool_t MHGausEvents::IsExcluded() const
824{
825 return TESTBIT(fFlags,kExcluded);
826}
827
828
829const Bool_t MHGausEvents::IsExpFitOK() const
830{
831 return TESTBIT(fFlags,kExpFitOK);
832}
833
834const Bool_t MHGausEvents::IsFourierSpectrumOK() const
835{
836 return TESTBIT(fFlags,kFourierSpectrumOK);
837}
838
839
840const Bool_t MHGausEvents::IsGausFitOK() const
841{
842 return TESTBIT(fFlags,kGausFitOK);
843}
844
845
846// -----------------------------------------------------------------------------------
847//
848// A default print
849//
850void MHGausEvents::Print(const Option_t *o) const
851{
852
853 *fLog << all << endl;
854 *fLog << all << "Results of the Gauss Fit in pixel: " << fPixId << endl;
855 *fLog << all << "Mean: " << GetMean() << endl;
856 *fLog << all << "Sigma: " << GetSigma() << endl;
857 *fLog << all << "Chisquare: " << GetChiSquare() << endl;
858 *fLog << all << "DoF: " << GetNdf() << endl;
859 *fLog << all << "Probability: " << GetProb() << endl;
860 *fLog << all << endl;
861
862}
863
864// --------------------------------------------------------------------------
865//
866// Re-normalize the results, has to be overloaded
867//
868void MHGausEvents::Renorm()
869{
870}
871
872// -----------------------------------------------------------------------------
873//
874// If flag IsGausFitOK() is set (histogram already successfully fitted),
875// returns kTRUE
876//
877// If both fMean and fSigma are still zero, call FitGaus()
878//
879// Repeats the Gauss fit in a smaller range, defined by:
880//
881// min = GetMean() - fBlackoutLimit * GetSigma();
882// max = GetMean() + fPickupLimit * GetSigma();
883//
884// The fit results are retrieved and stored in class-own variables.
885//
886// A flag IsGausFitOK() is set according to whether the fit probability
887// is smaller or bigger than fProbLimit, whether the NDF is bigger than
888// fNDFLimit and whether results are NaNs.
889//
890Bool_t MHGausEvents::RepeatFit(const Option_t *option)
891{
892
893 if (IsGausFitOK())
894 return kTRUE;
895
896 if ((fMean == 0.) && (fSigma == 0.))
897 return FitGaus();
898
899 //
900 // Get new fitting ranges
901 //
902 Axis_t rmin = fMean - fBlackoutLimit * fSigma;
903 Axis_t rmax = fMean + fPickupLimit * fSigma;
904
905 Axis_t hmin = fHGausHist.GetBinCenter(fHGausHist.GetXaxis()->GetFirst());
906 Axis_t hmax = fHGausHist.GetBinCenter(fHGausHist.GetXaxis()->GetLast()) ;
907
908 fFGausFit->SetRange(hmin < rmin ? rmin : hmin , hmax > rmax ? rmax : hmax);
909
910 fHGausHist.Fit(fFGausFit,option);
911
912 fMean = fFGausFit->GetParameter(1);
913 fMeanErr = fFGausFit->GetParameter(2);
914 fSigma = fFGausFit->GetParError(1) ;
915 fSigmaErr = fFGausFit->GetParError(2) ;
916 fProb = fFGausFit->GetProb() ;
917
918 //
919 // The fit result is accepted under condition:
920 // 1) The results are not nan's
921 // 2) The NDF is not smaller than fNDFLimit (default: fgNDFLimit)
922 // 3) The Probability is greater than fProbLimit (default: fgProbLimit)
923 //
924 if ( TMath::IsNaN ( fMean )
925 || TMath::IsNaN ( fMeanErr )
926 || TMath::IsNaN ( fProb )
927 || TMath::IsNaN ( fSigma )
928 || TMath::IsNaN ( fSigmaErr )
929 || fFGausFit->GetNDF() < fNDFLimit
930 || fProb < fProbLimit )
931 return kFALSE;
932
933 SetGausFitOK(kTRUE);
934 return kTRUE;
935
936}
937
938// --------------------------------------------------------------------------
939//
940// Default Reset(), can be overloaded.
941//
942// Executes:
943// - Clear()
944// - fHGausHist.Reset()
945// - fEvents.Set(0)
946//
947void MHGausEvents::Reset()
948{
949
950 Clear();
951 fHGausHist.Reset();
952 fEvents.Set(0);
953
954}
955
956// --------------------------------------------------------------------------
957//
958// Set Excluded bit from outside
959//
960void MHGausEvents::SetExcluded(const Bool_t b)
961{
962 b ? SETBIT(fFlags,kExcluded) : CLRBIT(fFlags,kExcluded);
963}
964
965
966// -------------------------------------------------------------------
967//
968// The flag setters are to be used ONLY for Monte-Carlo!!
969//
970void MHGausEvents::SetExpFitOK(const Bool_t b)
971{
972
973 b ? SETBIT(fFlags,kExpFitOK) : CLRBIT(fFlags,kExpFitOK);
974}
975
976// -------------------------------------------------------------------
977//
978// The flag setters are to be used ONLY for Monte-Carlo!!
979//
980void MHGausEvents::SetFourierSpectrumOK(const Bool_t b)
981{
982
983 b ? SETBIT(fFlags,kFourierSpectrumOK) : CLRBIT(fFlags,kFourierSpectrumOK);
984}
985
986
987// -------------------------------------------------------------------
988//
989// The flag setters are to be used ONLY for Monte-Carlo!!
990//
991void MHGausEvents::SetGausFitOK(const Bool_t b)
992{
993 b ? SETBIT(fFlags,kGausFitOK) : CLRBIT(fFlags,kGausFitOK);
994
995}
Note: See TracBrowser for help on using the repository browser.