/* ======================================================================== *\ ! ! * ! * 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): Wolfgang Wittek 5/2002 ! ! Copyright: MAGIC Software Development, 2000-2002 ! ! \* ======================================================================== */ ////////////////////////////////////////////////////////////////////////////// // // // MHEffOnTime // // // // calculates the effective on time for each bin in the variable Var // // (Var may be time or Theta) // // // // Important : The sample of events used for this should be as close // // to the sample of recorded events as possible. // // This means that NO additional cuts (be it quality cuts or // // gamma/hadron cuts) should be applied (see MAGIC-TDAS 02-02).// // // ////////////////////////////////////////////////////////////////////////////// #include "MHEffOnTime.h" #include #include #include #include #include #include #include "MBinning.h" #include "MParList.h" #include "MLog.h" #include "MLogManip.h" ClassImp(MHEffOnTime); // -------------------------------------------------------------------------- // // Default Constructor. It sets the name of the variable ("Time" or "Theta") // and the units of the variable ("[s]" or "[\\circ])") // MHEffOnTime::MHEffOnTime(const char *varname, const char *unit) : fHEffOn(), fHProb(), fHLambda(), fHRdead() { fVarname = varname; fUnit = unit; TString strg(fVarname); strg += " "; strg += fUnit; // // set the name and title of this object // TString strg1("MHEffOnTime-"); strg1 += fVarname; fName = strg1; fTitle = "1-D histogram of Eff On Time"; // effective on time versus Var fHEffOn.SetName("EffOn"); TString strg2("effective On Time vs. "); strg2 += fVarname; fHEffOn.SetTitle(strg2); fHEffOn.SetDirectory(NULL); fHEffOn.SetXTitle(strg); fHEffOn.SetYTitle("effective ontime [s]"); // chi2-probability versus Var fHProb.SetName("Chi2-prob"); TString strg3("Chi2-prob of OnTimeFit vs. "); strg3 += fVarname; fHProb.SetTitle(strg3); fHProb.SetDirectory(NULL); fHProb.SetXTitle(strg); fHProb.SetYTitle("chi2-probability"); // lambda versus Var fHLambda.SetName("lambda"); TString strg4("lambda from OnTimeFit vs. "); strg4 += fVarname; fHLambda.SetTitle(strg4); fHLambda.SetDirectory(NULL); fHLambda.SetXTitle(strg); fHLambda.SetYTitle("\\lambda [Hz]"); // Rdead versus Var // Rdead is the fraction from real time lost by the dead time fHRdead.SetName("Rdead"); TString strg5("Rdead of OnTimeFit vs. "); strg5 += fVarname; fHRdead.SetTitle(strg5); fHRdead.SetDirectory(NULL); fHRdead.SetXTitle(strg); fHRdead.SetYTitle("Rdead"); } // ----------------------------------------------------------------------- // // Calculate the effective on time by fitting the distribution of // time differences // void MHEffOnTime::Calc(TH2D *hist, const Bool_t Draw) { // Draw != 0 means the distribution of time differences should be drawn // nbins = number of Var bins const Int_t nbins = hist->GetNbinsY(); // start of 'for' loop --------------------------- for (int i=1; i<=nbins; i++) { TString strg0("Calc-"); strg0 += fVarname; TH1D &h = *hist->ProjectionX(strg0, i, i, "E"); // Nmdel = Nm * binwidth, with Nm = number of observed events const Double_t Nmdel = h.Integral("width"); const Double_t Nm = h.Integral(); //................................................... // determine range (yq[0], yq[1]) of time differences // where fit should be performed; // require a fraction >=xq[0] of all entries to lie below yq[0] // and a fraction <=xq[1] of all entries to lie below yq[1]; // within the range (yq[0], yq[1]) there must be no empty bin; // choose pedestrian approach as long as GetQuantiles is not available Double_t xq[2] = { 0.15, 0.95 }; Double_t yq[2]; // GetQuantiles doesn't seem to be available in root 3.01/06 // h.GetQuantiles(2,yq,xq); const Int_t jbins = h.GetNbinsX(); fHEffOn.SetBinContent (i, 1.e-20); fHProb.SetBinContent (i, 1.e-20); fHLambda.SetBinContent(i, 1.e-20); fHRdead.SetBinContent (i, 1.e-20); // start of 'if' loop --------------------------- if (Nm > 0.0) { // del is bin width in time difference const Double_t del = Nmdel/Nm; Double_t sum1 = 0.0; yq[0] = h.GetBinLowEdge(jbins+1); for (int j=1; j<=jbins; j++) { if (sum1 >= xq[0]*Nm) { yq[0] = h.GetBinLowEdge(j); break; } sum1 += h.GetBinContent(j); } Double_t sum2 = 0.0; yq[1] = h.GetBinLowEdge(jbins+1); for (int j=1; j<=jbins; j++) { const Double_t content = h.GetBinContent(j); sum2 += content; if (sum2 >= xq[1]*Nm || content == 0.0) { yq[1] = h.GetBinLowEdge(j); break; } } //................................................... // parameter 0 = lambda // parameter 1 = N0 with N0 = ideal number of events // parameter 2 = del (fixed) with del = bin width of time difference TF1 func("Poisson", " [1]*[2] * [0] * exp(-[0] *x)", yq[0], yq[1]); func.FixParameter(2, del); func.SetParameter(0, 100); // [Hz] func.SetParameter(1, Nm); func.SetParLimits(0, 0, 1000); // [Hz] func.SetParLimits(1, 0, 10*Nm); func.SetParName(0, "lambda"); func.SetParName(1, "N0"); func.SetParName(2, "del"); // options : 0 (=zero) do not plot the function // 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("Poisson", "0IRQ"); const Double_t lambda = func.GetParameter(0); const Double_t N0 = func.GetParameter(1); // const Double_t chi2 = func.GetChisquare(); const Double_t Prob = func.GetProb(); const Int_t NDF = func.GetNDF(); // was fit successful ? if (NDF>0 && Prob>0.01 && lambda>0.0 && N0>0.0) { // start error calculation ..................... Double_t emat[2][2]; // Double_t eplus, eminus, eparab, gcc; gMinuit->mnemat(&emat[0][0], 2); // for (int m=0; m<2; m++) // { // *fLog << "emat[" << m << "][n] = "; // for (int n=0; n<2; n++) // { // *fLog << emat[m][n] << " "; // } // *fLog << endl; // } // *fLog << "eplus, eminus, eparab, gcc :" << endl; // for (int k=0; k<2; k++) // { // gMinuit->mnerrs(k, eplus, eminus, eparab, gcc); // *fLog << eplus << " " << eminus << " " << eparab << " " // << gcc << endl; // } // Rdead : fraction of real time lost by the dead time // kappa = number of observed events (Nm) divided by // the number of genuine events (N0) // Teff : effective on-time Double_t Rdead, kappa, Teff, dTeff, dldl, dl, dRdead; Double_t dN0dN0; //Double_t dldN0,lN0corr; Teff = Nm/lambda; kappa = Nm/N0; Rdead = 1.0 - kappa; dldl = emat[0][0]; dN0dN0 = emat[1][1]; // dldN0 = emat[0][1]; dTeff = Teff * sqrt(dldl/(lambda*lambda) + 1.0/Nm); dl = sqrt(dldl); dRdead = kappa * sqrt(dN0dN0/(N0*N0) + 1.0/Nm); // lN0corr = dldN0 / sqrt(dldl * dN0dN0); // *fLog << "MHEffOnTime : correlation between lambda and N0 = " // << lN0corr << endl; // end error calculation ..................... // the effective on time is Nm/lambda fHEffOn.SetBinContent(i, Teff); fHEffOn.SetBinError (i, dTeff); // plot chi2-probability of fit fHProb.SetBinContent(i, Prob); // lambda from fit fHLambda.SetBinContent(i, lambda); fHLambda.SetBinError (i, dl); // Rdead from fit fHRdead.SetBinContent(i, Rdead); fHRdead.SetBinError (i,dRdead); } //........................ // draw the distribution of time differences if requested // if (Draw == kTRUE) { char txt[100]; TString strg1(fVarname); strg1 += "-bin %d"; sprintf(txt, strg1, i); new TCanvas(txt, txt); // TCanvas &c = *MakeDefCanvas(txt, txt); // gROOT->SetSelectedPad(NULL); gPad->SetLogy(); gStyle->SetOptFit(1011); // gStyle->SetOptStat(1); h.SetName(txt); h.SetXTitle("time difference [s]"); h.SetYTitle("Counts"); h.DrawCopy(); func.SetRange(yq[0], yq[1]); // Range of Drawing func.DrawCopy("same"); // c.Modified(); // c.Update(); } //........................ } // end of 'if' loop --------------------------- delete &h; } // end of 'for' loop --------------------------- // gStyle->SetOptStat(1111); } // ------------------------------------------------------------------------- // // Set the binnings and prepare the filling of the histograms // Bool_t MHEffOnTime::SetupFill(const MParList *plist) { TString strg0("Binning"); strg0 += fVarname; const MBinning* binsVar = (MBinning*)plist->FindObject(strg0); if (!binsVar) { *fLog << err << dbginf << strg0 << " [MBinning] not found... aborting." << endl; return kFALSE; } SetBinning(&fHEffOn, binsVar); SetBinning(&fHProb, binsVar); SetBinning(&fHLambda, binsVar); SetBinning(&fHRdead, binsVar); fHEffOn.Sumw2(); fHProb.Sumw2(); fHLambda.Sumw2(); fHRdead.Sumw2(); return kTRUE; } // ------------------------------------------------------------------------- // // Dummy Fill // Bool_t MHEffOnTime::Fill(const MParContainer *par) { return kTRUE; } // ------------------------------------------------------------------------- // // Draw a copy of the histogram // TObject *MHEffOnTime::DrawClone(Option_t *opt) const { TString strg0("EffOnTime"); strg0 += fVarname; TString strg1("Results from on time fit vs. "); strg1 += fVarname; TCanvas &c = *MakeDefCanvas(strg0, strg1); c.Divide(2, 2); gROOT->SetSelectedPad(NULL); c.cd(1); ((TH2*)&fHEffOn)->DrawCopy(opt); c.cd(2); ((TH2*)&fHProb)->DrawCopy(opt); c.cd(3); ((TH2*)&fHLambda)->DrawCopy(opt); c.cd(4); ((TH2*)&fHRdead)->DrawCopy(opt); c.Modified(); c.Update(); return &c; } // ------------------------------------------------------------------------- // // Draw the histogram // void MHEffOnTime::Draw(Option_t *opt) { TString strg0("EffOnTime"); strg0 += fVarname; TString strg1("Results from on time fit vs. "); strg1 += fVarname; if (!gPad) MakeDefCanvas(strg0, strg1); gPad->Divide(2,2); gPad->cd(1); fHEffOn.Draw(opt); gPad->cd(2); fHProb.Draw(opt); gPad->cd(3); fHLambda.Draw(opt); gPad->cd(4); fHRdead.Draw(opt); gPad->Modified(); gPad->Update(); }