/* ======================================================================== *\ ! ! * ! * 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, 07/2005 ! ! Copyright: MAGIC Software Development, 2000-2005 ! ! \* ======================================================================== */ ///////////////////////////////////////////////////////////////////////////// // // MHPhi // // Plot delta phi the angle between the reconstructed shower origin and // the source position. // // More detail can be found at: // http://www.astro.uni-wuerzburg.de/results/ringmethod/ // // Class Version 2: // + TH1D fHPhi; // Phi plot of the signal w.r.t. source // + TH1D fHPhiOff; // Phi plot of the signal w.r.t. source+180deg // + TH1D fHTemplate; // Template how the background should look in the ideal case // // + TH1D fHInhom; // Phi plot off the signal w.r.t. source (out of the ring with the signal) // + TH1D fHInhomOff; // Phi plot off the signal w.r.t. source+180deg (out of the ring with the signal) // // + Int_t fNumBinsSignal; // Number of bins for signal region // + Float_t fThetaCut; // Theta cut // + Float_t fDistSrc; // Nominal distance of source from center in wobble // // + Bool_t fUseAntiPhiCut; // Whether to use a anti-phi cut or not // //////////////////////////////////////////////////////////////////////////// #include "MHPhi.h" #include #include #include #include #include #include "MLog.h" #include "MLogManip.h" #include "MParList.h" #include "MHillas.h" #include "MSrcPosCam.h" #include "MParameters.h" #include "MGeomCam.h" #include "MBinning.h" #include "MMath.h" ClassImp(MHPhi); using namespace std; // -------------------------------------------------------------------------- // // Setup histograms // MHPhi::MHPhi(const char *name, const char *title) : fHillas(0), fSrcPos(0), fDisp(0), fNumBinsSignal(2), fThetaCut(0.23), fDistSrc(0.4), fUseAntiPhiCut(kTRUE) { fName = name ? name : "MHPhi"; fTitle = title ? title : "Graphs for rate data"; // Init Graphs fHPhi.SetNameTitle("Phi", "\\Delta\\Phi-Distribution"); fHPhi.SetXTitle("\\Delta\\Phi' [\\circ]"); fHPhi.SetYTitle("Counts"); fHPhi.SetMinimum(0); fHPhi.SetDirectory(0); fHPhi.Sumw2(); fHPhi.SetBit(TH1::kNoStats); fHPhi.SetMarkerStyle(kFullDotMedium); fHPhi.SetLineColor(kBlue); fHPhi.SetMarkerColor(kBlue); fHPhi.GetYaxis()->SetTitleOffset(1.3); fHPhiOff.SetMinimum(0); fHPhiOff.SetDirectory(0); fHPhiOff.Sumw2(); fHPhiOff.SetBit(TH1::kNoStats); fHPhiOff.SetLineColor(kRed); fHPhiOff.SetMarkerColor(kRed); fHTemplate.SetMinimum(0); fHTemplate.SetDirectory(0); fHTemplate.SetBit(TH1::kNoStats); fHTemplate.SetLineColor(kGreen); fHInhom.SetNameTitle("Inhomogeneity", "\\Delta\\Phi-Distribution"); fHInhom.SetXTitle("\\Delta\\Phi' [\\circ]"); fHInhom.SetYTitle("Counts"); fHInhom.Sumw2(); fHInhom.SetMinimum(0); fHInhom.SetDirectory(0); fHInhom.SetBit(TH1::kNoStats); fHInhom.GetYaxis()->SetTitleOffset(1.3); fHInhomOff.Sumw2(); fHInhomOff.SetMinimum(0); fHInhomOff.SetDirectory(0); fHInhomOff.SetBit(TH1::kNoStats); fHInhomOff.SetLineColor(kRed); fHInhomOff.SetMarkerColor(kRed); } // -------------------------------------------------------------------------- // // Setup the Binning for the histograms automatically if the correct // instances of MBinning // Bool_t MHPhi::SetupFill(const MParList *plist) { fHillas = (MHillas*)plist->FindObject("MHillas"); if (!fHillas) { *fLog << err << "MHillas not found... abort." << endl; return kFALSE; } fSrcPos = (MSrcPosCam*)plist->FindObject("MSrcPosCam"); if (!fSrcPos) { *fLog << err << "MSrcPosCam not found... abort." << endl; return kFALSE; } fDisp = (MParameterD*)plist->FindObject("Disp", "MParameterD"); if (!fDisp) { *fLog << err << "Disp [MParameterD] not found... abort." << endl; return kFALSE; } MGeomCam *geom = (MGeomCam*)plist->FindObject("MGeomCam"); if (!geom) { *fLog << err << "MGeomCam not found... abort." << endl; return kFALSE; } fConvMm2Deg = geom->GetConvMm2Deg(); MParameterD *cut = (MParameterD*)plist->FindObject("ThetaSquaredCut", "MParameterD"); if (!cut) *fLog << warn << "ThetaSquareCut [MParameterD] not found... using default theta<" << fThetaCut << "." << endl; else fThetaCut = TMath::Sqrt(cut->GetVal()); const Double_t w = TMath::ATan(fThetaCut/fDistSrc); const Float_t sz = TMath::RadToDeg()*w/fNumBinsSignal; const Int_t n = TMath::Nint(TMath::Ceil(180/sz)); MBinning(n+3, 0, (n+3)*sz).Apply(fHPhi); MBinning(n+3, 0, (n+3)*sz).Apply(fHPhiOff); MBinning(n+3, 0, (n+3)*sz).Apply(fHTemplate); MBinning(n+3, 0, (n+3)*sz).Apply(fHInhom); MBinning(n+3, 0, (n+3)*sz).Apply(fHInhomOff); return kTRUE; } // -------------------------------------------------------------------------- // // Fill the histograms with data from a MMuonCalibPar and // MMuonSearchPar container. // Int_t MHPhi::Fill(const MParContainer *par, const Stat_t weight) { // Here we calculate an upper phi cut to take a // possible anti-theta cut into account const Double_t ulim = fUseAntiPhiCut ? 180-fHPhi.GetBinLowEdge(fNumBinsSignal+1)*1.1 : 180; // Calculate the shower origin and the source position in units of deg const TVector2 pos = fHillas->GetMean()*fConvMm2Deg + fHillas->GetNormAxis()*fDisp->GetVal(); const TVector2 src = fSrcPos->GetXY()*fConvMm2Deg; // Calculate radial distance between shower origin and source const Double_t d = pos.Mod() - src.Mod(); // define an upper and lower cut for the radial distance between both const Double_t dR = fThetaCut; const Double_t dr = fThetaCut*0.913; // calculate the phi-angle of the shower origin w.r.t. the source position const Double_t delta = src.DeltaPhi(pos)*TMath::RadToDeg(); // Define the radii of the upper and lower ring border const Double_t R = src.Mod()+dR; const Double_t r = src.Mod()-dr; // Calculate a scale to scale all source positions to the // nominal distance to center const Double_t scale = src.Mod()/fDistSrc; // Fill a phi-histograms with all events outside the ring // Take the upper phi cut into account if ((d<-dr || d>dR)/*TMath::Abs(d)>fThetaCut*1.2*/ && TMath::Abs(delta)dR) return kTRUE; // Fill the histograms for on and off with the scaled phi // only if we are below the upper phi cut if (TMath::Abs(delta)SetBorderMode(0); AppendPad("update"); pad->Divide(2,2); // -------------------------- pad->cd(1); gPad->SetBorderMode(0); gPad->SetFrameBorderMode(0); fHPhi.Draw(); fHPhiOff.Draw("same"); TH1D *h1 = new TH1D(fHTemplate); h1->SetName("Template"); h1->SetBit(kCanDelete); h1->SetDirectory(0); h1->Draw("same"); AppendPad("result1"); // -------------------------- pad->cd(2); gPad->SetBorderMode(0); gPad->SetFrameBorderMode(0); fHInhom.Draw(); fHInhomOff.Draw("same"); TH1D *h2 = new TH1D(fHTemplate); h2->SetName("Template"); h2->SetBit(kCanDelete); h2->SetDirectory(0); h2->Draw("same"); // -------------------------- pad->cd(3); gPad->SetBorderMode(0); gPad->SetFrameBorderMode(0); fHPhi.Draw(); TH1D *h4 = new TH1D(fHInhom); h4->SetName("Inhomogeneity"); h4->SetBit(kCanDelete); h4->SetDirectory(0); h4->Draw("same"); h1->Draw("same"); // -------------------------- pad->cd(4); gPad->SetBorderMode(0); gPad->SetFrameBorderMode(0); TH1D *h3 = new TH1D(fHPhi); h3->SetName("Result"); h3->SetBit(kCanDelete); h3->SetDirectory(0); h3->Draw(); h1->Draw("same"); AppendPad("result4"); // -------------------------- } void MHPhi::PaintUpdate() const { TVirtualPad *pad1 = gPad->GetPad(1); TVirtualPad *pad2 = gPad->GetPad(2); TVirtualPad *pad3 = gPad->GetPad(3); TVirtualPad *pad4 = gPad->GetPad(4); Double_t sig2 = 0; Double_t bg2 = 0; Double_t f2 = 1; TH1D *htemp = pad1 ? dynamic_cast(pad1->FindObject("Template")) : NULL; if (htemp) { fHTemplate.Copy(*htemp); htemp->SetName("Template"); htemp->SetDirectory(0); Double_t sc1 = 1; Double_t sc2 = 1; TH1D *res = pad4 ? dynamic_cast(pad4->FindObject("Result")) : NULL; if (res) { fHPhi.Copy(*res); // Scale inhomogeneity to match the phi-plot in the off-region sc1 = res->Integral(fNumBinsSignal+1, 9999)/fHInhom.Integral(fNumBinsSignal+1, 9999); // Scale inhomogeneity to match the phi-plot in the off-region sc2 = fHInhom.Integral()/htemp->Integral(); res->Add(&fHInhom, -sc1); res->Add(htemp, sc1*sc2); res->SetName("Result"); res->SetDirectory(0); htemp->Scale(res->Integral(fNumBinsSignal+1, 9999)/htemp->Integral(fNumBinsSignal+1, 9999)); sig2 = res->Integral(1, fNumBinsSignal); bg2 = fHPhi.Integral(fNumBinsSignal+1, 9999); f2 = htemp->Integral(1, fNumBinsSignal)/htemp->Integral(fNumBinsSignal+1, 9999); } TH1D *hinhom = pad3 ? dynamic_cast(pad3->FindObject("Inhomogeneity")) : NULL; if (hinhom) { fHInhom.Copy(*hinhom); hinhom->SetName("Inhomogeneity"); hinhom->SetDirectory(0); hinhom->Scale(sc1); } } htemp = pad2 ? dynamic_cast(pad2->FindObject("Template")) : NULL; if (htemp) { fHTemplate.Copy(*htemp); htemp->Scale(fHInhom.Integral()/htemp->Integral()); htemp->SetName("Template"); htemp->SetDirectory(0); } } void MHPhi::PaintText(const TH1D &res) const { const Double_t cut = res.GetBinLowEdge(fNumBinsSignal+1); const Double_t sig = res.Integral(1, fNumBinsSignal); const Double_t bg = res.Integral(fNumBinsSignal+1, 9999); const Double_t f = fHTemplate.Integral(1, fNumBinsSignal)/fHTemplate.Integral(fNumBinsSignal+1, 9999); const Double_t S0 = MMath::SignificanceLiMaSigned(sig, bg*f); const Double_t S = MMath::SignificanceLiMaSigned(sig, bg, f); const TString fmt = Form("\\sigma_{L/M}=%.1f (\\sigma_{0}=%.1f) \\Delta\\Phi_{on}<%.1f\\circ E=%.0f B=%.0f f=%.2f", S, S0, cut, sig-bg*f, bg*f, f); const Double_t b = bg *f/fNumBinsSignal; const Double_t e = TMath::Sqrt(bg)*f/fNumBinsSignal; TLatex text(0.275, 0.95, fmt); text.SetBit(TLatex::kTextNDC); text.SetTextSize(0.042); text.Paint(); TLine line; line.SetLineColor(14); line.PaintLine(cut, gPad->GetUymin(), cut, gPad->GetUymax()); // Here we calculate an upper phi cut to take a // possible anti-theta cut into account const Double_t ulim = fUseAntiPhiCut ? 180-fHPhi.GetBinLowEdge(fNumBinsSignal+1)*1.1 : 180; line.SetLineStyle(kDotted); line.PaintLine(ulim, gPad->GetUymin(), ulim, gPad->GetUymax()); line.SetLineStyle(kSolid); line.SetLineColor(kBlack); line.PaintLine(0, b, cut, b); line.PaintLine(cut/2, b-e, cut/2, b+e); line.SetLineStyle(kDashed); line.PaintLine(cut, b, fHPhi.GetXaxis()->GetXmax(), b); TMarker m; m.SetMarkerStyle(kFullDotMedium); m.PaintMarker(cut/2, b); } void MHPhi::Paint(Option_t *o) { TString opt(o); if (opt=="update") PaintUpdate(); if (opt=="result1") PaintText(fHPhi); if (opt=="result4") { TH1D *res = gPad ? dynamic_cast(gPad->FindObject("Result")) : NULL; if (res) PaintText(*res); } } Int_t MHPhi::ReadEnv(const TEnv &env, TString prefix, Bool_t print) { Bool_t rc = kFALSE; if (IsEnvDefined(env, prefix, "NumBinsSignal", print)) { SetNumBinsSignal(GetEnvValue(env, prefix, "NumBinsSignal", (Int_t)fNumBinsSignal)); rc = kTRUE; } if (IsEnvDefined(env, prefix, "UseAntiPhiCut", print)) { SetUseAntiPhiCut(GetEnvValue(env, prefix, "UseAntiPhiCut", (Int_t)fUseAntiPhiCut)); rc = kTRUE; } return rc; }