/* ======================================================================== *\ ! ! * ! * 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, 09/2002 ! Abelardo Moralejo, 03/2003 ! ! Copyright: MAGIC Software Development, 2000-2002 ! ! \* ======================================================================== */ // // fcn is the function to be minimized using TMinuit::Migrad // void fcn(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag) { MEvtLoop *evtloop = (MEvtLoop*)gMinuit->GetObjectFit(); MTaskList *tlist = (MTaskList*)evtloop->GetParList()->FindObject("MTaskList"); // GetTaskList(); MChisqEval *eval = (MChisqEval*) tlist->FindObject("MChisqEval"); MEnergyEstParam *eest = (MEnergyEstParam*)tlist->FindObject("MEnergyEstParam"); eest->SetCoeff(TArrayD(eest->GetNumCoeff(), par)); evtloop->Eventloop(); f = eval->GetChisq(); } //------------------------------------------------------------------------ void CT1EnergyEst(Float_t maxhadronness=0.22, Float_t maxdist = 1.) { // // Upper cut in Maxdist taken from D. Kranich's Ph D. // We have to convert maxdist from degrees to mm: // MGeomCamCT1 gct1; maxdist /= gct1.GetConvMm2Deg(); // // Fill events into a MHMatrix // MParList parlist; MHMatrix matrix; // // colenergy and colimpact are the indexes of the matrix columns containing // the MC energy and impact parameter. // Int_t colenergy = matrix.AddColumn("MMcEvt.fEnergy"); Int_t colimpact = matrix.AddColumn("MMcEvt.fImpact"); MEnergyEstParam eest("Hillas"); eest.Add("HillasSrc"); eest.InitMapping(&matrix); // // Here we read in the events for the training. Second argument of AddFile is // the number of events. With 2000 it is rather fast, but only the lowest zenith // angles will enter in the minimization. // MReadTree read("Events"); read.AddFile("MC_ON2.root",2000); read.DisableAutoScheme(); // // Filter to keep the most gamma-like events: // TString hcut("MHadronness.fHadronness<"); hcut += maxhadronness; hcut += " && HillasSrc.fDist < "; hcut += maxdist; MF filterhadrons(hcut); // // Fill the matrix used later in the minimization loop by Minuit: // if (!matrix.Fill(&parlist, &read, &filterhadrons)) return; // // Setup the tasklist used to evaluate the needed chisq // MTaskList tasklist; parlist.AddToList(&tasklist); MMatrixLoop loop(&matrix); MChisqEval eval; eval.SetY1(new MDataElement(&matrix, colenergy)); eval.SetY2(new MDataMember("MEnergyEst.fEnergy")); eval.SetOwner(); tasklist.AddToList(&loop); tasklist.AddToList(&eest); tasklist.AddToList(&eval); MEvtLoop evtloop; evtloop.SetParList(&parlist); // // Be careful: This is not thread safe // TMinuit minuit(12); minuit.SetPrintLevel(-1); minuit.SetFCN(fcn); // Ready for: minuit.mnexcm("SET ERR", arglist, 1, ierflg) if (minuit.SetErrorDef(1)) { cout << "SetErrorDef failed." << endl; return; } // // Set initial values of the parameters (close enough to the final ones, taken // from previous runs of the procedure). Parameter fA[4] is not used in the default // energy estimation model (from D. Kranich). // TArrayD fA(5); TArrayD fB(7); fA[0] = 21006.2; fA[1] = -43.2648; fA[2] = -690.403; fA[3] = -0.0428544; fA[4] = 1.; fB[0] = -3391.05; fB[1] = 136.58; fB[2] = 0.253807; fB[3] = 254.363; fB[4] = 61.0386; fB[5] = -0.0190984; fB[6] = -421695; // // Set starting values and step sizes for parameters // for (Int_t i=0; iWrite("EnergyParams"); out.Close(); // // End of Part 1 (estimation of the parameters) // //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// // // Part 2: Now test how the energy estimation method works. // // // Create a empty Parameter List and an empty Task List // The tasklist is identified in the eventloop by its name // MTaskList tlist2; MParList parlist2; parlist2.AddToList(&tlist2); // // Now setup the tasks and tasklist: // --------------------------------- // MReadTree read2("Events"); read2.AddFile("MC_ON2.root"); read2.DisableAutoScheme(); // // Create some histograms to display the results: // MH3 mh3ed("log10(MMcEvt.fEnergy)", "MEnergyEst.fEnergy/MMcEvt.fEnergy-1"); MH3 mh3ed2("log10(MEnergyEst.fEnergy)", "MEnergyEst.fEnergy/MMcEvt.fEnergy-1"); MH3 mhe("log10(MMcEvt.fEnergy)", "log10(MEnergyEst.fEnergy)"); MFillH hfilled(&mh3ed); MFillH hfilled2(&mh3ed2); MFillH hfillee(&mhe); mhe.SetName("HistEE"); mh3ed.SetName("HistEnergyDelta"); mh3ed2.SetName("HistEnergyDelta"); MBinning binsedx("BinningHistEnergyDeltaX"); MBinning binsedy("BinningHistEnergyDeltaY"); MBinning binseex("BinningHistEEX"); MBinning binseey("BinningHistEEY"); binsedx.SetEdges(25, 2.5, 5.); binsedy.SetEdges(30, -1., 1.); binseex.SetEdges(25, 2.5, 5.); binseey.SetEdges(30, 2., 5.); parlist2.AddToList(&binsedx); parlist2.AddToList(&binsedy); parlist2.AddToList(&binseex); parlist2.AddToList(&binseey); // // Create energy estimator task, add necessary containers and // initialize parameters read from file: // MEnergyEstParam eest2("Hillas"); eest2.Add("HillasSrc"); TFile enparam("energyest.root"); TArrayD parA(5); TArrayD parB(7); for (Int_t i=0; i"); hcut2 += maxhadronness; hcut2 += "|| HillasSrc.fDist > "; hcut2 += maxdist; MContinue cont(hcut2); tlist2.AddToList(&cont); tlist2.AddToList(&eest2); // tlist2.AddToList(new MPrint("MMcEvt")); // tlist2.AddToList(new MPrint("MEnergyEst")); tlist2.AddToList(&hfilled); tlist2.AddToList(&hfilled2); tlist2.AddToList(&hfillee); // // Create and setup the eventloop // MProgressBar bar; MEvtLoop evtloop2; evtloop2.SetProgressBar(&bar); evtloop2.SetParList(&parlist2); // // Execute your analysis // if (!evtloop2.Eventloop()) return; // // Plot results: // mhe.GetHist()->GetXaxis()->SetTitle("log_{10} E_{MC} (GeV)"); mhe.GetHist()->GetYaxis()->SetTitle("log_{10} E_{EST} (GeV)"); mhe.GetHist()->GetXaxis()->SetTitleOffset(1.2); TCanvas *c = new TCanvas("energy","CT1 Energy estimation"); c->Divide(2,2); c->cd(1); energy_1->SetBottomMargin(0.12); mhe.DrawClone("PROFXnonew"); mh3ed.GetHist()->GetXaxis()->SetTitle("log_{10} E_{MC} (GeV)"); mh3ed.GetHist()->GetYaxis()->SetTitle("\\frac{E_{EST} - E_{MC}}{E_{MC}}"); mh3ed.GetHist()->GetXaxis()->SetTitleOffset(1.2); mh3ed.GetHist()->GetYaxis()->SetTitleOffset(1.5); c->cd(2); energy_2->SetLeftMargin(0.15); energy_2->SetBottomMargin(0.12); mh3ed.DrawClone("PROFXnonew"); mh3ed2.GetHist()->GetXaxis()->SetTitle("log_{10} E_{EST} (GeV)"); mh3ed2.GetHist()->GetYaxis()->SetTitle("\\frac{E_{EST} - E_{MC}}{E_{MC}}"); mh3ed2.GetHist()->GetXaxis()->SetTitleOffset(1.2); mh3ed2.GetHist()->GetYaxis()->SetTitleOffset(1.5); c->cd(3); energy_3->SetLeftMargin(0.15); energy_3->SetBottomMargin(0.12); mh3ed2.DrawClone("PROFXnonew"); ((TH2*)mh3ed2.GetHist())->ProjectionY("deltae"); c->cd(4); energy_4->SetLeftMargin(0.1); energy_4->SetRightMargin(0.05); energy_4->SetBottomMargin(0.12); deltae.GetXaxis()->SetTitleOffset(1.2); deltae.GetXaxis()->SetTitle("(E_{EST} - E_{MC}) / E_{MC}"); deltae.Draw("e"); TFile out2("energyest.root", "update"); ((TH2*)mh3ed.GetHist())->Write("mh3ed"); ((TH2*)mh3ed2.GetHist())->Write("mh3ed2"); ((TH2*)mhe.GetHist())->Write("mhe"); deltae.Write(); out2.Close(); return; }