/* ======================================================================== *\ ! ! * ! * 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, 4/2005 ! ! Copyright: MAGIC Software Development, 2000-2005 ! ! \* ======================================================================== */ ///////////////////////////////////////////////////////////////////////////// // // MJSpectrum // // Program to calculate spectrum // ///////////////////////////////////////////////////////////////////////////// #include "MJSpectrum.h" // Root #include #include #include #include #include #include #include // Environment #include "MLog.h" #include "MLogManip.h" #include "MStatusArray.h" #include "MStatusDisplay.h" // Container #include "MH3.h" #include "MBinning.h" #include "MDataSet.h" // Spectrum #include "../mhflux/MAlphaFitter.h" #include "../mhflux/MHAlpha.h" #include "../mhflux/MHCollectionArea.h" #include "../mhflux/MHEnergyEst.h" // Eventloop #include "MEvtLoop.h" #include "MTaskList.h" #include "MParList.h" // Tasks/Filter #include "MReadMarsFile.h" #include "MReadMarsFile.h" #include "MFEventSelector2.h" #include "MFDataMember.h" #include "MEnergyEstimate.h" #include "MTaskEnv.h" #include "MFillH.h" #include "MHillasCalc.h" #include "MSrcPosCalc.h" #include "MContinue.h" ClassImp(MJSpectrum); using namespace std; MJSpectrum::MJSpectrum(const char *name, const char *title) : fCut0(0),fCut1(0), fCut2(0), fCut3(0), fEstimateEnergy(0), fRefill(kFALSE), fSimpleMode(kTRUE), fRawMc(kFALSE) { fName = name ? name : "MJSpectrum"; fTitle = title ? title : "Standard program to calculate spectrum"; } MJSpectrum::~MJSpectrum() { if (fCut0) delete fCut0; if (fCut1) delete fCut1; if (fCut2) delete fCut2; if (fCut3) delete fCut3; if (fEstimateEnergy) delete fEstimateEnergy; } // -------------------------------------------------------------------------- // // Setup a task estimating the energy. The given task is cloned. // void MJSpectrum::SetEnergyEstimator(const MTask *task) { if (fEstimateEnergy) delete fEstimateEnergy; fEstimateEnergy = task ? (MTask*)task->Clone() : 0; } Bool_t MJSpectrum::ReadTask(MTask* &task, const char *name) const { if (task) { delete task; task = 0; } task = (MTask*)gFile->Get(name); if (!task) { *fLog << err << dbginf << "ERROR - " << name << " doen't exist in file!" << endl; return kFALSE; } if (!task->InheritsFrom(MTask::Class())) { *fLog << err << dbginf << "ERROR - " << name << " read doesn't inherit from MTask!" << endl; delete task; return kFALSE; } task->SetName(name); return kTRUE; } void MJSpectrum::PrintSetup(const MAlphaFitter &fit) const { fLog->Separator("Alpha Fitter"); *fLog << all; fit.Print(); fLog->Separator("Used Cuts"); fCut0->Print(); fCut1->Print(); fCut2->Print(); fCut3->Print(); //gLog.Separator("Energy Estimator"); //fEstimateEnergy->Print(); } Float_t MJSpectrum::ReadInput(MParList &plist, TH1D &h1, TH1D &h2) { *fLog << inf << "Reading from file: " << fPathIn << endl; TFile file(fPathIn, "READ"); if (!file.IsOpen()) { *fLog << err << dbginf << "ERROR - Could not open file " << fPathIn << endl; return -1; } MStatusArray arr; if (arr.Read()<=0) { *fLog << "MStatusDisplay not found in file... abort." << endl; return -1; } TH1D *vstime = (TH1D*)arr.FindObjectInCanvas("Theta", "TH1D", "OnTime"); TH1D *size = (TH1D*)arr.FindObjectInCanvas("Excess", "TH1D", "Hist"); if (!vstime || !size) return -1; vstime->Copy(h1); size->Copy(h2); h1.SetDirectory(0); h2.SetDirectory(0); if (fDisplay) arr.DisplayIn(*fDisplay, "Hist"); if (!ReadTask(fCut0, "Cut0")) return -1; if (!ReadTask(fCut1, "Cut1")) return -1; if (!ReadTask(fCut2, "Cut2")) return -1; if (!ReadTask(fCut3, "Cut3")) return -1; TObjArray arrread; TIter Next(plist); TObject *o=0; while ((o=Next())) if (o->InheritsFrom(MBinning::Class())) arrread.Add(o); arrread.Add(plist.FindObject("MAlphaFitter")); if (!ReadContainer(arrread)) return -1; return vstime->Integral(); } Bool_t MJSpectrum::ReadOrigMCDistribution(const MDataSet &set, TH1 &h) const { // Some debug output fLog->Separator("Compiling original MC distribution"); *fLog << inf << "Please stand by, this may take a while..." << flush; if (fDisplay) fDisplay->SetStatusLine1("Compiling MC distribution..."); // Create chain TChain chain("OriginalMC"); set.AddFilesOn(chain); // Prepare histogram h.Reset(); // Fill histogram from chain h.SetDirectory(gROOT); if (h.InheritsFrom(TH2::Class())) { h.SetNameTitle("ThetaEMC", "Event-Distribution vs Theta and Energy for MC (produced)"); h.SetXTitle("\\Theta [\\circ]"); h.SetYTitle("E [GeV]"); h.SetZTitle("Counts"); chain.Draw("MMcEvtBasic.fEnergy:MMcEvtBasic.fTelescopeTheta*TMath::RadToDeg()>>ThetaEMC", "", "goff"); } else { h.SetNameTitle("ThetaMC", "Event-Distribution vs Theta for MC (produced)"); h.SetXTitle("\\Theta [\\circ]"); h.SetYTitle("Counts"); chain.Draw("MMcEvtBasic.fTelescopeTheta*TMath::RadToDeg()>>ThetaMC", "", "goff"); } h.SetDirectory(0); *fLog << "done." << endl; if (fDisplay) fDisplay->SetStatusLine2("done."); if (h.GetEntries()>0) return kTRUE; *fLog << err << "ERROR - Histogram with original MC distribution empty..." << endl; return h.GetEntries()>0; } Bool_t MJSpectrum::GetThetaDistribution(TH1D &temp1, TH1D &temp2) const { // Display some stuff if (fDisplay) { TCanvas &c = fDisplay->AddTab("ZdDist"); c.Divide(2,2); // On-Time vs. Theta c.cd(1); gPad->SetBorderMode(0); temp1.DrawCopy(); // Number of MC events (produced) vs Theta c.cd(2); gPad->SetBorderMode(0); temp2.SetName("NVsTheta"); temp2.DrawCopy(); c.cd(4); gPad->SetBorderMode(0); c.cd(3); gPad->SetBorderMode(0); } // Calculate the Probability temp1.Divide(&temp2); temp1.Scale(1./temp1.GetMaximum()); // Some cosmetics: Name, Axis, etc. temp1.SetName("ProbVsTheta"); temp1.SetTitle("Probability vs. Zenith Angle to choose MC events"); temp1.SetYTitle("Probability"); if (fDisplay) temp1.DrawCopy(); return kTRUE; } void MJSpectrum::DisplayResult(const TH2D &h2) const { if (!fDisplay || !fDisplay->CdCanvas("ZdDist")) return; TH1D &proj = *h2.ProjectionX(); proj.SetNameTitle("ThetaFinal", "Final Theta Distribution"); proj.SetXTitle("\\Theta [\\circ]"); proj.SetYTitle("Counts"); proj.SetLineColor(kBlue); proj.SetDirectory(0); proj.SetBit(kCanDelete); TVirtualPad *pad = gPad; pad->cd(4); proj.DrawCopy(); pad->cd(1); TH1D *theta = (TH1D*)gPad->FindObject("Theta"); if (theta) { proj.Scale(theta->GetMaximum()/proj.GetMaximum()); theta->SetMaximum(1.05*TMath::Max(theta->GetMaximum(), proj.GetMaximum())); } proj.Draw("same"); } Bool_t MJSpectrum::Refill(MParList &plist, TH1D &h2) const { // Try to find the class used to determin the signal! TString cls("MHAlpha"); if (fDisplay) { TCanvas *c = fDisplay->GetCanvas("Hist"); if (c) { TIter Next(c->GetListOfPrimitives()); TObject *obj=0; while ((obj=Next())) if (obj->InheritsFrom(MHAlpha::Class())) break; if (obj) cls = obj->ClassName(); } } cout << "FOUND: "<< cls << endl; // Now fill the histogram *fLog << endl; fLog->Separator("Refill Excess"); *fLog << endl; MTaskList tlist; plist.AddToList(&tlist); MReadTree read("Events"); read.DisableAutoScheme(); read.AddFile(fPathIn); MEnergyEstimate est; MTaskEnv taskenv1("EstimateEnergy"); taskenv1.SetDefault(fEstimateEnergy ? fEstimateEnergy : &est); MFillH fill1(Form("HistEOff [%s]", cls.Data()), "", "FillHistEOff"); MFillH fill2(Form("HistE [%s]", cls.Data()), "", "FillHistE"); MFDataMember f0("DataType.fVal", '<', 0.5, "FilterOffData"); MFDataMember f1("DataType.fVal", '>', 0.5, "FilterOnData"); fill1.SetFilter(&f0); fill2.SetFilter(&f1); tlist.AddToList(&read); tlist.AddToList(&taskenv1); tlist.AddToList(&f0); tlist.AddToList(&f1); tlist.AddToList(&fill1); tlist.AddToList(&fill2); MEvtLoop loop(fName); loop.SetParList(&plist); loop.SetDisplay(fDisplay); loop.SetLogStream(fLog); if (!SetupEnv(loop)) return kFALSE; if (!loop.Eventloop()) { *fLog << err << GetDescriptor() << ": Refilling of data failed." << endl; return kFALSE; } tlist.PrintStatistics(); if (!loop.GetDisplay()) { *fLog << err << GetDescriptor() << ": Execution stopped by user." << endl; return kFALSE; } const MHAlpha *halpha = (MHAlpha *)plist.FindObject("HistE"); if (!halpha) { *fLog << err << GetDescriptor() << ": HistE [MHAlpha] not found... abort." << endl; return kFALSE; } halpha->GetHEnergy().Copy(h2); h2.SetDirectory(0); return kTRUE; } Bool_t MJSpectrum::IntermediateLoop(MParList &plist, MH3 &mh1, TH1D &temp1, const MDataSet &set) const { MTaskList tlist1; plist.Replace(&tlist1); MReadMarsFile readmc("OriginalMC"); //readmc.DisableAutoScheme(); set.AddFilesOn(readmc); readmc.EnableBranch("MMcEvtBasic.fTelescopeTheta"); readmc.EnableBranch("MMcEvtBasic.fEnergy"); mh1.SetLogy(); mh1.SetLogz(); mh1.SetName("ThetaE"); MFillH fill0(&mh1); //fill0.SetDrawOption("projx only"); MBinning *bins2 = (MBinning*)plist.FindObject("BinningEnergyEst"); MBinning *bins3 = (MBinning*)plist.FindObject("BinningTheta"); if (bins2 && bins3) { bins2->SetName("BinningThetaEY"); bins3->SetName("BinningThetaEX"); } tlist1.AddToList(&readmc); temp1.SetXTitle("MMcEvtBasic.fTelescopeTheta*kRad2Deg"); MH3 mh3mc(temp1); MFEventSelector2 sel1(mh3mc); sel1.SetHistIsProbability(); fill0.SetFilter(&sel1); if (!fRawMc) tlist1.AddToList(&sel1); tlist1.AddToList(&fill0); MEvtLoop loop1(fName); loop1.SetParList(&plist); loop1.SetLogStream(fLog); loop1.SetDisplay(fDisplay); if (!SetupEnv(loop1)) return kFALSE; if (!loop1.Eventloop(fMaxEvents)) { *fLog << err << GetDescriptor() << ": Processing of MC-data failed." << endl; return kFALSE; } tlist1.PrintStatistics(); if (!loop1.GetDisplay()) { *fLog << err << GetDescriptor() << ": Execution stopped by user." << endl; return kFALSE; } if (bins2 && bins3) { bins2->SetName("BinningEnergyEst"); bins3->SetName("BinningTheta"); } return kTRUE; } void MJSpectrum::DisplaySpectrum(MHCollectionArea &area, TH1D &excess, MHEnergyEst &hest, Double_t ontime) const { TH1D collarea(area.GetHEnergy()); TH1D spectrum(excess); TH1D weights; hest.GetWeights(weights); cout << "Effective On time: " << ontime << "s" << endl; spectrum.SetDirectory(NULL); spectrum.SetBit(kCanDelete); spectrum.Scale(1./ontime); spectrum.Divide(&collarea); spectrum.SetNameTitle("Preliminary", "N/sm^{2} versus Energy (before unfolding)"); spectrum.SetYTitle("N/sm^{2}"); TCanvas &c1 = fDisplay->AddTab("Spectrum"); c1.Divide(2,2); c1.cd(1); gPad->SetBorderMode(0); gPad->SetLogx(); gPad->SetLogy(); gPad->SetGridx(); gPad->SetGridy(); collarea.DrawCopy(); c1.cd(2); gPad->SetBorderMode(0); gPad->SetLogx(); gPad->SetLogy(); gPad->SetGridx(); gPad->SetGridy(); spectrum.DrawCopy(); c1.cd(3); gPad->SetBorderMode(0); gPad->SetLogx(); gPad->SetLogy(); gPad->SetGridx(); gPad->SetGridy(); weights.DrawCopy(); //spectrum.Divide(&weights); spectrum.Multiply(&weights); spectrum.SetNameTitle("Flux", "N/TeVsm^{2} versus Energy (after unfolding)"); for (int i=0; iSetBorderMode(0); gPad->SetLogx(); gPad->SetLogy(); gPad->SetGridx(); gPad->SetGridy(); spectrum.SetXTitle("E [GeV]"); spectrum.SetYTitle("N/TeVsm^{2}"); spectrum.DrawCopy(); TF1 f("f", "[1]*(x/1e3)^[0]", 50, 3e4); f.SetParameter(0, -2.87); f.SetParameter(1, 1.9e-6); f.SetLineColor(kGreen); spectrum.Fit(&f, "NI", "", 55, 2e4); f.DrawCopy("same"); /* TString str; str += "(1.68#pm0.15)10^{-7}"; str += "(\\frac{E}{TeV})^{-2.59#pm0.06}"; str += "\\frac{ph}{TeVm^{2}s}"; TLatex tex; tex.DrawLatex(2e2, 7e-5, str); */ } Bool_t MJSpectrum::PlotSame(MStatusArray &arr, MParList &plist, const char *name, const char *tab, const char *plot) const { cout << name << endl; TString same(name); same += "Same"; TH1 *h1 = (TH1*)arr.FindObjectInCanvas(name, "TH1F", tab); TH1 *h2 = (TH1*)arr.FindObjectInCanvas(same, "TH1F", tab); if (!h1 || !h2) return kFALSE; TObject *obj = plist.FindObject(plot); if (!obj) { *fLog << warn << plot << " not in parameter list... skipping." << endl; return kFALSE; } TH1 *h3 = (TH1*)obj->FindObject(name); if (!h3) { *fLog << warn << name << " not found in " << plot << "... skipping." << endl; return kFALSE; } const MAlphaFitter *fit = (MAlphaFitter*)plist.FindObject("MAlphaFitter"); const Double_t scale = fit ? fit->GetScaleFactor() : 1; gPad->SetBorderMode(0); h2->SetLineColor(kBlack); h3->SetLineColor(kBlue); h2->Add(h1, -scale); h2->Scale(1./h2->Integral()); h3->Scale(1./h3->Integral()); h2->SetMaximum(1.05*TMath::Max(h2->GetMaximum(), h3->GetMaximum())); h2 = h2->DrawCopy(); h3 = h3->DrawCopy("same"); // Don't do this on the original object! h2->SetStats(kFALSE); h3->SetStats(kFALSE); return kTRUE; } Bool_t MJSpectrum::DisplaySize(MParList &plist) const { *fLog << inf << "Reading from file: " << fPathIn << endl; TFile file(fPathIn, "READ"); if (!file.IsOpen()) { *fLog << err << dbginf << "ERROR - Could not open file " << fPathIn << endl; return kFALSE; } file.cd(); MStatusArray arr; if (arr.Read()<=0) { *fLog << "MStatusDisplay not found in file... abort." << endl; return kFALSE; } TH1 *excess = (TH1D*)arr.FindObjectInCanvas("Excess", "TH1D", "Hist"); if (!excess) return kFALSE; // ------------------- Plot excess versus size ------------------- TCanvas &c = fDisplay->AddTab("Excess"); c.Divide(3,2); c.cd(1); gPad->SetBorderMode(0); gPad->SetLogx(); gPad->SetLogy(); gPad->SetGridx(); gPad->SetGridy(); excess->SetTitle("Number of excess events vs Size (data, mc/blue)"); excess->Scale(1./excess->Integral()); excess = excess->DrawCopy(); // Don't do this on the original object! excess->SetStats(kFALSE); TObject *o=0; if ((o=plist.FindObject("ExcessSize"))) { TH1 *histsel = (TH1F*)o->FindObject(""); if (histsel) { histsel->Scale(1./histsel->Integral()); histsel->SetLineColor(kBlue); histsel->SetBit(kCanDelete); histsel = histsel->DrawCopy("same"); // Don't do this on the original object! histsel->SetStats(kFALSE); } } // -------------- Comparison of Image Parameters -------------- c.cd(2); PlotSame(arr, plist, "Dist", "HilSrc", "MHHilSrcMCPost"); c.cd(3); PlotSame(arr, plist, "Length", "PostCut", "MHHillasMCPost"); c.cd(4); PlotSame(arr, plist, "M3l", "HilExt", "MHHilExtMCPost"); c.cd(5); PlotSame(arr, plist, "Conc1", "NewPar", "MHNewParMCPost"); c.cd(6); PlotSame(arr, plist, "Width", "PostCut", "MHHillasMCPost"); return kTRUE; } Bool_t MJSpectrum::Process(const MDataSet &set) { if (!set.IsValid()) { *fLog << err << "ERROR - DataSet invalid!" << endl; return kFALSE; } CheckEnv(); // -------------------------------------------------------------------------------- *fLog << inf; fLog->Separator(GetDescriptor()); *fLog << "Compile Monte Carlo Sample (data set " << set.GetName() << ")" << endl; *fLog << endl; MBinning bins1("BinningAlpha"); MBinning bins2("BinningEnergyEst"); MBinning bins3("BinningTheta"); MBinning bins4("BinningFalseSource"); MBinning bins5("BinningWidth"); MBinning bins6("BinningLength"); MBinning bins7("BinningDist"); MBinning bins8("BinningMaxDist"); MBinning bins9("BinningM3Long"); MBinning bins0("BinningConc1"); MAlphaFitter fit; MParList plist; plist.AddToList(&bins1); plist.AddToList(&bins2); plist.AddToList(&bins3); plist.AddToList(&bins4); plist.AddToList(&bins5); plist.AddToList(&bins6); plist.AddToList(&bins7); plist.AddToList(&bins8); plist.AddToList(&bins9); plist.AddToList(&bins0); plist.AddToList(&fit); TH1D temp1, size; const Float_t ontime = ReadInput(plist, temp1, size); if (ontime<0) { *fLog << err << GetDescriptor() << ": Could not determin effective on time..." << endl; return kFALSE; } PrintSetup(fit); bins3.SetEdges(temp1, 'x'); TH1D temp2(temp1); if (!ReadOrigMCDistribution(set, temp2)) return kFALSE; if (!GetThetaDistribution(temp1, temp2)) return kFALSE; TH1D excess; if (!Refill(plist, excess)) return kFALSE; TH2D hist; MH3 mh1("MMcEvtBasic.fTelescopeTheta*kRad2Deg", "MMcEvtBasic.fEnergy"); if (fSimpleMode) { hist.UseCurrentStyle(); MH::SetBinning(&hist, &bins3/*temp1.GetXaxis()*/, &bins2/*excess.GetXaxis()*/); if (!ReadOrigMCDistribution(set, hist)) return kFALSE; if (!fRawMc) { for (int y=0; ySeparator("Calculate efficiencies"); *fLog << endl; MTaskList tlist2; plist.Replace(&tlist2); MReadMarsFile read("Events"); read.DisableAutoScheme(); set.AddFilesOn(read); // Selector to get correct (final) theta-distribution temp1.SetXTitle("MPointingPos.fZd"); MH3 mh3(temp1); MFEventSelector2 sel2(mh3); sel2.SetHistIsProbability(); MContinue contsel(&sel2); contsel.SetInverted(); // Get correct source position MSrcPosCalc calc; // Calculate corresponding Hillas parameters MHillasCalc hcalc1; MHillasCalc hcalc2("MHillasCalcAnti"); hcalc1.SetFlags(MHillasCalc::kCalcHillasSrc); hcalc2.SetFlags(MHillasCalc::kCalcHillasSrc); hcalc2.SetNameHillasSrc("MHillasSrcAnti"); hcalc2.SetNameSrcPosCam("MSrcPosAnti"); // Fill collection area and energy estimator (unfolding) // Make sure to use the same binning for MHCollectionArea and MHEnergyEst MHCollectionArea area; area.SetHistAll(fSimpleMode ? hist : (TH2D&)mh1.GetHist()); MHEnergyEst hest; MFillH fill3(&area, "", "FillCollectionArea"); MFillH fill4(&hest, "", "FillEnergyEst"); MH3 hsize("MHillas.fSize"); //MH3 henergy("MEnergyEst.fVal"); hsize.SetName("ExcessSize"); //henergy.SetName("EnergyEst"); MBinning bins(size, "BinningExcessSize"); plist.AddToList(&hsize); //plist.AddToList(&henergy); plist.AddToList(&bins); MFillH fill1a("MHHillasMCPre [MHHillas]", "MHillas", "FillHillasPre"); MFillH fill2a("MHHillasMCPost [MHHillas]", "MHillas", "FillHillasPost"); MFillH fill3a("MHVsSizeMCPost [MHVsSize]", "MHillasSrc", "FillVsSizePost"); MFillH fill4a("MHHilExtMCPost [MHHillasExt]", "MHillasSrc", "FillHilExtPost"); MFillH fill5a("MHHilSrcMCPost [MHHillasSrc]", "MHillasSrc", "FillHilSrcPost"); MFillH fill6a("MHImgParMCPost [MHImagePar]", "MImagePar", "FillImgParPost"); MFillH fill7a("MHNewParMCPost [MHNewImagePar]", "MNewImagePar", "FillNewParPost"); MFillH fill8a("ExcessSize [MH3]", "", "FillExcessSize"); //MFillH fill9a("EnergyEst [MH3]", "", "FillExcessEEst"); fill1a.SetNameTab("PreCut"); fill2a.SetNameTab("PostCut"); fill3a.SetNameTab("VsSize"); fill4a.SetNameTab("HilExt"); fill5a.SetNameTab("HilSrc"); fill6a.SetNameTab("ImgPar"); fill7a.SetNameTab("NewPar"); fill8a.SetBit(MFillH::kDoNotDisplay); //fill9a.SetBit(MFillH::kDoNotDisplay); MEnergyEstimate est; MTaskEnv taskenv1("EstimateEnergy"); taskenv1.SetDefault(fEstimateEnergy ? fEstimateEnergy : &est); tlist2.AddToList(&read); if (!fRawMc) tlist2.AddToList(&contsel); tlist2.AddToList(&calc); tlist2.AddToList(&hcalc1); tlist2.AddToList(&hcalc2); tlist2.AddToList(&fill1a); tlist2.AddToList(fCut0); tlist2.AddToList(fCut1); tlist2.AddToList(fCut2); tlist2.AddToList(fCut3); tlist2.AddToList(&taskenv1); tlist2.AddToList(&fill3); tlist2.AddToList(&fill4); tlist2.AddToList(&fill2a); tlist2.AddToList(&fill3a); tlist2.AddToList(&fill4a); tlist2.AddToList(&fill5a); tlist2.AddToList(&fill6a); tlist2.AddToList(&fill7a); tlist2.AddToList(&fill8a); //tlist2.AddToList(&fill9a); MEvtLoop loop2(fName); loop2.SetParList(&plist); loop2.SetDisplay(fDisplay); loop2.SetLogStream(fLog); if (!SetupEnv(loop2)) return kFALSE; if (!loop2.Eventloop(fMaxEvents)) { *fLog << err << GetDescriptor() << ": Processing of MC-data failed." << endl; return kFALSE; } tlist2.PrintStatistics(); if (!loop2.GetDisplay()) { *fLog << err << GetDescriptor() << ": Execution stopped by user." << endl; return kFALSE; } // -------------------------- Spectrum ---------------------------- DisplaySpectrum(area, excess, hest, ontime); DisplaySize(plist); if (!fPathOut.IsNull()) fDisplay->SaveAsRoot(fPathOut); return kTRUE; }