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

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