/* ======================================================================== *\ ! ! * ! * 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 4/2002 ! Author(s): Abelardo Moralejo 5/2003 ! Author(s): Thomas Bretz 1/2005 ! ! Copyright: MAGIC Software Development, 2000-2005 ! ! \* ======================================================================== */ ////////////////////////////////////////////////////////////////////////////// // // MHEnergyEst // // calculates the migration matrix E-est vs. E-true // for different bins in Theta // ////////////////////////////////////////////////////////////////////////////// #include "MHEnergyEst.h" #include #include #include #include "MString.h" #include "MMcEvt.hxx" #include "MEnergyEst.h" #include "MBinning.h" #include "MParList.h" #include "MParameters.h" #include "MHMatrix.h" #include "MLog.h" #include "MLogManip.h" ClassImp(MHEnergyEst); using namespace std; // -------------------------------------------------------------------------- // // Default Constructor. It sets name and title of the histogram. // MHEnergyEst::MHEnergyEst(const char *name, const char *title) : fMcEvt(0), fEnergy(0), fResult(0), fMatrix(0) { // // set the name and title of this object // fName = name ? name : "MHEnergyEst"; fTitle = title ? title : "3-D histogram E-true E-est Theta"; fHEnergy.SetDirectory(NULL); fHEnergy.SetName("EnergyEst"); fHEnergy.SetTitle("Histogram in E_{est}, E_{mc} and \\Theta"); fHEnergy.SetXTitle("E_{est} [GeV]"); fHEnergy.SetYTitle("E_{mc} [GeV]"); fHEnergy.SetZTitle("\\Theta [\\circ]"); fHResolution.SetDirectory(NULL); fHResolution.SetName("EnergyRes"); fHResolution.SetTitle("Histogram in \\frac{\\Delta E}{E_{mc}} vs E_{est} and E_{mc}"); fHResolution.SetXTitle("E_{est} [GeV]"); fHResolution.SetYTitle("E_{mc} [GeV]"); fHResolution.SetZTitle("\\frac{E_{est} - E_{mc}}{E_{mc}}"); fHImpact.SetDirectory(NULL); fHImpact.SetName("Impact"); fHImpact.SetTitle("\\frac{\\Delta E}{E} vs Impact parameter"); fHImpact.SetXTitle("Impact parameter [m]"); fHImpact.SetYTitle("\\frac{E_{est} - E_{mc}}{E_{mc}}"); fHEnergy.Sumw2(); fHImpact.Sumw2(); fHResolution.Sumw2(); MBinning binsi, binse, binst, binsr; binse.SetEdgesLog(25, 10, 10000); binst.SetEdgesCos(50, 0, 60); binsi.SetEdges(10, 0, 400); binsr.SetEdges(10, 0, 1); SetBinning(&fHEnergy, &binse, &binse, &binst); SetBinning(&fHImpact, &binsi, &binsr); SetBinning(&fHResolution, &binse, &binse, &binsr); } // -------------------------------------------------------------------------- // // Set the binnings and prepare the filling of the histograms // Bool_t MHEnergyEst::SetupFill(const MParList *plist) { if (!fMatrix) { fMcEvt = (MMcEvt*)plist->FindObject("MMcEvt"); if (!fMcEvt) { *fLog << err << "MMcEvt not found... aborting." << endl; return kFALSE; } } fEnergy = (MEnergyEst*)plist->FindObject("MEnergyEst"); if (!fEnergy) { *fLog << err << "MEnergyEst not found... aborting." << endl; return kFALSE; } fResult = (MParameterD*)const_cast(plist)->FindCreateObj("MParameterD", "MinimizationValue"); if (!fResult) return kFALSE; MBinning binst, binse, binsi, binsr; binse.SetEdges(fHEnergy, 'x'); binst.SetEdges(fHEnergy, 'z'); binsi.SetEdges(fHImpact, 'x'); binsr.SetEdges(fHImpact, 'y'); binst.SetEdges(*plist, "BinningTheta"); binse.SetEdges(*plist, "BinningEnergyEst"); binsi.SetEdges(*plist, "BinningImpact"); binsr.SetEdges(*plist, "BinningEnergyRes"); SetBinning(&fHEnergy, &binse, &binse, &binst); SetBinning(&fHImpact, &binsi, &binsr); SetBinning(&fHResolution, &binse, &binse, &binsr); fChisq = 0; return kTRUE; } // -------------------------------------------------------------------------- // // Fill the histogram // Bool_t MHEnergyEst::Fill(const MParContainer *par, const Stat_t w) { const Double_t eest = fEnergy->GetEnergy(); const Double_t etru = fMatrix ? GetVal(0) : fMcEvt->GetEnergy(); const Double_t theta = fMatrix ? GetVal(2) : fMcEvt->GetTelescopeTheta()*TMath::RadToDeg(); const Double_t imp = fMatrix ? GetVal(1) : fMcEvt->GetImpact()/100; const Double_t res = (eest-etru)/etru; fHEnergy.Fill(eest, etru, theta, w); fHResolution.Fill(eest, etru, res, w); fHImpact.Fill(imp, res, w); fChisq += res*res; return kTRUE; } Bool_t MHEnergyEst::Finalize() { fChisq /= GetNumExecutions(); fResult->SetVal(fChisq); *fLog << all << "Mean Energy Resoltuion: " << Form("%.1f%%", TMath::Sqrt(fChisq)*100) << endl; return kTRUE; } void MHEnergyEst::Paint(Option_t *opt) { TVirtualPad *pad = gPad; pad->cd(1); TH1D *hx=0; TH1D *hy=0; if (pad->GetPad(1)) { pad->GetPad(1)->cd(1); if ((hx=(TH1D*)gPad->FindObject("EnergyEst_ex"))) { TH1D *h2 = (TH1D*)fHEnergy.Project3D("dum_ex"); hx->Reset(); hx->Add(h2); delete h2; } if ((hy=(TH1D*)gPad->FindObject("EnergyEst_ey"))) { TH1D *h2 = (TH1D*)fHEnergy.Project3D("dum_ey"); hy->Reset(); hy->Add(h2); delete h2; } if (hx && hy) { hy->SetMaximum(); hy->SetMaximum(TMath::Max(hx->GetMaximum(), hy->GetMaximum())*1.2); if (hy->GetMaximum()>0) gPad->SetLogy(); } if (pad->GetPad(1)->GetPad(2)) { pad->GetPad(1)->GetPad(2)->cd(1); /*h =*/ fHImpact.ProjectionX("Impact", -1, 9999, "e"); pad->GetPad(1)->GetPad(2)->cd(2); if ((hx=(TH1D*)gPad->FindObject("EnergyEst_z"))) { TH1D *h2 = (TH1D*)fHEnergy.Project3D("dum_z"); hx->Reset(); hx->Add(h2); delete h2; } } } if (pad->GetPad(2)) { pad->GetPad(2)->cd(1); UpdatePlot(fHEnergy, "yx", kTRUE); TLine *l = (TLine*)gPad->FindObject("TLine"); if (l) { const Float_t min = TMath::Max(fHEnergy.GetXaxis()->GetXmin(), fHEnergy.GetYaxis()->GetXmin()); const Float_t max = TMath::Min(fHEnergy.GetXaxis()->GetXmax(), fHEnergy.GetYaxis()->GetXmax()); l->SetX1(min); l->SetX2(max); l->SetY1(min); l->SetY2(max); } pad->GetPad(2)->cd(2); UpdatePlot(fHResolution, "zy"); pad->GetPad(2)->cd(3); UpdatePlot(fHResolution, "zx"); } } void MHEnergyEst::UpdatePlot(TH3 &h, const char *how, Bool_t logy) { TH2D *hyx=0; if (!(hyx=(TH2D*)gPad->FindObject(MString::Form("%s_%s", h.GetName(), how)))) return; TH2D *h2 = (TH2D*)h.Project3D(MString::Form("dum_%s", how)); hyx->Reset(); hyx->Add(h2); delete h2; TH1D *hx = 0; if ((hx=(TH1D*)gPad->FindObject("Prof"))) { hx = hyx->ProfileX("Prof", -1, 9999, "s"); if (logy && hx->GetMaximum()>0) gPad->SetLogy(); } } TH1 *MHEnergyEst::MakePlot(TH3 &h, const char *how) { gPad->SetBorderMode(0); gPad->SetLogx(); gROOT->GetListOfCleanups()->Add(gPad); // WHY? TH2D *h2 = (TH2D*)h.Project3D(how); TH1D *h1 = h2->ProfileX("Prof", -1, 9999, "s"); h1->SetDirectory(NULL); //h1->SetBit(kCanDelete); h1->SetLineWidth(2); h1->SetLineColor(kRed); // PROBLEM! h1->SetStats(kFALSE); h2->SetDirectory(NULL); h2->SetBit(kCanDelete); h2->SetFillColor(kBlue); h1->Draw("E3"); h2->Draw("boxsame"); h1->Draw("Chistsame"); return h1; } // -------------------------------------------------------------------------- // // Draw the histogram // void MHEnergyEst::Draw(Option_t *opt) { TVirtualPad *pad = gPad ? gPad : MakeDefCanvas(this); // Do the projection before painting the histograms into // the individual pads AppendPad(""); pad->SetBorderMode(0); pad->Divide(2, 1, 0, 0); TH1 *h; pad->cd(1); gPad->SetBorderMode(0); gPad->Divide(1, 2, 0, 0); TVirtualPad *pad2 = gPad; pad2->cd(1); gPad->SetBorderMode(0); gPad->SetLogx(); h = (TH1D*)fHEnergy.Project3D("ey"); h->SetBit(TH1::kNoStats); h->SetTitle("Energy disribution: Monte Carlo E_{mc} (black), Estimated E_{est} (green)"); h->SetXTitle("E [GeV]"); // E_mc h->SetYTitle("Counts"); h->SetBit(kCanDelete); h->SetDirectory(NULL); h->SetMarkerStyle(kFullDotMedium); h->Draw(); h = (TH1D*)fHEnergy.Project3D("ex"); h->SetBit(TH1::kNoTitle|TH1::kNoStats); h->SetXTitle("E [GeV]"); // E_est h->SetYTitle("Counts"); h->SetBit(kCanDelete); h->SetDirectory(NULL); h->SetMarkerStyle(kFullDotMedium); h->SetLineColor(kGreen); h->SetMarkerColor(kGreen); h->Draw("same"); // FIXME: LEGEND pad2->cd(2); gPad->SetBorderMode(0); TVirtualPad *pad3 = gPad; pad3->Divide(2, 1, 0, 0); pad3->cd(1); gPad->SetBorderMode(0); h = fHImpact.ProjectionX("Impact", -1, 9999, "e"); h->SetBit(TH1::kNoStats); h->SetTitle("Distribution of Impact"); h->SetDirectory(NULL); h->SetXTitle("Impact [m]"); h->SetBit(kCanDelete); h->Draw(); pad3->cd(2); gPad->SetBorderMode(0); h = fHEnergy.Project3D("ez"); h->SetTitle("Distribution of Theta"); h->SetBit(TH1::kNoStats); h->SetDirectory(NULL); h->SetXTitle("\\Theta [\\circ]"); h->SetBit(kCanDelete); h->Draw(); pad->cd(2); gPad->SetBorderMode(0); gPad->Divide(1, 3, 0, 0); pad2 = gPad; pad2->cd(1); h = MakePlot(fHEnergy, "yx"); h->SetXTitle("E_{mc} [GeV]"); h->SetYTitle("E_{est} [GeV]"); h->SetTitle("Estimated energy E_{est} vs Monte Carlo energy E_{mc}"); TLine line; line.DrawLine(0,0,1,1); pad2->cd(2); h = MakePlot(fHResolution, "zy"); h->SetXTitle("E_{mc} [GeV]"); h->SetYTitle("\\frac{E_{est} - E_{mc}}{E_{mc}}"); h->SetTitle("Energy resolution \\Delta E / E vs Monte Carlo energy E_{mc}"); h->SetMinimum(0); h->SetMaximum(1); pad2->cd(3); h = MakePlot(fHResolution, "zx"); h->SetXTitle("E_{est} [GeV]"); h->SetYTitle("\\frac{E_{est} - E_{mc}}{E_{mc}}"); h->SetTitle("Energy Resolution \\Delta E / E vs estimated Energy E_{est}"); h->SetMinimum(0); h->SetMaximum(1); } // -------------------------------------------------------------------------- // // Returns the mapped value from the Matrix // Double_t MHEnergyEst::GetVal(Int_t i) const { return (*fMatrix)[fMap[i]]; } // -------------------------------------------------------------------------- // // You can use this function if you want to use a MHMatrix instead of the // given containers. This function adds all necessary columns to the // given matrix. Afterward you should fill the matrix with the corresponding // data (eg from a file by using MHMatrix::Fill). If you now loop // through the matrix (eg using MMatrixLoop) MEnergyEstParam2::Process // will take the values from the matrix instead of the containers. // void MHEnergyEst::InitMapping(MHMatrix *mat) { if (fMatrix) return; fMatrix = mat; fMap[0] = fMatrix->AddColumn("MMcEvt.fEnergy"); fMap[1] = fMatrix->AddColumn("MMcEvt.fImpact/100"); fMap[2] = fMatrix->AddColumn("MMcEvt.fTelescopeTheta*kRad2Deg"); } void MHEnergyEst::StopMapping() { fMatrix = NULL; }