/* ======================================================================== *\ ! ! * ! * 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, 1/2005 ! ! Copyright: MAGIC Software Development, 2000-2005 ! ! \* ======================================================================== */ ///////////////////////////////////////////////////////////////////////////// // // MJCut // // FIXME: Preparation for wobble mode missing // ///////////////////////////////////////////////////////////////////////////// #include "MJCut.h" #include #include #include "MLog.h" #include "MLogManip.h" #include "MParList.h" #include "MTaskList.h" #include "MEvtLoop.h" #include "MStatusDisplay.h" #include "MReadReports.h" #include "MPrint.h" #include "MContinue.h" #include "MEnergyEstimate.h" #include "MTaskEnv.h" #include "MSrcPosCalc.h" #include "MHillasCalc.h" #include "MFillH.h" #include "MWriteRootFile.h" #include "../mhflux/MAlphaFitter.h" #include "MBinning.h" #include "MDataSet.h" #include "MParameters.h" #include "MPointingPos.h" #include "MObservatory.h" ClassImp(MJCut); using namespace std; // -------------------------------------------------------------------------- // // Default constructor. // MJCut::MJCut(const char *name, const char *title) : fStoreSummary(kFALSE), fStoreResult(kFALSE), fWriteOnly(kFALSE), fIsWobble(kFALSE), fEstimateEnergy(0), fCalcHadronness(0) { fName = name ? name : "MJCut"; fTitle = title ? title : "Standard program to perform g/h-seperation cuts"; } MJCut::~MJCut() { if (fEstimateEnergy) delete fEstimateEnergy; if (fCalcHadronness) delete fCalcHadronness; } // -------------------------------------------------------------------------- // // Set the name of the summary file (events after cut0) // If you give a name the storage of this file is enabled implicitly. // If you give no filename the storage is neither enabled nor disabled, // but the storage file name is reset. // If no filename is set the default filename is used. // You can explicitly enable or disable the storage using EnableStoreOf*() // The default argument is no filename. // void MJCut::SetNameSummaryFile(const char *name) { fNameSummary=name; if (!fNameSummary.IsNull()) EnableStorageOfSummary(); } // -------------------------------------------------------------------------- // // Set the name of the summary file (events after cut3) // If you give a name the storage of this file is enabled implicitly. // If you give no filename the storage is neither enabled nor disabled, // but the storage file name is reset. // If no filename is set the default filename is used. // You can explicitly enable or disable the storage using EnableStoreOf*() // The default argument is no filename. // void MJCut::SetNameResultFile(const char *name) { fNameResult=name; if (!fNameResult.IsNull()) EnableStorageOfResult(); } // -------------------------------------------------------------------------- // // Setup a task estimating the energy. The given task is cloned. // void MJCut::SetEnergyEstimator(const MTask *task) { if (fEstimateEnergy) delete fEstimateEnergy; fEstimateEnergy = task ? (MTask*)task->Clone() : 0; } // -------------------------------------------------------------------------- // // Setup a task calculating the hadronness. The given task is cloned. // void MJCut::SetHadronnessCalculator(const MTask *task) { if (fCalcHadronness) delete fCalcHadronness; fCalcHadronness = task ? (MTask*)task->Clone() : 0; } // -------------------------------------------------------------------------- // // return fOutputPath+"/ganymed%08d.root", num // TString MJCut::GetOutputFile(UInt_t num) const { TString p(fPathOut); p += "/"; p += fNameOutput.IsNull() ? Form("ganymed%08d.root", num) : fNameOutput.Data(); return p; } /* Bool_t MJCut::ReadTasks(const char *fname, MTask* &env1, MTask* &env2) const { // const TString fname = Form("%s/calib%08d.root", fPathIn.Data(), fSequence.GetSequence()); *fLog << inf << "Reading from file: " << fname << endl; TFile file(fname, "READ"); if (!file.IsOpen()) { *fLog << err << dbginf << "ERROR - Could not open file " << fname << endl; return kFALSE; } TObject *o = file.Get("EstimateEnergy"); if (o && !o->InheritsFrom(MTask::Class())) { *fLog << err << dbginf << "ERROR - EstimateEnergy read from " << fname << " doesn't inherit from MTask!" << endl; return kFALSE; } env1 = o ? (MTask*)o->Clone() : NULL; o = file.Get("CalcHadronness"); if (o && !o->InheritsFrom(MTask::Class())) { *fLog << err << dbginf << "ERROR - CalcHadronness read from " << fname << " doesn't inherit from MTask!" << endl; return kFALSE; } env2 = o ? (MTask*)o->Clone() : NULL; return kTRUE; } */ // -------------------------------------------------------------------------- // // Write the tasks in cont to the file corresponding to analysis number num, // see GetOutputFile() // Bool_t MJCut::WriteTasks(UInt_t num, TObjArray &cont) const { if (fPathOut.IsNull()) { *fLog << inf << "No output path specified via SetPathOut - no output written." << endl; return kTRUE; } const TString oname(GetOutputFile(num)); *fLog << inf << "Writing to file: " << oname << endl; TFile file(oname, fOverwrite?"RECREATE":"NEW", "File created by MJCut", 9); if (!file.IsOpen()) { *fLog << err << "ERROR - Couldn't open file " << oname << " for writing..." << endl; return kFALSE; } return WriteContainer(cont); } // -------------------------------------------------------------------------- // // Write the result plots and other results to the file corresponding to // analysis number num, see GetOutputFile() // Bool_t MJCut::WriteResult(UInt_t num) const { TObjArray arr; return WriteContainer(arr, GetOutputFile(num), "UPDATE"); } // -------------------------------------------------------------------------- // // MJCut allows to setup several option by a resource file: // MJCut.WriteSummary: yes, no // MJCut.SummaryFile: filename // MJCut.WriteResult: yes, no // MJCut.ResultFile: filename // Bool_t MJCut::CheckEnvLocal() { const TString f0(GetEnv("SummaryFile", "")); const TString f1(GetEnv("ResultFile", "")); if (!f0.IsNull()) SetNameSummaryFile(f0); if (!f1.IsNull()) SetNameResultFile(f1); EnableStorageOfSummary(GetEnv("SummaryFile", fStoreSummary)); EnableStorageOfResult(GetEnv("ResultFile", fStoreResult)); EnableWobbleMode(GetEnv("WobbleMode", fIsWobble)); return kTRUE; } // -------------------------------------------------------------------------- // // Setup write to write: // container tree optional? // -------------- ---------- ----------- // "MHillas" to "Events" // "MHillasSrc" to "Events" // "MHadronness" to "Events" yes // "MEnergyEst" to "Events" yes // "DataType" to "Events" // void MJCut::SetupWriter(MWriteRootFile &write, const char *name) const { write.SetName(name); write.AddContainer("MHillas", "Events"); write.AddContainer("MHillasSrc", "Events"); write.AddContainer("MHillasSrcAnti", "Events", kFALSE); write.AddContainer("MHadronness", "Events", kFALSE); write.AddContainer("MEnergyEst", "Events", kFALSE); write.AddContainer("DataType", "Events"); // Should not be the default: Either as option, or as // setup from resource file // write.AddContainer("MHillasExt", "Events"); // write.AddContainer("MImagePar", "Events"); // write.AddContainer("MNewImagePar", "Events"); } Bool_t MJCut::ProcessFile(const MDataSet &set) { if (!set.IsValid()) { *fLog << err << "ERROR - DataSet invalid!" << endl; return kFALSE; } CheckEnv(); // -------------------------------------------------------------------------------- *fLog << inf; fLog->Separator(GetDescriptor()); *fLog << "Perform cuts for data set " << set.GetName() << endl; *fLog << endl; // -------------------------------------------------------------------------------- // Setup Parlist MParList plist; plist.AddToList(this); // take care of fDisplay! MParameterI par("DataType"); plist.AddToList(&par); // Setup Tasklist MTaskList tlist; plist.AddToList(&tlist); // La Palma Magic1 MObservatory obs; plist.AddToList(&obs); // Possible source position (eg. Wobble Mode) MPointingPos source("MSourcePos"); if (set.GetSourcePos(source)) { plist.AddToList(&source); *fLog << inf << "Using Source Position: " << source.GetTitle() << endl; } else *fLog << inf << "No source position applied..." << endl; // Initialize default binnings MBinning bins1(18, 0, 90, "BinningAlpha", "lin"); MBinning bins2(15, 10, 1e6 , "BinningEnergyEst", "log"); MBinning bins3(50, 0, 60, "BinningTheta", "cos"); MBinning bins4("BinningFalseSource"); plist.AddToList(&bins1); plist.AddToList(&bins2); plist.AddToList(&bins3); plist.AddToList(&bins4); // -------------------------------------------------------------------------------- // Setup fitter and histograms MAlphaFitter fit; plist.AddToList(&fit); if (fIsWobble) fit.SetScaleMode(MAlphaFitter::kNone); MFillH falpha("MHAlphaOff [MHAlpha]", "MHillasSrc", "FillAlpha"); MFillH ffs("MHFalseSourceOff [MHFalseSource]", "MHillas", "FillFS"); // FIXME: If fPathIn read cuts and energy estimator from file! MContinue cont0("", "Cut0"); MContinue cont1("", "Cut1"); MContinue cont2("", "Cut2"); MContinue cont3("", "Cut3"); cont0.SetAllowEmpty(); cont1.SetAllowEmpty(); cont2.SetAllowEmpty(); cont3.SetAllowEmpty(); // ------------- Loop Off Data -------------------- MReadReports readoff; readoff.AddTree("Events", "MTime.", kTRUE); readoff.AddTree("Drive"); readoff.AddTree("EffectiveOnTime"); if (fIsWobble) set.AddFilesOn(readoff); else set.AddFilesOff(readoff); const TString path(Form("%s/", fPathOut.Data())); TString fname0(path); TString fname1(path); fname0 += fNameSummary.IsNull() ? (TString) Form("ganymed%08d-summary.root", set.GetNumAnalysis()) : fNameSummary; fname1 += fNameResult.IsNull() ? (TString) Form("ganymed%08d-result.root", set.GetNumAnalysis()) : fNameResult; MWriteRootFile write0(fPathOut.IsNull()?0:fname0.Data(), fOverwrite?"RECREATE":"NEW"); MWriteRootFile write1(fPathOut.IsNull()?0:fname1.Data(), fOverwrite?"RECREATE":"NEW"); if (CanStoreSummary()) SetupWriter(write0, "WriteAfterCut0"); if (CanStoreSummary()) SetupWriter(write1, "WriteAfterCut3"); MEnergyEstimate est; MTaskEnv taskenv1("EstimateEnergy"); taskenv1.SetDefault(fEstimateEnergy ? fEstimateEnergy : &est); MTaskEnv taskenv2("CalcHadronness"); taskenv2.SetDefault(fCalcHadronness); MFillH fill1a("MHHillasOffPre [MHHillas]", "MHillas", "FillHillasPre"); MFillH fill2a("MHHillasOffPost [MHHillas]", "MHillas", "FillHillasPost"); MFillH fill3a("MHVsSizeOffPost [MHVsSize]", "MHillasSrc", "FillVsSizePost"); fill1a.SetNameTab("PreCut"); fill2a.SetNameTab("PostCut"); fill3a.SetNameTab("VsSize"); MPrint print2("MEffectiveOnTime"); // How to get source position from off- and on-data? MSrcPosCalc scalc; if (fIsWobble) scalc.SetWobbleMode(); /********************/ MHillasCalc hcalc; MHillasCalc hcalc2("MHillasCalcAnti"); hcalc.SetFlags(MHillasCalc::kCalcHillasSrc); hcalc2.SetFlags(MHillasCalc::kCalcHillasSrc); hcalc2.SetNameHillasSrc("MHillasSrcAnti"); hcalc2.SetNameSrcPosCam("MSrcPosAnti"); MTaskList tlist2; tlist2.AddToList(&scalc); tlist2.AddToList(&hcalc); if (fIsWobble) tlist2.AddToList(&hcalc2); tlist2.AddToList(&taskenv1); tlist2.AddToList(&taskenv2); tlist2.AddToList(&cont0); if (CanStoreSummary()) tlist2.AddToList(&write0); if (!fWriteOnly) tlist2.AddToList(&fill1a); tlist2.AddToList(&cont1); if (!fWriteOnly) tlist2.AddToList(&ffs); tlist2.AddToList(&cont2); if (!fWriteOnly) { tlist2.AddToList(&fill2a); tlist2.AddToList(&fill3a); } if (!fWriteOnly) tlist2.AddToList(&falpha); tlist2.AddToList(&cont3); if (CanStoreResult()) tlist2.AddToList(&write1); tlist.AddToList(&readoff); tlist.AddToList(&print2, "EffectiveOnTime"); tlist.AddToList(&tlist2, "Events"); par.SetVal(0); // Create and setup the eventloop MEvtLoop evtloop(fName); evtloop.SetParList(&plist); evtloop.SetDisplay(fDisplay); evtloop.SetLogStream(fLog); if (!SetupEnv(evtloop)) return kFALSE; if (set.HasOffSequences() || fIsWobble) { // Execute first analysis if (!evtloop.Eventloop(fMaxEvents)) { *fLog << err << GetDescriptor() << ": Processing of off-sequences failed." << endl; return kFALSE; } tlist.PrintStatistics(); if (!evtloop.GetDisplay()) { *fLog << err << GetDescriptor() << ": Execution stopped by user." << endl; return kFALSE; } } // ------------- Loop On Data -------------------- MReadReports readon; readon.AddTree("Events", "MTime.", kTRUE); readon.AddTree("Drive"); readon.AddTree("EffectiveOnTime"); set.AddFilesOn(readon); if (fIsWobble) scalc.SetWobbleMode(kFALSE); /********************/ MFillH fill1b("MHHillasOnPre [MHHillas]", "MHillas", "FillHillasPre"); MFillH fill2b("MHHillasOnPost [MHHillas]", "MHillas", "FillHillasPost"); MFillH fill3b("MHVsSizeOnPost [MHVsSize]", "MHillasSrc", "FillVsSizePost"); fill1b.SetNameTab("PreCut"); fill2b.SetNameTab("PostCut"); fill3b.SetNameTab("VsSize"); fill1b.SetDrawOption(set.HasOffSequences()||fIsWobble?"same":""); fill2b.SetDrawOption(set.HasOffSequences()||fIsWobble?"same":""); fill3b.SetDrawOption(set.HasOffSequences()||fIsWobble?"same":""); MFillH falpha2("MHAlpha", "MHillasSrc", "FillAlpha"); MFillH ffs2("MHFalseSource", "MHillas", "FillFS"); tlist.Replace(&readon); if (!fWriteOnly) { tlist2.Replace(&fill1b); tlist2.Replace(&fill2b); tlist2.Replace(&fill3b); tlist2.Replace(&falpha2); tlist2.Replace(&ffs2); } par.SetVal(1); TObjArray cont; cont.Add(&cont0); cont.Add(&cont1); cont.Add(&cont2); cont.Add(&cont3); if (taskenv1.GetTask()) cont.Add(taskenv1.GetTask()); if (taskenv2.GetTask()) cont.Add(taskenv2.GetTask()); if (!WriteTasks(set.GetNumAnalysis(), cont)) return kFALSE; // Execute first analysis if (!evtloop.Eventloop(fMaxEvents)) { *fLog << err << GetDescriptor() << ": Processing of on-sequences failed." << endl; return kFALSE; } tlist.PrintStatistics(); // FIXME: Perform fit and plot energy dependant alpha plots // and fit result to new tabs! if (!WriteResult(set.GetNumAnalysis())) return kFALSE; *fLog << all << GetDescriptor() << ": Done." << endl; *fLog << endl << endl; return kTRUE; }