/* ======================================================================== *\ ! ! * ! * This file is part of MARS, the MAGIC Analysis and Reconstruction ! * Software. It is distributed to you in the hope that it can be a useful ! * and timesaving tool in analysing Data of imaging Cerenkov telescopes. ! * It is distributed WITHOUT ANY WARRANTY. ! * ! * Permission to use, copy, modify and distribute this software and its ! * documentation for any purpose is hereby granted without fee, ! * provided that the above copyright notice appear in all copies and ! * that both that copyright notice and this permission notice appear ! * in supporting documentation. It is provided "as is" without express ! * or implied warranty. ! * ! ! ! Author(s): Thomas Bretz, 3/2004 ! ! Copyright: MAGIC Software Development, 2000-2004 ! ! \* ======================================================================== */ ////////////////////////////////////////////////////////////////////////////// // // MAlphaFitter // // Create a single Alpha-Plot. The alpha-plot is fitted online. You can // check the result when it is filles in the MStatusDisplay // For more information see MHFalseSource::FitSignificance // // For convinience (fit) the output significance is stored in a // container in the parlisrt // // PRELIMINARY! // ////////////////////////////////////////////////////////////////////////////// #include "MAlphaFitter.h" #include #include #include #include "MMath.h" #include "MLogManip.h" ClassImp(MAlphaFitter); using namespace std; // -------------------------------------------------------------------------- // // This is a preliminary implementation of a alpha-fit procedure for // all possible source positions. It will be moved into its own // more powerfull class soon. // // The fit function is "gaus(0)+pol2(3)" which is equivalent to: // [0]*exp(-0.5*((x-[1])/[2])^2) + [3] + [4]*x + [5]*x^2 // or // A*exp(-0.5*((x-mu)/sigma)^2) + a + b*x + c*x^2 // // Parameter [1] is fixed to 0 while the alpha peak should be // symmetric around alpha=0. // // Parameter [4] is fixed to 0 because the first derivative at // alpha=0 should be 0, too. // // In a first step the background is fitted between bgmin and bgmax, // while the parameters [0]=0 and [2]=1 are fixed. // // In a second step the signal region (alphaSetParameters(fCoefficients.GetArray()); fFunc->FixParameter(1, 0); fFunc->FixParameter(4, 0); fFunc->SetParLimits(2, 0, 90); fFunc->SetParLimits(3, -1, 1); const Double_t alpha0 = h.GetBinContent(1); const Double_t alphaw = h.GetXaxis()->GetBinWidth(1); // Check for the regios which is not filled... if (alpha0==0) return kFALSE; //*fLog << warn << "Histogram empty." << endl; // First fit a polynom in the off region fFunc->FixParameter(0, 0); fFunc->FixParameter(2, 1); fFunc->ReleaseParameter(3); for (int i=5; iGetNpar(); i++) fFunc->ReleaseParameter(i); // options : N do not store the function, do not draw // I use integral of function in bin rather than value at bin center // R use the range specified in the function range // Q quiet mode h.Fit(fFunc, "NQI", "", bgmin, bgmax); fChiSqBg = fFunc->GetChisquare()/fFunc->GetNDF(); // ------------------------------------ if (paint) { fFunc->SetRange(0, 90); fFunc->SetLineColor(kRed); fFunc->SetLineWidth(2); fFunc->Paint("same"); } // ------------------------------------ fFunc->ReleaseParameter(0); //func.ReleaseParameter(1); fFunc->ReleaseParameter(2); fFunc->FixParameter(3, fFunc->GetParameter(3)); for (int i=5; iGetNpar(); i++) fFunc->FixParameter(i, fFunc->GetParameter(i)); // Do not allow signals smaller than the background const Double_t A = alpha0-fFunc->GetParameter(3); const Double_t dA = TMath::Abs(A); fFunc->SetParLimits(0, -dA*4, dA*4); fFunc->SetParLimits(2, 0, 90); // Now fit a gaus in the on region on top of the polynom fFunc->SetParameter(0, A); fFunc->SetParameter(2, sigmax*0.75); // options : N do not store the function, do not draw // I use integral of function in bin rather than value at bin center // R use the range specified in the function range // Q quiet mode h.Fit(fFunc, "NQI", "", 0, sigmax); fChiSqSignal = fFunc->GetChisquare()/fFunc->GetNDF(); fCoefficients.Set(fFunc->GetNpar(), fFunc->GetParameters()); //const Bool_t ok = NDF>0 && chi2<2.5*NDF; // ------------------------------------ if (paint) { fFunc->SetLineColor(kGreen); fFunc->SetLineWidth(2); fFunc->Paint("same"); } // ------------------------------------ //const Double_t s = fFunc->Integral(0, fSigInt)/alphaw; fFunc->SetParameter(0, 0); fFunc->SetParameter(2, 1); //const Double_t b = fFunc->Integral(0, fSigInt)/alphaw; //fSignificance = MMath::SignificanceLiMaSigned(s, b); const Int_t bin = h.GetXaxis()->FindFixBin(fSigInt*0.999); fIntegralMax = h.GetBinLowEdge(bin+1); fEventsBackground = fFunc->Integral(0, fIntegralMax)/alphaw; fEventsSignal = h.Integral(0, bin); fEventsExcess = fEventsSignal-fEventsBackground; fSignificance = MMath::SignificanceLiMaSigned(fEventsSignal, fEventsBackground); if (fEventsExcess<0) fEventsExcess=0; return kTRUE; } void MAlphaFitter::PaintResult(Float_t x, Float_t y, Float_t size) const { TLatex text(x, y, Form("\\sigma_{Li/Ma}=%.1f \\omega=%.1f\\circ E=%d (\\alpha<%.1f\\circ) (\\chi_{b}^{2}=%.1f \\chi_{s}^{2}=%.1f)", fSignificance, GetGausSigma(), (int)fEventsExcess, fIntegralMax, fChiSqBg, fChiSqSignal)); text.SetBit(TLatex::kTextNDC); text.SetTextSize(size); text.Paint(); } void MAlphaFitter::Copy(TObject &o) const { MAlphaFitter &f = static_cast(o); f.fSigInt = fSigInt; f.fSigMax = fSigMax; f.fBgMin = fBgMin; f.fBgMax = fBgMax; f.fPolynomOrder = fPolynomOrder; f.fCoefficients.Set(fCoefficients.GetSize()); f.fCoefficients.Reset(); TF1 *fcn = f.fFunc; f.fFunc = new TF1(*fFunc); gROOT->GetListOfFunctions()->Remove(f.fFunc); f.fFunc->SetName("Dummy"); delete fcn; } void MAlphaFitter::Print(Option_t *o) const { *fLog << inf << GetDescriptor() << ": Fitting..." << endl; *fLog << " ...background from " << fBgMin << " to " << fBgMax << endl; *fLog << " ...signal to " << fSigMax << " (integrate into bin at " << fSigInt << ")" << endl; *fLog << " ...polynom order " << fPolynomOrder << endl; }