source: trunk/MagicSoft/Mars/mhflux/MAlphaFitter.cc@ 5725

Last change on this file since 5725 was 5692, checked in by tbretz, 20 years ago
*** empty log message ***
File size: 14.2 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): Thomas Bretz, 3/2004 <mailto:tbretz@astro.uni-wuerzburg.de>
19!
20! Copyright: MAGIC Software Development, 2000-2004
21!
22!
23\* ======================================================================== */
24
25//////////////////////////////////////////////////////////////////////////////
26//
27// MAlphaFitter
28//
29// Create a single Alpha-Plot. The alpha-plot is fitted online. You can
30// check the result when it is filles in the MStatusDisplay
31// For more information see MHFalseSource::FitSignificance
32//
33// For convinience (fit) the output significance is stored in a
34// container in the parlisrt
35//
36// PRELIMINARY!
37//
38//////////////////////////////////////////////////////////////////////////////
39#include "MAlphaFitter.h"
40
41#include <TF1.h>
42#include <TH1.h>
43#include <TH3.h>
44
45#include <TRandom.h>
46
47#include <TLatex.h>
48
49#include "MMath.h"
50
51#include "MLogManip.h"
52
53ClassImp(MAlphaFitter);
54
55using namespace std;
56
57void MAlphaFitter::Clear(Option_t *o)
58{
59 fSignificance=0;
60 fEventsExcess=0;
61 fEventsSignal=0;
62 fEventsBackground=0;
63
64 fChiSqSignal=0;
65 fChiSqBg=0;
66 fIntegralMax=0;
67
68 fCoefficients.Reset();
69}
70
71// --------------------------------------------------------------------------
72//
73// This is a preliminary implementation of a alpha-fit procedure for
74// all possible source positions. It will be moved into its own
75// more powerfull class soon.
76//
77// The fit function is "gaus(0)+pol2(3)" which is equivalent to:
78// [0]*exp(-0.5*((x-[1])/[2])^2) + [3] + [4]*x + [5]*x^2
79// or
80// A*exp(-0.5*((x-mu)/sigma)^2) + a + b*x + c*x^2
81//
82// Parameter [1] is fixed to 0 while the alpha peak should be
83// symmetric around alpha=0.
84//
85// Parameter [4] is fixed to 0 because the first derivative at
86// alpha=0 should be 0, too.
87//
88// In a first step the background is fitted between bgmin and bgmax,
89// while the parameters [0]=0 and [2]=1 are fixed.
90//
91// In a second step the signal region (alpha<sigmax) is fittet using
92// the whole function with parameters [1], [3], [4] and [5] fixed.
93//
94// The number of excess and background events are calculated as
95// s = int(hist, 0, 1.25*sigint)
96// b = int(pol2(3), 0, 1.25*sigint)
97//
98// The Significance is calculated using the Significance() member
99// function.
100//
101Bool_t MAlphaFitter::Fit(TH1D &h, Bool_t paint)
102{
103 Clear();
104 if (h.GetEntries()==0)
105 return kFALSE;
106
107 Double_t sigmax=fSigMax;
108 Double_t bgmin =fBgMin;
109 Double_t bgmax =fBgMax;
110
111 //*fLog << inf << "Fit: " << sigmax << " " << fSigInt << " " << bgmin << " " << bgmax << endl;
112
113 //TF1 fFunc("", Form("gaus(0) + pol%d(3)", fPolynomOrder), 0, 90);
114
115 //fFunc->SetParameters(fCoefficients.GetArray());
116
117 fFunc->FixParameter(1, 0);
118 fFunc->FixParameter(4, 0);
119 fFunc->SetParLimits(2, 0, 90);
120 fFunc->SetParLimits(3, -1, 1);
121
122 const Double_t alpha0 = h.GetBinContent(1);
123 const Double_t alphaw = h.GetXaxis()->GetBinWidth(1);
124
125 // Check for the regios which is not filled...
126 if (alpha0==0)
127 return kFALSE; //*fLog << warn << "Histogram empty." << endl;
128
129 // First fit a polynom in the off region
130 fFunc->FixParameter(0, 0);
131 fFunc->FixParameter(2, 1);
132 fFunc->ReleaseParameter(3);
133
134 for (int i=5; i<fFunc->GetNpar(); i++)
135 fFunc->ReleaseParameter(i);
136
137 // options : N do not store the function, do not draw
138 // I use integral of function in bin rather than value at bin center
139 // R use the range specified in the function range
140 // Q quiet mode
141 h.Fit(fFunc, "NQI", "", bgmin, bgmax);
142
143 fChiSqBg = fFunc->GetChisquare()/fFunc->GetNDF();
144
145 // ------------------------------------
146 if (paint)
147 {
148 fFunc->SetRange(0, 90);
149 fFunc->SetLineColor(kRed);
150 fFunc->SetLineWidth(2);
151 fFunc->Paint("same");
152 }
153 // ------------------------------------
154
155 fFunc->ReleaseParameter(0);
156 //func.ReleaseParameter(1);
157 fFunc->ReleaseParameter(2);
158 fFunc->FixParameter(3, fFunc->GetParameter(3));
159 for (int i=5; i<fFunc->GetNpar(); i++)
160 fFunc->FixParameter(i, fFunc->GetParameter(i));
161
162 // Do not allow signals smaller than the background
163 const Double_t A = alpha0-fFunc->GetParameter(3);
164 const Double_t dA = TMath::Abs(A);
165 fFunc->SetParLimits(0, -dA*4, dA*4);
166 fFunc->SetParLimits(2, 0, 90);
167
168 // Now fit a gaus in the on region on top of the polynom
169 fFunc->SetParameter(0, A);
170 fFunc->SetParameter(2, sigmax*0.75);
171
172 // options : N do not store the function, do not draw
173 // I use integral of function in bin rather than value at bin center
174 // R use the range specified in the function range
175 // Q quiet mode
176 h.Fit(fFunc, "NQI", "", 0, sigmax);
177
178 fChiSqSignal = fFunc->GetChisquare()/fFunc->GetNDF();
179 fCoefficients.Set(fFunc->GetNpar(), fFunc->GetParameters());
180
181 //const Bool_t ok = NDF>0 && chi2<2.5*NDF;
182
183 // ------------------------------------
184 if (paint)
185 {
186 fFunc->SetLineColor(kGreen);
187 fFunc->SetLineWidth(2);
188 fFunc->Paint("same");
189 }
190 // ------------------------------------
191
192 //const Double_t s = fFunc->Integral(0, fSigInt)/alphaw;
193 fFunc->SetParameter(0, 0);
194 fFunc->SetParameter(2, 1);
195 //const Double_t b = fFunc->Integral(0, fSigInt)/alphaw;
196 //fSignificance = MMath::SignificanceLiMaSigned(s, b);
197
198 const Int_t bin = h.GetXaxis()->FindFixBin(fSigInt*0.999);
199
200 fIntegralMax = h.GetBinLowEdge(bin+1);
201 fEventsBackground = fFunc->Integral(0, fIntegralMax)/alphaw;
202 fEventsSignal = h.Integral(0, bin);
203 fEventsExcess = fEventsSignal-fEventsBackground;
204 fSignificance = MMath::SignificanceLiMaSigned(fEventsSignal, fEventsBackground);
205
206 if (fEventsExcess<0)
207 fEventsExcess=0;
208
209 return kTRUE;
210}
211
212Bool_t MAlphaFitter::Fit(TH1D &hon, TH1D &hof, Bool_t paint)
213{
214 /*
215 Clear();
216 if (hon.GetEntries()==0)
217 return kFALSE;
218 */
219
220 TH1D h(hon);
221 h.Add(&hof, -1);
222
223 MAlphaFitter fit(*this);
224 fit.SetPolynomOrder(1);
225
226 if (!fit.Fit(h, paint))
227 return kFALSE;
228
229 fChiSqSignal = fit.GetChiSqSignal();
230 fChiSqBg = fit.GetChiSqBg();
231 fCoefficients = fit.GetCoefficients();
232
233 const Int_t bin = hon.GetXaxis()->FindFixBin(fSigInt*0.999);
234
235 fIntegralMax = hon.GetBinLowEdge(bin+1);
236 fEventsBackground = hof.Integral(0, bin);
237 fEventsSignal = hon.Integral(0, bin);
238 fEventsExcess = fEventsSignal-fEventsBackground;
239 fSignificance = MMath::SignificanceLiMaSigned(fEventsSignal, fEventsBackground);
240
241 if (fEventsExcess<0)
242 fEventsExcess=0;
243/*
244 TF1 func("", "gaus(0)+pol0(3)", 0., 90.);
245
246 const Double_t A = fEventsSignal/bin;
247 const Double_t dA = TMath::Abs(A);
248 func.SetParLimits(0, -dA*4, dA*4);
249 func.SetParLimits(2, 0, 90);
250 func.SetParLimits(3, -dA, dA);
251
252 func.SetParameter(0, A);
253 func.FixParameter(1, 0);
254 func.SetParameter(2, fSigMax*0.75);
255 func.SetParameter(3, 0);
256
257 // options : N do not store the function, do not draw
258 // I use integral of function in bin rather than value at bin center
259 // R use the range specified in the function range
260 // Q quiet mode
261 TH1D h(hon);
262 h.Add(&hof, -1);
263 h.Fit(&func, "NQI", "", 0, 90);
264
265 fChiSqSignal = func.GetChisquare()/func.GetNDF();
266
267 const Int_t bin1 = h.GetXaxis()->FindFixBin(func.GetParameter(2)*2);
268
269 fChiSqBg = 0;
270 for (int i=bin1; i<=h.GetNbinsX(); i++)
271 {
272 const Float_t val = h.GetBinContent(i);
273 fChiSqBg = val*val;
274 }
275 if (fChiSqBg>0)
276 fChiSqBg /= h.GetNbinsX()+1-bin1;
277
278 fCoefficients.Set(func.GetNpar(), func.GetParameters());
279
280 // ------------------------------------
281 if (paint)
282 {
283 func.SetLineColor(kBlue);
284 func.SetLineWidth(2);
285 func.Paint("same");
286 }
287 // ------------------------------------
288 */
289 return kTRUE;
290}
291
292void MAlphaFitter::PaintResult(Float_t x, Float_t y, Float_t size) const
293{
294 TLatex text(x, y, Form("\\sigma_{Li/Ma}=%.1f \\omega=%.1f\\circ E=%d (\\alpha<%.1f\\circ) (\\chi_{b}^{2}/ndf=%.1f \\chi_{s}^{2}/ndf=%.1f c_{0}=%.1f)",
295 fSignificance, GetGausSigma(),
296 (int)fEventsExcess, fIntegralMax,
297 fChiSqBg, fChiSqSignal, fCoefficients[3]));
298
299 text.SetBit(TLatex::kTextNDC);
300 text.SetTextSize(size);
301 text.Paint();
302}
303
304void MAlphaFitter::Copy(TObject &o) const
305{
306 MAlphaFitter &f = static_cast<MAlphaFitter&>(o);
307
308 f.fSigInt = fSigInt;
309 f.fSigMax = fSigMax;
310 f.fBgMin = fBgMin;
311 f.fBgMax = fBgMax;
312 f.fScaleMin = fScaleMin;
313 f.fScaleMax = fScaleMax;
314 f.fPolynomOrder = fPolynomOrder;
315 f.fScaleMode = fScaleMode;
316 f.fScaleUser = fScaleUser;
317 f.fCoefficients.Set(fCoefficients.GetSize());
318 f.fCoefficients.Reset();
319
320 TF1 *fcn = f.fFunc;
321 f.fFunc = new TF1(*fFunc);
322 gROOT->GetListOfFunctions()->Remove(f.fFunc);
323 f.fFunc->SetName("Dummy");
324 delete fcn;
325}
326
327void MAlphaFitter::Print(Option_t *o) const
328{
329 *fLog << inf << GetDescriptor() << ": Fitting..." << endl;
330 *fLog << " ...background from " << fBgMin << " to " << fBgMax << endl;
331 *fLog << " ...signal to " << fSigMax << " (integrate into bin at " << fSigInt << ")" << endl;
332 *fLog << " ...polynom order " << fPolynomOrder << endl;
333 *fLog << " ...scale mode: ";
334 switch (fScaleMode)
335 {
336 case kNone: *fLog << "none."; break;
337 case kEntries: *fLog << "entries."; break;
338 case kIntegral: *fLog << "integral."; break;
339 case kOffRegion: *fLog << "off region."; break;
340 case kLeastSquare: *fLog << "least square."; break;
341 case kUserScale: *fLog << "user def (" << fScaleUser << ")"; break;
342 }
343 *fLog << endl;
344
345 if (TString(o).Contains("result"))
346 {
347 *fLog << "Result:" << endl;
348 *fLog << " - Significance " << fSignificance << endl;
349 *fLog << " - Excess Events " << fEventsExcess << endl;
350 *fLog << " - Signal Events " << fEventsSignal << endl;
351 *fLog << " - Background Events " << fEventsBackground << endl;
352 *fLog << " - Chi^2/ndf (Signal) " << fChiSqSignal << endl;
353 *fLog << " - Chi^2/ndf (Background) " << fChiSqBg << endl;
354 *fLog << " - Signal integrated " << fIntegralMax << "°" << endl;
355 }
356}
357
358Bool_t MAlphaFitter::FitEnergy(const TH3D &hon, UInt_t bin, Bool_t paint)
359{
360 const TString name(Form("TempAlphaEnergy%06d", gRandom->Integer(1000000)));
361 TH1D *h = hon.ProjectionZ(name, -1, 9999, bin, bin, "E");
362 h->SetDirectory(0);
363
364 const Bool_t rc = Fit(*h, paint);
365 delete h;
366 return rc;
367}
368
369Bool_t MAlphaFitter::FitTheta(const TH3D &hon, UInt_t bin, Bool_t paint)
370{
371 const TString name(Form("TempAlphaTheta%06d", gRandom->Integer(1000000)));
372 TH1D *h = hon.ProjectionZ(name, bin, bin, -1, 9999, "E");
373 h->SetDirectory(0);
374
375 const Bool_t rc = Fit(*h, paint);
376 delete h;
377 return rc;
378}
379
380Bool_t MAlphaFitter::FitAlpha(const TH3D &hon, Bool_t paint)
381{
382 const TString name(Form("TempAlpha%06d", gRandom->Integer(1000000)));
383 TH1D *h = hon.ProjectionZ(name, -1, 9999, -1, 9999, "E");
384 h->SetDirectory(0);
385
386 const Bool_t rc = Fit(*h, paint);
387 delete h;
388 return rc;
389}
390
391Bool_t MAlphaFitter::FitEnergy(const TH3D &hon, const TH3D &hof, UInt_t bin, Bool_t paint)
392{
393 const TString name1(Form("TempAlpha%06d_on", gRandom->Integer(1000000)));
394 const TString name0(Form("TempAlpha%06d_off", gRandom->Integer(1000000)));
395 TH1D *h1 = hon.ProjectionZ(name1, -1, 9999, bin, bin, "E");
396 TH1D *h0 = hof.ProjectionZ(name0, -1, 9999, bin, bin, "E");
397 h1->SetDirectory(0);
398 h0->SetDirectory(0);
399
400 Scale(*h0, *h1);
401
402 const Bool_t rc = Fit(*h1, *h0, paint);
403
404 delete h0;
405 delete h1;
406
407 return rc;
408}
409
410Bool_t MAlphaFitter::FitTheta(const TH3D &hon, const TH3D &hof, UInt_t bin, Bool_t paint)
411{
412 const TString name1(Form("TempAlpha%06d_on", gRandom->Integer(1000000)));
413 const TString name0(Form("TempAlpha%06d_off", gRandom->Integer(1000000)));
414
415 TH1D *h1 = hon.ProjectionZ(name1, bin, bin, -1, 9999, "E");
416 TH1D *h0 = hof.ProjectionZ(name0, bin, bin, -1, 9999, "E");
417 h1->SetDirectory(0);
418 h0->SetDirectory(0);
419
420 Scale(*h0, *h1);
421
422 const Bool_t rc = Fit(*h1, *h0, paint);
423
424 delete h0;
425 delete h1;
426
427 return rc;
428}
429
430Bool_t MAlphaFitter::FitAlpha(const TH3D &hon, const TH3D &hof, Bool_t paint)
431{
432 const TString name1(Form("TempAlpha%06d_on", gRandom->Integer(1000000)));
433 const TString name0(Form("TempAlpha%06d_off", gRandom->Integer(1000000)));
434
435 TH1D *h1 = hon.ProjectionZ(name1, -1, 9999, -1, 9999, "E");
436 TH1D *h0 = hof.ProjectionZ(name0, -1, 9999, -1, 9999, "E");
437 h1->SetDirectory(0);
438 h0->SetDirectory(0);
439
440 Scale(*h0, *h1);
441
442 const Bool_t rc = Fit(*h1, *h0, paint);
443
444 delete h0;
445 delete h1;
446
447 return rc;
448}
449
450void MAlphaFitter::Scale(TH1D &of, const TH1D &on) const
451{
452 Float_t scaleon = 1;
453 Float_t scaleof = 1;
454 switch (fScaleMode)
455 {
456 case kNone:
457 return;
458
459 case kEntries:
460 scaleon = on.GetEntries();
461 scaleof = of.GetEntries();
462 break;
463
464 case kIntegral:
465 scaleon = on.Integral();
466 scaleof = of.Integral();
467 break;
468
469 case kOffRegion:
470 {
471 const Int_t min = on.GetXaxis()->FindFixBin(fScaleMin);
472 const Int_t max = on.GetXaxis()->FindFixBin(fScaleMax);
473 scaleon = on.Integral(min, max);
474 scaleof = of.Integral(min, max);
475 }
476 break;
477
478 case kUserScale:
479 scaleon = fScaleUser;
480 break;
481
482 default:
483 return;
484 }
485
486 if (scaleof!=0)
487 of.Scale(scaleon/scaleof);
488}
Note: See TracBrowser for help on using the repository browser.