source: trunk/MagicSoft/Mars/mhcalib/MHGausEvents.cc@ 6385

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