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

Last change on this file since 6800 was 6800, 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), fFlags(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// -----------------------------------------------------------------------------
278//
279// Create the x-axis for the event graph
280//
281Float_t *MHGausEvents::CreateEventXaxis(Int_t n)
282{
283
284 Float_t *xaxis = new Float_t[n];
285
286 if (fEventFrequency)
287 for (Int_t i=0;i<n;i++)
288 xaxis[i] = (Float_t)i/fEventFrequency;
289 else
290 for (Int_t i=0;i<n;i++)
291 xaxis[i] = (Float_t)i;
292
293 return xaxis;
294
295}
296
297
298// -------------------------------------------------------------------
299//
300// Create the fourier spectrum using the class MFFT.
301// The result is projected into a histogram and fitted by an exponential
302//
303void MHGausEvents::CreateFourierSpectrum()
304{
305
306 if (fFExpFit)
307 return;
308
309 if (fEvents.GetSize() < 8)
310 {
311 *fLog << warn << "Cannot create Fourier spectrum in: " << fName
312 << ". Number of events smaller than 8 " << endl;
313 return;
314 }
315
316 //
317 // The number of entries HAS to be a potence of 2,
318 // so we can only cut out from the last potence of 2 to the rest.
319 // Another possibility would be to fill everything with
320 // zeros, but that gives a low frequency peak, which we would
321 // have to cut out later again.
322 //
323 // So, we have to live with the possibility that at the end
324 // of the calibration run, something has happened without noticing
325 // it...
326 //
327
328 // This cuts only the non-used zero's, but MFFT will later cut the rest
329 fEvents.StripZeros();
330
331 if (fEvents.GetSize() < 8)
332 {
333 /*
334 *fLog << warn << "Cannot create Fourier spectrum. " << endl;
335 *fLog << warn << "Number of events (after stripping of zeros) is smaller than 8 "
336 << "in pixel: " << fPixId << endl;
337 */
338 return;
339 }
340
341 MFFT fourier;
342
343 fPowerSpectrum = fourier.PowerSpectrumDensity(&fEvents);
344 fHPowerProbability = ProjectArray(*fPowerSpectrum, fPowerProbabilityBins,
345 Form("%s%s","PowerProb",GetName()),
346 "Probability of Power occurrance");
347 fHPowerProbability->SetXTitle("P(f)");
348 fHPowerProbability->SetYTitle("Counts");
349 fHPowerProbability->GetYaxis()->CenterTitle();
350 fHPowerProbability->SetDirectory(NULL);
351 fHPowerProbability->SetBit(kCanDelete);
352 //
353 // First guesses for the fit (should be as close to reality as possible,
354 //
355 const Double_t xmax = fHPowerProbability->GetXaxis()->GetXmax();
356
357 fFExpFit = new TF1("FExpFit","exp([0]-[1]*x)",0.,xmax);
358
359 const Double_t slope_guess = (TMath::Log(fHPowerProbability->GetEntries())+1.)/xmax;
360 const Double_t offset_guess = slope_guess*xmax;
361
362 //
363 // For the fits, we have to take special care since ROOT
364 // has stored the function pointer in a global list which
365 // lead to removing the object twice. We have to take out
366 // the following functions of the global list of functions
367 // as well:
368 //
369 gROOT->GetListOfFunctions()->Remove(fFExpFit);
370 fFExpFit->SetParameters(offset_guess, slope_guess);
371 fFExpFit->SetParNames("Offset","Slope");
372 fFExpFit->SetParLimits(0,offset_guess/2.,2.*offset_guess);
373 fFExpFit->SetParLimits(1,slope_guess/1.5,1.5*slope_guess);
374 fFExpFit->SetRange(0.,xmax);
375
376 fHPowerProbability->Fit(fFExpFit,"RQL0");
377
378 if (GetExpProb() > fProbLimit)
379 SetExpFitOK(kTRUE);
380
381 //
382 // For the moment, this is the only check, later we can add more...
383 //
384 SetFourierSpectrumOK(IsExpFitOK());
385
386 return;
387}
388
389// ----------------------------------------------------------------------------------
390//
391// Create a graph to display the array fEvents
392// If the variable fEventFrequency is set, the x-axis is transformed into real time.
393//
394void MHGausEvents::CreateGraphEvents()
395{
396
397 fEvents.StripZeros();
398
399 const Int_t n = fEvents.GetSize();
400
401 if (n==0)
402 return;
403
404 fGraphEvents = new TGraph(n,CreateEventXaxis(n),fEvents.GetArray());
405 fGraphEvents->SetTitle("Evolution of Events with time");
406 fGraphEvents->GetXaxis()->SetTitle((fEventFrequency) ? "Time [s]" : "Event Nr.");
407 fGraphEvents->GetYaxis()->SetTitle(fHGausHist.GetXaxis()->GetTitle());
408 fGraphEvents->GetYaxis()->CenterTitle();
409}
410
411// ----------------------------------------------------------------------------------
412//
413// Create a graph to display the array fPowerSpectrum
414// If the variable fEventFrequency is set, the x-axis is transformed into real frequency.
415//
416void MHGausEvents::CreateGraphPowerSpectrum()
417{
418
419 fPowerSpectrum->StripZeros();
420
421 const Int_t n = fPowerSpectrum->GetSize();
422
423 fGraphPowerSpectrum = new TGraph(n,CreatePSDXaxis(n),fPowerSpectrum->GetArray());
424 fGraphPowerSpectrum->SetTitle("Power Spectrum Density");
425 fGraphPowerSpectrum->GetXaxis()->SetTitle((fEventFrequency) ? "Frequency [Hz]" : "Frequency");
426 fGraphPowerSpectrum->GetYaxis()->SetTitle("P(f)");
427 fGraphPowerSpectrum->GetYaxis()->CenterTitle();
428
429}
430
431
432// -----------------------------------------------------------------------------
433//
434// Create the x-axis for the event graph
435//
436Float_t *MHGausEvents::CreatePSDXaxis(Int_t n)
437{
438
439 Float_t *xaxis = new Float_t[n];
440
441 if (fEventFrequency)
442 for (Int_t i=0;i<n;i++)
443 xaxis[i] = 0.5*(Float_t)i*fEventFrequency/n;
444 else
445 for (Int_t i=0;i<n;i++)
446 xaxis[i] = 0.5*(Float_t)i/n;
447
448 return xaxis;
449
450}
451
452// -----------------------------------------------------------------------------
453//
454// Default draw:
455//
456// The following options can be chosen:
457//
458// "EVENTS": displays a TGraph of the array fEvents
459// "FOURIER": display a TGraph of the fourier transform of fEvents
460// displays the projection of the fourier transform with the fit
461//
462// The following picture shows a typical outcome of call to Draw("fourierevents"):
463// - The first plot shows the distribution of the values with the Gauss fit
464// (which did not succeed, in this case, for obvious reasons)
465// - The second plot shows the TGraph with the events vs. time
466// - The third plot shows the fourier transform and a small peak at about 85 Hz.
467// - The fourth plot shows the projection of the fourier components and an exponential
468// fit, with the result that the observed deviation is still statistical with a
469// probability of 0.5%.
470//
471//Begin_Html
472/*
473<img src="images/MHGausEventsDraw.gif">
474*/
475//End_Html
476//
477void MHGausEvents::Draw(const Option_t *opt)
478{
479
480 TVirtualPad *pad = gPad ? gPad : MH::MakeDefCanvas(this,600, 600);
481
482 TString option(opt);
483 option.ToLower();
484
485 Int_t win = 1;
486 Int_t nofit = 0;
487
488 if (option.Contains("events"))
489 {
490 option.ReplaceAll("events","");
491 win += 1;
492 }
493 if (option.Contains("fourier"))
494 {
495 option.ReplaceAll("fourier","");
496 win += 2;
497 }
498
499 if (IsEmpty())
500 win--;
501
502 if (option.Contains("nofit"))
503 {
504 option.ReplaceAll("nofit","");
505 nofit++;
506 }
507
508 pad->SetBorderMode(0);
509 if (win > 1)
510 pad->Divide(1,win);
511
512 Int_t cwin = 1;
513
514 gPad->SetTicks();
515
516 if (!IsEmpty())
517 {
518 pad->cd(cwin++);
519
520 if (!IsOnlyOverflow() && !IsOnlyUnderflow())
521 gPad->SetLogy();
522
523 fHGausHist.Draw(option);
524
525 if (!nofit)
526 if (fFGausFit)
527 {
528 fFGausFit->SetLineColor(IsGausFitOK() ? kGreen : kRed);
529 fFGausFit->Draw("same");
530 }
531 }
532
533 if (option.Contains("events"))
534 {
535 pad->cd(cwin++);
536 DrawEvents();
537 }
538 if (option.Contains("fourier"))
539 {
540 pad->cd(cwin++);
541 DrawPowerSpectrum();
542 pad->cd(cwin);
543 DrawPowerProjection();
544 }
545}
546
547// -----------------------------------------------------------------------------
548//
549// DrawEvents:
550//
551// Will draw the graph with the option "A", unless the option:
552// "SAME" has been chosen
553//
554void MHGausEvents::DrawEvents(Option_t *opt)
555{
556
557 if (!fGraphEvents)
558 CreateGraphEvents();
559
560 if (!fGraphEvents)
561 return;
562
563 fGraphEvents->SetBit(kCanDelete);
564 fGraphEvents->SetTitle("Events with time");
565
566 TString option(opt);
567 option.ToLower();
568
569 if (option.Contains("same"))
570 {
571 option.ReplaceAll("same","");
572 fGraphEvents->Draw(option+"L");
573 }
574 else
575 fGraphEvents->Draw(option+"AL");
576}
577
578
579// -----------------------------------------------------------------------------
580//
581// DrawPowerSpectrum
582//
583// Will draw the fourier spectrum of the events sequence with the option "A", unless the option:
584// "SAME" has been chosen
585//
586void MHGausEvents::DrawPowerSpectrum(Option_t *option)
587{
588
589 TString opt(option);
590
591 if (!fPowerSpectrum)
592 CreateFourierSpectrum();
593
594 if (fPowerSpectrum)
595 {
596 if (!fGraphPowerSpectrum)
597 CreateGraphPowerSpectrum();
598
599 if (!fGraphPowerSpectrum)
600 return;
601
602 if (opt.Contains("same"))
603 {
604 opt.ReplaceAll("same","");
605 fGraphPowerSpectrum->Draw(opt+"L");
606 }
607 else
608 {
609 fGraphPowerSpectrum->Draw(opt+"AL");
610 fGraphPowerSpectrum->SetBit(kCanDelete);
611 }
612 }
613}
614
615// -----------------------------------------------------------------------------
616//
617// DrawPowerProjection
618//
619// Will draw the projection of the fourier spectrum onto the power probability axis
620// with the possible options of TH1D
621//
622void MHGausEvents::DrawPowerProjection(Option_t *option)
623{
624
625 TString opt(option);
626
627 if (!fHPowerProbability)
628 CreateFourierSpectrum();
629
630 if (fHPowerProbability && fHPowerProbability->GetEntries() > 0)
631 {
632 gPad->SetLogy();
633 fHPowerProbability->Draw(opt.Data());
634 if (fFExpFit)
635 {
636 fFExpFit->SetLineColor(IsExpFitOK() ? kGreen : kRed);
637 fFExpFit->Draw("same");
638 }
639 }
640}
641
642
643// --------------------------------------------------------------------------
644//
645// Fill fEvents with f
646// If size of fEvents is 0, initializes it to 512
647// If size of fEvents is smaller than fCurrentSize, double the size
648// Increase fCurrentSize by 1
649//
650void MHGausEvents::FillArray(const Float_t f)
651{
652
653 if (fEvents.GetSize() == 0)
654 fEvents.Set(512);
655
656 if (fCurrentSize >= fEvents.GetSize())
657 fEvents.Set(fEvents.GetSize()*2);
658
659 fEvents.AddAt(f,fCurrentSize++);
660}
661
662
663// --------------------------------------------------------------------------
664//
665// Fills fHGausHist with f
666// Returns kFALSE, if overflow or underflow occurred, else kTRUE
667//
668Bool_t MHGausEvents::FillHist(const Float_t f)
669{
670 return fHGausHist.Fill(f) > -1;
671}
672
673// --------------------------------------------------------------------------
674//
675// Executes:
676// - FillArray()
677// - FillHist()
678//
679Bool_t MHGausEvents::FillHistAndArray(const Float_t f)
680{
681
682 FillArray(f);
683 return FillHist(f);
684}
685
686// -------------------------------------------------------------------
687//
688// Fit fGausHist with a Gaussian after stripping zeros from both ends
689// and rebinned to the number of bins specified in fBinsAfterStripping
690//
691// The fit results are retrieved and stored in class-own variables.
692//
693// A flag IsGausFitOK() is set according to whether the fit probability
694// is smaller or bigger than fProbLimit, whether the NDF is bigger than
695// fNDFLimit and whether results are NaNs.
696//
697Bool_t MHGausEvents::FitGaus(Option_t *option, const Double_t xmin, const Double_t xmax)
698{
699
700 if (IsGausFitOK())
701 return kTRUE;
702
703 //
704 // First, strip the zeros from the edges which contain only zeros and rebin
705 // to fBinsAfterStripping bins. If fBinsAfterStripping is 0, reduce bins only by
706 // a factor 10.
707 //
708 // (ATTENTION: The Chisquare method is more sensitive,
709 // the _less_ bins, you have!)
710 //
711 StripZeros(&fHGausHist,
712 fBinsAfterStripping ? fBinsAfterStripping
713 : (fNbins > 1000 ? fNbins/10 : 0));
714
715 TAxis *axe = fHGausHist.GetXaxis();
716 //
717 // Get the fitting ranges
718 //
719 Axis_t rmin = ((xmin==0.) && (xmax==0.)) ? fHGausHist.GetBinCenter(axe->GetFirst()) : xmin;
720 Axis_t rmax = ((xmin==0.) && (xmax==0.)) ? fHGausHist.GetBinCenter(axe->GetLast()) : xmax;
721
722 //
723 // First guesses for the fit (should be as close to reality as possible,
724 //
725 const Stat_t entries = fHGausHist.Integral(axe->FindBin(rmin),axe->FindBin(rmax),"width");
726 const Double_t mu_guess = fHGausHist.GetBinCenter(fHGausHist.GetMaximumBin());
727 const Double_t sigma_guess = fHGausHist.GetRMS();
728 const Double_t area_guess = entries/TMath::Sqrt(TMath::TwoPi())/sigma_guess;
729
730 fFGausFit = new TF1("GausFit","gaus",rmin,rmax);
731
732 if (!fFGausFit)
733 {
734 *fLog << warn << dbginf << "WARNING: Could not create fit function for Gauss fit "
735 << "in: " << fName << endl;
736 return kFALSE;
737 }
738
739 //
740 // For the fits, we have to take special care since ROOT
741 // has stored the function pointer in a global list which
742 // lead to removing the object twice. We have to take out
743 // the following functions of the global list of functions
744 // as well:
745 //
746 gROOT->GetListOfFunctions()->Remove(fFGausFit);
747
748 fFGausFit->SetParameters(area_guess,mu_guess,sigma_guess);
749 fFGausFit->SetParNames("Area","#mu","#sigma");
750 fFGausFit->SetParLimits(0,0.,area_guess*25.);
751 fFGausFit->SetParLimits(1,rmin,rmax);
752 fFGausFit->SetParLimits(2,0.,rmax-rmin);
753 fFGausFit->SetRange(rmin,rmax);
754
755 fHGausHist.Fit(fFGausFit,option);
756
757 fMean = fFGausFit->GetParameter(1);
758 fSigma = fFGausFit->GetParameter(2);
759 fMeanErr = fFGausFit->GetParError(1);
760 fSigmaErr = fFGausFit->GetParError(2);
761 fProb = fFGausFit->GetProb();
762 //
763 // The fit result is accepted under condition:
764 // 1) The results are not nan's
765 // 2) The NDF is not smaller than fNDFLimit (default: fgNDFLimit)
766 // 3) The Probability is greater than fProbLimit (default: fgProbLimit)
767 //
768 if ( TMath::IsNaN(fMean)
769 || TMath::IsNaN(fMeanErr)
770 || TMath::IsNaN(fProb)
771 || TMath::IsNaN(fSigma)
772 || TMath::IsNaN(fSigmaErr)
773 || fFGausFit->GetNDF() < fNDFLimit
774 || fProb < fProbLimit )
775 return kFALSE;
776
777 SetGausFitOK(kTRUE);
778 return kTRUE;
779}
780
781
782const Double_t MHGausEvents::GetChiSquare() const
783{
784 return ( fFGausFit ? fFGausFit->GetChisquare() : 0.);
785}
786
787
788const Double_t MHGausEvents::GetExpChiSquare() const
789{
790 return ( fFExpFit ? fFExpFit->GetChisquare() : 0.);
791}
792
793
794const Int_t MHGausEvents::GetExpNdf() const
795{
796 return ( fFExpFit ? fFExpFit->GetNDF() : 0);
797}
798
799
800const Double_t MHGausEvents::GetExpProb() const
801{
802 return ( fFExpFit ? fFExpFit->GetProb() : 0.);
803}
804
805
806const Int_t MHGausEvents::GetNdf() const
807{
808 return ( fFGausFit ? fFGausFit->GetNDF() : 0);
809}
810
811const Double_t MHGausEvents::GetOffset() const
812{
813 return ( fFExpFit ? fFExpFit->GetParameter(0) : 0.);
814}
815
816
817
818// --------------------------------------------------------------------------
819//
820// If fFExpFit exists, returns fit parameter 1 (Slope of Exponential fit),
821// otherwise 0.
822//
823const Double_t MHGausEvents::GetSlope() const
824{
825 return ( fFExpFit ? fFExpFit->GetParameter(1) : 0.);
826}
827
828// --------------------------------------------------------------------------
829//
830// Default InitBins, can be overloaded.
831//
832// Executes:
833// - fHGausHist.SetBins(fNbins,fFirst,fLast)
834//
835void MHGausEvents::InitBins()
836{
837 // const TAttAxis att(fHGausHist.GetXaxis());
838 fHGausHist.SetBins(fNbins,fFirst,fLast);
839 // att.Copy(fHGausHist.GetXaxis());
840}
841
842// --------------------------------------------------------------------------
843//
844// Return kFALSE if number of entries is 0
845//
846const Bool_t MHGausEvents::IsEmpty() const
847{
848 return !(fHGausHist.GetEntries());
849}
850
851// --------------------------------------------------------------------------
852//
853// Return kTRUE if number of entries is bin content of fNbins+1
854//
855const Bool_t MHGausEvents::IsOnlyOverflow() const
856{
857 return fHGausHist.GetEntries() == fHGausHist.GetBinContent(fNbins+1);
858}
859
860// --------------------------------------------------------------------------
861//
862// Return kTRUE if number of entries is bin content of 0
863//
864const Bool_t MHGausEvents::IsOnlyUnderflow() const
865{
866 return fHGausHist.GetEntries() == fHGausHist.GetBinContent(0);
867}
868
869
870const Bool_t MHGausEvents::IsExcluded() const
871{
872 return TESTBIT(fFlags,kExcluded);
873}
874
875
876const Bool_t MHGausEvents::IsExpFitOK() const
877{
878 return TESTBIT(fFlags,kExpFitOK);
879}
880
881const Bool_t MHGausEvents::IsFourierSpectrumOK() const
882{
883 return TESTBIT(fFlags,kFourierSpectrumOK);
884}
885
886
887const Bool_t MHGausEvents::IsGausFitOK() const
888{
889 return TESTBIT(fFlags,kGausFitOK);
890}
891
892
893// -----------------------------------------------------------------------------------
894//
895// A default print
896//
897void MHGausEvents::Print(const Option_t *o) const
898{
899
900 *fLog << all << endl;
901 *fLog << all << "Results of the Gauss Fit in: " << fName << endl;
902 *fLog << all << "Mean: " << GetMean() << endl;
903 *fLog << all << "Sigma: " << GetSigma() << endl;
904 *fLog << all << "Chisquare: " << GetChiSquare() << endl;
905 *fLog << all << "DoF: " << GetNdf() << endl;
906 *fLog << all << "Probability: " << GetProb() << endl;
907 *fLog << all << endl;
908
909}
910
911
912// --------------------------------------------------------------------------
913//
914// Default Reset(), can be overloaded.
915//
916// Executes:
917// - Clear()
918// - fHGausHist.Reset()
919// - fEvents.Set(0)
920// - InitBins()
921//
922void MHGausEvents::Reset()
923{
924
925 Clear();
926 fHGausHist.Reset();
927 fEvents.Set(0);
928 InitBins();
929}
930
931// --------------------------------------------------------------------------
932//
933// Set Excluded bit from outside
934//
935void MHGausEvents::SetExcluded(const Bool_t b)
936{
937 b ? SETBIT(fFlags,kExcluded) : CLRBIT(fFlags,kExcluded);
938}
939
940
941// -------------------------------------------------------------------
942//
943// The flag setters are to be used ONLY for Monte-Carlo!!
944//
945void MHGausEvents::SetExpFitOK(const Bool_t b)
946{
947
948 b ? SETBIT(fFlags,kExpFitOK) : CLRBIT(fFlags,kExpFitOK);
949}
950
951// -------------------------------------------------------------------
952//
953// The flag setters are to be used ONLY for Monte-Carlo!!
954//
955void MHGausEvents::SetFourierSpectrumOK(const Bool_t b)
956{
957
958 b ? SETBIT(fFlags,kFourierSpectrumOK) : CLRBIT(fFlags,kFourierSpectrumOK);
959}
960
961
962// -------------------------------------------------------------------
963//
964// The flag setters are to be used ONLY for Monte-Carlo!!
965//
966void MHGausEvents::SetGausFitOK(const Bool_t b)
967{
968 b ? SETBIT(fFlags,kGausFitOK) : CLRBIT(fFlags,kGausFitOK);
969
970}
971
972// ----------------------------------------------------------------------------
973//
974// Simulates Gaussian events and fills them into the histogram and the array
975// In order to do a fourier analysis, call CreateFourierSpectrum()
976//
977void MHGausEvents::SimulateGausEvents(const Float_t mean, const Float_t sigma, const Int_t nevts)
978{
979
980 if (!IsEmpty())
981 *fLog << warn << "The histogram is already filled, will superimpose simulated events on it..." << endl;
982
983 for (Int_t i=0;i<nevts;i++) {
984 const Double_t ran = gRandom->Gaus(mean,sigma);
985 FillHistAndArray(ran);
986 }
987
988}
Note: See TracBrowser for help on using the repository browser.