source: trunk/MagicSoft/Mars/mcalib/MHGausEvent.cc@ 3124

Last change on this file since 3124 was 3115, checked in by gaug, 21 years ago
*** empty log message ***
File size: 8.0 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 11/2003 <mailto:markus@ifae.es>
19!
20! Copyright: MAGIC Software Development, 2000-2002
21!
22!
23\* ======================================================================== */
24
25//////////////////////////////////////////////////////////////////////////////
26//
27// MHGausEvent
28//
29// A base class for all kind of event which follow a Gaussian distribution
30// with time, i.e. observables containing white noise.
31//
32// The class provides the basic tools for fitting,
33// spectrum analysis, etc.
34//
35//////////////////////////////////////////////////////////////////////////////
36#include "MHGausEvent.h"
37
38#include <TH1.h>
39#include <TF1.h>
40
41#include "MFFT.h"
42#include "MArray.h"
43
44#include "MLog.h"
45#include "MLogManip.h"
46
47ClassImp(MHGausEvent);
48
49using namespace std;
50
51// --------------------------------------------------------------------------
52//
53// Default Constructor.
54//
55MHGausEvent::MHGausEvent(const char *name, const char *title)
56 : fHGausHist(NULL), fHPowerProbability(NULL),
57 fFGausFit(NULL), fFExpFit(NULL),
58 fEvents(NULL), fPowerSpectrum(NULL)
59{
60
61 fName = name ? name : "MHGausEvent";
62 fTitle = title ? title : "Events which follow a Gaussian distribution";
63
64 Clear();
65}
66
67
68MHGausEvent::~MHGausEvent()
69{
70 Clear();
71
72 if (fHGausHist)
73 delete fHGausHist;
74}
75
76
77
78void MHGausEvent::Clear(Option_t *o)
79{
80
81 fGausHistBins = 50;
82 fGausHistAxisFirst = 0.;
83 fGausHistAxisLast = 100.;
84
85 fPowerProbabilityBins = 30;
86
87 fProbLimit = 0.01;
88 fGausFitOK = kFALSE;
89 fExpFitOK = kFALSE;
90 fOscillating = kFALSE;
91
92 fMean = 0.;
93 fSigma = 0.;
94 fMeanErr = 0.;
95 fSigmaErr = 0.;
96
97 fProb = 0.;
98
99 if (fHPowerProbability)
100 delete fHPowerProbability;
101 if (fFGausFit)
102 delete fFGausFit;
103 if (fEvents)
104 delete fEvents;
105 if (fPowerSpectrum)
106 delete fPowerSpectrum;
107}
108
109
110void MHGausEvent::Reset()
111{
112
113 Clear();
114 fHGausHist->Reset();
115
116}
117
118const Double_t MHGausEvent::GetChiSquare() const
119{
120 return ( fFGausFit ? fFGausFit->GetChisquare() : 0.);
121}
122
123const Int_t MHGausEvent::GetNdf() const
124{
125 return ( fFGausFit ? fFGausFit->GetNDF() : 0);
126}
127
128
129const Double_t MHGausEvent::GetExpChiSquare() const
130{
131 return ( fFExpFit ? fFExpFit->GetChisquare() : 0.);
132}
133
134
135const Int_t MHGausEvent::GetExpNdf() const
136{
137 return ( fFExpFit ? fFExpFit->GetNDF() : 0);
138}
139
140const Double_t MHGausEvent::GetExpProb() const
141{
142 return ( fFExpFit ? fFExpFit->GetProb() : 0.);
143}
144
145const Double_t MHGausEvent::GetOffset() const
146{
147 return ( fFExpFit ? fFExpFit->GetParameter(0) : 0.);
148}
149
150const Double_t MHGausEvent::GetSlope() const
151{
152 return ( fFExpFit ? fFExpFit->GetParameter(1) : 0.);
153}
154
155
156
157Bool_t MHGausEvent::CheckOscillations()
158{
159
160 if (fFExpFit)
161 return IsOscillating();
162
163 if (!fEvents)
164 return kFALSE;
165
166 //
167 // The number of entries HAS to be a potence of 2,
168 // so we can only cut out from the last potence of 2 to the rest.
169 // Another possibility would be to fill everything with
170 // zeros, but that gives a low frequency peak, which we would
171 // have to cut out later again.
172 //
173 // So, we have to live with the possibility that at the end
174 // of the calibration run, something has happened without noticing
175 // it...
176 //
177
178 // This cuts only the non-used zero's, but MFFT will later cut the rest
179 MArray::StripZeros(*fEvents);
180
181 MFFT fourier;
182
183 fPowerSpectrum = fourier.PowerSpectrumDensity(fEvents);
184 fHPowerProbability = ProjectArray(*fPowerSpectrum, fPowerProbabilityBins,
185 "PowerProbability",
186 "Probability of Power occurrance");
187 //
188 // First guesses for the fit (should be as close to reality as possible,
189 //
190 const Double_t xmax = fHPowerProbability->GetXaxis()->GetXmax();
191
192 fFExpFit = new TF1("FExpFit","exp([0]-[1]*x)",0.,xmax);
193
194 const Double_t slope_guess = (TMath::Log(fHPowerProbability->GetEntries())+1.)/xmax;
195 const Double_t offset_guess = slope_guess*xmax;
196
197 fFExpFit->SetParameters(offset_guess, slope_guess);
198 fFExpFit->SetParNames("Offset","Slope");
199 fFExpFit->SetParLimits(0,offset_guess/2.,2.*offset_guess);
200 fFExpFit->SetParLimits(1,slope_guess/1.5,1.5*slope_guess);
201 fFExpFit->SetRange(0.,xmax);
202
203 fHPowerProbability->Fit(fFExpFit,"RQL0");
204
205 if (GetExpProb() < fProbLimit)
206 fExpFitOK = kFALSE;
207
208 // For the moment, this is the only check, later we can add more...
209 fOscillating = fExpFitOK;
210
211 return fOscillating;
212}
213
214
215Bool_t MHGausEvent::IsEmpty() const
216{
217 return !(fHGausHist->GetEntries());
218}
219
220Bool_t MHGausEvent::IsOscillating()
221{
222
223 if (fFExpFit)
224 return fOscillating;
225
226 return CheckOscillations();
227
228}
229
230
231Bool_t MHGausEvent::FitGaus(Option_t *option)
232{
233
234 if (IsGausFitOK())
235 return kTRUE;
236
237 //
238 // First, cut the edges which contain only zeros and rebin
239 // to about 20 bins.
240 //
241 // (ATTENTION: The Chisquare method is more sensitive,
242 // the _less_ bins, you have!)
243 //
244 Int_t newbins = 20;
245 MH::CutEdges(fHGausHist,newbins);
246
247 //
248 // Get the fitting ranges
249 //
250 Axis_t rmin = fHGausHist->GetXaxis()->GetFirst();
251 Axis_t rmax = fHGausHist->GetXaxis()->GetLast();
252
253 //
254 // First guesses for the fit (should be as close to reality as possible,
255 //
256 const Stat_t entries = fHGausHist->Integral("width");
257 const Double_t mu_guess = fHGausHist->GetBinCenter(fHGausHist->GetMaximumBin());
258 const Double_t sigma_guess = (rmax-rmin)/2.;
259 const Double_t area_guess = entries/TMath::Sqrt(TMath::TwoPi())/sigma_guess;
260
261 fFGausFit = new TF1("GausFit","gaus",rmin,rmax);
262
263 if (!fFGausFit)
264 {
265 *fLog << warn << dbginf << "WARNING: Could not create fit function for Gauss fit" << endl;
266 return kFALSE;
267 }
268
269 fFGausFit->SetParameters(area_guess,mu_guess,sigma_guess);
270 fFGausFit->SetParNames("Area","#mu","#sigma");
271 fFGausFit->SetParLimits(0,0.,entries);
272 fFGausFit->SetParLimits(1,rmin,rmax);
273 fFGausFit->SetParLimits(2,0.,rmax-rmin);
274 fFGausFit->SetRange(rmin,rmax);
275
276 fHGausHist->Fit(fFGausFit,option);
277
278 fMean = fFGausFit->GetParameter(1);
279 fSigma = fFGausFit->GetParameter(2);
280 fMeanErr = fFGausFit->GetParError(1);
281 fSigmaErr = fFGausFit->GetParError(2);
282
283 fProb = fFGausFit->GetProb();
284 //
285 // The fit result is accepted under condition:
286 // 1) The results are not nan's
287 // 2) The NDF is not smaller than fNDFLimit (5)
288 // 3) The Probability is greater than fProbLimit (default 0.001 == 99.9%)
289 //
290 if ( TMath::IsNaN(fMean)
291 || TMath::IsNaN(fMeanErr)
292 || TMath::IsNaN(fProb)
293 || TMath::IsNaN(fSigma)
294 || TMath::IsNaN(fSigmaErr) )
295 {
296 fGausFitOK = kFALSE;
297 return kFALSE;
298 }
299
300 fGausFitOK = kTRUE;
301 return kTRUE;
302}
303
304void MHGausEvent::Print(const Option_t *o) const
305{
306
307 *fLog << all << endl;
308 *fLog << all << "Results of the Gauss Fit: " << endl;
309 *fLog << all << "Mean: " << GetMean() << endl;
310 *fLog << all << "Sigma: " << GetSigma() << endl;
311 *fLog << all << "Chisquare: " << GetChiSquare() << endl;
312 *fLog << all << "DoF: " << GetNdf() << endl;
313 *fLog << all << "Probability: " << GetProb() << endl;
314 *fLog << all << endl;
315
316}
317
Note: See TracBrowser for help on using the repository browser.