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

Last change on this file since 3627 was 3625, checked in by gaug, 21 years ago
*** empty log message ***
File size: 20.7 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. with the function TH1F::SetBins(..) )
43// - The histogram is filled with the functions FillHist() or FillHistAndArray().
44// - The histogram can be fitted with the function FitGaus(). This involves stripping
45// of all zeros at the lower and upper end of the histogram and re-binning to
46// a new number of bins, specified in the variable fBinsAfterStripping.
47// - The fit result's probability is compared to a reference probability fProbLimit
48// The NDF is compared to fNDFLimit and a check is made whether results are NaNs.
49// Accordingly, a flag IsGausFitOK() is set.
50//
51// 2) The TArrayF fEvents:
52// ==========================
53//
54// It is created with 0 entries and not expanded unless FillArray() or FillHistAndArray()
55// are called.
56// - A first call to FillArray() or FillHistAndArray() initializes fEvents by default
57// to 512 entries.
58// - Any later call to FillArray() or FillHistAndArray() fills up the array.
59// Reaching the limit, the array is expanded by a factor 2.
60// - The array can be fourier-transformed into the array fPowerSpectrum.
61// Note that any FFT accepts only number of events which are a power of 2.
62// Thus, fEvents is cut to the next power of 2 smaller than its actual number of entries.
63// Be aware that you might lose information at the end of your analysis.
64// - Calling the function CreateFourierSpectrum() creates the array fPowerSpectrum
65// and its projection fHPowerProbability which in turn is fit to an exponential.
66// - The fit result's probability is compared to a referenc probability fProbLimit
67// and accordingly the flag IsExpFitOK() is set.
68// - The flag IsFourierSpectrumOK() is set accordingly to IsExpFitOK().
69// Later, a closer check will be installed.
70// - You can display all arrays by calls to: CreateGraphEvents() and
71// CreateGraphPowerSpectrum() and successive calls to the corresponding Getters.
72//
73//////////////////////////////////////////////////////////////////////////////
74#include "MHGausEvents.h"
75
76#include <TH1.h>
77#include <TF1.h>
78#include <TGraph.h>
79#include <TPad.h>
80#include <TVirtualPad.h>
81#include <TCanvas.h>
82#include <TStyle.h>
83
84#include "MFFT.h"
85#include "MArray.h"
86
87#include "MH.h"
88
89#include "MLog.h"
90#include "MLogManip.h"
91
92ClassImp(MHGausEvents);
93
94using namespace std;
95
96const Float_t MHGausEvents::fgProbLimit = 0.001;
97const Int_t MHGausEvents::fgNDFLimit = 2;
98const Int_t MHGausEvents::fgPowerProbabilityBins = 20;
99const Int_t MHGausEvents::fgBinsAfterStripping = 40;
100// --------------------------------------------------------------------------
101//
102// Default Constructor.
103// Sets:
104// - the default Probability Bins for fPowerProbabilityBins (fgPowerProbabilityBins)
105// - the default Probability Limit for fProbLimit (fgProbLimit)
106// - the default NDF Limit for fNDFLimit (fgNDFLimit)
107// - the default number of bins after stripping for fBinsAfterStipping (fgBinsAfterStipping)
108// - the default name of the fHGausHist ("HGausHist")
109// - the default title of the fHGausHist ("Histogram of Events with Gaussian Distribution")
110// - the default directory of the fHGausHist (NULL)
111//
112// Initializes:
113// - fEvents to 0 entries
114// - fHGausHist()
115// - all other pointers to NULL
116// - all variables to 0.
117// - all flags to kFALSE
118//
119MHGausEvents::MHGausEvents(const char *name, const char *title)
120 : fEventFrequency(0), fHPowerProbability(NULL),
121 fPowerSpectrum(NULL),
122 fGraphEvents(NULL), fGraphPowerSpectrum(NULL),
123 fHGausHist(), fEvents(0),
124 fFGausFit(NULL), fFExpFit(NULL)
125{
126
127 fName = name ? name : "MHGausEvents";
128 fTitle = title ? title : "Events with expected Gaussian distributions";
129
130 Clear();
131
132 SetPowerProbabilityBins();
133 SetProbLimit();
134 SetNDFLimit();
135 SetBinsAfterStripping();
136
137 fHGausHist.SetName("HGausHist");
138 fHGausHist.SetTitle("Histogram of Events with Gaussian Distribution");
139 // important, other ROOT will not draw the axes:
140 fHGausHist.UseCurrentStyle();
141 fHGausHist.SetDirectory(NULL);
142}
143
144
145
146// --------------------------------------------------------------------------
147//
148// Default Destructor.
149//
150// Deletes (if Pointer is not NULL):
151//
152// - fHPowerProbability
153// - fFGausFit
154// - fFExpFit
155// - fPowerSpectrum
156// - fGraphEvents
157// - fGraphPowerSpectrum
158//
159MHGausEvents::~MHGausEvents()
160{
161
162 // delete histograms
163 if (fHPowerProbability)
164 delete fHPowerProbability;
165
166 // delete fits
167 if (fFGausFit)
168 delete fFGausFit;
169 if (fFExpFit)
170 delete fFExpFit;
171
172 // delete arrays
173 if (fPowerSpectrum)
174 delete fPowerSpectrum;
175
176 // delete graphs
177 if (fGraphEvents)
178 delete fGraphEvents;
179 if (fGraphPowerSpectrum)
180 delete fGraphPowerSpectrum;
181}
182
183// --------------------------------------------------------------------------
184//
185// Sets:
186// - all other pointers to NULL
187// - all variables to 0., except fEventFrequency
188// - all flags to kFALSE
189//
190// Deletes (if not NULL):
191// - all pointers
192//
193void MHGausEvents::Clear(Option_t *o)
194{
195
196 SetGausFitOK ( kFALSE );
197 SetExpFitOK ( kFALSE );
198 SetFourierSpectrumOK( kFALSE );
199
200 fMean = 0.;
201 fSigma = 0.;
202 fMeanErr = 0.;
203 fSigmaErr = 0.;
204 fProb = 0.;
205
206 fCurrentSize = 0;
207
208 if (fHPowerProbability)
209 {
210 delete fHPowerProbability;
211 fHPowerProbability = NULL;
212 }
213
214 // delete fits
215 if (fFGausFit)
216 {
217 delete fFGausFit;
218 fFGausFit = NULL;
219 }
220
221 if (fFExpFit)
222 {
223 delete fFExpFit;
224 fFExpFit = NULL;
225 }
226
227 // delete arrays
228 if (fPowerSpectrum)
229 {
230 delete fPowerSpectrum;
231 fPowerSpectrum = NULL;
232 }
233
234 // delete graphs
235 if (fGraphEvents)
236 {
237 delete fGraphEvents;
238 fGraphEvents = NULL;
239 }
240
241 if (fGraphPowerSpectrum)
242 {
243 delete fGraphPowerSpectrum;
244 fGraphPowerSpectrum = NULL;
245 }
246}
247
248// --------------------------------------------------------------------------
249//
250// Executes:
251// - Clear()
252// - fHGausHist.Reset()
253// - fEvents.Set(0)
254//
255void MHGausEvents::Reset()
256{
257
258 Clear();
259 fHGausHist.Reset();
260 fEvents.Set(0);
261
262}
263
264// --------------------------------------------------------------------------
265//
266// Executes:
267// - FillArray()
268// - FillHist()
269//
270Bool_t MHGausEvents::FillHistAndArray(const Float_t f)
271{
272
273 FillArray(f);
274 return FillHist(f);
275}
276
277// --------------------------------------------------------------------------
278//
279// Fills fHGausHist with f
280// Returns kFALSE, if overflow or underflow occurred, else kTRUE
281//
282Bool_t MHGausEvents::FillHist(const Float_t f)
283{
284 return fHGausHist.Fill(f) > -1;
285}
286
287// --------------------------------------------------------------------------
288//
289// Fill fEvents with f
290// If size of fEvents is 0, initializes it to 512
291// If size of fEvents is smaller than fCurrentSize, double the size
292// Increase fCurrentSize by 1
293//
294void MHGausEvents::FillArray(const Float_t f)
295{
296 if (fEvents.GetSize() == 0)
297 fEvents.Set(512);
298
299 if (fCurrentSize >= fEvents.GetSize())
300 fEvents.Set(fEvents.GetSize()*2);
301
302 fEvents.AddAt(f,fCurrentSize++);
303}
304
305
306const Double_t MHGausEvents::GetChiSquare() const
307{
308 return ( fFGausFit ? fFGausFit->GetChisquare() : 0.);
309}
310
311const Int_t MHGausEvents::GetNdf() const
312{
313 return ( fFGausFit ? fFGausFit->GetNDF() : 0);
314}
315
316
317const Double_t MHGausEvents::GetExpChiSquare() const
318{
319 return ( fFExpFit ? fFExpFit->GetChisquare() : 0.);
320}
321
322
323const Int_t MHGausEvents::GetExpNdf() const
324{
325 return ( fFExpFit ? fFExpFit->GetNDF() : 0);
326}
327
328
329const Double_t MHGausEvents::GetExpProb() const
330{
331 return ( fFExpFit ? fFExpFit->GetProb() : 0.);
332}
333
334
335const Double_t MHGausEvents::GetOffset() const
336{
337 return ( fFExpFit ? fFExpFit->GetParameter(0) : 0.);
338}
339
340
341const Double_t MHGausEvents::GetSlope() const
342{
343 return ( fFExpFit ? fFExpFit->GetParameter(1) : 0.);
344}
345
346
347const Bool_t MHGausEvents::IsEmpty() const
348{
349 return !(fHGausHist.GetEntries());
350}
351
352
353const Bool_t MHGausEvents::IsFourierSpectrumOK() const
354{
355 return TESTBIT(fFlags,kFourierSpectrumOK);
356}
357
358
359const Bool_t MHGausEvents::IsGausFitOK() const
360{
361 return TESTBIT(fFlags,kGausFitOK);
362}
363
364
365const Bool_t MHGausEvents::IsExpFitOK() const
366{
367 return TESTBIT(fFlags,kExpFitOK);
368}
369
370
371// -------------------------------------------------------------------
372//
373// The flag setters are to be used ONLY for Monte-Carlo!!
374//
375void MHGausEvents::SetGausFitOK(const Bool_t b)
376{
377 b ? SETBIT(fFlags,kGausFitOK) : CLRBIT(fFlags,kGausFitOK);
378
379}
380// -------------------------------------------------------------------
381//
382// The flag setters are to be used ONLY for Monte-Carlo!!
383//
384void MHGausEvents::SetExpFitOK(const Bool_t b)
385{
386
387 b ? SETBIT(fFlags,kExpFitOK) : CLRBIT(fFlags,kExpFitOK);
388}
389
390// -------------------------------------------------------------------
391//
392// The flag setters are to be used ONLY for Monte-Carlo!!
393//
394void MHGausEvents::SetFourierSpectrumOK(const Bool_t b)
395{
396
397 b ? SETBIT(fFlags,kFourierSpectrumOK) : CLRBIT(fFlags,kFourierSpectrumOK);
398}
399
400
401// -------------------------------------------------------------------
402//
403// Create the fourier spectrum using the class MFFT.
404// The result is projected into a histogram and fitted by an exponential
405//
406void MHGausEvents::CreateFourierSpectrum()
407{
408
409 if (fFExpFit)
410 return;
411
412 //
413 // The number of entries HAS to be a potence of 2,
414 // so we can only cut out from the last potence of 2 to the rest.
415 // Another possibility would be to fill everything with
416 // zeros, but that gives a low frequency peak, which we would
417 // have to cut out later again.
418 //
419 // So, we have to live with the possibility that at the end
420 // of the calibration run, something has happened without noticing
421 // it...
422 //
423
424 // This cuts only the non-used zero's, but MFFT will later cut the rest
425 MArray::StripZeros(fEvents);
426
427 MFFT fourier;
428
429 fPowerSpectrum = fourier.PowerSpectrumDensity(&fEvents);
430 fHPowerProbability = ProjectArray(*fPowerSpectrum, fPowerProbabilityBins,
431 "PowerProbability",
432 "Probability of Power occurrance");
433 fHPowerProbability->SetXTitle("P(f)");
434 fHPowerProbability->SetDirectory(NULL);
435 //
436 // First guesses for the fit (should be as close to reality as possible,
437 //
438 const Double_t xmax = fHPowerProbability->GetXaxis()->GetXmax();
439
440 fFExpFit = new TF1("FExpFit","exp([0]-[1]*x)",0.,xmax);
441
442 const Double_t slope_guess = (TMath::Log(fHPowerProbability->GetEntries())+1.)/xmax;
443 const Double_t offset_guess = slope_guess*xmax;
444
445 fFExpFit->SetParameters(offset_guess, slope_guess);
446 fFExpFit->SetParNames("Offset","Slope");
447 fFExpFit->SetParLimits(0,offset_guess/2.,2.*offset_guess);
448 fFExpFit->SetParLimits(1,slope_guess/1.5,1.5*slope_guess);
449 fFExpFit->SetRange(0.,xmax);
450
451 fHPowerProbability->Fit(fFExpFit,"RQL0");
452
453 if (GetExpProb() > fProbLimit)
454 SetExpFitOK(kTRUE);
455
456 //
457 // For the moment, this is the only check, later we can add more...
458 //
459 SetFourierSpectrumOK(IsExpFitOK());
460
461 return;
462}
463
464// -------------------------------------------------------------------
465//
466// Fit fGausHist with a Gaussian after stripping zeros from both ends
467// and rebinned to the number of bins specified in fBinsAfterStripping
468//
469// The fit results are retrieved and stored in class-own variables.
470//
471// A flag IsGausFitOK() is set according to whether the fit probability
472// is smaller or bigger than fProbLimit, whether the NDF is bigger than
473// fNDFLimit and whether results are NaNs.
474//
475Bool_t MHGausEvents::FitGaus(Option_t *option, const Double_t xmin, const Double_t xmax)
476{
477
478 if (IsGausFitOK())
479 return kTRUE;
480
481 //
482 // First, strip the zeros from the edges which contain only zeros and rebin
483 // to about fBinsAfterStripping bins.
484 //
485 // (ATTENTION: The Chisquare method is more sensitive,
486 // the _less_ bins, you have!)
487 //
488 StripZeros(&fHGausHist,fBinsAfterStripping);
489
490 //
491 // Get the fitting ranges
492 //
493 Axis_t rmin = (xmin==0.) && (xmax==0.) ? fHGausHist.GetBinCenter(fHGausHist.GetXaxis()->GetFirst()) : xmin;
494 Axis_t rmax = (xmin==0.) && (xmax==0.) ? fHGausHist.GetBinCenter(fHGausHist.GetXaxis()->GetLast()) : xmax;
495
496 //
497 // First guesses for the fit (should be as close to reality as possible,
498 //
499 const Stat_t entries = fHGausHist.Integral("width");
500 const Double_t mu_guess = fHGausHist.GetBinCenter(fHGausHist.GetMaximumBin());
501 const Double_t sigma_guess = fHGausHist.GetRMS();
502 const Double_t area_guess = entries/TMath::Sqrt(TMath::TwoPi())/sigma_guess;
503
504 fFGausFit = new TF1("GausFit","gaus",rmin,rmax);
505
506 if (!fFGausFit)
507 {
508 *fLog << warn << dbginf << "WARNING: Could not create fit function for Gauss fit" << endl;
509 return kFALSE;
510 }
511
512 fFGausFit->SetParameters(area_guess,mu_guess,sigma_guess);
513 fFGausFit->SetParNames("Area","#mu","#sigma");
514 fFGausFit->SetParLimits(0,0.,area_guess*1.5);
515 fFGausFit->SetParLimits(1,rmin,rmax);
516 fFGausFit->SetParLimits(2,0.,rmax-rmin);
517 fFGausFit->SetRange(rmin,rmax);
518
519 fHGausHist.Fit(fFGausFit,option);
520
521
522 fMean = fFGausFit->GetParameter(1);
523 fSigma = fFGausFit->GetParameter(2);
524 fMeanErr = fFGausFit->GetParError(1);
525 fSigmaErr = fFGausFit->GetParError(2);
526 fProb = fFGausFit->GetProb();
527 //
528 // The fit result is accepted under condition:
529 // 1) The results are not nan's
530 // 2) The NDF is not smaller than fNDFLimit (5)
531 // 3) The Probability is greater than fProbLimit (default 0.001 == 99.9%)
532 //
533 if ( TMath::IsNaN(fMean)
534 || TMath::IsNaN(fMeanErr)
535 || TMath::IsNaN(fProb)
536 || TMath::IsNaN(fSigma)
537 || TMath::IsNaN(fSigmaErr)
538 || fFGausFit->GetNDF() < fNDFLimit
539 || fProb < fProbLimit )
540 return kFALSE;
541
542 SetGausFitOK(kTRUE);
543 return kTRUE;
544}
545
546// -----------------------------------------------------------------------------
547//
548// Bypasses the Gauss fit by taking mean and RMS from the histogram
549//
550// Errors are determined in the following way:
551// MeanErr = RMS / Sqrt(entries)
552// SigmaErr = RMS / (2.*Sqrt(entries) )
553//
554void MHGausEvents::BypassFit()
555{
556
557 const Stat_t entries = fHGausHist.GetEntries();
558
559 if (entries <= 0.)
560 {
561 *fLog << warn << GetDescriptor() << ": Cannot bypass fit. Number of entries smaller or equal 0" << endl;
562 return;
563 }
564
565 SetMean ( fHGausHist.GetMean() );
566 SetMeanErr ( fHGausHist.GetRMS() / TMath::Sqrt(entries) );
567 SetSigma ( fHGausHist.GetRMS() );
568 SetSigmaErr ( fHGausHist.GetRMS() / TMath::Sqrt(entries) / 2. );
569}
570
571// -----------------------------------------------------------------------------------
572//
573// A default print
574//
575void MHGausEvents::Print(const Option_t *o) const
576{
577
578 *fLog << all << endl;
579 *fLog << all << "Results of the Gauss Fit: " << endl;
580 *fLog << all << "Mean: " << GetMean() << endl;
581 *fLog << all << "Sigma: " << GetSigma() << endl;
582 *fLog << all << "Chisquare: " << GetChiSquare() << endl;
583 *fLog << all << "DoF: " << GetNdf() << endl;
584 *fLog << all << "Probability: " << GetProb() << endl;
585 *fLog << all << endl;
586
587}
588
589// ----------------------------------------------------------------------------------
590//
591// Create a graph to display the array fEvents
592// If the variable fEventFrequency is set, the x-axis is transformed into real time.
593//
594void MHGausEvents::CreateGraphEvents()
595{
596
597 MArray::StripZeros(fEvents);
598
599 const Int_t n = fEvents.GetSize();
600
601 fGraphEvents = new TGraph(n,CreateEventXaxis(n),fEvents.GetArray());
602 fGraphEvents->SetTitle("Evolution of Events with time");
603 fGraphEvents->GetXaxis()->SetTitle((fEventFrequency) ? "Time [s]" : "Event Nr.");
604}
605
606// ----------------------------------------------------------------------------------
607//
608// Create a graph to display the array fPowerSpectrum
609// If the variable fEventFrequency is set, the x-axis is transformed into real frequency.
610//
611void MHGausEvents::CreateGraphPowerSpectrum()
612{
613
614 MArray::StripZeros(*fPowerSpectrum);
615
616 const Int_t n = fPowerSpectrum->GetSize();
617
618 fGraphPowerSpectrum = new TGraph(n,CreatePSDXaxis(n),fPowerSpectrum->GetArray());
619 fGraphPowerSpectrum->SetTitle("Power Spectrum Density");
620 fGraphPowerSpectrum->GetXaxis()->SetTitle((fEventFrequency) ? "Frequency [Hz]" : "Frequency");
621 fGraphPowerSpectrum->GetYaxis()->SetTitle("P(f)");
622}
623
624// -----------------------------------------------------------------------------
625//
626// Create the x-axis for the event graph
627//
628Float_t *MHGausEvents::CreateEventXaxis(Int_t n)
629{
630
631 Float_t *xaxis = new Float_t[n];
632
633 if (fEventFrequency)
634 for (Int_t i=0;i<n;i++)
635 xaxis[i] = (Float_t)i/fEventFrequency;
636 else
637 for (Int_t i=0;i<n;i++)
638 xaxis[i] = (Float_t)i;
639
640 return xaxis;
641
642}
643
644// -----------------------------------------------------------------------------
645//
646// Create the x-axis for the event graph
647//
648Float_t *MHGausEvents::CreatePSDXaxis(Int_t n)
649{
650
651 Float_t *xaxis = new Float_t[n];
652
653 if (fEventFrequency)
654 for (Int_t i=0;i<n;i++)
655 xaxis[i] = 0.5*(Float_t)i*fEventFrequency/n;
656 else
657 for (Int_t i=0;i<n;i++)
658 xaxis[i] = 0.5*(Float_t)i/n;
659
660 return xaxis;
661
662}
663
664// -----------------------------------------------------------------------------
665//
666// Default draw:
667//
668// The following options can be chosen:
669//
670// "EVENTS": displays a TGraph of the array fEvents
671// "FOURIER": display a TGraph of the fourier transform of fEvents
672// displays the projection of the fourier transform with the fit
673//
674void MHGausEvents::Draw(const Option_t *opt)
675{
676
677 TVirtualPad *pad = gPad ? gPad : MH::MakeDefCanvas(this,600, 900);
678
679 TString option(opt);
680 option.ToLower();
681
682 Int_t win = 1;
683
684 if (option.Contains("events"))
685 {
686 option.ReplaceAll("events","");
687 win += 1;
688 }
689 if (option.Contains("fourier"))
690 {
691 option.ReplaceAll("fourier","");
692 win += 2;
693 }
694
695 pad->SetTicks();
696 pad->SetBorderMode(0);
697 pad->Divide(1,win);
698 pad->cd(1);
699
700 if (!IsEmpty())
701 gPad->SetLogy();
702
703 fHGausHist.Draw(opt);
704
705 if (fFGausFit)
706 {
707 fFGausFit->SetLineColor(IsGausFitOK() ? kGreen : kRed);
708 fFGausFit->Draw("same");
709 }
710 switch (win)
711 {
712 case 2:
713 pad->cd(2);
714 DrawEvents();
715 break;
716 case 3:
717 pad->cd(2);
718 DrawPowerSpectrum(*pad,3);
719 break;
720 case 4:
721 pad->cd(2);
722 DrawEvents();
723 pad->cd(3);
724 DrawPowerSpectrum(*pad,4);
725 break;
726 }
727}
728
729void MHGausEvents::DrawEvents()
730{
731
732 if (!fGraphEvents)
733 CreateGraphEvents();
734
735 fGraphEvents->SetBit(kCanDelete);
736 fGraphEvents->SetTitle("Events with time");
737 fGraphEvents->Draw("AL");
738
739}
740
741
742void MHGausEvents::DrawPowerSpectrum(TVirtualPad &pad, Int_t i)
743{
744
745 if (fPowerSpectrum)
746 {
747 if (!fGraphPowerSpectrum)
748 CreateGraphPowerSpectrum();
749
750 fGraphPowerSpectrum->Draw("AL");
751 fGraphPowerSpectrum->SetBit(kCanDelete);
752 }
753
754 pad.cd(i);
755
756 if (fHPowerProbability && fHPowerProbability->GetEntries() > 0)
757 {
758 gPad->SetLogy();
759 fHPowerProbability->Draw();
760 if (fFExpFit)
761 {
762 fFExpFit->SetLineColor(IsExpFitOK() ? kGreen : kRed);
763 fFExpFit->Draw("same");
764 }
765 }
766}
767
768
Note: See TracBrowser for help on using the repository browser.