diff --git a/CAFAna/.gitignore b/CAFAna/.gitignore index c3934281..295a7ba8 100644 --- a/CAFAna/.gitignore +++ b/CAFAna/.gitignore @@ -7,4 +7,6 @@ cmake/CMakeFiles/ *.root *.pdf *.png +._* +.DS_* support/ diff --git a/CAFAna/Analysis/AnalysisBinnings.cxx b/CAFAna/Analysis/AnalysisBinnings.cxx index 713bb949..e215e3a9 100644 --- a/CAFAna/Analysis/AnalysisBinnings.cxx +++ b/CAFAna/Analysis/AnalysisBinnings.cxx @@ -10,35 +10,35 @@ using namespace ana; AxisBlob GetAxisBlob(std::string const &blob_name) { - //Should all be statically initialized on first method call to ensure that the vars have been initialized beforehand - // Axes - static HistAxis const axRecoEnuFDnumu("Reco energy (GeV)", kFDRecoBinning, - kRecoE_numu); - static HistAxis const axRecoEnuFDnue("Reco energy (GeV)", kFDRecoBinning, - kRecoE_nue); - static HistAxis const axErecYrecND("Reco energy (GeV)", kNDRecoBinning, - kRecoEnergyND, "y_{rec}", kYBinning, - kRecoYND); - static HistAxis const axRecoEnuFDnumu_v3("Reco energy (GeV)", - kFDRecoBinning, kRecoE_numu); - static HistAxis const axRecoEnuFDnue_v3("Reco energy (GeV)", - kFDRecoV3Binning, kRecoE_nue); - static HistAxis const axErecYrecND_v3("Reco energy (GeV)", - kNDRecoV3Binning, kRecoEnergyND, - "y_{rec}", kYV3Binning, kRecoYND); - static HistAxis const axErecND("Reco energy (GeV)", kNDRecoBinning, - kRecoEnergyND); - - static HistAxis const axErecFD_FromDep("Reco energy (GeV)", kFDRecoBinning, - kRecoE_FromDep); - static HistAxis const axErecYrecND_FromDep( - "Reco energy (GeV)", kNDRecoBinning, kRecoE_FromDep, "y_{rec}", kYBinning, - kRecoY_FromDep); - static HistAxis const axErecYrecNDOA_FromDep( - "Reco energy (GeV)", kNDRecoOABinning, kRecoE_FromDep, "y_{rec}", kYBinning, - kRecoY_FromDep); - static HistAxis const axErecND_FromDep("#it{E}_{#nu}^{Rec.} (GeV)", - kNDRecoBinning, kRecoE_FromDep); +// //Should all be statically initialized on first method call to ensure that the vars have been initialized beforehand +// // Axes +// static HistAxis const axRecoEnuFDnumu("Reco energy (GeV)", kFDRecoBinning, +// kRecoE_numu); +// static HistAxis const axRecoEnuFDnue("Reco energy (GeV)", kFDRecoBinning, +// kRecoE_nue); +// static HistAxis const axErecYrecND("Reco energy (GeV)", kNDRecoBinning, +// kRecoEnergyND, "y_{rec}", kYBinning, +// kRecoYND); +// static HistAxis const axRecoEnuFDnumu_v3("Reco energy (GeV)", +// kFDRecoBinning, kRecoE_numu); +// static HistAxis const axRecoEnuFDnue_v3("Reco energy (GeV)", +// kFDRecoV3Binning, kRecoE_nue); +// static HistAxis const axErecYrecND_v3("Reco energy (GeV)", +// kNDRecoV3Binning, kRecoEnergyND, +// "y_{rec}", kYV3Binning, kRecoYND); +// static HistAxis const axErecND("Reco energy (GeV)", kNDRecoBinning, +// kRecoEnergyND); +// +// static HistAxis const axErecFD_FromDep("Reco energy (GeV)", kFDRecoBinning, +// kRecoE_FromDep); +// static HistAxis const axErecYrecND_FromDep( +// "Reco energy (GeV)", kNDRecoBinning, kRecoE_FromDep, "y_{rec}", kYBinning, +// kRecoY_FromDep); +// static HistAxis const axErecYrecNDOA_FromDep( +// "Reco energy (GeV)", kNDRecoOABinning, kRecoE_FromDep, "y_{rec}", kYBinning, +// kRecoY_FromDep); +// static HistAxis const axErecND_FromDep("#it{E}_{#nu}^{Rec.} (GeV)", +// kNDRecoBinning, kRecoE_FromDep); static HistAxis const axTrueE_unibin("#it{E}_{#nu} (GeV)", kTrueBinning, kTrueEnergy); @@ -46,76 +46,79 @@ AxisBlob GetAxisBlob(std::string const &blob_name) { static HistAxis const axTrueE_unibin_coarse( "#it{E}_{#nu} (GeV)", kTrueCoarseBinning, kTrueEnergy); - static HistAxis const axErec_FromDep_unibin("#it{E}_{#nu}^{Rec.} (GeV)", - kTrueBinning, kRecoE_FromDep); - static HistAxis const axErecND_unibin("#it{E}_{#nu}^{Rec.} (GeV)", - kTrueBinning, kRecoEnergyND); - static HistAxis const axRecoEnuFDnumu_unibin("Reco energy (GeV)", - kTrueBinning, kRecoE_numu); - static HistAxis const axRecoEnuFDnue_unibin("Reco energy (GeV)", - kTrueBinning, kRecoE_nue); - - static HistAxis const axErecND_coarsebin( - "Reco energy (GeV)", kRecoCoarseBinning, kRecoEnergyND); - static HistAxis const axRecoEnuFDnumu_coarsebin( - "Reco energy (GeV)", kRecoCoarseBinning, kRecoE_numu); - - static HistAxis const axRecoEnuFDnue_coarsebin( - "Reco energy (GeV)", kRecoCoarseBinning, kRecoE_nue); - - static HistAxis const axErecND_verycoarsebin( - "Reco energy (GeV)", kRecoVeryCoarseBinning, kRecoEnergyND); - static HistAxis const axRecoEnuFDnumu_verycoarsebin( - "Reco energy (GeV)", kRecoVeryCoarseBinning, kRecoE_numu); - - static HistAxis const axRecoEnuFDnue_verycoarsebin( - "Reco energy (GeV)", kRecoVeryCoarseBinning, kRecoE_nue); - - static HistAxis const axErecND_onebin("Reco energy (GeV)", kOneBinBinning, - kRecoEnergyND); - static HistAxis const axRecoEnuFDnumu_onebin("Reco energy (GeV)", kOneBinBinning, - kRecoE_numu); - - static HistAxis const axRecoEnuFDnue_onebin("Reco energy (GeV)", kOneBinBinning, - kRecoE_nue); - - static AxisBlob const default_axes_v4{&axErecYrecND, &axRecoEnuFDnumu, - &axRecoEnuFDnue}; - static AxisBlob const default_axes_v3{&axErecYrecND_v3, &axRecoEnuFDnumu_v3, - &axRecoEnuFDnue_v3}; - static AxisBlob const fake_data_axes{&axErecYrecND_FromDep, &axErecFD_FromDep, - &axErecFD_FromDep}; - - static AxisBlob const Ax1DND_unibin{&axErecND_unibin, &axRecoEnuFDnumu_unibin, - &axRecoEnuFDnue_unibin}; - static AxisBlob const Ax1DND_FromDep_unibin{ - &axErec_FromDep_unibin, &axErec_FromDep_unibin, &axErec_FromDep_unibin}; - - AxisBlob AxToUse = - (GetAnaVersion() == kV4) ? default_axes_v4 : default_axes_v3; - if (blob_name == "1DND") { - AxToUse.NDAx = &axErecND; - } else if (blob_name == "FromDep") { - AxToUse.NDAx = &axErecYrecND_FromDep; - AxToUse.FDAx_numu = &axErecFD_FromDep; - AxToUse.FDAx_nue = &axErecFD_FromDep; - } else if (blob_name == "1DNDFromDep") { - AxToUse.NDAx = &axErecND_FromDep; - AxToUse.FDAx_numu = &axErecFD_FromDep; - AxToUse.FDAx_nue = &axErecFD_FromDep; - } else if (blob_name == "CoarseBin1D") { - AxToUse.NDAx = &axErecND_coarsebin; - AxToUse.FDAx_numu = &axRecoEnuFDnumu_coarsebin; - AxToUse.FDAx_nue = &axRecoEnuFDnue_coarsebin; - } else if (blob_name == "VeryCoarseBin1D") { - AxToUse.NDAx = &axErecND_verycoarsebin; - AxToUse.FDAx_numu = &axRecoEnuFDnumu_verycoarsebin; - AxToUse.FDAx_nue = &axRecoEnuFDnue_verycoarsebin; - } else if (blob_name == "OneBin") { - AxToUse.NDAx = &axErecND_onebin; - AxToUse.FDAx_numu = &axRecoEnuFDnumu_onebin; - AxToUse.FDAx_nue = &axRecoEnuFDnue_onebin; - } else if (blob_name == "ETrue") { +// static HistAxis const axErec_FromDep_unibin("#it{E}_{#nu}^{Rec.} (GeV)", +// kTrueBinning, kRecoE_FromDep); +// static HistAxis const axErecND_unibin("#it{E}_{#nu}^{Rec.} (GeV)", +// kTrueBinning, kRecoEnergyND); +// static HistAxis const axRecoEnuFDnumu_unibin("Reco energy (GeV)", +// kTrueBinning, kRecoE_numu); +// static HistAxis const axRecoEnuFDnue_unibin("Reco energy (GeV)", +// kTrueBinning, kRecoE_nue); +// +// static HistAxis const axErecND_coarsebin( +// "Reco energy (GeV)", kRecoCoarseBinning, kRecoEnergyND); +// static HistAxis const axRecoEnuFDnumu_coarsebin( +// "Reco energy (GeV)", kRecoCoarseBinning, kRecoE_numu); +// +// static HistAxis const axRecoEnuFDnue_coarsebin( +// "Reco energy (GeV)", kRecoCoarseBinning, kRecoE_nue); +// +// static HistAxis const axErecND_verycoarsebin( +// "Reco energy (GeV)", kRecoVeryCoarseBinning, kRecoEnergyND); +// static HistAxis const axRecoEnuFDnumu_verycoarsebin( +// "Reco energy (GeV)", kRecoVeryCoarseBinning, kRecoE_numu); +// +// static HistAxis const axRecoEnuFDnue_verycoarsebin( +// "Reco energy (GeV)", kRecoVeryCoarseBinning, kRecoE_nue); +// +// static HistAxis const axErecND_onebin("Reco energy (GeV)", kOneBinBinning, +// kRecoEnergyND); +// static HistAxis const axRecoEnuFDnumu_onebin("Reco energy (GeV)", kOneBinBinning, +// kRecoE_numu); +// +// static HistAxis const axRecoEnuFDnue_onebin("Reco energy (GeV)", kOneBinBinning, +// kRecoE_nue); +// +// static AxisBlob const default_axes_v4{&axErecYrecND, &axRecoEnuFDnumu, +// &axRecoEnuFDnue}; +// static AxisBlob const default_axes_v3{&axErecYrecND_v3, &axRecoEnuFDnumu_v3, +// &axRecoEnuFDnue_v3}; +// static AxisBlob const fake_data_axes{&axErecYrecND_FromDep, &axErecFD_FromDep, +// &axErecFD_FromDep}; +// +// static AxisBlob const Ax1DND_unibin{&axErecND_unibin, &axRecoEnuFDnumu_unibin, +// &axRecoEnuFDnue_unibin}; +// static AxisBlob const Ax1DND_FromDep_unibin{ +// &axErec_FromDep_unibin, &axErec_FromDep_unibin, &axErec_FromDep_unibin}; + +static AxisBlob const default_axes_true{&axTrueE_unibin_coarse, &axTrueE_unibin_coarse, + &axTrueE_unibin_coarse}; + AxisBlob AxToUse = default_axes_true; + //(GetAnaVersion() == kV4) ? default_axes_v4 : default_axes_v3; +// if (blob_name == "1DND") { +// AxToUse.NDAx = &axErecND; +// } else if (blob_name == "FromDep") { +// AxToUse.NDAx = &axErecYrecND_FromDep; +// AxToUse.FDAx_numu = &axErecFD_FromDep; +// AxToUse.FDAx_nue = &axErecFD_FromDep; +// } else if (blob_name == "1DNDFromDep") { +// AxToUse.NDAx = &axErecND_FromDep; +// AxToUse.FDAx_numu = &axErecFD_FromDep; +// AxToUse.FDAx_nue = &axErecFD_FromDep; +// } else if (blob_name == "CoarseBin1D") { +// AxToUse.NDAx = &axErecND_coarsebin; +// AxToUse.FDAx_numu = &axRecoEnuFDnumu_coarsebin; +// AxToUse.FDAx_nue = &axRecoEnuFDnue_coarsebin; +// } else if (blob_name == "VeryCoarseBin1D") { +// AxToUse.NDAx = &axErecND_verycoarsebin; +// AxToUse.FDAx_numu = &axRecoEnuFDnumu_verycoarsebin; +// AxToUse.FDAx_nue = &axRecoEnuFDnue_verycoarsebin; +// } else if (blob_name == "OneBin") { +// AxToUse.NDAx = &axErecND_onebin; +// AxToUse.FDAx_numu = &axRecoEnuFDnumu_onebin; +// AxToUse.FDAx_nue = &axRecoEnuFDnue_onebin; +// } else + if (blob_name == "ETrue") { AxToUse.NDAx = &axTrueE_unibin; AxToUse.FDAx_numu = &axTrueE_unibin; AxToUse.FDAx_nue = &axTrueE_unibin; @@ -123,18 +126,18 @@ AxisBlob GetAxisBlob(std::string const &blob_name) { AxToUse.NDAx = &axTrueE_unibin_coarse; AxToUse.FDAx_numu = &axTrueE_unibin_coarse; AxToUse.FDAx_nue = &axTrueE_unibin_coarse; - } else if (blob_name == "FakeData") { - AxToUse = fake_data_axes; - } else if (blob_name == "v4") { - AxToUse = default_axes_v4; - } else if (blob_name == "v3") { - AxToUse = default_axes_v3; - } else if (blob_name == "CoarseNue") { - AxToUse.FDAx_nue = &axRecoEnuFDnue_coarsebin; - } else if (blob_name == "VeryCoarseNue") { - AxToUse.FDAx_nue = &axRecoEnuFDnue_verycoarsebin; - } else if (blob_name == "OneBinNue") { - AxToUse.FDAx_nue = &axRecoEnuFDnue_onebin; - } + } //else if (blob_name == "FakeData") { +// AxToUse = fake_data_axes; +// } else if (blob_name == "v4") { +// AxToUse = default_axes_v4; +// } else if (blob_name == "v3") { +// AxToUse = default_axes_v3; +// } else if (blob_name == "CoarseNue") { +// AxToUse.FDAx_nue = &axRecoEnuFDnue_coarsebin; +// } else if (blob_name == "VeryCoarseNue") { +// AxToUse.FDAx_nue = &axRecoEnuFDnue_verycoarsebin; +// } else if (blob_name == "OneBinNue") { +// AxToUse.FDAx_nue = &axRecoEnuFDnue_onebin; +// } return AxToUse; } diff --git a/CAFAna/Analysis/AnalysisVars.cxx b/CAFAna/Analysis/AnalysisVars.cxx index f2ac8aa8..6a39db63 100644 --- a/CAFAna/Analysis/AnalysisVars.cxx +++ b/CAFAna/Analysis/AnalysisVars.cxx @@ -6,41 +6,41 @@ using namespace ana; // List of vars // -->FD -Var const kRecoE_nue = SIMPLEVAR(Ev_reco_nue); -Var const kRecoE_numu = SIMPLEVAR(Ev_reco_numu); -Var const kRecoE_FromDep = SIMPLEVAR(eRec_FromDep); -Var const kFDNumuPid = SIMPLEVAR(cvnnumu); -Var const kFDNuePid = SIMPLEVAR(cvnnue); -Var const kMVANUMU = SIMPLEVAR(mvanumu); - -Var const kLepEReco_numu = SIMPLEVAR(RecoLepEnNumu); -Var const kLepEReco_nue = SIMPLEVAR(RecoLepEnNue); - -Var const kHadEReco_numu = SIMPLEVAR(RecoHadEnNumu); -Var const kHadEReco_nue = SIMPLEVAR(RecoHadEnNue); - -Var const kEVisReco_numu = SIMPLEVAR(EVisReco_numu); -Var const kEVisReco_nue = SIMPLEVAR(EVisReco_nue); - -// -->ND -Var const kRecoEnergyND = SIMPLEVAR(Ev_reco); -Var const kRecoYND = (SIMPLEVAR(Ev_reco) - SIMPLEVAR(Elep_reco)) / - SIMPLEVAR(Ev_reco); -Var const kRecoY_FromDep = - (SIMPLEVAR(eRec_FromDep) - SIMPLEVAR(LepE)) / - SIMPLEVAR(eRec_FromDep); - -Var const kNDLepEReco = SIMPLEVAR(Elep_reco); -Var const kNDEVisReco = SIMPLEVAR(EVisReco_ND); - -// -->Common ND & FD -Var const kTrueEnergy = SIMPLEVAR(Ev); -Var const kProxyERec = SIMPLEVAR(eRecProxy); -Var const kEVisTrue = SIMPLEVAR(VisTrue_NDFD); - -Var const kPEReco = SIMPLEVAR(eRecoP); -Var const kPipmEReco = SIMPLEVAR(eRecoPip) + SIMPLEVAR(eRecoPim); -Var const kPi0EReco = SIMPLEVAR(eRecoPi0); - -// CV weighting -Weight const kCVXSecWeights = SIMPLEWEIGHT(total_xsSyst_cv_wgt); // kUnweighted +//Var const kRecoE_nue = SIMPLEVAR(Ev_reco_nue); +//Var const kRecoE_numu = SIMPLEVAR(Ev_reco_numu); +//Var const kRecoE_FromDep = SIMPLEVAR(eRec_FromDep); +//Var const kFDNumuPid = SIMPLEVAR(cvnnumu); +//Var const kFDNuePid = SIMPLEVAR(cvnnue); +//Var const kMVANUMU = SIMPLEVAR(mvanumu); +// +//Var const kLepEReco_numu = SIMPLEVAR(RecoLepEnNumu); +//Var const kLepEReco_nue = SIMPLEVAR(RecoLepEnNue); +// +//Var const kHadEReco_numu = SIMPLEVAR(RecoHadEnNumu); +//Var const kHadEReco_nue = SIMPLEVAR(RecoHadEnNue); +// +//Var const kEVisReco_numu = SIMPLEVAR(EVisReco_numu); +//Var const kEVisReco_nue = SIMPLEVAR(EVisReco_nue); +// +//// -->ND +//Var const kRecoEnergyND = SIMPLEVAR(Ev_reco); +//Var const kRecoYND = (SIMPLEVAR(Ev_reco) - SIMPLEVAR(Elep_reco)) / +// SIMPLEVAR(Ev_reco); +//Var const kRecoY_FromDep = +// (SIMPLEVAR(eRec_FromDep) - SIMPLEVAR(LepE)) / +// SIMPLEVAR(eRec_FromDep); +// +//Var const kNDLepEReco = SIMPLEVAR(Elep_reco); +//Var const kNDEVisReco = SIMPLEVAR(EVisReco_ND); +// +//// -->Common ND & FD +//Var const kTrueEnergy = SIMPLEVAR(Ev); +//Var const kProxyERec = SIMPLEVAR(eRecProxy); +//Var const kEVisTrue = SIMPLEVAR(VisTrue_NDFD); +// +//Var const kPEReco = SIMPLEVAR(eRecoP); +//Var const kPipmEReco = SIMPLEVAR(eRecoPip) + SIMPLEVAR(eRecoPim); +//Var const kPi0EReco = SIMPLEVAR(eRecoPi0); +// +//// CV weighting +//Weight const kCVXSecWeights = SIMPLEWEIGHT(total_xsSyst_cv_wgt); // kUnweighted diff --git a/CAFAna/Analysis/AnalysisVars.h b/CAFAna/Analysis/AnalysisVars.h index 376cf89a..756454e2 100644 --- a/CAFAna/Analysis/AnalysisVars.h +++ b/CAFAna/Analysis/AnalysisVars.h @@ -3,39 +3,39 @@ #include "CAFAna/Core/Var.h" #include "CAFAna/Core/Weight.h" -// List of vars -// -->FD -extern ana::Var const kRecoE_nue; -extern ana::Var const kRecoE_numu; -extern ana::Var const kRecoE_FromDep; -extern ana::Var const kFDNumuPid; -extern ana::Var const kFDNuePid; -extern ana::Var const kMVANUMU; - -extern ana::Var const kLepEReco_numu; -extern ana::Var const kLepEReco_nue; - -extern ana::Var const kHadEReco_numu; -extern ana::Var const kHadEReco_nue; - -extern ana::Var const kEVisReco_numu; -extern ana::Var const kEVisReco_nue; - -// -->ND -extern ana::Var const kRecoEnergyND; -extern ana::Var const kRecoYND; -extern ana::Var const kRecoY_FromDep; - -extern ana::Var const kNDLepEReco; -extern ana::Var const kNDEVisReco; - -// --> Common ND & FD -extern ana::Var const kTrueEnergy; -extern ana::Var const kProxyERec; -extern ana::Var const kEVisTrue; -extern ana::Var const kPEReco; // proton -extern ana::Var const kPipmEReco; // charged pion -extern ana::Var const kPi0EReco; // neutral pion - -// CV weighting -extern ana::Weight const kCVXSecWeights; // kUnweighted +//// List of vars +//// -->FD +//extern ana::Var const kRecoE_nue; +//extern ana::Var const kRecoE_numu; +//extern ana::Var const kRecoE_FromDep; +//extern ana::Var const kFDNumuPid; +//extern ana::Var const kFDNuePid; +//extern ana::Var const kMVANUMU; +// +//extern ana::Var const kLepEReco_numu; +//extern ana::Var const kLepEReco_nue; +// +//extern ana::Var const kHadEReco_numu; +//extern ana::Var const kHadEReco_nue; +// +//extern ana::Var const kEVisReco_numu; +//extern ana::Var const kEVisReco_nue; +// +//// -->ND +//extern ana::Var const kRecoEnergyND; +//extern ana::Var const kRecoYND; +//extern ana::Var const kRecoY_FromDep; +// +//extern ana::Var const kNDLepEReco; +//extern ana::Var const kNDEVisReco; +// +//// --> Common ND & FD +//extern ana::Var const kTrueEnergy; +//extern ana::Var const kProxyERec; +//extern ana::Var const kEVisTrue; +//extern ana::Var const kPEReco; // proton +//extern ana::Var const kPipmEReco; // charged pion +//extern ana::Var const kPi0EReco; // neutral pion +// +//// CV weighting +//extern ana::Weight const kCVXSecWeights; // kUnweighted diff --git a/CAFAna/Analysis/common_fit_definitions.cxx b/CAFAna/Analysis/common_fit_definitions.cxx index 6a45b860..78233c5b 100644 --- a/CAFAna/Analysis/common_fit_definitions.cxx +++ b/CAFAna/Analysis/common_fit_definitions.cxx @@ -1,3 +1,5 @@ +#if 0 // TODO TODO TODO + #include "CAFAna/Analysis/common_fit_definitions.h" #include "CAFAna/Analysis/AnalysisVersion.h" @@ -195,7 +197,7 @@ SystShifts GetFakeDataGeneratorSystShift(std::string input) { dial_vals.push_back(val); } - std::vector FDSyst = GetListOfSysts(); + std::vector FDSyst = {};//GetListOfSysts(); KeepSysts(FDSyst, fake_data_names); for (uint i=0; i systs = GetListOfSysts(); + static std::vector systs = {};//GetListOfSysts(); // Hackity hackity hack hack bool fileNameIsStub = (fileName.find(".root") == std::string::npos); @@ -994,9 +1003,9 @@ double RunFitPoint(std::string stateFileName, std::string sampleString, } } - std::vector fdlos = - GetListOfSysts(false, false, false, false, false, false, - true /*add fake data*/, false); + std::vector fdlos = {}; + // GetListOfSysts(false, false, false, false, false, false, + // true /*add fake data*/, false); syststoload.insert(syststoload.end(), fdlos.begin(), fdlos.end()); PI_load = false; } @@ -1437,3 +1446,5 @@ double RunFitPoint(std::string stateFileName, std::string sampleString, return thischisq; } + +#endif diff --git a/CAFAna/CMakeLists.txt b/CAFAna/CMakeLists.txt index 3f804411..a5bf0308 100644 --- a/CAFAna/CMakeLists.txt +++ b/CAFAna/CMakeLists.txt @@ -81,11 +81,14 @@ include(${CMAKE_SOURCE_DIR}/cmake/FindExternals.cmake) include(${CMAKE_SOURCE_DIR}/cmake/c++CompilerSetup.cmake) ################################################################################ -## CAFAna proper - -set(CAFANA_SUBDIRS Analysis Core Cuts Decomp Experiment Extrap Fit Prediction Systs Vars PRISM bin scripts fcl) - +#set(CAFANA_SUBDIRS Analysis Core Cuts Experiment Extrap Fit Prediction Systs Vars PRISM bin scripts fcl) +## CAFAna proper (ignore PRISM for the moment) +## Also remove scripts (second to last) +#set(CAFANA_SUBDIRS Analysis Core Cuts Experiment Extrap Fit Prediction Systs Vars bin fcl) +#ok we are doing the most basic, removing aaal cuts vars etx. +set(CAFANA_SUBDIRS Core bin fcl) foreach(SUBDIR ${CAFANA_SUBDIRS}) + add_subdirectory(${SUBDIR}) endforeach() diff --git a/CAFAna/Core/CMakeLists.txt b/CAFAna/Core/CMakeLists.txt index 658c0a75..9d65a2f5 100644 --- a/CAFAna/Core/CMakeLists.txt +++ b/CAFAna/Core/CMakeLists.txt @@ -1,13 +1,17 @@ set(Core_implementation_files Binning.cxx IFitVar.cxx - Instantiations.cxx + IRecordSource.cxx FixupRecord.cxx ISyst.cxx + Multiverse.cxx Loaders.cxx LoadFromFile.cxx OscCurve.cxx - OscillatableSpectrum.cxx + EnsembleRatio.cxx + EnsembleSpectrum.cxx + EnsembleReweightableSpectrum.cxx +# OscillatableSpectrum.cxx ProfilerSupport.cxx Registry.cxx SpectrumLoader.cxx @@ -24,14 +28,21 @@ set(Core_header_files FixupRecord.h HistAxis.h IFitVar.h + IRecordSink.h + IRecordSource.h ISyst.h + FitMultiverse.h + Multiverse.h Loaders.h LoadFromFile.h MathUtil.h MultiVar.h OscCalcFwdDeclare.h OscCurve.h - OscillatableSpectrum.h + EnsembleRatio.h + EnsembleSpectrum.h + EnsembleReweightableSpectrum.h +# OscillatableSpectrum.h SpectrumLoader.h SpectrumLoaderBase.h StanTypedefs.h diff --git a/CAFAna/Core/Cut.h b/CAFAna/Core/Cut.h index a157614b..46055af7 100644 --- a/CAFAna/Core/Cut.h +++ b/CAFAna/Core/Cut.h @@ -6,8 +6,39 @@ namespace ana { - using Cut = _Cut; +// using Cut = _Cut; + + /// \brief Representation of a cut (selection) to be applied to a \ref + /// caf::StandardRecord object + /// + /// A Cut consists of a function, taking a StandardRecord and returning a + /// boolean indicating if that event passes the cut. + /// + /// Cut objects may be combined with the standard boolean operations && || + /// and ! + typedef _Cut InteractionCut; + typedef _Cut Cut; + typedef _Cut TruthCut; + typedef _Cut TruthPartCut; + typedef _Cut NDCut; + + /// \brief Equivalent of \ref Cut acting on \ref caf::StandardRecord. For use in + /// spill-by-spill data quality cuts ???? + typedef _Cut SRCut; /// The simplest possible cut: pass everything, used as a default - const Cut kNoCut(NoCut{}); + const Cut kNoCut(NoCut{}); + const TruthCut kNoTruthCut(NoCut{}); + const TruthPartCut kNoTruthPartCut(NoCut{}); + const NDCut kNoNDCut(NoCut{}); + const SRCut kNoSRCut(NoCut{}); + + typedef _Cut RecoPartCut; + + const RecoPartCut kNoPartCut(NoCut{}); + +// typedef _Cut RecoPartCut; +// const RecoPartCut kNoPartCut(NoCut{}); + + } diff --git a/CAFAna/Core/EnsembleRatio.cxx b/CAFAna/Core/EnsembleRatio.cxx new file mode 100644 index 00000000..a313fb01 --- /dev/null +++ b/CAFAna/Core/EnsembleRatio.cxx @@ -0,0 +1,228 @@ +#include "CAFAna/Core/EnsembleRatio.h" + +#include "CAFAna/Core/EnsembleSpectrum.h" + +#include "CAFAna/Core/FitMultiverse.h" +#include "CAFAna/Core/Utilities.h" + +#include "cafanacore/UtilsExt.h" + +#include "TEfficiency.h" +#include "TGraphAsymmErrors.h" + +#include + +namespace ana +{ + //---------------------------------------------------------------------- + EnsembleRatio::EnsembleRatio(const EnsembleSpectrum& num, + const EnsembleSpectrum& denom, + bool purOrEffErrs) + : fMultiverse(&num.GetMultiverse()), + fHist(num.fHist), + fAxis(num.GetLabels(), num.GetBinnings()) + { + CheckMultiverses(denom.GetMultiverse(), __func__); + + fHist.Divide(denom.fHist); + // TODO TODO this should handle livetime too + fHist.Scale(denom.POT()/num.POT()); + + // This is clumsy, but the old histogram operation considered 0/0 = 0, + // which is actually pretty useful (at least PredictionInterp relies on + // this). + for(int i = 0; i < fHist.GetNbinsX()+2; ++i){ + if(denom.fHist.GetBinContent(i) == 0){ + if(num.fHist.GetBinContent(i) == 0){ + fHist.SetBinContent(i, 0); + } + else{ + // Actual infinities break ROOT plotting + fHist.SetBinContent(i, 1e100); + // As in fact do merely very large numbers + // fHist.SetBinContent(i, std::numeric_limits::max()); + } + } + } + + if(purOrEffErrs){ + if(!AlmostEqual(num.POT(), denom.POT())){ + std::cout << "EnsembleRatio: Warning: creating purity or efficiency ratio between two spectra with different POTs" + << "\n " << num.POT() << " vs " << denom.POT() + << "\n That doesn't make much sense" << std::endl; + } + + Eigen::ArrayXd errsqarr(fHist.GetNbinsX()+2); + + const double kOneSigma = .6827; + for(int i = 0; i < fHist.GetNbinsX()+2; ++i){ + const double n = num.fHist.GetBinContent(i); + const double d = denom.fHist.GetBinContent(i); + + // Clopper-Peason is the TEfficiency default and "recommended by the + // PDG". If the user wants something else (for rendering purposes) they + // should use TEfficiency directly. + const double up = TEfficiency::ClopperPearson(n+d, n, kOneSigma, true); + const double dn = TEfficiency::ClopperPearson(n+d, n, kOneSigma, false); + + // Crudely symmetrizes asymmetric errors. The underlying Hist class + // can't cope with that, only really makes sense for plotting. In which + // case the user should do it themselves. + errsqarr[i] = util::sqr((up-dn)/2); + } // end for i + + Eigen::ArrayXd valarr = fHist.GetEigen(); + // Replace fHist with same values but new errors + fHist = Hist::AdoptWithErrors(std::move(valarr), std::move(errsqarr)); + } + } + + //---------------------------------------------------------------------- + unsigned int EnsembleRatio::NUniverses() const + { + return fMultiverse->NUniv(); + } + + //---------------------------------------------------------------------- + Ratio EnsembleRatio::Universe(unsigned int univIdx) const + { + const int nbins = fAxis.GetBins1D().NBins()+2; + + if(fHist.HasStan()){ + return Ratio(std::move(Eigen::ArrayXstan(fHist.GetEigenStan().segment(nbins*univIdx, nbins))), + fAxis.GetLabels(), fAxis.GetBinnings()); + } + else{ + Eigen::ArrayXd arr(fHist.GetEigen().segment(nbins*univIdx, nbins)); + + if(Hist::StatErrorsEnabled()){ + Eigen::ArrayXd errarr(fHist.GetEigenSqErrors().segment(nbins*univIdx, nbins)); + return Ratio(std::move(arr), std::move(errarr), + fAxis.GetLabels(), fAxis.GetBinnings()); + } + else{ + return Ratio(std::move(arr), fAxis.GetLabels(), fAxis.GetBinnings()); + } + } + } + + //---------------------------------------------------------------------- + TGraphAsymmErrors* EnsembleRatio::ErrorBand() const + { + // TODO lots of code duplication with EnsembleSpectrum + + const Eigen::ArrayXd arr = fHist.GetEigen(); + + TGraphAsymmErrors* g = new TGraphAsymmErrors; + + const int nbins = fAxis.GetBins1D().NBins()+2; + const std::vector& edges = fAxis.GetBins1D().Edges(); + + for(int binIdx = 1; binIdx+1 < nbins; ++binIdx){ + const double xnom = (edges[binIdx-1] + edges[binIdx]) / 2; // bin center + const double ynom = arr[binIdx]; + g->SetPoint(binIdx-1, xnom, ynom); + + const double dx = edges[binIdx] - edges[binIdx-1]; + + std::vector ys; + ys.reserve(NUniverses()-1); + for(unsigned int univIdx = 1; univIdx < NUniverses(); ++univIdx) + ys.push_back(arr[univIdx*nbins + binIdx]); + + // 1 sigma + const double y0 = FindQuantile(.5-0.6827/2, ys); + const double y1 = FindQuantile(.5+0.6827/2, ys); + + // It's theoretically possible for the central value to be outside the + // error bands - clamp to zero in that case + g->SetPointError(binIdx-1, dx/2, dx/2, + std::max(ynom-y0, 0.), + std::max(y1-ynom, 0.)); + } // end for binIdx + + return g; + } + + //---------------------------------------------------------------------- + Eigen::MatrixXd EnsembleRatio::CovarianceMatrix() + { + assert (fMultiverse->MultiverseType() == kRandomGas); + + const Eigen::ArrayXd& arr = fHist.GetEigen(); + + const int nbins = fAxis.GetBins1D().NBins()+2; + std::vector histVec; + histVec.reserve(NUniverses()); + + for(unsigned int univIdx = 1; univIdx < NUniverses(); ++univIdx) + histVec.push_back(arr.segment(nbins*univIdx, nbins)); + + return ana::CalcCovMx(histVec);// returns TMatrixD + } + + //---------------------------------------------------------------------- + Eigen::MatrixXd EnsembleRatio::BiasMatrix() + { + assert (fMultiverse->MultiverseType() == kRandomGas); + + const Eigen::ArrayXd& arr = fHist.GetEigen(); + + const int nbins = fAxis.GetBins1D().NBins()+2; + std::vector histVec; + histVec.reserve(NUniverses()); + + for(unsigned int univIdx = 1; univIdx < NUniverses(); ++univIdx) + histVec.push_back(arr.segment(nbins*univIdx, nbins)); + + return ana::CalcBiasMx(arr.segment(0, nbins), histVec); + } + //---------------------------------------------------------------------- + void EnsembleRatio::CheckMultiverses(const FitMultiverse& rhs, + const std::string& func) const + { + if(&rhs == fMultiverse) return; + + std::cout << "EnsembleRatio::" << func << ": attempting to combine two spectra made with different multiverses: " << std::endl; + std::cout << " " << fMultiverse->ShortName() << std::endl; + std::cout << "vs" << std::endl; + std::cout << rhs.ShortName() << std::endl; + abort(); + } + + //---------------------------------------------------------------------- + EnsembleRatio& EnsembleRatio::operator*=(const EnsembleRatio& rhs) + { + CheckMultiverses(rhs.GetMultiverse(), __func__); + + fHist.Multiply(rhs.fHist); + + return *this; + } + + //---------------------------------------------------------------------- + EnsembleRatio EnsembleRatio::operator*(const EnsembleRatio& rhs) const + { + EnsembleRatio ret = *this; + ret *= rhs; + return ret; + } + + //---------------------------------------------------------------------- + EnsembleRatio& EnsembleRatio::operator/=(const EnsembleRatio& rhs) + { + CheckMultiverses(rhs.GetMultiverse(), __func__); + + fHist.Divide(rhs.fHist); + + return *this; + } + + //---------------------------------------------------------------------- + EnsembleRatio EnsembleRatio::operator/(const EnsembleRatio& rhs) const + { + EnsembleRatio ret = *this; + ret /= rhs; + return ret; + } +} \ No newline at end of file diff --git a/CAFAna/Core/EnsembleRatio.h b/CAFAna/Core/EnsembleRatio.h new file mode 100644 index 00000000..e9c9ca34 --- /dev/null +++ b/CAFAna/Core/EnsembleRatio.h @@ -0,0 +1,60 @@ +#pragma once + +#include "cafanacore/Ratio.h" + +#include "TGraphAsymmErrors.h" + +#include + +namespace ana +{ + class EnsembleSpectrum; + class FitMultiverse; + + class EnsembleRatio + { + public: + friend class EnsembleSpectrum; + + EnsembleRatio(const EnsembleSpectrum& num, + const EnsembleSpectrum& denom, + bool purOrEffErrs = false); + + Ratio Nominal() const {return Universe(0);} + unsigned int NUniverses() const; + Ratio Universe(unsigned int i) const; + + const FitMultiverse& GetMultiverse() const {return *fMultiverse;} + + TGraphAsymmErrors* ErrorBand() const; + + /// Wrapper for \ref CalcCovMx + Eigen::MatrixXd CovarianceMatrix(); + + /// Wrapper for \ref CalcBiasMx + Eigen::MatrixXd BiasMatrix(); + + EnsembleRatio& operator*=(const EnsembleRatio& rhs); + EnsembleRatio operator*(const EnsembleRatio& rhs) const; + + EnsembleRatio& operator/=(const EnsembleRatio& rhs); + EnsembleRatio operator/(const EnsembleRatio& rhs) const; + + protected: + friend class EnsembleReweightableSpectrum; + Eigen::ArrayXd GetEigen() const {return fHist.GetEigen();} + + void CheckMultiverses(const FitMultiverse& rhs, + const std::string& func) const; + + const FitMultiverse* fMultiverse; + Hist fHist; + LabelsAndBins fAxis; + }; + + inline EnsembleRatio operator/(const EnsembleSpectrum& lhs, + const EnsembleSpectrum& rhs) + { + return EnsembleRatio(lhs, rhs); + } +} \ No newline at end of file diff --git a/CAFAna/Core/EnsembleReweightableSpectrum.cxx b/CAFAna/Core/EnsembleReweightableSpectrum.cxx new file mode 100644 index 00000000..ee024e56 --- /dev/null +++ b/CAFAna/Core/EnsembleReweightableSpectrum.cxx @@ -0,0 +1,411 @@ +#include "CAFAna/Core/EnsembleReweightableSpectrum.h" + +#include "CAFAna/Core/EnsembleRatio.h" +#include "CAFAna/Core/FitMultiverse.h" + +#include "CAFAna/Core/Binning.h" +#include "CAFAna/Core/Ratio.h" +//#include "CAFAna/Core/Stan.h" + +#include "TDirectory.h" +#include "TH2.h" +#include "TObjString.h" + +#include +#include +#include + +namespace ana +{ + //---------------------------------------------------------------------- + EnsembleReweightableSpectrum:: + EnsembleReweightableSpectrum(IValuePairEnsembleSource& src, + const LabelsAndBins& recoAxis, + const LabelsAndBins& trueAxis) + : EnsembleReweightableSpectrum(src.GetMultiverse(), recoAxis, trueAxis) + { + fMat.resize(trueAxis.GetBins1D().NBins()+2, + (recoAxis.GetBins1D().NBins()+2) * fMultiverse->NUniv()); + + fMat.setZero(); + + src.Register(this); + } + + //---------------------------------------------------------------------- + EnsembleReweightableSpectrum:: + EnsembleReweightableSpectrum(const FitMultiverse* multiverse, + const Eigen::MatrixXd&& mat, + const LabelsAndBins& recoAxis, + const LabelsAndBins& trueAxis, + double pot, double livetime) + : fMultiverse(multiverse), fMat(mat), fPOT(pot), fLivetime(livetime), + fAxisX(recoAxis), fAxisY(trueAxis) + { + } + + //---------------------------------------------------------------------- + EnsembleReweightableSpectrum::~EnsembleReweightableSpectrum() + { + } + // why is copy constructor not working? + //---------------------------------------------------------------------- + //EnsembleReweightableSpectrum::EnsembleReweightableSpectrum(const EnsembleReweightableSpectrum& rhs) + // : fMultiverse(rhs.fMultiverse), + // fMat(rhs.fMat), + // fPOT(rhs.fPOT), + // fLivetime(rhs.fLivetime), + // fAxisX(rhs.fAxisX), + // fAxisY(rhs.fAxisY) + //{ + //} + + //---------------------------------------------------------------------- + EnsembleReweightableSpectrum& EnsembleReweightableSpectrum::operator=(const EnsembleReweightableSpectrum& rhs) + { + if(this == &rhs) return *this; + + fMultiverse = rhs.fMultiverse; + fMat = rhs.fMat; + fPOT = rhs.fPOT; + fLivetime = rhs.fLivetime; + fAxisX = rhs.fAxisX; + fAxisY = rhs.fAxisY; + + return *this; + } + + //---------------------------------------------------------------------- + void EnsembleReweightableSpectrum::FillSingle(double x, double y, double w, int universeId) + { + // Filling a single constituent universe + const int xbin = fAxisX.GetBins1D().FindBin(x); + const int ybin = fAxisY.GetBins1D().FindBin(y); + const unsigned int nbinsx = fAxisX.GetBins1D().NBins()+2; + fMat(ybin, nbinsx * universeId + xbin) += w; + } + + //---------------------------------------------------------------------- + void EnsembleReweightableSpectrum::FillEnsemble(double x, double y, const std::vector& ws) + { + const unsigned int xbin = fAxisX.GetBins1D().FindBin(x); + const unsigned int ybin = fAxisY.GetBins1D().FindBin(y); + const unsigned int nbinsx = fAxisX.GetBins1D().NBins()+2; + + const unsigned int nuniv = fMultiverse->NUniv(); + assert(ws.size() == nuniv); + + for(unsigned int univIdx = 0; univIdx < nuniv; ++univIdx) + fMat(ybin, nbinsx * univIdx + xbin) += ws[univIdx]; + } + + //---------------------------------------------------------------------- + void EnsembleReweightableSpectrum::FillPOT(double pot) + { + fPOT += pot; + } + + //---------------------------------------------------------------------- + void EnsembleReweightableSpectrum::FillLivetime(double livetime) + { + fLivetime += livetime; + } + + //---------------------------------------------------------------------- + unsigned int EnsembleReweightableSpectrum::NUniverses() const + { + return fMultiverse->NUniv(); + } + + //---------------------------------------------------------------------- + ReweightableSpectrum EnsembleReweightableSpectrum::Universe(unsigned int univIdx) const + { + const int nbinsx = fAxisX.GetBins1D().NBins()+2; + const int nbinsy = fAxisY.GetBins1D().NBins()+2; // or fMat.cols() + return ReweightableSpectrum(fMat.block(0, nbinsx*univIdx, nbinsy, nbinsx), + fAxisX, fAxisY, fPOT, fLivetime); + } + + /// Helper for \ref Unweighted + inline Eigen::ArrayXd ProjectionX(const Eigen::MatrixXd& mat) + { + return Eigen::RowVectorXd::Ones(mat.rows()) * mat; + } + + /// Helper for \ref WeightingVariable + inline Eigen::ArrayXd ProjectionY(const Eigen::MatrixXd& mat) + { + return mat * Eigen::VectorXd::Ones(mat.cols()); + } + + //---------------------------------------------------------------------- + EnsembleSpectrum EnsembleReweightableSpectrum::UnWeighted() const + { + return EnsembleSpectrum(fMultiverse, + Hist::Adopt(ProjectionX(fMat)), + fPOT, fLivetime, fAxisX); + } + + //---------------------------------------------------------------------- + EnsembleSpectrum EnsembleReweightableSpectrum::WeightingVariable() const + { + return EnsembleSpectrum(fMultiverse, + Hist::Adopt(ProjectionY(fMat)), + fPOT, fLivetime, fAxisY); + } + + //---------------------------------------------------------------------- + EnsembleSpectrum EnsembleReweightableSpectrum::WeightedBy(const Ratio& ws) const + { + // This version is appropriate for oscillations. We should probably add + // another that takes EnsembleRatio. + + const Eigen::VectorXd& vec = ws.GetEigen(); + + return EnsembleSpectrum(fMultiverse, + Hist::Adopt(Eigen::ArrayXd(vec.transpose() * fMat)), + fPOT, fLivetime, fAxisX); + } + + //---------------------------------------------------------------------- + EnsembleReweightableSpectrum& EnsembleReweightableSpectrum::PlusEqualsHelper(const EnsembleReweightableSpectrum& rhs, int sign, const std::string& func) + { + CheckMultiverses(rhs.GetMultiverse(), func); + + // In this case it would be OK to have no POT/livetime + if(rhs.fMat.sum() == 0) return *this; + + + if((!fPOT && !fLivetime) || (!rhs.fPOT && !rhs.fLivetime)){ + std::cout << "Error: can't sum EnsembleReweightableSpectrum with no POT or livetime." + << fPOT << " " << rhs.fPOT + << std::endl; + // abort(); + return *this; + } + + if(!fLivetime && !rhs.fPOT){ + std::cout << "Error: can't sum EnsembleReweightableSpectrum with POT (" + << fPOT << ") but no livetime and EnsembleReweightableSpectrum with livetime (" + << rhs.fLivetime << " sec) but no POT." << std::endl; + abort(); + } + + if(!fPOT && !rhs.fLivetime){ + std::cout << "Error: can't sum EnsembleReweightableSpectrum with livetime (" + << fLivetime << " sec) but no POT and EnsembleReweightableSpectrum with POT (" + << rhs.fPOT << ") but no livetime." << std::endl; + abort(); + } + + // And now there are still a bunch of good cases to consider + + if(fPOT && rhs.fPOT){ + // Scale by POT when possible + fMat += rhs.fMat * sign*fPOT/rhs.fPOT; + + if(fLivetime && rhs.fLivetime){ + // If POT/livetime ratios match, keep regular lifetime, otherwise zero + // it out. + if(AlmostEqual(fLivetime*rhs.fPOT, rhs.fLivetime*fPOT)) + fLivetime = 0; + } + if(!fLivetime && rhs.fLivetime){ + // If the RHS has a livetime and we don't, copy it in (suitably scaled) + fLivetime = rhs.fLivetime * fPOT/rhs.fPOT; + } + // Otherwise, keep our own livetime (if any) + + return *this; + } + + if(fLivetime && rhs.fLivetime){ + // Scale by livetime, the only thing in common + fMat += rhs.fMat * sign*fLivetime/rhs.fLivetime; + + if(!fPOT && rhs.fPOT){ + // If the RHS has a POT and we don't, copy it in (suitably scaled) + fPOT = rhs.fPOT * fLivetime/rhs.fLivetime; + } + // Otherwise, keep our own POT (if any) + + return *this; + } + + // That should have been all the cases. I definitely want to know what + // happened if it wasn't. + std::cout << "EnsembleReweightableSpectrum::operator+=(). How did we get here? " + << fPOT << " " << fLivetime << " " + << rhs.fPOT << " " << rhs.fLivetime << std::endl; + abort(); + } + + //---------------------------------------------------------------------- + EnsembleReweightableSpectrum& EnsembleReweightableSpectrum::operator+=(const EnsembleReweightableSpectrum& rhs) + { + return PlusEqualsHelper(rhs, +1, __func__); + } + + //---------------------------------------------------------------------- + EnsembleReweightableSpectrum EnsembleReweightableSpectrum::operator+(const EnsembleReweightableSpectrum& rhs) const + { + EnsembleReweightableSpectrum ret = *this; + ret += rhs; + return ret; + } + + //---------------------------------------------------------------------- + EnsembleReweightableSpectrum& EnsembleReweightableSpectrum::operator-=(const EnsembleReweightableSpectrum& rhs) + { + return PlusEqualsHelper(rhs, -1, __func__); + } + + //---------------------------------------------------------------------- + EnsembleReweightableSpectrum EnsembleReweightableSpectrum::operator-(const EnsembleReweightableSpectrum& rhs) const + { + EnsembleReweightableSpectrum ret = *this; + ret -= rhs; + return ret; + } + + //---------------------------------------------------------------------- + void EnsembleReweightableSpectrum::SaveTo(TDirectory* dir, + const std::string& name) const + { + _SaveTo(dir, name, "EnsembleReweightableSpectrum"); + } + + //---------------------------------------------------------------------- + void EnsembleReweightableSpectrum::_SaveTo(TDirectory* dir, + const std::string& name, + const std::string& type) const + { + TDirectory* tmp = gDirectory; + + dir = dir->mkdir(name.c_str()); // switch to sbudir + dir->cd(); + + TObjString(type.c_str()).Write("type"); + + fMultiverse->SaveTo(dir, "multiverse"); + + TH2D* hist = MakeTH2D("hist", "", + Binning::Simple(fMat.cols(), 0, fMat.cols()), + fAxisY.GetBins1D()); + hist->GetXaxis()->SetTitle(fAxisX.GetLabel1D().c_str()); + hist->GetYaxis()->SetTitle(fAxisY.GetLabel1D().c_str()); + for(int i = 0; i < fMat.cols(); ++i){ + for(int j = 0; j < fMat.rows(); ++j){ + hist->SetBinContent(i, j, fMat(j, i)); + } + } + hist->Write("hist"); + + TH1D hPot("", "", 1, 0, 1); + hPot.Fill(.5, fPOT); + hPot.Write("pot"); + TH1D hLivetime("", "", 1, 0, 1); + hLivetime.Fill(.5, fLivetime); + hLivetime.Write("livetime"); + + for(unsigned int i = 0; i < fAxisX.NDimensions(); ++i){ + TObjString(fAxisX.GetLabels()[i].c_str()).Write(TString::Format("label%d", i).Data()); + fAxisX.GetBinnings()[i].SaveTo(dir, TString::Format("bins%d", i).Data()); + } + + for(unsigned int i = 0; i < fAxisY.NDimensions(); ++i){ + TObjString(fAxisY.GetLabels()[i].c_str()).Write(TString::Format("labely%d", i).Data()); + fAxisY.GetBinnings()[i].SaveTo(dir, TString::Format("binsy%d", i).Data()); + } + + dir->Write(); + delete dir; + + delete hist; + + tmp->cd(); + } + + //---------------------------------------------------------------------- + std::unique_ptr EnsembleReweightableSpectrum::LoadFrom(TDirectory* dir, const std::string& name) + { + dir = dir->GetDirectory(name.c_str()); // switch to subdir + assert(dir); + + TObjString* tag = (TObjString*)dir->Get("type"); + assert(tag); + assert(tag->GetString() == "EnsembleReweightableSpectrum"); + delete tag; + + TH2D* spect = (TH2D*)dir->Get("hist"); + assert(spect); + TH1* hPot = (TH1*)dir->Get("pot"); + assert(hPot); + TH1* hLivetime = (TH1*)dir->Get("livetime"); + assert(hLivetime); + + std::vector labels, labelsy; + std::vector bins, binsy; + + for(int i = 0; ; ++i){ + const std::string subname = TString::Format("bins%d", i).Data(); + TDirectory* subdir = dir->GetDirectory(subname.c_str()); + if(!subdir) break; + delete subdir; + bins.push_back(*Binning::LoadFrom(dir, subname.c_str())); + TObjString* label = (TObjString*)dir->Get(TString::Format("label%d", i)); + labels.push_back(label ? label->GetString().Data() : ""); + } + + for(int i = 0; ; ++i){ + const std::string subname = TString::Format("binsy%d", i).Data(); + TDirectory* subdir = dir->GetDirectory(subname.c_str()); + if(!subdir) break; + delete subdir; + binsy.push_back(*Binning::LoadFrom(dir, subname.c_str())); + TObjString* labely = (TObjString*)dir->Get(TString::Format("labely%d", i)); + labelsy.push_back(labely ? labely->GetString().Data() : ""); + } + + // Backwards compatibility + if(labelsy.empty()) labelsy.push_back(spect->GetYaxis()->GetTitle()); + if(binsy.empty()) binsy.push_back(Binning::FromTAxis(spect->GetYaxis())); + + const LabelsAndBins xax(labels, bins); + const LabelsAndBins yax(labelsy, binsy); + + const FitMultiverse* multiverse = FitMultiverse::LoadFrom(dir, "multiverse"); + + // ROOT histogram storage is row-major, but Eigen is column-major by + // default + typedef Eigen::Matrix MatRowMajor; + std::unique_ptr ret(new EnsembleReweightableSpectrum( + multiverse, + Eigen::Map(spect->GetArray(), + yax.GetBins1D().NBins()+2, + (xax.GetBins1D().NBins()+2) * multiverse->NUniv()), + xax, yax, hPot->Integral(0, -1), hLivetime->Integral(0, -1))); + + delete spect; + + delete hPot; + delete hLivetime; + + delete dir; + + return ret; + } + + //---------------------------------------------------------------------- + void EnsembleReweightableSpectrum::CheckMultiverses(const FitMultiverse& rhs, + const std::string& func) const + { + if(&rhs == fMultiverse) return; + + std::cout << "EnsembleReweightableSpectrum::" << func << ": attempting to combine two spectra made with different multiverses: " << std::endl; + std::cout << " " << fMultiverse->ShortName() << std::endl; + std::cout << "vs" << std::endl; + std::cout << rhs.ShortName() << std::endl; + abort(); + } +} \ No newline at end of file diff --git a/CAFAna/Core/EnsembleReweightableSpectrum.h b/CAFAna/Core/EnsembleReweightableSpectrum.h new file mode 100644 index 00000000..f58c4dc7 --- /dev/null +++ b/CAFAna/Core/EnsembleReweightableSpectrum.h @@ -0,0 +1,122 @@ +#pragma once + +#include "CAFAna/Core/EnsembleSpectrum.h" + +#include "cafanacore/ReweightableSpectrum.h" + +#include + +class TDirectory; + +namespace ana +{ + class FitMultiverse; + + template class _Var; + + /// %Spectrum with the value of a second variable, allowing for reweighting + class EnsembleReweightableSpectrum: public IValuePairEnsembleSink + { + public: + EnsembleReweightableSpectrum(IValuePairEnsembleSource& src, + const LabelsAndBins& recoAxis, + const LabelsAndBins& trueAxis); + + template + EnsembleReweightableSpectrum(_IRecordEnsembleSource& src, + const _HistAxis<_Var>& recoAxis, + const _HistAxis<_Var>& trueAxis) + : EnsembleReweightableSpectrum(src.GetVars(recoAxis.GetVar1D(), trueAxis.GetVar1D()), recoAxis, trueAxis) + { + } + + virtual ~EnsembleReweightableSpectrum(); + // why is copy constructor not working? + //EnsembleReweightableSpectrum(const EnsembleReweightableSpectrum& rhs); + EnsembleReweightableSpectrum& operator=(const EnsembleReweightableSpectrum& rhs); + + virtual void FillSingle(double x, double y, double w, int universeId) override; + + virtual void FillEnsemble(double x, double y, const std::vector& ws) override; + + virtual void FillPOT(double pot) override; + virtual void FillLivetime(double livetime) override; + + double POT() const{return fPOT;} + double Livetime() const{return fLivetime;} + + EnsembleSpectrum UnWeighted() const; + + EnsembleSpectrum WeightingVariable() const; + + /// Reco spectrum with truth weights applied + EnsembleSpectrum WeightedBy(const Ratio& weights) const; + +// Not implemented for now + /// Rescale bins so that \ref WeightingVariable will return \a target +// void ReweightToTrueSpectrum(const EnsembleSpectrum& target); + /// Recale bins so that \ref Unweighted will return \a target +// void ReweightToRecoSpectrum(const EnsembleSpectrum& target); + + // Arithmetic operators are as if these are unlike samples, each a + // contribution to one total, not seperate sources of stats for the same + // sample. + EnsembleReweightableSpectrum& operator+=(const EnsembleReweightableSpectrum& rhs); + EnsembleReweightableSpectrum operator+(const EnsembleReweightableSpectrum& rhs) const; + + EnsembleReweightableSpectrum& operator-=(const EnsembleReweightableSpectrum& rhs); + EnsembleReweightableSpectrum operator-(const EnsembleReweightableSpectrum& rhs) const; + + void SaveTo(TDirectory* dir, const std::string& name) const; + + static std::unique_ptr LoadFrom(TDirectory* dir, const std::string& name); + + unsigned int NDimensions() const{return fAxisX.NDimensions();} + + unsigned int NUniverses() const; + ReweightableSpectrum Nominal() const {return Universe(0);} + ReweightableSpectrum Universe(unsigned int univIdx) const; + + // TODO consider naming confusion with Universe() above + const FitMultiverse& GetMultiverse() const {return *fMultiverse;} + + const std::vector& GetLabels() const {return fAxisX.GetLabels();} + const std::vector& GetBinnings() const {return fAxisX.GetBinnings();} + const std::vector& GetTrueBinnings() const {return fAxisY.GetBinnings();} + + protected: + // Derived classes can be trusted take care of their own construction + EnsembleReweightableSpectrum(const FitMultiverse* multiverse, + const LabelsAndBins& axisX, + const LabelsAndBins& axisY) + : fMultiverse(multiverse), + fPOT(0), fLivetime(0), + fAxisX(axisX), fAxisY(axisY) + { + } + + // Helper for LoadFrom + EnsembleReweightableSpectrum(const FitMultiverse* multiverse, + const Eigen::MatrixXd&& mat, + const LabelsAndBins& recoAxis, + const LabelsAndBins& trueAxis, + double pot, double livetime); + + + EnsembleReweightableSpectrum& PlusEqualsHelper(const EnsembleReweightableSpectrum& rhs, int sign, const std::string& func); + + void _SaveTo(TDirectory* dir, + const std::string& name, + const std::string& type) const; + + void CheckMultiverses(const FitMultiverse& rhs, const std::string& func) const; + + const FitMultiverse* fMultiverse; + + Eigen::MatrixXd fMat; + double fPOT; + double fLivetime; + + LabelsAndBins fAxisX, fAxisY; + }; +} \ No newline at end of file diff --git a/CAFAna/Core/EnsembleSpectrum.cxx b/CAFAna/Core/EnsembleSpectrum.cxx new file mode 100644 index 00000000..908df76f --- /dev/null +++ b/CAFAna/Core/EnsembleSpectrum.cxx @@ -0,0 +1,521 @@ +#include "CAFAna/Core/EnsembleSpectrum.h" + +#include "CAFAna/Core/EnsembleRatio.h" + +#include "CAFAna/Core/FitMultiverse.h" +#include "CAFAna/Core/Utilities.h" + +#include "TDirectory.h" +#include "TGraphAsymmErrors.h" +#include "TH1.h" +#include "TObjString.h" +#include "TPad.h" +#include + +namespace ana +{ + //---------------------------------------------------------------------- + EnsembleSpectrum::EnsembleSpectrum(IValueEnsembleSource& src, + const LabelsAndBins& axis) + : fMultiverse(src.GetMultiverse()), + fHist(Hist::Zero((axis.GetBins1D().NBins()+2) * fMultiverse->NUniv())), + fPOT(0), fLivetime(0), + fAxis(axis) + { + src.Register(this); + } + + //---------------------------------------------------------------------- + EnsembleSpectrum EnsembleSpectrum::MergeSpectra(const std::vector specs, + const FitMultiverse* multiverse) + { + + // we take characteristics from the first spectrum + LabelsAndBins labelsAndBins = LabelsAndBins(specs[0].GetLabels(), specs[0].GetBinnings()); + double pot = specs[0].POT(); + double livetime = specs[0].Livetime(); + long unsigned int bins = labelsAndBins.GetBins1D().NBins(); + + // are these two extrabins overflow and underflow? + //Eigen::ArrayXd data(bins+2, 1); + // not sure why this one works but not the one above + // we will replace contents here with that of th edifferent spectra + Eigen::ArrayXd data = specs[0].GetEigen().replicate(multiverse->NUniv(), 1); + for ( unsigned int i = 0; iNUniv(); i++){ + // sanity checks + assert(specs[i].ToTH1(pot).GetNbinsX()==bins && "one of the spectra has different nbins!"); + assert(specs[i].POT() == pot && "one of the spectra has a different POT!"); + assert(specs[i].Livetime() == livetime && "one of the spectra has a different livetime!"); + + // get this universe spectra eigenarray + Eigen::ArrayXd spec = specs[i].GetEigen(); + // copy into new array + for (unsigned int b = 0; b <= bins ; b++){ + data[ b + (bins+2)*i ] = spec[b]; + } + } + + assert( data.rows() == fHist.GetEigen().rows() && "data and hist are different size"); + + return EnsembleSpectrum(multiverse, Hist::Adopt(std::move(data)), specs[0].POT(), specs[0].Livetime(), + LabelsAndBins(specs[0].GetLabels(), specs[0].GetBinnings())); + } + + //---------------------------------------------------------------------- + EnsembleSpectrum EnsembleSpectrum::MergeEnsembles( const std::vector ensembles, + const FitMultiverse* multiverse) + { + + unsigned int nunivs = 0; + for (auto & ensemble : ensembles){ + nunivs += ensemble.NUniverses(); + } + nunivs -= ensembles.size(); // subtract all nominals (number of ensembles), + nunivs += 1; // and add one more (we just need one nom) + + // need something that stitches together the different multiverses + // in the meantime user has to make sure the multiverse provided matches the ensembles given... + assert(multiverse->NUniv() == nunivs && "The FitMultiverse provided does not match the size of EnsembleSpectrum"); + + LabelsAndBins labelsAndBins = LabelsAndBins(ensembles[0].Nominal().GetLabels(), ensembles[0].GetBinnings()); + double pot = ensembles[0].Nominal().POT(); + double livetime = ensembles[0].Nominal().Livetime(); + long unsigned int bins = labelsAndBins.GetBins1D().NBins(); + + + //we will store data here + Eigen::ArrayXd data = ensembles[0].Nominal().GetEigen().replicate(nunivs, 1); + // first copy the nominal of first ensemble, assuming they are all the same + Eigen::ArrayXd nom = ensembles[0].Nominal().GetEigen(); + for (unsigned int b = 0; b <= bins ; b++){ + data[ b ] = nom[b]; + } + + // now the rest of the universes + unsigned int univcount = 1; + for (unsigned int i = 0; iNUniv(), 1); + + return EnsembleSpectrum(multiverse, Hist::Adopt(std::move(data)), spec.POT(), spec.Livetime(), + LabelsAndBins(spec.GetLabels(), spec.GetBinnings())); + } + + //---------------------------------------------------------------------- + void EnsembleSpectrum::FillSingle(double x, double w, int universeId) + { + // Filling a single constituent universe + const int bin = fAxis.GetBins1D().FindBin(x); + fHist.Fill((fAxis.GetBins1D().NBins()+2) * universeId + bin, w); + } + + //---------------------------------------------------------------------- + void EnsembleSpectrum::FillEnsemble(double x, const std::vector& ws) + { + const unsigned int bin = fAxis.GetBins1D().FindBin(x); + const unsigned int nbins = fAxis.GetBins1D().NBins()+2; + + const unsigned int nuniv = fMultiverse->NUniv(); + assert(ws.size() == nuniv); + + for(unsigned int univIdx = 0; univIdx < nuniv; ++univIdx) + fHist.Fill(nbins * univIdx + bin, ws[univIdx]); + } + + //---------------------------------------------------------------------- + void EnsembleSpectrum::FillPOT(double pot) + { + fPOT += pot; + } + + //---------------------------------------------------------------------- + void EnsembleSpectrum::FillLivetime(double livetime) + { + fLivetime += livetime; + } + + //---------------------------------------------------------------------- + unsigned int EnsembleSpectrum::NUniverses() const + { + return fMultiverse->NUniv(); + } + + //---------------------------------------------------------------------- + Spectrum EnsembleSpectrum::Universe(unsigned int univIdx) const + { + const int nbins = fAxis.GetBins1D().NBins()+2; + if(fHist.HasStan()){ + return Spectrum(Eigen::ArrayXstan(fHist.GetEigenStan().segment(nbins*univIdx, nbins)), + fAxis, fPOT, fLivetime); + } + else{ + return Spectrum(Eigen::ArrayXd(fHist.GetEigen().segment(nbins*univIdx, nbins)), + fAxis, fPOT, fLivetime); + } + } + + //---------------------------------------------------------------------- + TGraphAsymmErrors* EnsembleSpectrum::ErrorBand(double exposure, + EExposureType expotype, + EBinType bintype) const + { + // TODO lots of code duplication with EnsembleRatio + + const Eigen::ArrayXd arr = fHist.GetEigen() * exposure / (expotype == kPOT ? fPOT : fLivetime); + + TGraphAsymmErrors* g = new TGraphAsymmErrors; + + const int nbins = fAxis.GetBins1D().NBins()+2; + const std::vector& edges = fAxis.GetBins1D().Edges(); + + for(int binIdx = 1; binIdx+1 < nbins; ++binIdx){ + const double dx = edges[binIdx] - edges[binIdx-1]; + assert(dx > 0); + + const double xnom = (edges[binIdx-1] + edges[binIdx]) / 2; // bin center + const double ynom = (bintype == kBinDensity) ? arr[binIdx] / dx : arr[binIdx]; + g->SetPoint(binIdx-1, xnom, ynom); + + std::vector ys; + ys.reserve(NUniverses()-1); + for(unsigned int univIdx = 1; univIdx < NUniverses(); ++univIdx) + ys.push_back((bintype == kBinDensity) ? arr[univIdx*nbins + binIdx] / dx : arr[univIdx*nbins + binIdx]); + + // 1 sigma + const double y0 = FindQuantile(.5-0.6827/2, ys); + const double y1 = FindQuantile(.5+0.6827/2, ys); + + // It's theoretically possible for the central value to be outside the + // error bands - clamp to zero in that case + g->SetPointError(binIdx-1, dx/2, dx/2, + std::max(ynom-y0, 0.), + std::max(y1-ynom, 0.)); + } // end for binIdx + + return g; + } + + //---------------------------------------------------------------------- + Eigen::MatrixXd EnsembleSpectrum::CovarianceMatrix(const double exposure, EExposureType expotype) + { + assert (fMultiverse->MultiverseType() == kRandomGas); + + const Eigen::ArrayXd& arr = fHist.GetEigen() * exposure / (expotype == kPOT ? fPOT : fLivetime); + + const int nbins = fAxis.GetBins1D().NBins()+2; + std::vector histVec; + histVec.reserve(NUniverses()); + + for(unsigned int univIdx = 1; univIdx < NUniverses(); ++univIdx) + histVec.push_back(arr.segment(nbins*univIdx, nbins)); + + return ana::CalcCovMx(histVec); + } + + //---------------------------------------------------------------------- + Eigen::MatrixXd EnsembleSpectrum::BiasMatrix(const double exposure, EExposureType expotype) + { + assert (fMultiverse->MultiverseType() == kRandomGas); + + const Eigen::ArrayXd& arr = fHist.GetEigen() * exposure / (expotype == kPOT ? fPOT : fLivetime); + + const int nbins = fAxis.GetBins1D().NBins()+2; + std::vector histVec; + histVec.reserve(NUniverses()); + + for(unsigned int univIdx = 1; univIdx < NUniverses(); ++univIdx) + histVec.push_back(arr.segment(nbins*univIdx, nbins)); + + return ana::CalcBiasMx(arr.segment(0, nbins), histVec); + } + + //---------------------------------------------------------------------- + void EnsembleSpectrum::Scale(double c) + { + fHist.Scale(c); + } + + //---------------------------------------------------------------------- + EnsembleSpectrum& EnsembleSpectrum::PlusEqualsHelper(const EnsembleSpectrum& rhs, int sign, const std::string& func) + { + CheckMultiverses(rhs.GetMultiverse(), func); + + // In this case it would be OK to have no POT/livetime + if(rhs.fHist.Initialized() && rhs.fHist.Integral() == 0) return *this; + + if((!fPOT && !fLivetime) || (!rhs.fPOT && !rhs.fLivetime)){ + std::cout << "Error: can't sum Spectrum with no POT or livetime: " + << fPOT << " " << rhs.fPOT << " " << fLivetime << " " << rhs.fLivetime + << std::endl; + abort(); + } + + if(!fLivetime && !rhs.fPOT){ + std::cout << "Error: can't sum Spectrum with POT (" + << fPOT << ") but no livetime and Spectrum with livetime (" + << rhs.fLivetime << " sec) but no POT." << std::endl; + abort(); + } + + if(!fPOT && !rhs.fLivetime){ + std::cout << "Error: can't sum Spectrum with livetime (" + << fLivetime << " sec) but no POT and Spectrum with POT (" + << rhs.fPOT << ") but no livetime." << std::endl; + abort(); + } + + // And now there are still a bunch of good cases to consider + + if(fPOT && rhs.fPOT){ + // Scale by POT when possible + fHist.Add(rhs.fHist, sign*fPOT/rhs.fPOT); + + if(fLivetime && rhs.fLivetime){ + // If POT/livetime ratios match, keep regular lifetime, otherwise zero + // it out. + if(!AlmostEqual(fLivetime*rhs.fPOT, rhs.fLivetime*fPOT)) + fLivetime = 0; + } + if(!fLivetime && rhs.fLivetime){ + // If the RHS has a livetime and we don't, copy it in (suitably scaled) + fLivetime = rhs.fLivetime * fPOT/rhs.fPOT; + } + // Otherwise, keep our own livetime (if any) + + return *this; + } + + if(fLivetime && rhs.fLivetime){ + // Scale by livetime, the only thing in common + fHist.Add(rhs.fHist, sign*fLivetime/rhs.fLivetime); + + if(!fPOT && rhs.fPOT){ + // If the RHS has a POT and we don't, copy it in (suitably scaled) + fPOT = rhs.fPOT * fLivetime/rhs.fLivetime; + } + // Otherwise, keep our own POT (if any) + + return *this; + } + + // That should have been all the cases. I definitely want to know what + // happened if it wasn't. + std::cout << "EnsembleSpectrum::operator+=(). How did we get here? " + << fPOT << " " << fLivetime << " " + << rhs.fPOT << " " << rhs.fLivetime << std::endl; + abort(); + } + + //---------------------------------------------------------------------- + EnsembleSpectrum& EnsembleSpectrum::operator+=(const EnsembleSpectrum& rhs) + { + return PlusEqualsHelper(rhs, +1, __func__); + } + + //---------------------------------------------------------------------- + EnsembleSpectrum EnsembleSpectrum::operator+(const EnsembleSpectrum& rhs) const + { + EnsembleSpectrum ret = *this; + ret += rhs; + return ret; + } + + //---------------------------------------------------------------------- + EnsembleSpectrum& EnsembleSpectrum::operator-=(const EnsembleSpectrum& rhs) + { + return PlusEqualsHelper(rhs, -1, __func__); + } + + //---------------------------------------------------------------------- + EnsembleSpectrum EnsembleSpectrum::operator-(const EnsembleSpectrum& rhs) const + { + EnsembleSpectrum ret = *this; + ret -= rhs; + return ret; + } + + //---------------------------------------------------------------------- + EnsembleSpectrum& EnsembleSpectrum::operator*=(const EnsembleRatio& rhs) + { + CheckMultiverses(rhs.GetMultiverse(), __func__); + fHist.Multiply(rhs.fHist); + + return *this; + } + + //---------------------------------------------------------------------- + EnsembleSpectrum EnsembleSpectrum::operator*(const EnsembleRatio& rhs) const + { + EnsembleSpectrum ret = *this; + ret *= rhs; + return ret; + } + + //---------------------------------------------------------------------- + EnsembleSpectrum& EnsembleSpectrum::operator/=(const EnsembleRatio& rhs) + { + CheckMultiverses(rhs.GetMultiverse(), __func__); + fHist.Divide(rhs.fHist); + + return *this; + } + + //---------------------------------------------------------------------- + EnsembleSpectrum EnsembleSpectrum::operator/(const EnsembleRatio& rhs) const + { + EnsembleSpectrum ret = *this; + ret /= rhs; + return ret; + } + + //---------------------------------------------------------------------- + void EnsembleSpectrum::SaveTo(TDirectory* dir, const std::string& name) const + { + TDirectory* tmp = gDirectory; + + dir = dir->mkdir(name.c_str()); // switch to subdir + dir->cd(); + + TObjString("EnsembleSpectrum").Write("type"); + + fMultiverse->SaveTo(dir, "multiverse"); + + // TODO potentially version of Write() that doesn't take binning + fHist.Write(Binning::Simple(fHist.GetNbinsX(), 0, fHist.GetNbinsX())); + + TH1D hPot("", "", 1, 0, 1); + hPot.Fill(.5, fPOT); + hPot.Write("pot"); + TH1D hLivetime("", "", 1, 0, 1); + hLivetime.Fill(.5, fLivetime); + hLivetime.Write("livetime"); + + for(unsigned int i = 0; i < NDimensions(); ++i){ + TObjString(GetLabels()[i].c_str()).Write(TString::Format("label%d", i).Data()); + GetBinnings()[i].SaveTo(dir, TString::Format("bins%d", i).Data()); + } + + dir->Write(); + delete dir; + + tmp->cd(); + } + + //---------------------------------------------------------------------- + EnsembleSpectrum::EnsembleSpectrum(const FitMultiverse* multiverse, + const Hist&& hist, + double pot, + double livetime, + const LabelsAndBins& axis) + : fMultiverse(multiverse), fHist(hist), fPOT(pot), fLivetime(livetime), fAxis(axis) + { + } + + //---------------------------------------------------------------------- + std::unique_ptr EnsembleSpectrum::LoadFrom(TDirectory* topdir, const std::string& name) + { + std::unique_ptr dir(topdir->GetDirectory(name.c_str())); // switch to subdir + assert(dir); + + DontAddDirectory guard; + + std::unique_ptr tag((TObjString*)dir->Get("type")); + assert(tag); + assert(tag->GetString() == "EnsembleSpectrum"); + + std::unique_ptr hPot((TH1*)dir->Get("pot")); + assert(hPot); + std::unique_ptr hLivetime((TH1*)dir->Get("livetime")); + assert(hLivetime); + + // TODO LabelsAndBins::LoadFrom() or FromDirectory() + std::vector labels; + std::vector bins; + for(int i = 0; ; ++i){ + const std::string subname = TString::Format("bins%d", i).Data(); + TDirectory* subdir = dir->GetDirectory(subname.c_str()); + if(!subdir) break; + delete subdir; + bins.push_back(*Binning::LoadFrom(dir.get(), subname)); + std::unique_ptr label((TObjString*)dir->Get(TString::Format("label%d", i))); + labels.push_back(label->GetString().Data()); + } + + return std::unique_ptr(new EnsembleSpectrum(FitMultiverse::LoadFrom(dir.get(), "multiverse"), + Hist::FromDirectory(dir.get()), + hPot->GetBinContent(1), + hLivetime->GetBinContent(1), + LabelsAndBins(labels, bins))); + } + + //---------------------------------------------------------------------- + void EnsembleSpectrum::CheckMultiverses(const FitMultiverse& rhs, + const std::string& func) const + { + if(&rhs == fMultiverse) return; + + std::cout << "EnsembleSpectrum::" << func << ": attempting to combine two spectra made with different multiverses: " << std::endl; + std::cout << " " << fMultiverse->ShortName() << std::endl; + std::cout << "vs" << std::endl; + std::cout << rhs.ShortName() << std::endl; + abort(); + } + + //---------------------------------------------------------------------- + void DrawErrorBand(TH1* nom, TGraphAsymmErrors* band, int bandCol, double alpha) + { + if(bandCol == -1) bandCol = nom->GetLineColor()-10; // hopefully a lighter version + + // Check if this pad has already been drawn in + const bool same = gPad && !gPad->GetListOfPrimitives()->IsEmpty(); + + nom->Draw(same ? "hist same" : "hist"); + + band->SetFillColorAlpha(bandCol, alpha); + band->Draw("e2 same"); + + nom->Draw("hist same"); + + // If we are the first spectrum to draw, scale the y-axis appropriately to + // fit the error band as well as the nominal + if(!same){ + double maxY = 0; + // Don't consider underflow or overflow bins when determining maximum + for(int i = 1; i < band->GetN()-1; ++i){ + if(band->GetY()[i] > 1e99) continue; // effectively infinite + maxY = std::max(maxY, band->GetY()[i] + band->GetErrorYhigh(i)); + } + + // Use non-zero lower value so that SetLogy() still works + nom->GetYaxis()->SetRangeUser(1e-10, 1.1 * maxY); + } + + gPad->RedrawAxis(); + } +} \ No newline at end of file diff --git a/CAFAna/Core/EnsembleSpectrum.h b/CAFAna/Core/EnsembleSpectrum.h new file mode 100644 index 00000000..3bfc082d --- /dev/null +++ b/CAFAna/Core/EnsembleSpectrum.h @@ -0,0 +1,141 @@ +#pragma once + +#include "cafanacore/Spectrum.h" + +#include "CAFAna/Core/Cut.h" +#include "CAFAna/Core/HistAxis.h" +#include "CAFAna/Core/IRecordSource.h" +#include "CAFAna/Core/Weight.h" + +#include + +class TGraphAsymmErrors; + +namespace ana +{ + class EnsembleRatio; + class FitMultiverse; + + class EnsembleSpectrum : public IValueEnsembleSink + { + public: + friend class EnsembleRatio; + + /// Construct an ensemble spectrum from a source of values and an axis + /// definition + EnsembleSpectrum(IValueEnsembleSource& src, const LabelsAndBins& axis); + + /// \brief Shorthand construction with a source of records and a HistAxis + /// defining the Var to extract from those records. + template + EnsembleSpectrum(_IRecordEnsembleSource& src, + const _HistAxis<_Var>& axis) + : EnsembleSpectrum(src[axis.GetVar1D()], axis) + { + } + + /// Construct an ensemble spectrum from a set of spectrum which correspond to the given multiverse + static EnsembleSpectrum MergeSpectra(const std::vector specs, const FitMultiverse* multiverse); + + /// Construct an ensemble spectrum merging several ensemble spectrum. + /// user has to make sure the multiverse provided matches the ensembles given + static EnsembleSpectrum MergeEnsembles( const std::vector ensembles, const FitMultiverse* multiverse); + +// // The only valid thing to do with such a spectrum is to assign something +// /// else into it. +// static EnsembleSpectrum Uninitialized(){return EnsembleSpectrum();} +// virtual ~EnsembleSpectrum(); + /// \brief Creates an ensemble spectrum for "data" from an input \ref Spectrum + // which is replicated nUniverse times from the multiverse which it adopts. + // Note that this is a temporary workaround for now + static EnsembleSpectrum ReplicatedData(const Spectrum& spec, const FitMultiverse* multiverse); + + Spectrum Nominal() const {return Universe(0);} + unsigned int NUniverses() const; + Spectrum Universe(unsigned int i) const; + + // TODO consider naming confusion with Universe() above + const FitMultiverse& GetMultiverse() const {return *fMultiverse;} + + double POT() const {return fPOT;} + + double Livetime() const {return fLivetime;} + + /// Result can be painted prettily with \ref DrawErrorBand + TGraphAsymmErrors* ErrorBand(double exposure, + EExposureType expotype = kPOT, + EBinType bintype = kBinContent) const; + + /// Wrapper for \ref CalcCovMx + Eigen::MatrixXd CovarianceMatrix(const double exposure, EExposureType expotype=kPOT); + + /// Wrapper for \ref CalcBiasMx + Eigen::MatrixXd BiasMatrix(const double exposure, EExposureType expotype=kPOT); + + virtual void FillSingle(double x, double w, int universeId) override; + + virtual void FillEnsemble(double x, const std::vector& ws) override; + + virtual void FillPOT(double pot) override; + + /// DO NOT USE UNLESS YOU ARE 110% CERTAIN THERE ISN'T A BETTER WAY! + void OverridePOT(double newpot) {fPOT = newpot;} + + virtual void FillLivetime(double livetime) override; + + void Scale(double c); + + EnsembleSpectrum& operator+=(const EnsembleSpectrum& rhs); + EnsembleSpectrum operator+(const EnsembleSpectrum& rhs) const; + + EnsembleSpectrum& operator-=(const EnsembleSpectrum& rhs); + EnsembleSpectrum operator-(const EnsembleSpectrum& rhs) const; + + EnsembleSpectrum& operator*=(const EnsembleRatio& rhs); + EnsembleSpectrum operator*(const EnsembleRatio& rhs) const; + + EnsembleSpectrum& operator/=(const EnsembleRatio& rhs); + EnsembleSpectrum operator/(const EnsembleRatio& rhs) const; + + void SaveTo(TDirectory* dir, const std::string& name) const; + static std::unique_ptr LoadFrom(TDirectory* dir, + const std::string& name); + + unsigned int NDimensions() const{return fAxis.NDimensions();} + std::vector GetLabels() const {return fAxis.GetLabels();} + std::vector GetBinnings() const {return fAxis.GetBinnings();} + + protected: + friend class EnsembleReweightableSpectrum; + + /// Helper for LoadFrom() + EnsembleSpectrum(const FitMultiverse* multiverse, + const Hist&& hist, + double pot, + double livetime, + const LabelsAndBins& axis); + + void CheckMultiverses(const FitMultiverse& rhs, + const std::string& func) const; + + /// Helper for operator+= and operator-= + EnsembleSpectrum& PlusEqualsHelper(const EnsembleSpectrum& rhs, int sign, + const std::string& func); + + const FitMultiverse* fMultiverse; + + mutable Hist fHist; + mutable double fPOT; + mutable double fLivetime; + mutable LabelsAndBins fAxis; + }; + + // Commutative + inline EnsembleSpectrum operator*(const EnsembleRatio& lhs, const EnsembleSpectrum& rhs){return rhs*lhs;} + inline EnsembleSpectrum operator/(const EnsembleRatio& lhs, const EnsembleSpectrum& rhs){return rhs/lhs;} + + void DrawErrorBand(TH1* nom, + TGraphAsymmErrors* band, + int bandCol = -1, + double alpha = 1); +} \ No newline at end of file diff --git a/CAFAna/Core/EnsembleSpectrumMerger.cxx b/CAFAna/Core/EnsembleSpectrumMerger.cxx new file mode 100644 index 00000000..af3411d2 --- /dev/null +++ b/CAFAna/Core/EnsembleSpectrumMerger.cxx @@ -0,0 +1,65 @@ +#include "CAFAna/Core/EnsembleSpectrum.h" + +#include "CAFAna/Core/EnsembleRatio.h" + +#include "CAFAna/Core/FitMultiverse.h" +#include "CAFAna/Core/Utilities.h" +#include "CAFAna/Core/EnsembleSpectrum.h" +#include "CAFAna/Core/EnsembleSpectrumMerger.h" +#include +#include + + +namespace ana{ + + EnsembleSpectrumMerger::EnsembleSpectrumMerger(std::vector< Spectrum> specs, + const FitMultiverse* multiverse, + const LabelsAndBins& axis) + + EnsembleSpectrum EnsembleSpectrumMerger::GetEnsembleSpectrum + : fMultiverse(multiverse), + fHist(Hist::Zero((axis.GetBins1D().NBins()+2) * fMultiverse->NUniv())), + fPOT(specs[0].POT()), + fLivetime(specs[0].Livetime()), + fAxis(axis) + { + + std::cout<< "how many multiverses? "<< fMultiverse->NUniv()<NUniv());// append here all the spectra + Eigen::ArrayXd data(bins+2, 1); + for ( unsigned int i = 0; iNUniv(); i++){ + // sanity checks + assert(specs[i].ToTH1(pot).GetNbinsX()==bins && "one of the spectra has different nbins!"); + assert(specs[i].POT() == pot && "one of the spectra has a different POT!"); + assert(specs[i].Livetime() == livetime && "one of the spectra has a different livetime!"); + + // get this universe spectra eigenarray + Eigen::ArrayXd spec = specs[i].GetEigen(); + // copy into new array + for (unsigned int b = 0; b <= bins ; b++){ + data[ b + (bins+2)*i ] = spec[b]; + fHist.Fill(b + (bins+2)*i, spec[b]); + } + } + + assert( data.rows() == fHist.GetEigen().rows() && "data and hist are diffesrent size"); + std::cout<<"now moving data\n"; + } + +// //---------------------------------------------------------------------- +// EnsembleSpectrumMerger::~EnsembleSpectrumMerger() +// { +// } + +} \ No newline at end of file diff --git a/CAFAna/Core/EnsembleSpectrumMerger.h b/CAFAna/Core/EnsembleSpectrumMerger.h new file mode 100644 index 00000000..ee0a0970 --- /dev/null +++ b/CAFAna/Core/EnsembleSpectrumMerger.h @@ -0,0 +1,36 @@ + +#pragma once + +#include "cafanacore/Spectrum.h" + +#include "CAFAna/Core/Cut.h" +#include "CAFAna/Core/HistAxis.h" +#include "CAFAna/Core/IRecordSource.h" +#include "CAFAna/Core/Weight.h" +#include "CAFAna/Core/EnsembleSpectrum.h" +#include + +namespace ana{ + + + class EnsembleSpectrumMerger//: public EnsembleSpectrum + { + public: + EnsembleSpectrumMerger(std::vector specs, + const FitMultiverse* multiverse, const LabelsAndBins& axis); + + // virtual ~EnsembleSpectrumMerger(); + + protected: + const FitMultiverse* fMultiverse; + + mutable Hist fHist; + mutable double fPOT; + mutable double fLivetime; + mutable LabelsAndBins fAxis; + //EnsembleSpectrumMerger(){}; + + }; + + +} \ No newline at end of file diff --git a/CAFAna/Core/FitMultiverse.h b/CAFAna/Core/FitMultiverse.h new file mode 100644 index 00000000..cd4db765 --- /dev/null +++ b/CAFAna/Core/FitMultiverse.h @@ -0,0 +1,85 @@ +#pragma once + +#include "CAFAna/Core/IFitSyst.h" + +#include +#include + +class TDirectory; + +namespace ana +{ + template using _Universe = std::unordered_map; + + enum EMultiverseType{kHypercross, kRandomGas}; + + using FitUniverse = _Universe; + + /// \brief Collection of "universes" (SystShifts) + /// + /// Two Multiverses are equivalent if-and-only-if they have the same address + /// + /// Universe zero is always the nominal universe (no systematic shifts) + class FitMultiverse: public INamed + { + public: + // User should not delete these though + virtual ~FitMultiverse() {} + + /// \brief Named constructor. Scan each parameter sequentially + /// + /// \param systs The list of systematic parameters to scan + /// \param nsigma Each parameter will be scanned from -nsigma to +nsigma + static const FitMultiverse& Hypercross(const std::vector& systs, + int nsigma = 3); + + static const unsigned int kTrulyRandom = 123456789; + + /// \brief Named constructor. Throw all parameters as gaussians + /// + /// \param systs The list of systematic parameters to vary + /// \param Nuniv Number of universes to generate + /// \param seed Pseudo-random seed. Pass Multiverse::kTrulyRandom for a + /// real random seed. Beware incompatibility between universes + /// with different seeds. + static const FitMultiverse& RandomGas(const std::vector& systs, + int Nuniv, + unsigned int seed); + + /// Total number of universes, including nominal at index 0 + unsigned int NUniv() const {return fUnivs.size();} + + /// Details of a particular universe + const FitUniverse& GetUniverse(int i) const {return fUnivs[i];} + + // TO DO: a member that returns the systematic shifts used to create this Multiverse + // std::vector GetSysts(){return } + + void SaveTo(TDirectory* dir, const std::string& name) const; + + /// Usually these return unique_ptr, but Multiverses are globally managed + static const FitMultiverse* LoadFrom(TDirectory* dir, const std::string& name); + + /// Enum that specifies the type of multiverse + // remove const? + EMultiverseType MultiverseType() const {return fMultiverseType;}; + + protected: + FitMultiverse(const std::string& shortName, + const std::string& latexName, + const std::vector& univs, + const EMultiverseType multiverseType); + + FitMultiverse(const FitMultiverse&) = delete; + + /// Special move constructor ONLY to help derived _Multiverse classes + FitMultiverse(const FitMultiverse&&); + + std::string Checksum() const; + + std::vector fUnivs; + + EMultiverseType fMultiverseType; + }; + +} \ No newline at end of file diff --git a/CAFAna/Core/FixupRecord.cxx b/CAFAna/Core/FixupRecord.cxx index cee4e5ec..13d6aa53 100644 --- a/CAFAna/Core/FixupRecord.cxx +++ b/CAFAna/Core/FixupRecord.cxx @@ -15,172 +15,175 @@ namespace ana { void FixupRecord(caf::SRProxy* sr, TTree* tr) { - // Set GENIE_ScatteringMode and eRec_FromDep - if(sr->isFD){ - sr->eRec_FromDep = sr->eDepP + sr->eDepN + sr->eDepPip + - sr->eDepPim + sr->eDepPi0 + - sr->eDepOther + sr->LepE; - - sr->GENIE_ScatteringMode = - ana::GetGENIEModeFromSimbMode(sr->mode); - } - else { - sr->eRec_FromDep = sr->eRecoP + sr->eRecoN + - sr->eRecoPip + sr->eRecoPim + - sr->eRecoPi0 + sr->eRecoOther + - sr->LepE; - sr->GENIE_ScatteringMode = int(sr->mode); // TODO make this work without cast? - } - - // Patch up isFHC which isn't set properly in FD CAFs - if(sr->isFD){ - if(sr->isFHC != 0 && sr->isFHC != 1){ - if(sr->run == 20000001 || sr->run == 20000002 || - sr->run == 20000003) { - sr->isFHC = true; - static bool once = true; - if(once) { - std::cout << "\nPatching up FD file to be considered FHC" - << std::endl; - once = false; - } - } - else if(sr->run == 20000004 || sr->run == 20000005 || - sr->run == 20000006) { - sr->isFHC = false; - static bool once = true; - if(once){ - std::cout << "\nPatching up FD file to be considered RHC" - << std::endl; - once = false; - } - } - else { - std::cout - << "When patching FD CAF with unknown isFHC, saw unknown run " - << sr->run << std::endl; - abort(); - } - } - } - else{ - // ND - if(sr->isFHC == -1){ - // nu-on-e files - sr->isFHC = true; - static bool once = true; - if (once) { - std::cout << "\nPatching up nu-on-e file to be considered FHC" - << std::endl; - once = false; - } - } - else if (sr->isFHC != 0 && sr->isFHC != 1) { - std::cout << "isFHC not set properly in ND file: " << sr->isFHC - << std::endl; - abort(); - } - } - - if(tr->GetNbranches() == 302 || tr->GetNbranches() == 280 /*ndgas*/){ - static bool once = true; - if(once){ - once = false; - std::cout << "Detected TDR-era file. Skipping CV weights, which aren't going to work" << std::endl; - } - return; - } - - // These aren't going to change during the job, so do it once up-front. - static const std::vector& XSSyst_names = GetAllXSecSystNames(); - - // HACK HACK HACK for knobs that aren't in file - static bool hackOnce = true; - static std::vector veto(XSSyst_names.size()); - if(hackOnce){ - hackOnce = false; - for(unsigned int syst_it = 0; syst_it < XSSyst_names.size(); ++syst_it){ - if(ana::GetXSecSystName(syst_it) == "Mnv2p2hGaussEnhancement_NN" || - ana::GetXSecSystName(syst_it) == "Mnv2p2hGaussEnhancement_2p2h" || - ana::GetXSecSystName(syst_it) == "Mnv2p2hGaussEnhancement_1p1h" || - ana::GetXSecSystName(syst_it) == "MissingProtonFakeData" || - ana::GetXSecSystName(syst_it) == "NuWroReweightFakeData" - ) veto[syst_it] = true; - } - } - - // HACK to survive the absence of crazyFlux values in the file - sr->wgt_CrazyFlux = std::vector(7, 1); - - // Reformat the genie systs - sr->total_xsSyst_cv_wgt = 1; - - std::vector XSSyst_cv_tmp(XSSyst_names.size()); - for(unsigned int syst_it = 0; syst_it < XSSyst_names.size(); ++syst_it){ - XSSyst_cv_tmp[syst_it] = 1; - } - - static auto AnaV = GetAnaVersion(); - if(AnaV == kV3){ - for(unsigned int syst_it = 0; syst_it < XSSyst_names.size(); ++syst_it){ - // Do some error checking here - if(std::isnan(sr->cvwgt[syst_it]) || - std::isinf(sr->cvwgt[syst_it]) || - sr->cvwgt[syst_it] == 0){ - std::cout << "Warning: " << XSSyst_names[syst_it] - << " has a bad CV of " << sr->cvwgt[syst_it] - << std::endl; - } - else { - sr->total_xsSyst_cv_wgt *= sr->cvwgt[syst_it]; - } - } - } - else{ - static std::vector alreadyWarned(XSSyst_names.size(), false); - - for(unsigned int syst_it = 0; syst_it < XSSyst_names.size(); ++syst_it){ - // Continuation of the hack from further up - if(veto[syst_it]) continue; - - if(IsDoNotIncludeSyst(syst_it)){ // Multiply CV weight back into - // response splines. - if(std::isnan(sr->cvwgt[syst_it]) || - std::isinf(sr->cvwgt[syst_it]) || - XSSyst_cv_tmp[syst_it] == 0) { - if(!alreadyWarned[syst_it]){ - alreadyWarned[syst_it] = true; - std::cout << "Warning: " << XSSyst_names[syst_it] - << " has a bad CV of " << sr->cvwgt[syst_it] - << " - will only warn once" - << std::endl; - } - } - else{ - const int Nuniv = 7; // HACK HACK HACK sr->xsSyst_wgt[syst_it].size(); - for(int univ_it = 0; univ_it < Nuniv; ++univ_it){ - sr->xsSyst_wgt[syst_it][univ_it] *= sr->cvwgt[syst_it]; - } - } - } - else{ // Include CV weight in the total - // Do some error checking here - if(std::isnan(sr->cvwgt[syst_it]) || - std::isinf(sr->cvwgt[syst_it]) || - sr->cvwgt[syst_it] == 0) { - if(!alreadyWarned[syst_it]){ - alreadyWarned[syst_it] = true; - std::cout << "Warning: " << XSSyst_names[syst_it] - << " has a bad CV of " << sr->cvwgt[syst_it] - << " - will only warn once" - << std::endl; - } - } - else{ - sr->total_xsSyst_cv_wgt *= sr->cvwgt[syst_it]; - } - } - } - } // end version switch +// // Set GENIE_ScatteringMode and eRec_FromDep +// if(sr->isFD){ +// sr->eRec_FromDep = sr->eDepP + sr->eDepN + sr->eDepPip + +// sr->eDepPim + sr->eDepPi0 + +// sr->eDepOther + sr->LepE; +// +// sr->GENIE_ScatteringMode = +// ana::GetGENIEModeFromSimbMode(sr->mode); +// } +// else { +// sr->eRec_FromDep = sr->eRecoP + sr->eRecoN + +// sr->eRecoPip + sr->eRecoPim + +// sr->eRecoPi0 + sr->eRecoOther + +// sr->LepE; +// sr->GENIE_ScatteringMode = int(sr->mode); // TODO make this work without cast? +// } +// +// // Patch up isFHC which isn't set properly in FD CAFs +// if(sr->isFD){ +// if(sr->isFHC != 0 && sr->isFHC != 1){ +// if(sr->run == 20000001 || sr->run == 20000002 || +// sr->run == 20000003) { +// sr->isFHC = true; +// static bool once = true; +// if(once) { +// std::cout << "\nPatching up FD file to be considered FHC" +// << std::endl; +// once = false; +// } +// } +// else if(sr->run == 20000004 || sr->run == 20000005 || +// sr->run == 20000006) { +// sr->isFHC = false; +// static bool once = true; +// if(once){ +// std::cout << "\nPatching up FD file to be considered RHC" +// << std::endl; +// once = false; +// } +// } +// else { +// std::cout +// << "When patching FD CAF with unknown isFHC, saw unknown run " +// << sr->run << std::endl; +// abort(); +// } +// } +// } +// else{ +// // ND +// if(sr->isFHC == -1){ +// // nu-on-e files +// sr->isFHC = true; +// static bool once = true; +// if (once) { +// std::cout << "\nPatching up nu-on-e file to be considered FHC" +// << std::endl; +// once = false; +// } +// } +// else if (sr->isFHC != 0 && sr->isFHC != 1) { +// std::cout << "isFHC not set properly in ND file: " << sr->isFHC +// << std::endl; +// abort(); +// } +// } +// +// if(tr->GetNbranches() == 302 || tr->GetNbranches() == 280 /*ndgas*/){ +// static bool once = true; +// if(once){ +// once = false; +// std::cout << "Detected TDR-era file. Skipping CV weights, which aren't going to work" << std::endl; +// } +// return; +// } +// +// // These aren't going to change during the job, so do it once up-front. +// static const std::vector& XSSyst_names = GetAllXSecSystNames(); +// +// // HACK HACK HACK for knobs that aren't in file +// static bool hackOnce = true; +// static std::vector veto(XSSyst_names.size()); +// if(hackOnce){ +// hackOnce = false; +// for(unsigned int syst_it = 0; syst_it < XSSyst_names.size(); ++syst_it){ +// if(ana::GetXSecSystName(syst_it) == "Mnv2p2hGaussEnhancement_NN" || +// ana::GetXSecSystName(syst_it) == "Mnv2p2hGaussEnhancement_2p2h" || +// ana::GetXSecSystName(syst_it) == "Mnv2p2hGaussEnhancement_1p1h" || +// ana::GetXSecSystName(syst_it) == "MissingProtonFakeData" || +// ana::GetXSecSystName(syst_it) == "NuWroReweightFakeData" +// ) veto[syst_it] = true; +// } +// } +// +// // HACK to survive the absence of crazyFlux values in the file +// sr->wgt_CrazyFlux = std::vector(7, 1); +// +// // Reformat the genie systs +// sr->total_xsSyst_cv_wgt = 1; +// +// std::vector XSSyst_cv_tmp(XSSyst_names.size()); +// for(unsigned int syst_it = 0; syst_it < XSSyst_names.size(); ++syst_it){ +// XSSyst_cv_tmp[syst_it] = 1; +// } +// +// //HACK HACK HACK - skip the CV Xsec weights for now https://github.com/DUNE/lblpwgtools/commit/4a7dffcc7b888bf615c7b1c4bb79e84f10eb716a +// //return; +// +// static auto AnaV = GetAnaVersion(); +// if(AnaV == kV3){ +// for(unsigned int syst_it = 0; syst_it < XSSyst_names.size(); ++syst_it){ +// // Do some error checking here +// if(std::isnan(sr->cvwgt[syst_it]) || +// std::isinf(sr->cvwgt[syst_it]) || +// sr->cvwgt[syst_it] == 0){ +// std::cout << "Warning: " << XSSyst_names[syst_it] +// << " has a bad CV of " << sr->cvwgt[syst_it] +// << std::endl; +// } +// else { +// sr->total_xsSyst_cv_wgt *= sr->cvwgt[syst_it]; +// } +// } +// } +// else{ +// static std::vector alreadyWarned(XSSyst_names.size(), false); +// +// for(unsigned int syst_it = 0; syst_it < XSSyst_names.size(); ++syst_it){ +// // Continuation of the hack from further up +// if(veto[syst_it]) continue; +// +// if(IsDoNotIncludeSyst(syst_it)){ // Multiply CV weight back into +// // response splines. +// if(std::isnan(sr->cvwgt[syst_it]) || +// std::isinf(sr->cvwgt[syst_it]) || +// XSSyst_cv_tmp[syst_it] == 0) { +// if(!alreadyWarned[syst_it]){ +// alreadyWarned[syst_it] = true; +// std::cout << "Warning: " << XSSyst_names[syst_it] +// << " has a bad CV of " << sr->cvwgt[syst_it] +// << " - will only warn once" +// << std::endl; +// } +// } +// else{ +// const int Nuniv = 7; // HACK HACK HACK sr->xsSyst_wgt[syst_it].size(); +// for(int univ_it = 0; univ_it < Nuniv; ++univ_it){ +// sr->xsSyst_wgt[syst_it][univ_it] *= sr->cvwgt[syst_it]; +// } +// } +// } +// else{ // Include CV weight in the total +// // Do some error checking here +// if(std::isnan(sr->cvwgt[syst_it]) || +// std::isinf(sr->cvwgt[syst_it]) || +// sr->cvwgt[syst_it] == 0) { +// if(!alreadyWarned[syst_it]){ +// alreadyWarned[syst_it] = true; +// std::cout << "Warning: " << XSSyst_names[syst_it] +// << " has a bad CV of " << sr->cvwgt[syst_it] +// << " - will only warn once" +// << std::endl; +// } +// } +// else{ +// sr->total_xsSyst_cv_wgt *= sr->cvwgt[syst_it]; +// } +// } +// } +// } // end version switch } } diff --git a/CAFAna/Core/HistAxis.h b/CAFAna/Core/HistAxis.h index c4e81507..168122cf 100644 --- a/CAFAna/Core/HistAxis.h +++ b/CAFAna/Core/HistAxis.h @@ -7,4 +7,9 @@ namespace ana { typedef _HistAxis HistAxis; + typedef _HistAxis SRHistAxis; + typedef _HistAxis TruthHistAxis; + typedef _HistAxis TruthPartHistAxis; + typedef _HistAxis RecoPartHistAxis; + typedef _HistAxis NDHistAxis; } diff --git a/CAFAna/Core/IRecordSink.h b/CAFAna/Core/IRecordSink.h new file mode 100644 index 00000000..d2e0b11f --- /dev/null +++ b/CAFAna/Core/IRecordSink.h @@ -0,0 +1,15 @@ +#pragma once + +#include "cafanacore/IRecordSink.h" +#include "cafanacore/IRecordEnsembleSink.h" + +#include "duneanaobj/StandardRecord/Proxy/FwdDeclare.h" + +namespace ana +{ + using ISRSink = _IRecordSink; + using IInteractionSink = _IRecordSink; + +// using ISpillEnsembleSink = _IRecordEnsembleSink; + using IInteractionEnsembleSink = _IRecordEnsembleSink; +} \ No newline at end of file diff --git a/CAFAna/Core/IRecordSource.cxx b/CAFAna/Core/IRecordSource.cxx new file mode 100644 index 00000000..36a43aab --- /dev/null +++ b/CAFAna/Core/IRecordSource.cxx @@ -0,0 +1,353 @@ +#include "CAFAna/Core/IRecordSource.h" + +#include "CAFAna/Core/Multiverse.h" + +#include "CAFAna/Core/SystShifts.h" + +#include "duneanaobj/StandardRecord/Proxy/SRProxy.h" + +# include + +namespace ana +{ + + //---------------------------------------------------------------------- + class ShiftedInteractionEnsembleSource: + public PassthroughExposure + { + public: + ShiftedInteractionEnsembleSource(IInteractionSource& src, + const Multiverse& multiverse); + + virtual void HandleRecord(const caf::SRInteractionProxy* ixn, double weight) override; + + virtual const ana::FitMultiverse* GetMultiverse() const override {return fMultiverse;} + + protected: + const ana::FitMultiverse* fMultiverse; + std::vector fShifts; + }; + + //---------------------------------------------------------------------- + ShiftedInteractionEnsembleSource:: + ShiftedInteractionEnsembleSource(IInteractionSource& src, const Multiverse& multiverse) + : fMultiverse(&multiverse) + { + src.Register(this); + + // Turn the universes into concrete SystShifts objects up-front + fShifts.reserve(multiverse.NUniv()); + // This next line is not working... + for(unsigned int i = 0; i < multiverse.NUniv(); ++i) fShifts.emplace_back(multiverse.GetUniverse(i)); + } + + //---------------------------------------------------------------------- + void ShiftedInteractionEnsembleSource::HandleRecord(const caf::SRInteractionProxy* slc, + double weight) + { + if(weight == 0) return; + + std::vector weights(fShifts.size(), weight); + + bool anyShifted = false; + + for(unsigned int univIdx = 0; univIdx < fShifts.size(); ++univIdx){ + // Need to provide a clean slate for each new set of systematic + // shifts to work from. Copying the whole StandardRecord is pretty + // expensive, so modify it in place and revert it afterwards. + + caf::SRProxySystController::BeginTransaction(); + + bool shifted = false; + + // Can special-case nominal to not pay cost of Shift() + if(!fShifts[univIdx].IsNominal()){ + // const_cast is naughty. I hope the fact that we put the record back + // afterwards absolves most sins. + fShifts[univIdx].Shift(const_cast(slc), weights[univIdx]); + // If there were only weighting systs applied then the cached + // nominal values are still valid. + shifted = caf::SRProxySystController::AnyShifted(); + } + + // Interaction was shifted or we are already in the slow path, so we have to + // handle this individually + if((shifted || anyShifted) && weights[univIdx] != 0) + for(IInteractionEnsembleSink* sink: fSinks) + sink->HandleSingleRecord(slc, weights[univIdx], univIdx); + + // Return StandardRecord to its unshifted form ready for the next + // histogram. + caf::SRProxySystController::Rollback(); + + // We entered the slow path for the first time for this universe, have to + // catch up with all the other universes we were hoping to be able to + // handle in the fast path. + if(shifted && !anyShifted){ + anyShifted = true; + + for(unsigned int prevIdx = 0; prevIdx < univIdx; ++prevIdx){ + if(weights[prevIdx] == 0) continue; + + for(IInteractionEnsembleSink* sink: fSinks){ + sink->HandleSingleRecord(slc, weights[prevIdx], prevIdx); + } + } // end for prevIdx + } // end if shifted for the first time + } // end for univIdx + + // Fast path in case none of the records got rewritten, can treat as an + // ensemble with weights. + if(!anyShifted){ + for(IInteractionEnsembleSink* sink: fSinks){ + sink->HandleEnsemble(slc, weights); + } + } + } + + //---------------------------------------------------------------------- + IInteractionEnsembleSource& IInteractionSource:: + Ensemble(const Multiverse& multiverse) + { + return fEnsembleSources.template Get(&multiverse, *this, multiverse); + } + //---------------------------------------------------------------------- + // Truth branch version of ensembles?? + + + //---------------------------------------------------------------------- + + template VectorAdaptor:: + VectorAdaptor(_IRecordSource>& src, + Func_t vecGetter) + : fVecGetter(vecGetter) + { + src.Register(this); + } + + //---------------------------------------------------------------------- + template void VectorAdaptor:: + HandleRecord(const caf::Proxy* rec, double weight) + { + for(const caf::Proxy& to: fVecGetter(rec)) + for(auto& sink: _IRecordSource>::fSinks) + sink->HandleRecord(&to, weight); + } + //---------------------------------------------------------------------- + template EnsembleVectorAdaptor:: + EnsembleVectorAdaptor(_IRecordEnsembleSource>& src, + Func_t vecGetter) + : fSource(&src), fVecGetter(vecGetter) + { + src.Register(this); + } + + //---------------------------------------------------------------------- + template void EnsembleVectorAdaptor:: + HandleSingleRecord(const caf::Proxy* rec, + double weight, + int universeId) + { + for(const caf::Proxy& to: fVecGetter(rec)) + for(auto& sink: _IRecordEnsembleSource>::fSinks) + sink->HandleSingleRecord(&to, weight, universeId); + } + + //---------------------------------------------------------------------- + template void EnsembleVectorAdaptor:: + HandleEnsemble(const caf::Proxy* rec, + const std::vector& weights) + { + for(const caf::Proxy& to: fVecGetter(rec)) + for(auto& sink: _IRecordEnsembleSource>::fSinks) + sink->HandleEnsemble(&to, weights); + } + + //---------------------------------------------------------------------- + //---------------------------------------------------------------------- + + template + const caf::Proxy>& GetRecoParticles(const caf::SRInteractionProxy* ixn) + { + if constexpr (PartType == RecoType::kDLP) + return ixn->part.dlp; + else if (PartType == RecoType::kPandora) + return ixn->part.pandora; + else if (PartType == RecoType::kPIDA) + return ixn->part.pida; + else + assert(false && "GetRecoParticles() is currently instrumented only for kDLP, kPandora or kPIDA only"); + //static_assertor RecoType " + std::to_string(PartType)); + } +// template +// const caf::Proxy>& GetTracks(const caf::SRInteractionProxy* ixn); +//{ +// +//} + template + const caf::Proxy> & GetInteractions(const caf::SRProxy* sr) + { + if constexpr(IntType == RecoType::kDLP) + return sr->common.ixn.dlp; + else if (IntType == RecoType::kPandora) + return sr->common.ixn.pandora; + else + assert(false &&"GetInteractions() is currently instrumented for RecoType kDLP or kPandora only" ); + } + + template + const caf::Proxy> & GetNDLarInteractions(const caf::SRProxy* sr) + { + if constexpr(IntType == RecoType::kDLP) + return sr->nd.lar.dlp; + else if (IntType == RecoType::kPandora) + return sr->nd.lar.pandora; + else + assert(false &&"GetNDLarInteractions() is currently instrumented for RecoType kDLP or kPandora only" ); + } + + const caf::Proxy>& + GetNuTruths(const caf::SRProxy* sr) + { + return sr->mc.nu; + } + + template + const caf::Proxy> & GetNuTruthParticles(const caf::SRTrueInteractionProxy* nu) + { + if constexpr(PartType == TruePType::kPrim) + return nu->prim; + else if (PartType == TruePType::kSec) + return nu->sec; + else if (PartType == TruePType::kPreFSI) + return nu->prefsi; + else + assert(false &&"GetNuTruthParticles() is currently instrumented for TruePType kPrim, kSec or kPreFSI only" ); + } + +// SR to Ixn or SR to TruIxn, only the matched ones? +// +//// // From True interactions to recointeractions +//// // usage: apply cuts on truth branch but get records from common branch +////template +// const caf::Proxy>& GetRecoInteractionsFromTruths(const caf::SRProxy* sr){ +// ///< Interaction ID == 'vertexID' from edep-sim (ND) or GENIE record id (FD) +// //auto nus = sr->mc.nu; +// ///< Indices of SRTrueInteraction(s), if relevant (use this index in SRTruthBranch::nu to get them) +// //auto ixns = sr->common.ixn; +// bool pdgmatch= false; +// // construct a vector of SRInteraction that match the SRTrueIteraction +// std::vector temp = sr->common.ixn.dlp; +// +// //if constexpr(IntType == RecoType::kDLP){ +// for(long unsigned nixn = 0; nixn < sr->common.ixn.dlp.size(); nixn++){ +// int recoid = sr->common.ixn.dlp[nixn].id; +// // find the truth thing.... +// pdgmatch = abs(sr->mc.nu[recoid].pdg ) == 14; +// if (pdgmatch ) temp.emplace_back(sr->common.ixn.dlp[nixn]/*the matched index interaction*/); +// } +// const caf::Proxy> ret = temp; +// return &ret; +// //} +//// else if (IntType == RecoType::kPandora) +//// sr->common.ixn.pandora.id; +//// return sr->common.ixn.pandora; +//// else +// // assert(false &&"GetRecoInteractionsFromTruths() is currently instrumented for RecoType kDLP or kPandora only" ); +// } + + //---------------------------------------------------------------------- + + // Instantiations + template class VectorAdaptor; + + template class VectorAdaptor; + + template class VectorAdaptor; + + template class VectorAdaptor; + + template class VectorAdaptor; + + template class EnsembleVectorAdaptor; + + template class EnsembleVectorAdaptor; + // ----------------------------------------------------------------------- + _IRecordSource::_IRecordSource() + { + // it would be better (lots less boilerplate) to do this in the initializers section, + // but I can't work out why it won't compile when the items are written + // in initializer list format + fParticleCollections.emplace(std::piecewise_construct, + std::forward_as_tuple(RecoType::kDLP), + std::forward_as_tuple(*this, GetRecoParticles)); + fParticleCollections.emplace(std::piecewise_construct, + std::forward_as_tuple(RecoType::kPandora), + std::forward_as_tuple(*this, GetRecoParticles)); + fParticleCollections.emplace(std::piecewise_construct, + std::forward_as_tuple(RecoType::kPIDA), + std::forward_as_tuple(*this, GetRecoParticles)); + } + + // ----------------------------------------------------------------------- + _IRecordSource::_IRecordSource() + { + fInteractionCollections.emplace(std::piecewise_construct, + std::forward_as_tuple(RecoType::kDLP), + std::forward_as_tuple(*this, GetInteractions)); + fInteractionCollections.emplace(std::piecewise_construct, + std::forward_as_tuple(RecoType::kPandora), + std::forward_as_tuple(*this, GetInteractions)); + fNDLarInteractionCollections.emplace(std::piecewise_construct, + std::forward_as_tuple(RecoType::kDLP), + std::forward_as_tuple(*this, GetNDLarInteractions)); + fNDLarInteractionCollections.emplace(std::piecewise_construct, + std::forward_as_tuple(RecoType::kPandora), + std::forward_as_tuple(*this, GetNDLarInteractions)); + } + // ----------------------------------------------------------------------- + _IRecordSource::_IRecordSource() + { + fNuTruthParticleCollections.emplace(std::piecewise_construct, + std::forward_as_tuple(TruePType::kPrim), + std::forward_as_tuple(*this, GetNuTruthParticles)); + fNuTruthParticleCollections.emplace(std::piecewise_construct, + std::forward_as_tuple(TruePType::kSec), + std::forward_as_tuple(*this, GetNuTruthParticles)); + fNuTruthParticleCollections.emplace(std::piecewise_construct, + std::forward_as_tuple(TruePType::kPreFSI), + std::forward_as_tuple(*this, GetNuTruthParticles)); + } + +// ----------------------------------------------------------------------- + _IRecordEnsembleSource::_IRecordEnsembleSource() + { + // it would be better (lots less boilerplate) to do this in the initializers section, + // but I can't work out why it won't compile when the items are written + // in initializer list format + fParticleCollections.emplace(std::piecewise_construct, + std::forward_as_tuple(RecoType::kDLP), + std::forward_as_tuple(*this, GetRecoParticles)); + fParticleCollections.emplace(std::piecewise_construct, + std::forward_as_tuple(RecoType::kPandora), + std::forward_as_tuple(*this, GetRecoParticles)); + fParticleCollections.emplace(std::piecewise_construct, + std::forward_as_tuple(RecoType::kPIDA), + std::forward_as_tuple(*this, GetRecoParticles)); + } +// ----------------------------------------------------------------------- + _IRecordEnsembleSource::_IRecordEnsembleSource() + { + fNuTruthParticleCollections.emplace(std::piecewise_construct, + std::forward_as_tuple(TruePType::kPrim), + std::forward_as_tuple(*this, GetNuTruthParticles)); + fNuTruthParticleCollections.emplace(std::piecewise_construct, + std::forward_as_tuple(TruePType::kSec), + std::forward_as_tuple(*this, GetNuTruthParticles)); + fNuTruthParticleCollections.emplace(std::piecewise_construct, + std::forward_as_tuple(TruePType::kPreFSI), + std::forward_as_tuple(*this, GetNuTruthParticles)); + } + + +} diff --git a/CAFAna/Core/IRecordSource.h b/CAFAna/Core/IRecordSource.h new file mode 100644 index 00000000..77ed7598 --- /dev/null +++ b/CAFAna/Core/IRecordSource.h @@ -0,0 +1,223 @@ +#pragma once + +#include "cafanacore/IRecordSource.h" + +#include "CAFAna/Core/IRecordSink.h" + +#include "duneanaobj/StandardRecord/Proxy/FwdDeclare.h" + +namespace ana +{ + // template class ISyst; + class ISyst; + + template class _Multiverse; + // using Multiverse = _Multiverse>; + //using MultiverseTrue = _Multiverse>; + using Multiverse = _Multiverse; + + class SystShifts; + + //---------------------------------------------------------------------- + // Introduce some aliases so we can express ourselves more succinctly + using ISRSource = _IRecordSource; + using IInteractionSource = _IRecordSource; + using INDLarInteractionSource = _IRecordSource; + using IParticleSource = _IRecordSource; + using INuTruthSource = _IRecordSource; + using INuTruthParticleSource = _IRecordSource; + //---------------------------------------------------------------------- + using IInteractionEnsembleSource = _IRecordEnsembleSource; + using ITrueInteractionEnsembleSource = _IRecordEnsembleSource; + using IParticleEnsembleSource = _IRecordEnsembleSource; + using INuTruthParticleEnsembleSource = _IRecordEnsembleSource; + //---------------------------------------------------------------------- + + enum class RecoType { + kDLP, + kPandora, + kPIDA + }; + enum class TruePType{ + kPrim, + kSec, + kPreFSI + }; + + /// Helper class for implementing looping over slices, tracks, etc + template class VectorAdaptor: + public PassthroughExposure<_IRecordSink>, + _IRecordSource>> + { + public: + typedef std::function>&(const caf::Proxy*)> Func_t; + + VectorAdaptor(_IRecordSource>& src, Func_t vecGetter); + virtual void HandleRecord(const caf::Proxy* rec, double weight) override; + protected: + Func_t fVecGetter; + }; + + //---------------------------------------------------------------------- + // Accessors needed by VectorAdaptor + + template + const caf::Proxy>& GetRecoParticles(const caf::SRInteractionProxy* ixn); + +// template +// const caf::Proxy>& GetTracks(const caf::SRInteractionProxy* ixn); +// +// template +// const caf::Proxy>& GetShowers(const caf::SRInteractionProxy* ixn);// or caf::SRProxy* sr? + + template + const caf::Proxy>& GetInteractions(const caf::SRProxy* sr); + + template + const caf::Proxy>& GetNDLarInteractions(const caf::SRProxy* sr); + + const caf::Proxy>& GetNuTruths(const caf::SRProxy* sr); + + template + const caf::Proxy>& GetNuTruthParticles(const caf::SRTrueInteractionProxy* nu); + // template + // const caf::Proxy>& GetRecoInteractionsFromTruths(const caf::SRProxy* sr); + // // usage: apply cuts on truth branch but get records from common branch + //const caf::Proxy>& GetRecoInteractionsFromTruths(const caf::SRProxy* sr); + //---------------------------------------------------------------------- + + template<> class _IRecordSource + : public _IRecordSourceDefaultImpl + { + public: + _IRecordSource(); + + // Weight-based ensembles are still supported + using _IRecordSourceDefaultImpl::Ensemble; + // But also support an ensemble based on SystShifts + IInteractionEnsembleSource& Ensemble(const Multiverse& multiverse); + + IParticleSource& RecoParticles( const RecoType kRType) {return fParticleCollections.at(kRType);} + + protected: + IDDict fEnsembleSources; + + std::unordered_map> fParticleCollections; + + }; + + template<> class _IRecordSource + : public _IRecordSourceDefaultImpl + { + public: + _IRecordSource(); + + //using _IRecordSourceDefaultImpl::Ensemble; + //ITrueInteractionEnsembleSource& Ensemble(const Multiverse& multiverse); + INuTruthParticleSource& TruthParticles(const TruePType kPType) {return fNuTruthParticleCollections.at(kPType);} + + protected: + //IDDict fEnsembleSources; + std::unordered_map> fNuTruthParticleCollections; + + }; + + + //---------------------------------------------------------------------- + // Standard Record sources also provide a source (which loops over the interactions) + template<> class _IRecordSource + : public _IRecordSourceDefaultImpl + { + public: + _IRecordSource(); + + IInteractionSource& Interactions( const RecoType kRType ) {return fInteractionCollections.at(kRType);} + INDLarInteractionSource& NDLarInteractions( const RecoType kRType ) {return fNDLarInteractionCollections.at(kRType);} + INuTruthSource& NuTruths() {return fNuTruths;} + //IInteractionSource& InteractionsTruthFiltered(){return fFilteredInteractions;} + protected: + std::unordered_map> fInteractionCollections; + std::unordered_map> fNDLarInteractionCollections; + VectorAdaptor fNuTruths{*this, GetNuTruths}; + //VectorAdaptor fFilteredInteractions{*this,GetRecoInteractionsFromTruths}; + + }; + + +// // --------------------------------- ******** +// // attempt to connect the nu tree with the reco / common tree +// +// template<> class _IRecordSource +// : public _IRecordSourceDefaultImpl +// { +// public: +// _IRecordSource(); +// +// IInteractionSource& Interactions( const RecoType kRType ) {return fRecoTrueInteractionCollections.at(kRType);} +// +// protected: +// std::unordered_map> fRecoTrueInteractionCollections; +// +// }; +// +// +// + + //---------------------------------------------------------------------- + /// Helper class for implementing looping over interactions, particles, etc + template class EnsembleVectorAdaptor: + public PassthroughExposure<_IRecordEnsembleSink>, + _IRecordEnsembleSource>> + { + public: + using Source_t = _IRecordEnsembleSource>; + using Func_t = std::function>&(const caf::Proxy*)>; + + EnsembleVectorAdaptor(Source_t& src, Func_t vecGetter); + + virtual void HandleSingleRecord(const caf::Proxy* rec, + double weight, + int universeIdx) override; + + virtual void HandleEnsemble(const caf::Proxy* rec, + const std::vector& weight) override; + + virtual const ana::FitMultiverse* GetMultiverse() const {return fSource->GetMultiverse();} + + protected: + const Source_t* fSource; + Func_t fVecGetter; + }; + + //---------------------------------------------------------------------- + // Provide ability to get particle sources from the reco branch + // ensemble source. + + template<> class _IRecordEnsembleSource + : public _IRecordEnsembleSourceDefaultImpl + { + public: + _IRecordEnsembleSource(); + + IParticleEnsembleSource& RecoParticles( const RecoType kRType) {return fParticleCollections.at(kRType);} + + protected: + std::unordered_map> fParticleCollections; + + }; + + // the analogous for truth branch + template<> class _IRecordEnsembleSource + : public _IRecordEnsembleSourceDefaultImpl + { + public: + _IRecordEnsembleSource(); + + INuTruthParticleEnsembleSource& TruthParticles(const TruePType kPType) {return fNuTruthParticleCollections.at(kPType);} + protected: + std::unordered_map> fNuTruthParticleCollections; + }; + + /// Still missing the analogous StandardRecord sources (which loop over interactions) + // SR->Interactions, SR->NDLARInte, SR->TrueInteraction +} diff --git a/CAFAna/Core/ISyst.cxx b/CAFAna/Core/ISyst.cxx index 9450e454..0c62a812 100644 --- a/CAFAna/Core/ISyst.cxx +++ b/CAFAna/Core/ISyst.cxx @@ -1,38 +1,45 @@ #include "CAFAna/Core/ISyst.h" -#include "CAFAna/Core/Registry.h" +#include "cafanacore/Registry.h" #include "CAFAna/Core/MathUtil.h" namespace ana { + //---------------------------------------------------------------------- + //template ISyst::ISyst(const std::string& shortName, ISyst::ISyst(const std::string& shortName, const std::string& latexName, - bool applyPenalty, - double min, - double max, - double cv) - : INamed(shortName, latexName), fApplyPenalty(applyPenalty), fMin(min), fMax(max), fCentral(cv) + bool applyPenalty, + double min, + double max) + //: _ISyst(shortName, latexName), fApplyPenalty(applyPenalty), fMin(min), fMax(max) + : _ISyst(shortName, latexName), fApplyPenalty(applyPenalty), fMin(min), fMax(max) { + //Registry>::Register(this); Registry::Register(this); } //---------------------------------------------------------------------- + //template ISyst::~ISyst() ISyst::~ISyst() { // Normally ISysts should last for the life of the process, but in case one // is deleted it's best not to leave a dangling pointer in Registry. + //Registry>::UnRegister(this); Registry::UnRegister(this); } //---------------------------------------------------------------------- + //template double ISyst::Penalty(double x ) const double ISyst::Penalty(double x) const { if(fApplyPenalty){ // Regular quadratic penalty term - // Error is always 1, so can ignore that - return (x-fCentral)*(x-fCentral); + return x*x; + // Error is always 1, so can ignore that (are we doing that??) + //return (x-fCentral)*(x-fCentral); } else{ // Otherwise, no penalty within range, but still apply one outside @@ -45,4 +52,7 @@ namespace ana return util::sqr((x-mean)/rad)-1; } } + + //template class ISyst; + //template class ISyst; } diff --git a/CAFAna/Core/ISyst.h b/CAFAna/Core/ISyst.h index 0600b382..48bdace6 100644 --- a/CAFAna/Core/ISyst.h +++ b/CAFAna/Core/ISyst.h @@ -1,8 +1,8 @@ #pragma once -#include "CAFAna/Core/FwdDeclare.h" +#include "cafanacore/ISyst.h" -#include "CAFAna/Core/INamed.h" +#include #include @@ -15,21 +15,23 @@ namespace ana /// /// The Shift() function alters the \ref caf::StandardRecord or the weight /// associated with the event. - class ISyst : public INamed + //template + //class ISyst: public _ISyst + class ISyst: public _ISyst { public: ISyst(const std::string& shortName, const std::string& latexName, - bool applyPenalty = true, - double min = -3, - double max = +3, - double cv = 0); - ISyst(const ISyst &) = delete; // no copying. - ISyst(ISyst && rhs) = delete; // no moving either. + bool applyPenalty = true, + double min = -3, + double max = +3); + // double cv = 0); + //ISyst(const ISyst &) = delete; // no copying. + //ISyst(ISyst && rhs) = delete; // no moving either. virtual ~ISyst(); - void operator=(const ISyst &) = delete; // still no copying. - void operator=(ISyst &&) = delete; // etc. + // void operator=(const ISyst &) = delete; // still no copying. + //void operator=(ISyst &&) = delete; // etc. virtual double Penalty(double x) const; @@ -40,20 +42,21 @@ namespace ana virtual double Min() const{return fMin;} virtual double Max() const{return fMax;} - /// Set the central value used - virtual void SetCentral(double val) const{fCentral = val;} + ///// Set the central value used + // virtual void SetCentral(double val) const{fCentral = val;} - /// Return the central value used - virtual double Central() const{return fCentral;} + ///// Return the central value used + //virtual double Central() const{return fCentral;} - /// \brief Perform the systematic shift - /// - /// \param sigma Number of sigma to shift record by - /// \param sr The record to inspect and alter - /// \param weight Scale this weight for reweighting systematics - virtual void Shift(double sigma, - caf::SRProxy* sr, - double& weight) const = 0; + // Is this even usegul? + ///// \brief Perform the systematic shift + ///// + ///// \param sigma Number of sigma to shift record by + ///// \param sr The record to inspect and alter + ///// \param weight Scale this weight for reweighting systematics + //virtual void Shift(double sigma, + // caf::SRProxy* sr, + // double& weight) const = 0; /// PredictionInterp normally interpolates between spectra made at /// +/-1,2,3sigma. For some systematics that's overkill. Override this @@ -67,7 +70,7 @@ namespace ana bool fApplyPenalty; double fMin; double fMax; - mutable double fCentral; // I make no apologies for this + //mutable double fCentral; // I make no apologies for this }; } // namespace diff --git a/CAFAna/Core/Instantiations.cxx b/CAFAna/Core/Instantiations.cxx deleted file mode 100644 index da2cc6e8..00000000 --- a/CAFAna/Core/Instantiations.cxx +++ /dev/null @@ -1,80 +0,0 @@ -#include "CAFAna/Core/SpectrumLoaderBase.h" - -#include "CAFAna/Core/SpectrumConstructors.txx" - -namespace ana -{ - template Spectrum::Spectrum(SpectrumLoaderBase& loader, - const HistAxis& axis, - const Cut& cut, - const SystShifts& shift, - const Weight& wei, - Spectrum::ESparse sparse); - - template Spectrum::Spectrum(const std::string& label, - const Binning& bins, - SpectrumLoaderBase& loader, - const Var& var, - const Cut& cut, - const SystShifts& shift, - const Weight& wei, - Spectrum::ESparse sparse); - - template Spectrum::Spectrum(SpectrumLoaderBase& loader, - const HistAxis& xAxis, - const HistAxis& yAxis, - const Cut& cut, - const SystShifts& shift, - const Weight& wei, - ESparse sparse); - - template Spectrum::Spectrum(const std::string& xLabel, - const std::string& yLabel, - SpectrumLoaderBase& loader, - const Binning& binsx, const Var& varx, - const Binning& binsy, const Var& vary, - const Cut& cut, - const SystShifts& shift, - const Weight& wei, - ESparse sparse); - - template Spectrum::Spectrum(SpectrumLoaderBase& loader, - const HistAxis& xAxis, - const HistAxis& yAxis, - const HistAxis& zAxis, - const Cut& cut, - const SystShifts& shift, - const Weight& wei, - ESparse sparse); - - template Spectrum::Spectrum(const std::string& xLabel, - const std::string& yLabel, - const std::string& zLabel, - SpectrumLoaderBase& loader, - const Binning& binsx, const Var& varx, - const Binning& binsy, const Var& vary, - const Binning& binsz, const Var& varz, - const Cut& cut, - const SystShifts& shift, - const Weight& wei, - ESparse sparse); - - template Spectrum::Spectrum(SpectrumLoaderBase& loader, - const _HistAxis& axis, - const Cut& cut, - const SystShifts& shift, - const Weight& wei); -} - -#include "CAFAna/Core/ReweightableSpectrum.h" -#include "CAFAna/Core/ReweightableSpectrumConstructors.txx" - -namespace ana -{ - template ReweightableSpectrum::ReweightableSpectrum(SpectrumLoaderBase& loader, - const HistAxis& recoAxis, - const HistAxis& trueAxis, - const Cut& cut, - const SystShifts& shift, - const Weight& wei); -} diff --git a/CAFAna/Core/LoadFromFile.h b/CAFAna/Core/LoadFromFile.h index ce41311a..1a9a45b2 100644 --- a/CAFAna/Core/LoadFromFile.h +++ b/CAFAna/Core/LoadFromFile.h @@ -25,8 +25,6 @@ namespace ana // derived class is actually in the file and hand off to that. The // implementations of these are in the cxx files for the base classes in // question. - class IDecomp; - template<> std::unique_ptr LoadFrom(TDirectory* dir, const std::string& label); class IExtrap; template<> std::unique_ptr LoadFrom(TDirectory* dir, const std::string& label); class IPrediction; diff --git a/CAFAna/Core/Loaders.cxx b/CAFAna/Core/Loaders.cxx index 468866aa..eab6f12d 100644 --- a/CAFAna/Core/Loaders.cxx +++ b/CAFAna/Core/Loaders.cxx @@ -1,6 +1,5 @@ #include "CAFAna/Core/Loaders.h" -#include "CAFAna/Core/SpectrumLoader.h" #include "CAFAna/Core/Utilities.h" #include @@ -9,120 +8,69 @@ namespace ana { //---------------------------------------------------------------------- - Loaders::Loaders() + template Sources::Sources() { } //---------------------------------------------------------------------- - Loaders::~Loaders() + template Sources::~Sources() { - // for(auto it: fLoaders) delete it.second; + // for(auto it: fSources) delete it.second; } //---------------------------------------------------------------------- - void Loaders::SetLoaderPath(const std::string& path, - caf::Det_t det, - DataMC datamc, - SwappingConfig swap) + template void Sources::AddLoader(SrcT* src, + DataMC datamc, + SwappingConfig swap) { assert(datamc == kMC || swap == kNonSwap); - assert(det == caf::kFARDET || swap == kNonSwap); - const Key_t key(det, datamc, swap); + const Key_t key(datamc, swap); // Clear out the old one if necessary - DisableLoader(det, datamc, swap); + DisableLoader(datamc, swap); - fLoaderPaths[key] = path; + fSources[key] = src; } //---------------------------------------------------------------------- - void Loaders::SetLoaderFiles(const std::vector& files, - caf::Det_t det, - DataMC datamc, - SwappingConfig swap) + template void Sources::DisableLoader(DataMC datamc, + SwappingConfig swap) { assert(datamc == kMC || swap == kNonSwap); - assert(det == caf::kFARDET || swap == kNonSwap); - const Key_t key(det, datamc, swap); - - // Clear out the old one if necessary - DisableLoader(det, datamc, swap); - - fLoaderFiles[key] = files; - } - - //---------------------------------------------------------------------- - void Loaders::AddLoader(SpectrumLoaderBase* file, - caf::Det_t det, - DataMC datamc, - SwappingConfig swap) - { - assert(datamc == kMC || swap == kNonSwap); - assert(det == caf::kFARDET || swap == kNonSwap); - - const Key_t key(det, datamc, swap); - - // Clear out the old one if necessary - DisableLoader(det, datamc, swap); - - fLoaders[key] = file; - } - - //---------------------------------------------------------------------- - void Loaders::DisableLoader(caf::Det_t det, - DataMC datamc, - SwappingConfig swap) - { - assert(datamc == kMC || swap == kNonSwap); - assert(det == caf::kFARDET || swap == kNonSwap); - - const Key_t key(det, datamc, swap); + const Key_t key(datamc, swap); // Clear out the current one if possible - auto it = fLoaders.find(key); - if(it != fLoaders.end()){ + auto it = fSources.find(key); + if(it != fSources.end()){ delete it->second; - fLoaders.erase(it); + fSources.erase(it); } - - fLoaderPaths.erase(key); - fLoaderFiles.erase(key); } //---------------------------------------------------------------------- - SpectrumLoaderBase& Loaders::GetLoader(caf::Det_t det, - DataMC datamc, - SwappingConfig swap) + template SrcT& Sources::GetLoader(DataMC datamc, + SwappingConfig swap) { assert(datamc == kMC || swap == kNonSwap); - assert(det == caf::kFARDET || swap == kNonSwap); - const Key_t key(det, datamc, swap); + const Key_t key(datamc, swap); - // Look up and return. Use fNull if no loader is set for this config - auto itLoader = fLoaders.find(key); - if(itLoader != fLoaders.end()) return *itLoader->second; + // Look up and return. Use kNullLoader if no loader is set for this config + auto itLoader = fSources.find(key); + if(itLoader != fSources.end()) return *itLoader->second; - auto itPath = fLoaderPaths.find(key); - if(itPath != fLoaderPaths.end()){ - fLoaders[key] = new SpectrumLoader(itPath->second); - return *fLoaders[key]; + if constexpr(std::is_same_v){ + return kNullLoader; } - auto itFiles = fLoaderFiles.find(key); - if(itFiles != fLoaderFiles.end()){ - fLoaders[key] = new SpectrumLoader(itFiles->second); - return *fLoaders[key]; + else{ + static NullSource null; + return null; } - - return fNull; - } - - //---------------------------------------------------------------------- - void Loaders::Go() - { - for(auto it: fLoaders) it.second->Go(); } -} + // Instantiate the ones we need + template class Sources; + template class Sources; +} \ No newline at end of file diff --git a/CAFAna/Core/Loaders.h b/CAFAna/Core/Loaders.h index 5b89dc78..b5a2eb24 100644 --- a/CAFAna/Core/Loaders.h +++ b/CAFAna/Core/Loaders.h @@ -1,12 +1,6 @@ #pragma once -#include "CAFAna/Core/SpectrumLoaderBase.h" - -namespace caf{ - typedef int Det_t; - const int kNEARDET = 1; - const int kFARDET = 2; -} +#include "CAFAna/Core/SpectrumLoader.h" #include @@ -14,57 +8,77 @@ namespace ana { class SpectrumLoader; + // TODO should these be in some sort of namespace? + enum DataMC{kData, kMC, kNumDataMCs}; + enum SwappingConfig{kNonSwap, kNueSwap, kNuTauSwap, kIntrinsic, kNumSwappingConfigs}; + /// \brief Collection of SpectrumLoaders for many configurations - class Loaders + template class Sources { public: - enum DataMC{kData, kMC}; - enum SwappingConfig{kNonSwap, kNueSwap, kNuTauSwap}; - enum FluxType{kFHC, kRHC}; - /// No loaders initialized. Use \ref SetLoaderPath to configure - Loaders(); - virtual ~Loaders(); - - /// Configure loader via wildcard \a path - void SetLoaderPath(const std::string& path, - caf::Det_t det, - DataMC datamc, - SwappingConfig swap = kNonSwap); + Sources(); + ~Sources(); - /// Configure loader via explicit file list - void SetLoaderFiles(const std::vector& files, - caf::Det_t det, - DataMC datamc, - SwappingConfig swap = kNonSwap); - - void AddLoader(SpectrumLoaderBase*, - caf::Det_t det, + void AddLoader(SrcT*, DataMC datamc, SwappingConfig swap = kNonSwap); - void DisableLoader(caf::Det_t det, - DataMC datamc, + void DisableLoader(DataMC datamc, SwappingConfig swap = kNonSwap); /// Retrieve a specific loader - SpectrumLoaderBase& GetLoader(caf::Det_t det, - DataMC datamc, - SwappingConfig swap = kNonSwap); + SrcT& GetLoader(DataMC datamc, + SwappingConfig swap = kNonSwap); - /// Call Go() on all the loaders - void Go(); + template auto& operator[](const T& x) + { + auto ret = new Sourcessecond)[x])>>; + + for(int dmc = 0; dmc < kNumDataMCs; ++dmc){ + for(int swap = 0; swap < kNumSwappingConfigs; ++swap){ + if(dmc == kData && swap != kNonSwap) continue; + ret->AddLoader(&GetLoader(DataMC(dmc), SwappingConfig(swap))[x], + DataMC(dmc), SwappingConfig(swap)); + } + } + + return *ret; + } protected: - typedef std::tuple Key_t; + typedef std::tuple Key_t; - // Hold a list of paths that have been set - std::map fLoaderPaths; - std::map> fLoaderFiles; - // Only reify them when someone actually calls GetLoader() - std::map fLoaders; + std::map fSources; + }; + + + using SRSources = Sources; + using InteractionSources = Sources; + + class Loaders: public Sources + { + public: + operator InteractionSources&() + { + InteractionSources* ret = new InteractionSources; + for(int dmc = 0; dmc < kNumDataMCs; ++dmc){ + for(int swap = 0; swap < kNumSwappingConfigs; ++swap){ + if(dmc == kData && swap != kNonSwap) continue; + // using only DLP, but I guess we should have an option to use Pandora? + ret->AddLoader(&GetLoader(DataMC(dmc), SwappingConfig(swap)).Interactions(RecoType::kDLP), + DataMC(dmc), SwappingConfig(swap)); + } + } + return *ret; + } + // I guess we will need an operator for Particles.. and soo on as we add more nested levels? - /// We give this back when a loader isn't set for some configuration - NullLoader fNull; + /// Call Go() on all the loaders + void Go() + { + for(auto it: fSources) it.second->Go(); + } }; -} // namespace + +} // namespace \ No newline at end of file diff --git a/CAFAna/Core/Multiverse.cxx b/CAFAna/Core/Multiverse.cxx new file mode 100644 index 00000000..42bfc1b5 --- /dev/null +++ b/CAFAna/Core/Multiverse.cxx @@ -0,0 +1,316 @@ +#include "CAFAna/Core/Multiverse.h" + +#include "CAFAna/Core/Registry.h" + +#include "TDirectory.h" +#include "TMD5.h" +#include "TObjString.h" + +#include +#include + +namespace ana +{ + // Multiverses live the lifetime of the process, but let's not leak them at + // shutdown + std::vector> gFitMultiverses; + + namespace{ + // This is "group separator" and appears to print as a space. It is + // unlikely to occur in a systematic name by accident, unlike more usual + // separators. + const char kSepChar(29); + const std::string kSep(1, kSepChar); + } + + //---------------------------------------------------------------------- + bool CompareSystsByShortName(const IFitSyst* a, const IFitSyst* b) + { + return a->ShortName() < b->ShortName(); + } + + //---------------------------------------------------------------------- + std::vector SortedSystList(const std::vector systs) + { + std::vector ret = systs; + std::sort(ret.begin(), ret.end(), CompareSystsByShortName); + return ret; + } + + //---------------------------------------------------------------------- + std::vector Tokenize(const std::string& str) + { + std::vector ret; + + size_t i0 = 0; + while(true){ + const size_t i1 = str.find(kSepChar, i0); + ret.push_back(str.substr(i0, i1-i0)); + if(i1 == std::string::npos) return ret; + i0 = i1+1; + } + } + + //---------------------------------------------------------------------- + std::string GetLabelValue(const std::string& str, const std::string& label) + { + if(str.substr(0, label.size()+1) != label+"="){ + std::cout << "FitMultiverse::LoadFrom(): expected '" + << label << "=value' " + << "got '" << str << "'" << std::endl; + abort(); + } + return str.substr(label.size()+1); + } + + //---------------------------------------------------------------------- + std::string ConsumeLabelValue(std::vector& tokens, + const std::string& label) + { + const std::string ret = GetLabelValue(tokens.front(), label); + tokens.erase(tokens.begin()); // effectively pop_front() + return ret; + } + + //---------------------------------------------------------------------- + unsigned int GetLabelIntValue(const std::string& str, const std::string& label) + { + const std::string valuestr = GetLabelValue(str, label); + + unsigned int ret; + size_t pos = -1; + try{ + ret = std::stoi(valuestr, &pos); + } + catch(const std::exception& ex){ + pos = -1; + ret = -1; // silence uninitialized variable warning + } + + if(pos != valuestr.size()){ // need to consume all the string + std::cout << "FitMultiverse::LoadFrom(): failed to parse integer parameter '" << str << "'" << std::endl; + abort(); + } + + return ret; + } + + //---------------------------------------------------------------------- + unsigned int ConsumeLabelIntValue(std::vector& tokens, + const std::string& label) + { + const unsigned int ret = GetLabelIntValue(tokens.front(), label); + tokens.erase(tokens.begin()); // effectively pop_front() + return ret; + } + + //---------------------------------------------------------------------- + std::vector SystNamesToSysts(const std::vector& names) + { + std::vector ret; + ret.reserve(names.size()); + + for(const std::string& name: names){ + ret.push_back(Registry::ShortNameToPtr(name, true)); + //ret.push_back(Registry>::ShortNameToPtr(name, true)); + //ret.push_back(Registry>::ShortNameToPtr(name, true)); + if(!ret.back()){ + std::cout << "FitMultiverse::LoadFrom(): couldn't find any syst with short name '" << name << "'" << std::endl; + abort(); + } + } + + return ret; + } + + //---------------------------------------------------------------------- + FitMultiverse::FitMultiverse(const std::string& shortName, + const std::string& latexName, + const std::vector& univs, + const EMultiverseType multiverseType) + : INamed(shortName, latexName), fUnivs(univs), fMultiverseType(multiverseType) + { + Registry::Register(this); + } + + //---------------------------------------------------------------------- + FitMultiverse::FitMultiverse(const FitMultiverse&& m) + : INamed(m), fUnivs(m.fUnivs), fMultiverseType(m.fMultiverseType) + { + // "leak" the entry in the global list so we don't double-delete it + for(auto& it: gFitMultiverses) if(it.get() == &m) it.release(); + + Registry::UnRegister(&m); + Registry::Register(this); + } + + //---------------------------------------------------------------------- + const FitMultiverse& FitMultiverse:: + Hypercross(const std::vector& systs_unsorted, int nsigma) + { + // Ensure reproducibility + const std::vector systs = SortedSystList(systs_unsorted); + + std::string name = "cross"+kSep+"nsigma="+std::to_string(nsigma); + for(const IFitSyst* s: systs) name += kSep + s->ShortName(); + + // Make sure that requesting the same multiverse multiple times always + // gives back the same object + const FitMultiverse* reg = Registry::ShortNameToPtr(name, true); + if(reg) return *reg; + + const std::string latexName = "Hypercross for #pm"+std::to_string(nsigma)+"#sigma over "+std::to_string(systs.size())+" systematics"; + + + std::vector univs; + univs.reserve(2*nsigma*systs.size()+1); + univs.emplace_back(); // nominal + for(const IFitSyst* s: systs){ + for(int i = -nsigma; i <= +nsigma; ++i){ + if(i == 0) continue; + FitUniverse univ; + univ.emplace(s, i); + univs.push_back(univ); + } + } // end for systs + + gFitMultiverses.emplace_back(new FitMultiverse(name, latexName, univs, kHypercross)); + return *gFitMultiverses.back(); + } + + //---------------------------------------------------------------------- + const FitMultiverse& FitMultiverse:: + RandomGas(const std::vector& systs_unsorted, int Nuniv, + unsigned int seed) + { + // Ensure reproducibility + const std::vector systs = SortedSystList(systs_unsorted); + + if(seed == kTrulyRandom) seed = std::random_device{}(); + + std::string name = "gas"+kSep+"nuniv="+std::to_string(Nuniv)+kSep+"seed="+std::to_string(seed); + for(const IFitSyst* s: systs) name += kSep+s->ShortName(); + + // Make sure that requesting the same multiverse multiple times always + // gives back the same object + const FitMultiverse* reg = Registry::ShortNameToPtr(name, true); + if(reg) return *reg; + + const std::string latexName = "Random multiverse with "+std::to_string(Nuniv)+" universes over "+std::to_string(systs.size())+" systematics"; + + // Use stdlib rather than rely on ROOT's dodgy random numbers + std::mt19937_64 generator(seed); // 64-bit Mersenne twister + std::normal_distribution gaus(0, 1); + + std::vector univs; + univs.reserve(Nuniv+1); + univs.emplace_back(); // nominal + for(int i = 0; i < Nuniv; ++i){ + FitUniverse univ; + for(const IFitSyst* s: systs){ + univ.emplace(s, gaus(generator)); + } + univs.push_back(univ); + } + + gFitMultiverses.emplace_back(new FitMultiverse(name, latexName, univs, kRandomGas)); + return *gFitMultiverses.back(); + } + + // TO DO: a member that creates a new multiverse from a vector of multiverses + // care has to be put in making sure they are compatible + //---------------------------------------------------------------------- + // const FitMultiverse& FitMultiverse::MergeMultiverse( std::vector multiverses ){ + // + // GetUniverse + // + // } + + //---------------------------------------------------------------------- + void FitMultiverse::SaveTo(TDirectory* dir, const std::string& name) const + { + // We could make a whole directory and fill it with a detailed record of + // this object. But this will be saved for every single EnsembleSpectrum, + // so try and make it as minimal as possible. We should be able to encode + // enough information to reconstruct ourselves in a simple string. + + TDirectory* tmp = gDirectory; + + dir->cd(); + TObjString((ShortName()+kSep+"md5="+Checksum()).c_str()).Write(name.c_str()); + + tmp->cd(); + } + + //---------------------------------------------------------------------- + const FitMultiverse* FitMultiverse::LoadFrom(TDirectory* dir, + const std::string& name) + { + TObjString* obj = (TObjString*)dir->Get(name.c_str()); + assert(obj); + const std::string str = obj->GetString().Data(); + + const std::string shortname = str.substr(0, str.rfind(kSep)); + + std::vector tokens = Tokenize(str); + assert(tokens.size() >= 2); // type and checksum at least + + const std::string md5 = GetLabelValue(tokens.back(), "md5"); + tokens.pop_back(); + + // If this multiverse is already known, just give it back directly + const FitMultiverse* ret = Registry::ShortNameToPtr(shortname, true); + + if(!ret){ + // Otherwise we need to construct one + const std::string type = tokens.front(); + tokens.erase(tokens.begin()); // effectively pop_front() + + if(type == "gas"){ + const int nuniv = ConsumeLabelIntValue(tokens, "nuniv"); + const unsigned int seed = ConsumeLabelIntValue(tokens, "seed"); + + ret = &FitMultiverse::RandomGas(SystNamesToSysts(tokens), nuniv, seed); + } + else if(type == "cross"){ + const int nsigma = ConsumeLabelIntValue(tokens, "nsigma"); + + ret = &FitMultiverse::Hypercross(SystNamesToSysts(tokens), nsigma); + } + else{ + std::cout << "Multiverse::LoadFrom(): unknown multiverse type '" + << type << "'" << std::endl; + abort(); + } + } + + if(ret->Checksum() != md5){ + std::cout << "Multiverse::LoadFrom(): checksum mismatch while loading '" << name << "' with content '" << str << "'" << std::endl; + abort(); + } + + return ret; + } + + //---------------------------------------------------------------------- + std::string FitMultiverse::Checksum() const + { + TMD5 md5; + + for(const FitUniverse& univ: fUnivs){ + std::vector keys; + for(auto it: univ) keys.push_back(it.first); + // Ensure reproducibility because the map doesn't guarantee any + // particular ordering + for(const IFitSyst* syst: SortedSystList(keys)){ + md5.Update((unsigned char*)syst->ShortName().c_str(), + syst->ShortName().size()); + const double val = univ.at(syst); + md5.Update((unsigned char*)&val, sizeof(double)); + } // end fo syst + } // end for univ + + md5.Final(); + return md5.AsString(); + } +} \ No newline at end of file diff --git a/CAFAna/Core/Multiverse.h b/CAFAna/Core/Multiverse.h new file mode 100644 index 00000000..4fa20da6 --- /dev/null +++ b/CAFAna/Core/Multiverse.h @@ -0,0 +1,91 @@ +#pragma once + +#include "CAFAna/Core/FitMultiverse.h" + +#include "CAFAna/Core/ISyst.h" + +namespace ana +{ + /// \brief Equivalent to FitMultiverse, but storing experiment-specific + /// systematic type SystT + /// + /// Internal implementation details: we store the systematics as FitSyst* in + /// the base class, but since we know they can only be set by the + /// constructors, which we control, it is safe to cast them back to the + /// derived class on-demand. + template class _Multiverse: public FitMultiverse + { + public: + static_assert(std::is_base_of_v); + + /// See FitMultiverse::Hypercross + static const _Multiverse& Hypercross(const std::vector& systs, + int nsigma = 3) + { + return Cached(FitMultiverse::Hypercross(ConvertSysts(systs), nsigma)); + } + + using FitMultiverse::kTrulyRandom; + + /// See FitMultiverse::RandomGas + static const _Multiverse& RandomGas(const std::vector& systs, + int Nuniv, + unsigned int seed) + { + return Cached(FitMultiverse::RandomGas(ConvertSysts(systs), Nuniv, seed)); + } + + // TO DO: a member that creates a new multiverse from a vector of multiverses + // static const _Multiverse& MergeMultiverse( Multiverse multiverse); + + /// Details of a particular universe + const _Universe& GetUniverse(int i) const + { + // TODO I think this cast is safe because the layout is identical? + return *((const _Universe*)&fUnivs[i]); + //return fUnivs[i]; + } + + protected: + /// Helper constructor for \ref Cached + _Multiverse(const FitMultiverse&& m) : FitMultiverse(std::move(m)) {} + + /// Helper function for named constructors + static std::vector ConvertSysts(const std::vector systs) + { + return {systs.begin(), systs.end()}; + } + + /// \brief We need to retain the property that identically-defined + /// multiverses are the same object (get the same pointers) + /// + /// If there is already a _Multiverse corresponding to \a m return that, + /// otherwise construct one + static const _Multiverse& Cached(const FitMultiverse& m) + { + // These will be deleted by the underlying FitMultiverse, so no need for + // unique_ptr here + static std::unordered_map cache; + if(!cache.count(&m)){ + // We need to create a _Multiverse inheriting from the passed-in + // FitMultiverse. Trouble is, we mustn't create a new FitMultiverse + // with the same definition, so we have to move the input to become the + // base of this new object. This is OK because 1. we only just created + // this FitMultiverse in the named constructor and 2. FitMultiverse + // defines a move constructor for us that takes care of Registry + // registration etc. + cache.emplace(&m, new _Multiverse(std::move(m))); + } + return *cache[&m]; + } + }; + + +// using Universe = _Universe>; +// using Multiverse = _Multiverse>; +// +// using UniverseTrue = _Universe>; +// using MultiverseTrue = _Multiverse>; + using Universe = _Universe; + using Multiverse = _Multiverse; +} diff --git a/CAFAna/Core/OscillatableSpectrum.cxx b/CAFAna/Core/OscillatableSpectrum.cxx index f1ba4b42..4f33dd3b 100644 --- a/CAFAna/Core/OscillatableSpectrum.cxx +++ b/CAFAna/Core/OscillatableSpectrum.cxx @@ -7,7 +7,7 @@ #include "CAFAna/Core/Utilities.h" #include "duneanaobj/StandardRecord/Proxy/SRProxy.h" - +#include "duneanaobj/StandardRecord/SRInteraction.h" #include "OscLib/IOscCalc.h" #include "TDirectory.h" @@ -20,34 +20,27 @@ namespace ana { + namespace{ // Duplicate here because we can't include Vars.h - const Var kTrueE([](const caf::SRProxy* sr) - {return sr->Ev;}); - - //---------------------------------------------------------------------- - OscillatableSpectrum:: - OscillatableSpectrum(const std::string& label, const Binning& bins, - SpectrumLoaderBase& loader, - const Var& var, - const Cut& cut, - const SystShifts& shift, - const Weight& wei) - : ReweightableSpectrum(loader, - HistAxis(label, bins, var), - HistAxis("True Energy (GeV)", kTrueEnergyBins, kTrueE), - cut, shift, wei) - { - } - + // These should be true informations, but I think we only have recoparticle atm + const Var kTrueE([](const caf::SRInteractionProxy* ixn) + { + //assert(sr->mc.nnu == 1); + assert(ixn->truth.size()>0); + /// uuumm what do we + return ixn->Enu.calo; + }); + const Cut kHasNu([](const caf::SRInteractionProxy* ixn) + { + //return sr->truth.index >= 0; + // this should return something at the true level, + //in the meantime just check there's interaction or whatever placeholder cut + return ixn->truth.size()>0;//dlp.size()>0; + }); + } //---------------------------------------------------------------------- - OscillatableSpectrum::OscillatableSpectrum(SpectrumLoaderBase& loader, - const HistAxis& axis, - const Cut& cut, - const SystShifts& shift, - const Weight& wei) - : ReweightableSpectrum(loader, axis, - HistAxis("True Energy (GeV)", kTrueEnergyBins, kTrueE), - cut, shift, wei) + OscillatableSpectrum::OscillatableSpectrum(IInteractionSource& src, const HistAxis& axis) + : ReweightableSpectrum(src[kHasNu], axis, HistAxis("True Energy (GeV)", kTrueEnergyBins, kTrueE)) { } @@ -246,21 +239,18 @@ namespace ana delete dir; - auto ret = std::make_unique(kNullLoader, - HistAxis(labels, bins), - kNoCut); + const HistAxis recoAxis(labels, bins); // ROOT histogram storage is row-major, but Eigen is column-major by // default typedef Eigen::Matrix MatRowMajor; - ret->fMat = Eigen::Map(spect->GetArray(), - ret->fMat.rows(), - ret->fMat.cols()); - delete spect; + auto ret = std::make_unique(Eigen::Map(spect->GetArray(), kTrueEnergyBins.NBins()+2, recoAxis.GetBins1D().NBins()+2), + recoAxis, + hPot->Integral(0, -1), + hLivetime->Integral(0, -1)); - ret->fPOT = hPot->Integral(0, -1); - ret->fLivetime = hLivetime->Integral(0, -1); + delete spect; delete hPot; delete hLivetime; diff --git a/CAFAna/Core/OscillatableSpectrum.h b/CAFAna/Core/OscillatableSpectrum.h index 68a9f6b5..90864265 100644 --- a/CAFAna/Core/OscillatableSpectrum.h +++ b/CAFAna/Core/OscillatableSpectrum.h @@ -1,14 +1,19 @@ #pragma once -#include "CAFAna/Core/ReweightableSpectrum.h" +#include "cafanacore/ReweightableSpectrum.h" +#include "cafanacore/FwdDeclare.h" +#include "cafanacore/Spectrum.h" +#include "cafanacore/ThreadLocal.h" #include "CAFAna/Core/Binning.h" -#include "CAFAna/Core/FwdDeclare.h" +//#include "CAFAna/Core/FwdDeclare.h" #include "CAFAna/Core/OscCalcFwdDeclare.h" -#include "CAFAna/Core/Spectrum.h" +//#include "CAFAna/Core/Spectrum.h" #include "CAFAna/Core/SpectrumLoaderBase.h" #include "CAFAna/Core/StanTypedefs.h" -#include "CAFAna/Core/ThreadLocal.h" +//#include "CAFAna/Core/ThreadLocal.h" + +#include "CAFAna/Core/IRecordSource.h" #include @@ -17,7 +22,7 @@ class TH2; class TH2D; -#include "CAFAna/Core/FwdDeclare.h" +//#include "CAFAna/Core/FwdDeclare.h" namespace ana { @@ -37,23 +42,7 @@ namespace ana class OscillatableSpectrum: public ReweightableSpectrum { public: - friend class SpectrumLoaderBase; - friend class SpectrumLoader; - friend class NullLoader; - - OscillatableSpectrum(const std::string& label, - const Binning& bins, - SpectrumLoaderBase& loader, - const Var& var, - const Cut& cut, - const SystShifts& shift = kNoShift, - const Weight& wei = kUnweighted); - - OscillatableSpectrum(SpectrumLoaderBase& loader, - const HistAxis& axis, - const Cut& cut, - const SystShifts& shift = kNoShift, - const Weight& wei = kUnweighted); + OscillatableSpectrum(ana::IInteractionSource& src, const HistAxis& axis); OscillatableSpectrum(const Eigen::MatrixXd&& mat, const HistAxis& recoAxis, diff --git a/CAFAna/Core/Registry.cxx b/CAFAna/Core/Registry.cxx index 417407b2..27ab60eb 100644 --- a/CAFAna/Core/Registry.cxx +++ b/CAFAna/Core/Registry.cxx @@ -2,10 +2,14 @@ #include "CAFAna/Core/IFitVar.h" #include "CAFAna/Core/ISyst.h" +#include "CAFAna/Core/FitMultiverse.h" namespace ana { // Instantiate the registries we need template class Registry; template class Registry; + //template class Registry< ISyst>; + //template class Registry< ISyst>; + template class Registry; } diff --git a/CAFAna/Core/SpectrumLoader.cxx b/CAFAna/Core/SpectrumLoader.cxx index d6bcb115..47b84231 100644 --- a/CAFAna/Core/SpectrumLoader.cxx +++ b/CAFAna/Core/SpectrumLoader.cxx @@ -28,14 +28,14 @@ namespace ana { //---------------------------------------------------------------------- - SpectrumLoader::SpectrumLoader(const std::string& wildcard, int max) - : SpectrumLoaderBase(wildcard), max_entries(max) + SpectrumLoader::SpectrumLoader(const std::string& wildcard)//, int max) + : SpectrumLoaderBase(wildcard)//, max_entries(max) { } //---------------------------------------------------------------------- - SpectrumLoader::SpectrumLoader(const std::vector& fnames, int max) - : SpectrumLoaderBase(fnames), max_entries(max) + SpectrumLoader::SpectrumLoader(const std::vector& fnames)//, int max) + : SpectrumLoaderBase(fnames)//, max_entries(max) { } @@ -46,30 +46,33 @@ namespace ana #ifdef WITH_SAM //---------------------------------------------------------------------- - SpectrumLoader SpectrumLoader::FromSAMProject(const std::string& proj, + SpectrumLoader* SpectrumLoader::FromSAMProject(const std::string& proj, int fileLimit) { - SpectrumLoader ret; - ret.fWildcard = "project " + proj; - ret.fFileSource = - std::unique_ptr(new SAMProjectSource(proj, fileLimit)); + SpectrumLoader* ret = new SpectrumLoader; + ret->fWildcard = "project "+proj; + ret->fFileSource = std::unique_ptr(new SAMProjectSource(proj, fileLimit)); return ret; } #endif +/* //---------------------------------------------------------------------- +* SpectrumLoader::~SpectrumLoader() +* { +* } +* +* struct CompareByID +* { +* bool operator()(const Cut& a, const Cut& b) const +* { +* return a.ID() < b.ID(); +* } +* }; +*/ //---------------------------------------------------------------------- SpectrumLoader::~SpectrumLoader() { } - - struct CompareByID - { - bool operator()(const Cut& a, const Cut& b) const - { - return a.ID() < b.ID(); - } - }; - //---------------------------------------------------------------------- void SpectrumLoader::Go() { @@ -79,15 +82,15 @@ namespace ana } fGone = true; - // Find all the unique cuts - std::set cuts; - for(auto& shiftdef: fHistDefs) - for(auto& cutdef: shiftdef.second) - cuts.insert(cutdef.first); - for(const Cut& cut: cuts) fAllCuts.push_back(cut); - - fLivetimeByCut.resize(fAllCuts.size()); - fPOTByCut.resize(fAllCuts.size()); + // // Find all the unique cuts + // std::set cuts; + // for(auto& shiftdef: fHistDefs) + // for(auto& cutdef: shiftdef.second) + // cuts.insert(cutdef.first); + // for(const Cut& cut: cuts) fAllCuts.push_back(cut); + // + // fLivetimeByCut.resize(fAllCuts.size()); + // fPOTByCut.resize(fAllCuts.size()); const int Nfiles = NFiles(); @@ -99,12 +102,15 @@ namespace ana while(TFile* f = GetNextFile()){ ++fileIdx; - if(Nfiles >= 0 && !prog){ - std::string sum = TString::Format("Filling %lu spectra", fHistDefs.TotalSize()).Data(); - sum += TString::Format(" from %d files matching '%s'", Nfiles, fWildcard.c_str()).Data(); - prog = new Progress(sum); +// need to find ISpillSink + if(Nfiles >= 0 && !prog){ + unsigned int totsinks = 0; + for(const ISRSink* s: fSinks) totsinks += s->NSinks(); + + prog = new Progress(TString::Format("Filling %u spectra from %d files matching '%s'", totsinks, Nfiles, fWildcard.c_str()).Data()); } + HandleFile(f, Nfiles == 1 ? prog : 0); if(Nfiles > 1 && prog) prog->SetProgress((fileIdx+1.)/Nfiles); @@ -119,10 +125,28 @@ namespace ana delete prog; } - ReportExposures(); + //ReportExposures(); + + //fHistDefs.RemoveLoader(this); + //fHistDefs.Clear(); + //Replace these histdefs with Sinks + for(ISRSink* sink: fSinks) sink->RemoveSource(this); + fSinks.clear(); + } + + //---------------------------------------------------------------------- + void SpectrumLoader::PrintGraph(std::ostream& os) const + { + os << "digraph{" << std::endl; + os << "comment = \"Render me with a command like: dot -Tpdf graph.dot > graph.pdf\"" << std::endl << std::endl; + Passthrough::PrintGraph(os); + os << "}"; + } - fHistDefs.RemoveLoader(this); - fHistDefs.Clear(); + //---------------------------------------------------------------------- + void SpectrumLoader::PrintGraph() const + { + PrintGraph(std::cout); } //---------------------------------------------------------------------- @@ -134,201 +158,222 @@ namespace ana // version. "caf" is ROOT's temporary save while the file is being produced // and may be incomplete. TTree* tr = (TTree*)f->Get("cafTree"); - if(!tr) tr = (TTree*)f->Get("caf"); - + //if(!tr) tr = (TTree*)f->Get("caf"); assert(tr); - caf::SRProxy sr(tr, ""); + // I think this is ok + caf::SRProxy sr(tr, "rec"); FloatingExceptionOnNaN fpnan(false); long Nentries = tr->GetEntries(); - if(max_entries != 0 && max_entries < Nentries) - Nentries = max_entries; + //if(max_entries != 0 && max_entries < Nentries) + // Nentries = max_entries; for(long n = 0; n < Nentries; ++n){ tr->LoadTree(n); - FixupRecord(&sr, tr); + // SBN here has fPOT and fNReadouts accounting... + // dont know what to do about that + // at the moment, I left fPOT to be handled in SpectrumLoaderBase same as fPOTFromHist + + // I think this was a thing used for old dune files?? + //FixupRecord(&sr, tr); - HandleRecord(&sr); + HandleRecord(&sr, 1); - if(prog && n%100 == 0) prog->SetProgress(double(n)/Nentries); + if(prog) prog->SetProgress(double(n)/Nentries); } // end for n } - //---------------------------------------------------------------------- - /// Helper for \ref SpectrumLoader::HandleRecord - template class CutVarCache +// No handleRecord stuff here... +/* //---------------------------------------------------------------------- +* /// Helper for \ref SpectrumLoader::HandleRecord +* template class CutVarCache +* { +* public: +* CutVarCache() : fCache(U::MaxID()+1) {} +* +* inline T Get(const U& var, const caf::SRProxy* sr) +* { +* const unsigned int id = var.ID(); +* +* if(fCache[id].set) return fCache[id].val; +* +* const T val = var(sr); +* fCache[id].val = val; +* fCache[id].set = true; +* return val; +* } +* +* protected: +* // Seems to be faster to do this than [unordered_]map +* struct CacheElem{ +* T val; bool set; +* }; +* std::vector fCache; +* }; +*/ +// Leaving the handle record to our Passthrough implementations (keeping here for ref...) +// //---------------------------------------------------------------------- +// void SpectrumLoader::HandleRecord(caf::SRProxy* sr) +// { +// // Some shifts only adjust the weight, so they're effectively nominal, but +// // aren't grouped with the other nominal histograms. Keep track of the +// // results for nominals in these caches to speed those systs up. +// CutVarCache nomCutCache; +// CutVarCache nomWeiCache; +// CutVarCache nomVarCache; +// +// for(auto& shiftdef: fHistDefs){ +// const SystShifts& shift = shiftdef.first; +// +// // Need to provide a clean slate for each new set of systematic shifts to +// // work from. Copying the whole StandardRecord is pretty expensive, so +// // modify it in place and revert it afterwards. +// +// // Please do not continue/break out of the shiftdef loop. If this is +// // required, let's use a RAII type here. +// caf::SRProxySystController::BeginTransaction(); +// +// double systWeight = 1; +// bool shifted = false; +// +// // Can special-case nominal to not pay cost of Shift() +// if(!shift.IsNominal()){ +// shift.Shift(sr, systWeight); +// // If there were only weighting systs applied then the cached nominal +// // values are still valid. +// shifted = caf::SRProxySystController::AnyShifted(); +// } +// +// for(auto& cutdef: shiftdef.second){ +// const Cut& cut = cutdef.first; +// +// const bool pass = shifted ? cut(sr) : nomCutCache.Get(cut, sr); +// // Cut failed, skip all the histograms that depended on it +// if(!pass) continue; +// +// for(auto& weidef: cutdef.second){ +// const Weight& weivar = weidef.first; +// +// double wei = shifted ? weivar(sr) : nomWeiCache.Get(weivar, sr); +// +// if(wei < 0){ +// std::cerr << "Negative weight " << wei +// << " returned from Var"; +// std::cerr << std::endl; +// abort(); +// } +// +// wei *= systWeight; +// if(wei == 0) continue; +// +// for(auto& vardef: weidef.second){ +// if(vardef.first.IsMulti()){ +// for(double val: vardef.first.GetMultiVar()(sr)){ +// for(Spectrum** s : vardef.second.spects) +// if(*s) (*s)->Fill(val, wei); +// } +// continue; +// } +// +// const Var& var = vardef.first.GetVar(); +// +// const double val = shifted ? var(sr) : nomVarCache.Get(var, sr); +// +// if(std::isnan(val) || std::isinf(val)){ +// std::cerr << "Warning: Bad value: " << val +// << " returned from a Var. The input variable(s) could " +// << "be NaN in the CAF, or perhaps your " +// << "Var code computed 0/0?"; +// std::cout << " Not filling into this histogram for this slice." +// << std::endl; +// continue; +// } +// +// for(Spectrum** s : vardef.second.spects) +// if(*s) (*s)->Fill(val, wei); +// +// for(auto rv: vardef.second.rwSpects){ +// ReweightableSpectrum** rw = rv.first; +// if(!*rw) continue; +// const double yval = rv.second(sr); +// +// if(std::isnan(yval) || std::isinf(yval)){ +// std::cerr << "Warning: Bad value: " << yval +// << " for reweighting Var"; +// std::cout << ". Not filling into histogram." << std::endl; +// continue; +// } +// +// // TODO: ignoring events with no true neutrino etc +// if(yval != 0) +// (*rw)->Fill(val, yval, wei); +// } // end for rw +// } // end for vardef +// } // end for weidef +// } // end for cutdef +// +// // Return StandardRecord to its unshifted form ready for the next +// // histogram. +// caf::SRProxySystController::Rollback(); +// } // end for shiftdef +// +// assert(!caf::SRProxySystController::AnyShifted()); +// } + +// //---------------------------------------------------------------------- +// void SpectrumLoader::ReportExposures() +// { +// // The POT member variables we use here were filled as part of +// // SpectrumLoaderBase::GetNextFile() as we looped through the input files. +// +// // Let's just assume no-one is using the Cut::POT() function yet, so this +// // printout remains relevant... +// +// std::cout << fPOT << " POT" << std::endl; +// } +// +// // cafanacore's spectra are expecting a different structure of +// // spectrumloader. But we can easily trick it with these. +// struct SpectrumSink +// { +// static void FillPOT(Spectrum* s, double pot){s->fPOT += pot;} +// }; +// struct ReweightableSpectrumSink +// { +// static void FillPOT(ReweightableSpectrum* rw, double pot){rw->fPOT += pot;} +// }; + +// //---------------------------------------------------------------------- +// void SpectrumLoader::StoreExposures() { +// for(auto& shiftdef: fHistDefs){ +// for(auto& cutdef: shiftdef.second){ +// for(auto& weidef: cutdef.second){ +// for(auto& vardef: weidef.second){ +// for(Spectrum** s : vardef.second.spects) +// if(*s) SpectrumSink::FillPOT(*s, fPOT); +// for(auto rv : vardef.second.rwSpects) +// if(*rv.first) ReweightableSpectrumSink::FillPOT(*rv.first, fPOT); +// } +// } +// } +// } +// } + + //---------------------------------------------------------------------- + void SpectrumLoader::StoreExposures() { - public: - CutVarCache() : fCache(U::MaxID()+1) {} - - inline T Get(const U& var, const caf::SRProxy* sr) - { - const unsigned int id = var.ID(); - - if(fCache[id].set) return fCache[id].val; - - const T val = var(sr); - fCache[id].val = val; - fCache[id].set = true; - return val; + if(fabs(fPOT - fPOTFromHist)/std::min(fPOT, fPOTFromHist) > 0.001){ + std::cout << fPOT << " POT from hdr differs from " << fPOTFromHist << " POT from the TotalPOT histogram!" << std::endl; + abort(); } - protected: - // Seems to be faster to do this than [unordered_]map - struct CacheElem{ - T val; bool set; - }; - std::vector fCache; - }; - - //---------------------------------------------------------------------- - void SpectrumLoader::HandleRecord(caf::SRProxy* sr) - { - // Some shifts only adjust the weight, so they're effectively nominal, but - // aren't grouped with the other nominal histograms. Keep track of the - // results for nominals in these caches to speed those systs up. - CutVarCache nomCutCache; - CutVarCache nomWeiCache; - CutVarCache nomVarCache; - - for(auto& shiftdef: fHistDefs){ - const SystShifts& shift = shiftdef.first; - - // Need to provide a clean slate for each new set of systematic shifts to - // work from. Copying the whole StandardRecord is pretty expensive, so - // modify it in place and revert it afterwards. - - // Please do not continue/break out of the shiftdef loop. If this is - // required, let's use a RAII type here. - caf::SRProxySystController::BeginTransaction(); - - double systWeight = 1; - bool shifted = false; - - // Can special-case nominal to not pay cost of Shift() - if(!shift.IsNominal()){ - shift.Shift(sr, systWeight); - // If there were only weighting systs applied then the cached nominal - // values are still valid. - shifted = caf::SRProxySystController::AnyShifted(); - } - - for(auto& cutdef: shiftdef.second){ - const Cut& cut = cutdef.first; - - const bool pass = shifted ? cut(sr) : nomCutCache.Get(cut, sr); - // Cut failed, skip all the histograms that depended on it - if(!pass) continue; - - for(auto& weidef: cutdef.second){ - const Weight& weivar = weidef.first; - - double wei = shifted ? weivar(sr) : nomWeiCache.Get(weivar, sr); - - if(wei < 0){ - std::cerr << "Negative weight " << wei - << " returned from Var"; - std::cerr << std::endl; - abort(); - } - - wei *= systWeight; - if(wei == 0) continue; - - for(auto& vardef: weidef.second){ - if(vardef.first.IsMulti()){ - for(double val: vardef.first.GetMultiVar()(sr)){ - for(Spectrum** s : vardef.second.spects) - if(*s) (*s)->Fill(val, wei); - } - continue; - } - - const Var& var = vardef.first.GetVar(); - - const double val = shifted ? var(sr) : nomVarCache.Get(var, sr); - - if(std::isnan(val) || std::isinf(val)){ - std::cerr << "Warning: Bad value: " << val - << " returned from a Var. The input variable(s) could " - << "be NaN in the CAF, or perhaps your " - << "Var code computed 0/0?"; - std::cout << " Not filling into this histogram for this slice." - << std::endl; - continue; - } - - for(Spectrum** s : vardef.second.spects) - if(*s) (*s)->Fill(val, wei); - - for(auto rv: vardef.second.rwSpects){ - ReweightableSpectrum** rw = rv.first; - if(!*rw) continue; - const double yval = rv.second(sr); - - if(std::isnan(yval) || std::isinf(yval)){ - std::cerr << "Warning: Bad value: " << yval - << " for reweighting Var"; - std::cout << ". Not filling into histogram." << std::endl; - continue; - } - - // TODO: ignoring events with no true neutrino etc - if(yval != 0) - (*rw)->Fill(val, yval, wei); - } // end for rw - } // end for vardef - } // end for weidef - } // end for cutdef - - // Return StandardRecord to its unshifted form ready for the next - // histogram. - caf::SRProxySystController::Rollback(); - } // end for shiftdef - - assert(!caf::SRProxySystController::AnyShifted()); - } - - //---------------------------------------------------------------------- - void SpectrumLoader::ReportExposures() - { - // The POT member variables we use here were filled as part of - // SpectrumLoaderBase::GetNextFile() as we looped through the input files. - - // Let's just assume no-one is using the Cut::POT() function yet, so this - // printout remains relevant... - - std::cout << fPOT << " POT" << std::endl; - } - - // cafanacore's spectra are expecting a different structure of - // spectrumloader. But we can easily trick it with these. - struct SpectrumSink - { - static void FillPOT(Spectrum* s, double pot){s->fPOT += pot;} - }; - struct ReweightableSpectrumSink - { - static void FillPOT(ReweightableSpectrum* rw, double pot){rw->fPOT += pot;} - }; + std::cout << fPOT << " POT over " << fNReadouts << " readouts" << std::endl; - //---------------------------------------------------------------------- - void SpectrumLoader::StoreExposures() { - for(auto& shiftdef: fHistDefs){ - for(auto& cutdef: shiftdef.second){ - for(auto& weidef: cutdef.second){ - for(auto& vardef: weidef.second){ - for(Spectrum** s : vardef.second.spects) - if(*s) SpectrumSink::FillPOT(*s, fPOT); - for(auto rv : vardef.second.rwSpects) - if(*rv.first) ReweightableSpectrumSink::FillPOT(*rv.first, fPOT); - } - } - } - } + FillPOT(fPOT); + FillLivetime(fNReadouts); } } // namespace ana diff --git a/CAFAna/Core/SpectrumLoader.h b/CAFAna/Core/SpectrumLoader.h index 4b22e73b..411300dd 100644 --- a/CAFAna/Core/SpectrumLoader.h +++ b/CAFAna/Core/SpectrumLoader.h @@ -4,9 +4,15 @@ #include +#include "duneanaobj/StandardRecord/Proxy/FwdDeclare.h" + +#include "CAFAna/Core/IRecordSource.h" +#include "CAFAna/Core/IRecordSink.h" + +#include "cafanacore/Passthrough.h" + class TFile; -#include "duneanaobj/StandardRecord/Proxy/FwdDeclare.h" namespace ana { @@ -20,21 +26,26 @@ namespace ana /// need. They will register with this loader. Finally, calling \ref Go will /// cause all the spectra to be filled at once. After this the loader may not /// be used again. - class SpectrumLoader: public SpectrumLoaderBase + class SpectrumLoader: public SpectrumLoaderBase, public Passthrough { public: - SpectrumLoader(const std::string& wildcard, int max = 0); - SpectrumLoader(const std::vector& fnames, int max = 0); + SpectrumLoader(const std::string& wildcard);//, int max = 0); + SpectrumLoader(const std::vector& fnames);//, int max = 0); #ifdef WITH_SAM /// Named constructor for SAM projects - static SpectrumLoader FromSAMProject(const std::string& proj, + static SpectrumLoader *FromSAMProject(const std::string& proj, int fileLimit = -1); #endif virtual ~SpectrumLoader(); virtual void Go() override; + virtual void PrintGraph(std::ostream& os) const override; + + // Print to stdout + virtual void PrintGraph() const; + protected: SpectrumLoader(); @@ -48,19 +59,37 @@ namespace ana virtual void HandleFile(TFile* f, Progress* prog = 0); - virtual void HandleRecord(caf::SRProxy* sr); + // This is handed off to + //virtual void HandleRecord(caf::SRProxy* sr); /// Save results of AccumulateExposures into the individual spectra virtual void StoreExposures(); /// Prints POT/livetime info for all spectra - virtual void ReportExposures(); + //virtual void ReportExposures(); + // int max_exntries; //this is in sbn, unsure if we need it + }; + + + class NullLoader: public SpectrumLoader + { + public: + virtual void Go() override {} + }; + static NullLoader kNullLoader; + + // SBN had null spill/slice sources, I guess we need both a StandardRecord and Interaction one? + static NullSource kNullSRSource; + static NullSource kNullInteractionSource; + static NullSource kNullTrueIntSource; + + /* We dont need this info here /// All unique cuts contained in fHistDefs std::vector fAllCuts; std::vector fLivetimeByCut; ///< Indexing matches fAllCuts std::vector fPOTByCut; ///< Indexing matches fAllCuts int max_entries; - }; + */ } diff --git a/CAFAna/Core/SpectrumLoaderBase.cxx b/CAFAna/Core/SpectrumLoaderBase.cxx index 7b7178ea..8afc329d 100644 --- a/CAFAna/Core/SpectrumLoaderBase.cxx +++ b/CAFAna/Core/SpectrumLoaderBase.cxx @@ -28,75 +28,78 @@ namespace ana { - //---------------------------------------------------------------------- - SpectrumLoaderBase::SpectList::~SpectList() - { - // We don't seem to be able to do this - maybe SpectList gets copied? - // Let's just bite the bullet and leak a few pointers. This all works - // completely differently in NOvA CAFAna with refactored SpectrumLoader. - // - // Clean up the memory allocated for the pointers themselves - // for(Spectrum** s: spects) delete *s; - // for(auto rv: rwSpects) delete *rv.first; - } - - // Work around ReweightableSpectrum's friend requirements - struct ReweightableSpectrumSink - { - static void AddLoader(ReweightableSpectrum** rw){(*rw)->AddLoader(rw);} - static void RemoveLoader(ReweightableSpectrum** rw){(*rw)->RemoveLoader(rw);} - }; - //---------------------------------------------------------------------- - void SpectrumLoaderBase::SpectList::RemoveLoader(SpectrumLoaderBase* l) - { - for(Spectrum** s: spects) if(*s) (*s)->RemoveLoader(s); - for(auto rv: rwSpects) if(*rv.first) ReweightableSpectrumSink::RemoveLoader(rv.first); - } - - //---------------------------------------------------------------------- - size_t SpectrumLoaderBase::SpectList::TotalSize() const - { - return spects.size() + rwSpects.size(); - } - - //---------------------------------------------------------------------- - template U& SpectrumLoaderBase::IDMap:: - operator[](const T& key) - { - for(auto& it: fElems){ - if(it.first.ID() == key.ID()) return it.second; - } - fElems.push_back(std::make_pair(key, U())); - return fElems.back().second; - } - - //---------------------------------------------------------------------- - template void SpectrumLoaderBase::IDMap:: - RemoveLoader(SpectrumLoaderBase* l) - { - for(auto& it: fElems) it.second.RemoveLoader(l); - } - - //---------------------------------------------------------------------- - template void SpectrumLoaderBase::IDMap::Clear() - { - fElems.clear(); - } - - //---------------------------------------------------------------------- - template size_t SpectrumLoaderBase::IDMap:: - TotalSize() - { - size_t ret = 0; - for(auto& it: fElems) ret += it.second.TotalSize(); - return ret; - } - +/* //---------------------------------------------------------------------- +* SpectrumLoaderBase::SpectList::~SpectList() +* { +* // We don't seem to be able to do this - maybe SpectList gets copied? +* // Let's just bite the bullet and leak a few pointers. This all works +* // completely differently in NOvA CAFAna with refactored SpectrumLoader. +* // +* // Clean up the memory allocated for the pointers themselves +* // for(Spectrum** s: spects) delete *s; +* // for(auto rv: rwSpects) delete *rv.first; +* } +*/ +// This is all deleagted to cafanacore?? +// Work around ReweightableSpectrum's friend requirements + +/* struct ReweightableSpectrumSink +* { +* static void AddLoader(ReweightableSpectrum** rw){(*rw)->AddLoader(rw);} +* static void RemoveLoader(ReweightableSpectrum** rw){(*rw)->RemoveLoader(rw);} +* }; +* //---------------------------------------------------------------------- +* void SpectrumLoaderBase::SpectList::RemoveLoader(SpectrumLoaderBase* l) +* { +* for(Spectrum** s: spects) if(*s) (*s)->RemoveLoader(s); +* for(auto rv: rwSpects) if(*rv.first) ReweightableSpectrumSink::RemoveLoader(rv.first); +* } +* +* //---------------------------------------------------------------------- +* size_t SpectrumLoaderBase::SpectList::TotalSize() const +* { +* return spects.size() + rwSpects.size(); +* } +* +* //---------------------------------------------------------------------- +* template U& SpectrumLoaderBase::IDMap:: +* operator[](const T& key) +* { +* for(auto& it: fElems){ +* if(it.first.ID() == key.ID()) return it.second; +* } +* fElems.push_back(std::make_pair(key, U())); +* return fElems.back().second; +* } +* +* //---------------------------------------------------------------------- +* template void SpectrumLoaderBase::IDMap:: +* RemoveLoader(SpectrumLoaderBase* l) +* { +* for(auto& it: fElems) it.second.RemoveLoader(l); +* } +* +* //---------------------------------------------------------------------- +* template void SpectrumLoaderBase::IDMap::Clear() +* { +* fElems.clear(); +* } +* +* //---------------------------------------------------------------------- +* template size_t SpectrumLoaderBase::IDMap:: +* TotalSize() +* { +* size_t ret = 0; +* for(auto& it: fElems) ret += it.second.TotalSize(); +* return ret; +* } +*/ // Start of SpectrumLoaderBase proper //---------------------------------------------------------------------- + // adding fPOTFromHist and fNReadouts SpectrumLoaderBase::SpectrumLoaderBase() - : fGone(false), fPOT(0) + : fGone(false), fPOT(0), fPOTFromHist(0), fNReadouts(0) { } @@ -122,8 +125,8 @@ namespace ana //---------------------------------------------------------------------- SpectrumLoaderBase::~SpectrumLoaderBase() { - fHistDefs.RemoveLoader(this); - fHistDefs.Clear(); + //fHistDefs.RemoveLoader(this); + //fHistDefs.Clear(); } //---------------------------------------------------------------------- @@ -173,67 +176,69 @@ namespace ana #endif } - //---------------------------------------------------------------------- - void SpectrumLoaderBase::AddSpectrum(Spectrum& spect, - const Var& var, - const Cut& cut, - const SystShifts& shift, - const Weight& wei) - { - if(fGone){ - std::cerr << "Error: can't add Spectra after the call to Go()" << std::endl; - abort(); - } - - Spectrum** ps = new Spectrum*; - *ps = &spect; - fHistDefs[shift][cut][wei][var].spects.push_back(ps); - - // Remember we have a Go() pending - spect.AddLoader(ps); - } - - //---------------------------------------------------------------------- - void SpectrumLoaderBase::AddSpectrum(Spectrum& spect, - const MultiVar& var, - const Cut& cut, - const SystShifts& shift, - const Weight& wei) - { - if(fGone){ - std::cerr << "Error: can't add Spectra after the call to Go()" << std::endl; - abort(); - } - - Spectrum** ps = new Spectrum*; - *ps = &spect; - fHistDefs[shift][cut][wei][var].spects.push_back(ps); - - // Remember we have a Go() pending - spect.AddLoader(ps); - } - - //---------------------------------------------------------------------- - void SpectrumLoaderBase::AddReweightableSpectrum(ReweightableSpectrum& spect, - const Var& xvar, - const Var& yvar, - const Cut& cut, - const SystShifts& shift, - const Weight& wei) - { - if(fGone){ - std::cerr << "Error: can't add Spectra after the call to Go()" << std::endl; - abort(); - } - - ReweightableSpectrum** prw = new ReweightableSpectrum*; - *prw = &spect; - fHistDefs[shift][cut][wei][xvar].rwSpects.emplace_back(prw, yvar); - - // Remember we have a Go() pending - ReweightableSpectrumSink::AddLoader(prw); - } +// I think this is keeping track of what spectrums are registered, that should be taken care of by sink/source?? +/* //---------------------------------------------------------------------- +* void SpectrumLoaderBase::AddSpectrum(Spectrum& spect, +* const Var& var, +* const Cut& cut, +* const SystShifts& shift, +* const Weight& wei) +* { +* if(fGone){ +* std::cerr << "Error: can't add Spectra after the call to Go()" << std::endl; +* abort(); +* } +* +* Spectrum** ps = new Spectrum*; +* *ps = &spect; +* fHistDefs[shift][cut][wei][var].spects.push_back(ps); +* +* // Remember we have a Go() pending +* spect.AddLoader(ps); +* } +* +* //---------------------------------------------------------------------- +* void SpectrumLoaderBase::AddSpectrum(Spectrum& spect, +* const MultiVar& var, +* const Cut& cut, +* const SystShifts& shift, +* const Weight& wei) +* { +* if(fGone){ +* std::cerr << "Error: can't add Spectra after the call to Go()" << std::endl; +* abort(); +* } +* +* Spectrum** ps = new Spectrum*; +* *ps = &spect; +* fHistDefs[shift][cut][wei][var].spects.push_back(ps); +* +* // Remember we have a Go() pending +* spect.AddLoader(ps); +* } +* +* //---------------------------------------------------------------------- +* void SpectrumLoaderBase::AddReweightableSpectrum(ReweightableSpectrum& spect, +* const Var& xvar, +* const Var& yvar, +* const Cut& cut, +* const SystShifts& shift, +* const Weight& wei) +* { +* if(fGone){ +* std::cerr << "Error: can't add Spectra after the call to Go()" << std::endl; +* abort(); +* } +* +* ReweightableSpectrum** prw = new ReweightableSpectrum*; +* *prw = &spect; +* fHistDefs[shift][cut][wei][xvar].rwSpects.emplace_back(prw, yvar); +* +* // Remember we have a Go() pending +* ReweightableSpectrumSink::AddLoader(prw); +* } +*/ //---------------------------------------------------------------------- int SpectrumLoaderBase::NFiles() const { @@ -250,41 +255,57 @@ namespace ana std::cout << "Bad file (zombie): " << f->GetName() << std::endl; abort(); } - +// Im not sure this will still be valid in the source/sink world... + TTree* trPot = 0; - if (f->GetListOfKeys()->Contains("meta")) + if (f->GetListOfKeys()->Contains("cafTree")) + trPot = (TTree*)f->Get("cafTree"); + else // this actually might break things... trPot = (TTree*)f->Get("meta"); - else - trPot = (TTree*)f->Get("pottree"); +// if (f->GetListOfKeys()->Contains("meta")) +// trPot = (TTree*)f->Get("meta"); +// else +// trPot = (TTree*)f->Get("pottree"); assert(trPot); - double pot; - trPot->SetBranchAddress("pot", &pot); + float pot; //double + trPot->SetBranchAddress("rec.beam.pulsepot", &pot); + //trPot->SetBranchAddress("pot", &pot); for(int n = 0; n < trPot->GetEntries(); ++n){ trPot->GetEntry(n); - fPOT += pot; + //unsure if this shoulf be fPOT or fPOTFromHist + // I think fPOT is accounted for in HandleFile in the SBN version + //fPOT += pot; + fPOTFromHist += pot; + fPOT += pot; } - return f; - } - //---------------------------------------------------------------------- - void NullLoader::Go() - { - } + // This is from the SBN version... + //TH1* hPOT = (TH1*)f->Get("TotalPOT"); + //assert(hPOT); + //fPOTFromHist += hPOT->Integral(0, -1); - //---------------------------------------------------------------------- - NullLoader::~NullLoader() - { + return f; } - // Apparently the existence of fHistDefs isn't enough and I need to spell - // this out to make sure the function bodies are generated. - template struct SpectrumLoaderBase::IDMap>>>; +// //---------------------------------------------------------------------- +// void NullLoader::Go() +// { +// } +// +// //---------------------------------------------------------------------- +// NullLoader::~NullLoader() +// { +// } +// +// // Apparently the existence of fHistDefs isn't enough and I need to spell +// // this out to make sure the function bodies are generated. +// template struct SpectrumLoaderBase::IDMap>>>; } // namespace diff --git a/CAFAna/Core/SpectrumLoaderBase.h b/CAFAna/Core/SpectrumLoaderBase.h index cf3f5fbf..59b00405 100644 --- a/CAFAna/Core/SpectrumLoaderBase.h +++ b/CAFAna/Core/SpectrumLoaderBase.h @@ -27,36 +27,36 @@ namespace ana class SpectrumLoaderBase { public: - - friend class ReweightableSpectrum; - friend class NDOscillatableSpectrum; - friend class OscillatableSpectrum; - friend class Spectrum; +// Dow we need these friends?? +// friend class ReweightableSpectrum; +// friend class NDOscillatableSpectrum; +// friend class OscillatableSpectrum; +// friend class Spectrum; virtual ~SpectrumLoaderBase(); - /// For use by the \ref Spectrum constructor - virtual void AddSpectrum(Spectrum& spect, - const Var& var, - const Cut& cut, - const SystShifts& shift, - const Weight& wei = kUnweighted); - - /// For use by the \ref Spectrum constructor - virtual void AddSpectrum(Spectrum& spect, - const MultiVar& var, - const Cut& cut, - const SystShifts& shift, - const Weight& wei = kUnweighted); - - /// For use by the constructors of \ref ReweightableSpectrum subclasses - virtual void AddReweightableSpectrum(ReweightableSpectrum& spect, - const Var& xvar, - const Var& yvar, - const Cut& cut, - const SystShifts& shift, - const Weight& wei); - +/* /// For use by the \ref Spectrum constructor +* virtual void AddSpectrum(Spectrum& spect, +* const Var& var, +* const Cut& cut, +* const SystShifts& shift, +* const Weight& wei = kUnweighted); +* +* /// For use by the \ref Spectrum constructor +* virtual void AddSpectrum(Spectrum& spect, +* const MultiVar& var, +* const Cut& cut, +* const SystShifts& shift, +* const Weight& wei = kUnweighted); +* +* /// For use by the constructors of \ref ReweightableSpectrum subclasses +* virtual void AddReweightableSpectrum(ReweightableSpectrum& spect, +* const Var& xvar, +* const Var& yvar, +* const Cut& cut, +* const SystShifts& shift, +* const Weight& wei); +*/ /// Load all the registered spectra virtual void Go() = 0; @@ -95,113 +95,122 @@ namespace ana double fPOT; ///< Accumulated by calls to \ref GetNextFile - /// \brief Helper class for \ref SpectrumLoaderBase - /// - /// List of Spectrum and OscillatableSpectrum, some utility functions - struct SpectList - { - ~SpectList(); - void RemoveLoader(SpectrumLoaderBase* l); - size_t TotalSize() const; - - // Doubled pointers are sadly necessary as we need the locations of the - // nodes to be constant so Spectrum can re-register itself if moved. - std::vector spects; - std::vector> rwSpects; - }; - - /// \brief Helper class for \ref SpectrumLoaderBase - /// - /// Functions like std::map except it should be faster to iterate - /// through the elements (while slower to fill) and it knows to compare Ts - /// via their ID() function. Various methods that forward through to the - /// \ref SpectList at the end of the chain. - template struct IDMap - { - U& operator[](const T& key); - - // Make class iterable. Keep inline for speed - typedef typename std::vector>::iterator it_t; - inline it_t begin(){return fElems.begin();} - inline it_t end(){return fElems.end();} - - void RemoveLoader(SpectrumLoaderBase* l); - void Clear(); - size_t TotalSize(); - protected: - std::vector> fElems; - }; - - class VarOrMultiVar - { - public: - // v could easily be a temporary, have to make a copy - VarOrMultiVar(const Var& v) : fVar(new Var(v)), fMultiVar(0) {} - VarOrMultiVar(const MultiVar& v) : fVar(0), fMultiVar(new MultiVar(v)) {} - ~VarOrMultiVar() {delete fVar; delete fMultiVar;} - - VarOrMultiVar(const VarOrMultiVar& v) - : fVar(v.fVar ? new Var(*v.fVar) : 0), - fMultiVar(v.fMultiVar ? new MultiVar(*v.fMultiVar) : 0) - { - } - - VarOrMultiVar(VarOrMultiVar&& v) - { - fVar = v.fVar; - fMultiVar = v.fMultiVar; - v.fVar = 0; - v.fMultiVar = 0; - } - - bool IsMulti() const {return fMultiVar;} - const Var& GetVar() const {assert(fVar); return *fVar;} - const MultiVar& GetMultiVar() const {assert(fMultiVar); return *fMultiVar;} - - int ID() const {return fVar ? fVar->ID() : fMultiVar->ID();} - - protected: - const Var* fVar; - const MultiVar* fMultiVar; - }; - - /// \brief All the spectra that need to be filled - /// - /// [shift][cut][wei][var] - IDMap>>> fHistDefs; - }; - /// \brief Dummy loader that doesn't load any files - /// - /// Useful when a loader is required for a component you want to ignore - class NullLoader: public SpectrumLoaderBase - { - public: - NullLoader() {} - ~NullLoader(); - - virtual void Go() override; - - void AddSpectrum(Spectrum& spect, - const Var& var, - const Cut& cut, - const SystShifts& shift, - const Weight& wei = kUnweighted) override {} - void AddSpectrum(Spectrum& spect, - const MultiVar& var, - const Cut& cut, - const SystShifts& shift, - const Weight& wei = kUnweighted) override {} - - void AddReweightableSpectrum(ReweightableSpectrum& spect, - const Var& xvar, - const Var& yvar, - const Cut& cut, - const SystShifts& shift, - const Weight& wei) override {} + // new additions + double fPOTFromHist; ///< Accumulated by calls to \ref GetNextFile + // Do we really need this? + int fNReadouts; }; - /// \brief Dummy loader that doesn't load any files - /// - /// Useful when a loader is required for a component you want to ignore - static NullLoader kNullLoader; +// we dont need helper classes?? Spectrums don need to be registered, source/sink machinery takes care of that? +/* /// \brief Helper class for \ref SpectrumLoaderBase +* /// +* /// List of Spectrum and OscillatableSpectrum, some utility functions +* struct SpectList +* { +* ~SpectList(); +* void RemoveLoader(SpectrumLoaderBase* l); +* size_t TotalSize() const; +* +* // Doubled pointers are sadly necessary as we need the locations of the +* // nodes to be constant so Spectrum can re-register itself if moved. +* std::vector spects; +* std::vector> rwSpects; +* }; +*/ +// Is this something that should be removed ? This is kind of mimics the interaction between recordsource/sink ???? +/* /// \brief Helper class for \ref SpectrumLoaderBase +* /// +* /// Functions like std::map except it should be faster to iterate +* /// through the elements (while slower to fill) and it knows to compare Ts +* /// via their ID() function. Various methods that forward through to the +* /// \ref SpectList at the end of the chain. +* template struct IDMap +* { +* U& operator[](const T& key); +* +* // Make class iterable. Keep inline for speed +* typedef typename std::vector>::iterator it_t; +* inline it_t begin(){return fElems.begin();} +* inline it_t end(){return fElems.end();} +* +* void RemoveLoader(SpectrumLoaderBase* l); +* void Clear(); +* size_t TotalSize(); +* protected: +* std::vector> fElems; +* }; +* +* class VarOrMultiVar +* { +* public: +* // v could easily be a temporary, have to make a copy +* VarOrMultiVar(const Var& v) : fVar(new Var(v)), fMultiVar(0) {} +* VarOrMultiVar(const MultiVar& v) : fVar(0), fMultiVar(new MultiVar(v)) {} +* ~VarOrMultiVar() {delete fVar; delete fMultiVar;} +* +* VarOrMultiVar(const VarOrMultiVar& v) +* : fVar(v.fVar ? new Var(*v.fVar) : 0), +* fMultiVar(v.fMultiVar ? new MultiVar(*v.fMultiVar) : 0) +* { +* } +* +* VarOrMultiVar(VarOrMultiVar&& v) +* { +* fVar = v.fVar; +* fMultiVar = v.fMultiVar; +* v.fVar = 0; +* v.fMultiVar = 0; +* } +* +* bool IsMulti() const {return fMultiVar;} +* const Var& GetVar() const {assert(fVar); return *fVar;} +* const MultiVar& GetMultiVar() const {assert(fMultiVar); return *fMultiVar;} +* +* int ID() const {return fVar ? fVar->ID() : fMultiVar->ID();} +* +* protected: +* const Var* fVar; +* const MultiVar* fMultiVar; +* }; +* +* /// \brief All the spectra that need to be filled +* /// +* /// [shift][cut][wei][var] +* IDMap>>> fHistDefs; +* }; +* +* /// \brief Dummy loader that doesn't load any files +* /// +* /// Useful when a loader is required for a component you want to ignore +* class NullLoader: public SpectrumLoaderBase +* { +* public: +* NullLoader() {} +* ~NullLoader(); +* +* virtual void Go() override; +* +* void AddSpectrum(Spectrum& spect, +* const Var& var, +* const Cut& cut, +* const SystShifts& shift, +* const Weight& wei = kUnweighted) override {} +* void AddSpectrum(Spectrum& spect, +* const MultiVar& var, +* const Cut& cut, +* const SystShifts& shift, +* const Weight& wei = kUnweighted) override {} +* +* void AddReweightableSpectrum(ReweightableSpectrum& spect, +* const Var& xvar, +* const Var& yvar, +* const Cut& cut, +* const SystShifts& shift, +* const Weight& wei) override {} +* }; +* /// \brief Dummy loader that doesn't load any files +* /// +* /// Useful when a loader is required for a component you want to ignore +* static NullLoader kNullLoader; +*/ } diff --git a/CAFAna/Core/SystShifts.cxx b/CAFAna/Core/SystShifts.cxx index 1f56db23..6cf1ee02 100644 --- a/CAFAna/Core/SystShifts.cxx +++ b/CAFAna/Core/SystShifts.cxx @@ -1,8 +1,9 @@ #include "CAFAna/Core/SystShifts.h" -#include "CAFAna/Core/ISyst.h" -#include "CAFAna/Core/Registry.h" #include "CAFAna/Core/MathUtil.h" + +#include "cafanacore/Registry.h" + #include "CAFAna/Core/Stan.h" #include "CAFAna/Core/StanUtils.h" @@ -14,6 +15,7 @@ #include "TH1D.h" #include "TMath.h" #include "TObjString.h" +#include "TRandom3.h" #include "TString.h" namespace ana @@ -24,16 +26,26 @@ namespace ana const SystShifts kNoShift = SystShifts::Nominal(); //---------------------------------------------------------------------- - SystShifts::SystShifts() : fID(0) {} + SystShifts::SystShifts() : fID(0) + { + } //---------------------------------------------------------------------- - SystShifts::SystShifts(const ISyst *syst, double shift) : fID(fgNextID++) +// SystShifts(const ISyst* syst, double shift); + SystShifts::SystShifts(const ISyst *syst, double shift) + : fID(fgNextID++) { if (shift != 0) fSystsDbl.emplace(syst, Clamp(shift, syst)); } - +// SystShifts(const ISyst* syst, double shift); +// : fID(fgNextID++) +// { +// if (shift != 0) +// fSystsDbl.emplace(syst, Clamp(shift, syst)); +// } //---------------------------------------------------------------------- + //SystShifts::SystShifts(const ISyst* syst, stan::math::var shift) SystShifts::SystShifts(const ISyst* syst, stan::math::var shift) : fID(fgNextID++) { @@ -42,16 +54,50 @@ namespace ana // so that when the Stan cache gets invalidated we can still return something usable. fSystsDbl.emplace(syst, Clamp(util::GetValAs(shift), syst)); } - +// SystShifts::SystShifts(const ISyst* syst, stan::math::var shift) +// : fID(fgNextID++) +// { +// fSystsStan.emplace(syst, Clamp(shift, syst)); +// // we're always going to maintain a "double" copy +// // so that when the Stan cache gets invalidated we can still return something usable. +// fSystsDbl.emplace(syst, Clamp(util::GetValAs(shift), syst)); +// } //---------------------------------------------------------------------- + //SystShifts::SystShifts(const std::map *, double> &shifts) SystShifts::SystShifts(const std::map &shifts) : fID(fgNextID++) { for (auto it : shifts) if (it.second != 0) fSystsDbl.emplace(it.first, Clamp(it.second, it.first)); } - +// SystShifts::SystShifts(const std::map *, double> &shifts) +//// SystShifts::SystShifts(const std::map &shifts) +// : fID(fgNextID++) { +// for (auto it : shifts) +// if (it.second != 0) +// fSystsDbl.emplace(it.first, Clamp(it.second, it.first)); +// } + //---------------------------------------------------------------------- + //SystShifts(const std::unordered_map*, double>& shifts) + SystShifts::SystShifts(const std::unordered_map& shifts) + : fID(fgNextID++) + { + for(auto it: shifts) + if(it.second != 0) //should I be clamping? + fSystsDbl.emplace(it.first, Clamp(it.second, it.first)); + //fSystsDbl.emplace(it.first, it.second); + } +// SystShifts(const std::unordered_map*, double>& shifts) +// //SystShifts::SystShifts(const std::unordered_map& shifts) +// : fID(fgNextID++) +// { +// for(auto it: shifts) +// if(it.second != 0) //should I be clamping? +// fSystsDbl.emplace(it.first, Clamp(it.second, it.first)); +// //fSystsDbl.emplace(it.first, it.second); +// } //---------------------------------------------------------------------- + //SystShifts(const std::map*, stan::math::var>& shifts) SystShifts::SystShifts(const std::map& shifts) : fID(fgNextID++) { @@ -61,7 +107,31 @@ namespace ana fSystsDbl.emplace(it.first, util::GetValAs(it.second)); } } - +// SystShifts(const std::map*, stan::math::var>& shifts) +// //SystShifts::SystShifts(const std::map& shifts) +// : fID(fgNextID++) +// { +// for(auto it: shifts) +// { +// fSystsStan.emplace(it.first, it.second); +// fSystsDbl.emplace(it.first, util::GetValAs(it.second)); +// } +// } + //---------------------------------------------------------------------- +// SystShifts SystShifts::RandomThrow(const std::vector*>& systs) + SystShifts SystShifts::RandomThrow(const std::vector& systs) + { + SystShifts ret; + for(const ISyst* s: systs) ret.SetShift(s, gRandom->Gaus(0, 1)); + return ret; + } +// SystShifts SystShifts::RandomThrow(const std::vector*>& systs) +//// SystShifts SystShifts::RandomThrow(const std::vector& systs) +// { +// SystShifts ret; +// for(const ISyst* s: systs) ret.SetShift(s, gRandom->Gaus(0, 1)); +// return ret; +// } //---------------------------------------------------------------------- std::unique_ptr SystShifts::Copy() const { @@ -69,6 +139,7 @@ namespace ana } //---------------------------------------------------------------------- + //void SetShift(const ISyst* syst, double shift, bool force) void SystShifts::SetShift(const ISyst* syst, double shift, bool force) { fID = fgNextID++; @@ -88,6 +159,26 @@ namespace ana fSystsDbl.erase(syst); if(force || shift != 0.) fSystsDbl.emplace(syst, Clamp(shift, syst)); } +// void SetShift(const ISyst* syst, double shift, bool force) +// //void SystShifts::SetShift(const ISyst* syst, double shift, bool force) +// { +// fID = fgNextID++; +// +// // if this slot already exists in the Stan systs, and we're not setting the same value, +// // some shenanigans are going on that we need to figure out. abort. +// auto itStan = fSystsStan.find(syst); +// if(itStan != fSystsStan.end() && (itStan->second != shift && std::isnan(shift) != std::isnan(itStan->second))) +// { +// std::cerr << "Error Syst '" << syst->ShortName() << " already has a Stan pull set (" << itStan->second << ") " +// << "and you're trying to set a different double one (" << shift << ")." << std::endl; +// std::cerr << "You almost certainly didn't mean to do that." << std::endl; +// std::cerr << "Abort." << std::endl; +// abort(); +// } +// +// fSystsDbl.erase(syst); +// if(force || shift != 0.) fSystsDbl.emplace(syst, Clamp(shift, syst)); +// } //---------------------------------------------------------------------- void SystShifts::SetShift(const ISyst* syst, stan::math::var shift) @@ -153,7 +244,7 @@ namespace ana stan::math::var SystShifts::LogPrior() const { return log(Prior()); } //---------------------------------------------------------------------- - void SystShifts::Shift(caf::SRProxy *sr, + void SystShifts::Shift(caf::SRInteractionProxy* sr, //caf::SRProxy *sr, double &weight) const { // always fSystsDbl here because this is only used in the event loop, not in fitting diff --git a/CAFAna/Core/SystShifts.h b/CAFAna/Core/SystShifts.h index d20134c7..355387ca 100644 --- a/CAFAna/Core/SystShifts.h +++ b/CAFAna/Core/SystShifts.h @@ -1,7 +1,6 @@ #pragma once -#include "CAFAna/Core/FwdDeclare.h" -#include "duneanaobj/StandardRecord/Proxy/FwdDeclare.h" +#include "CAFAna/Core/ISyst.h" #include "CAFAna/Core/StanVar.h" @@ -15,40 +14,44 @@ class TDirectory; namespace ana { - class ISyst; - class Restorer; - /// Simple record of shifts applied to systematic parameters class SystShifts { public: SystShifts(); - SystShifts(const ISyst* syst, double shift); +// SystShifts(const ISyst* syst, double shift); +// SystShifts(const ISyst* syst, double shift); + SystShifts(const ISyst* syst, double shift); +// SystShifts(const ISyst*syst, stan::math::var shift); +// SystShifts(const ISyst*, stan::math::var shift); SystShifts(const ISyst* syst, stan::math::var shift); +// SystShifts(const std::map*, double>& shifts); +// SystShifts(const std::map*, double>& shifts); SystShifts(const std::map& shifts); +// SystShifts(const std::unordered_map*, double>& shifts); +// SystShifts(const std::unordered_map*, double>& shifts); + SystShifts(const std::unordered_map& shifts); +// SystShifts(const std::map*, stan::math::var>& shifts); +// SystShifts(const std::map*, stan::math::var>& shifts); SystShifts(const std::map& shifts); - - virtual ~SystShifts() = default; - - /// SystShifts with the same set of systs should have the same ID - int ID() const {return fID;} + //virtual ~SystShifts() = default; static SystShifts Nominal() {return SystShifts();} - - std::vector ActiveSysts() const; - - /// Allow derived classes to overload so they can copy themselves - /// in case they overload Penalty(). Used in IFitter. - /// Note that you own the copy... - virtual std::unique_ptr Copy() const; + static SystShifts RandomThrow(const std::vector& systs); + //static SystShifts RandomThrow(const std::vector*>& systs); + //static SystShifts RandomThrow(const std::vector*>& systs); bool IsNominal() const {return fSystsDbl.empty(); } // since there's always a 'double' copy of any stan ones too /// shift: 0 = nominal; +-1 = 1sigma shifts etc. Arbitrary shifts allowed /// set force=true to insert a syst even if the shift is 0 + //void SetShift(const ISyst* syst, double shift, bool force=false); + //void SetShift(const ISyst* syst, double shift, bool force=false); + //void SetShift(const ISyst* syst, stan::math::var shift); + //void SetShift(const ISyst* syst, stan::math::var shift); void SetShift(const ISyst* syst, double shift, bool force=false); void SetShift(const ISyst* syst, stan::math::var shift); - + /// Templated so that Stan- and not-stan versions have the same interface. /// If you don't specify anything it'll just give you back the double, /// which is probably what you want anyway. @@ -58,12 +61,30 @@ namespace ana void ResetToNominal(); - bool HasStan(const ISyst* s) const {return fSystsStan.count(s);} - bool HasAnyStan() const {return !fSystsStan.empty();} - /// Penalty term for (frequentist) chi-squared fits double Penalty() const; + + //not sure if this is the right change + //void Shift(caf::SRProxy* sr, + void Shift(caf::SRInteractionProxy* sr, + double& weight) const; + + + /// Brief description of component shifts, for printing to screen + std::string ShortName() const; + /// Long description of component shifts, for plot labels + std::string LatexName() const; + + + /// Allow derived classes to overload so they can copy themselves + /// in case they overload Penalty(). Used in IFitter. + /// Note that you own the copy... + virtual std::unique_ptr Copy() const; + + bool HasStan(const ISyst* s) const {return fSystsStan.count(s);} + bool HasAnyStan() const {return !fSystsStan.empty();} + /// Prior used in Bayesian fitting. Override as needed. /// If it's more efficient to calculate log(prior) /// explicitly, override LogPrior() as well @@ -73,14 +94,10 @@ namespace ana /// override this virtual stan::math::var LogPrior() const; + /// SystShifts with the same set of systs should have the same ID + int ID() const {return fID;} - void Shift(caf::SRProxy* sr, - double& weight) const; - - /// Brief description of component shifts, for printing to screen - std::string ShortName() const; - /// Long description of component shifts, for plot labels - std::string LatexName() const; + std::vector ActiveSysts() const; void SaveTo(TDirectory* dir, const std::string& name) const; static std::unique_ptr LoadFrom(TDirectory* dir, const std::string& name); diff --git a/CAFAna/Core/Utilities.cxx b/CAFAna/Core/Utilities.cxx index 3ef7ddf5..7b0cf1ce 100644 --- a/CAFAna/Core/Utilities.cxx +++ b/CAFAna/Core/Utilities.cxx @@ -60,49 +60,62 @@ namespace ana } //---------------------------------------------------------------------- - std::unique_ptr CalcCovMx(const std::vector & binSets, int firstBin, int lastBin) + // Reduce code duplication between CalcCovMx and CalcBiasMx + Eigen::ArrayXd GetBinMeans(const std::vector& binSets) { - if (binSets.size() < 2) - return std::unique_ptr(nullptr); + const unsigned int nBins(binSets.front().size()); + const unsigned int nUniv(binSets.size()); - if (lastBin < 0) - lastBin = binSets[0]->GetSize() - 1; // indexed from 0 + Eigen::ArrayXd binMeans = Eigen::ArrayXd::Zero(nBins); + for(unsigned int univIdx = 0; univIdx < nUniv; ++univIdx) + binMeans += binSets[univIdx]; - int nBins = lastBin - firstBin + 1; // firstBin and lastBin are inclusive + binMeans *= 1./(nUniv); - std::vector binMeans(nBins); - for( const auto & binSet : binSets ) - { - for ( decltype(lastBin) binIdx = firstBin; binIdx <= lastBin; binIdx++ ) - binMeans[binIdx] += (*binSet)[binIdx]; - } - for (decltype(lastBin) binIdx = firstBin; binIdx <= lastBin; binIdx++) - binMeans[binIdx] /= binSets.size(); + return binMeans; + } + + //---------------------------------------------------------------------- + Eigen::MatrixXd CalcCovMx(const std::vector& binSets) + { + if (binSets.size() < 2) + return Eigen::MatrixXd(0,0); + + const unsigned int nUniv(binSets.size()); + const unsigned int nBins(binSets.front().size()); + const Eigen::ArrayXd binMeans = GetBinMeans(binSets); - auto covmx = std::make_unique(nBins, nBins); + Eigen::MatrixXd covmx = Eigen::MatrixXd::Zero(nBins, nBins); - for( unsigned int hist_idx = 0; hist_idx < binSets.size(); ++hist_idx ) + for(unsigned int univIdx = 0; univIdx < nUniv; ++univIdx) { - // first calculate the weighted sum of squares of the deviations - for( decltype(nBins) i = 0; i < nBins; i++ ) - { - double xi = (*(binSets[hist_idx]))[i]; - for( decltype(nBins) k = i; k < nBins; k++ ) - { - double xk = (*(binSets[hist_idx]))[k]; - (*covmx)[i][k] += (xi - binMeans[i]) * (xk - binMeans[k]); - if (i != k) - (*covmx)[k][i] = (*covmx)[i][k]; // covariance matrices are always symmetric - } - } - } // for (hist_idx) + // Get a column vector of the difference from the mean in each bin + Eigen::MatrixXd errs = (binSets[univIdx] - binMeans).matrix(); + + // Calculate the variance from column * row + covmx += errs * errs.transpose(); + } // for (univIdx) // now divide by N-1 to get sample covariance - (*covmx) *= 1./(binSets.size()-1); + covmx *= 1./(nUniv-1); return covmx; } + //---------------------------------------------------------------------- + Eigen::MatrixXd CalcBiasMx(const Eigen::ArrayXd& nom, const std::vector& binSets) + { + if (binSets.size() < 2) + return Eigen::MatrixXd(0,0); + + const Eigen::ArrayXd binMeans = GetBinMeans(binSets); + + // Get a column vector of the difference from the mean in each bin + Eigen::MatrixXd errs = (nom - binMeans).matrix(); + + // Calculate the variance from column * row + return errs * errs.transpose(); + } //---------------------------------------------------------------------- double LogLikelihood(const TH1* eh, const TH1* oh, bool useOverflow) @@ -165,6 +178,16 @@ namespace ana return ret; } + //---------------------------------------------------------------------- + TH2F * EigenMatrixToTH2(Eigen::MatrixXd m) + { + TH2F* h = new TH2F("", "", m.rows(), 0, m.rows(), m.cols() , 0 , m.cols() ); + for (int x = 0 ; x< m.rows();x++) + for (int y = 0 ; y< m.rows();y++) + h->SetBinContent(x,y,m(x,y)); + + return h; + } //---------------------------------------------------------------------- double Chi2CovMx(const Eigen::ArrayXd& e, const Eigen::ArrayXd& o, const Eigen::MatrixXd& covmxinv) { @@ -682,6 +705,36 @@ namespace ana return ret; } + + //---------------------------------------------------------------------- + double FindQuantile(double frac, std::vector& xs) + { + // This turns out to be a much more fraught issue than you would naively + // expect. This algorithm is equivalent to R-6 here: + // https://en.wikipedia.org/wiki/Quantile#Estimating_quantiles_from_a_sample + + // In principle we could use std::nth_element(). Probably doesn't matter + // much in practice since this is only for plotting. + std::sort(xs.begin(), xs.end()); + + const int N = xs.size(); + // The index we would ideally be sampling at + const double h = frac*(N+1); + // The indices on either side where we have to actually evaluate + const unsigned int h0 = std::floor(h); + const unsigned int h1 = std::ceil(h); + if(h0 == 0) return xs[0]; // Don't underflow indexing + if(h1 > xs.size()) return xs.back(); // Don't overflow indexing + // The values at those indices + const double x0 = xs[h0-1]; // wikipedia is using 1-based indexing + const double x1 = xs[h1-1]; + + if(h0 == h1) return x0; + + // Linear interpolation + return (h1-h)*x0 + (h-h0)*x1; + } + } diff --git a/CAFAna/Core/Utilities.h b/CAFAna/Core/Utilities.h index 4869b977..347c2971 100644 --- a/CAFAna/Core/Utilities.h +++ b/CAFAna/Core/Utilities.h @@ -60,7 +60,21 @@ namespace ana Note TH1D is a child class of TArrayD -- so you can pass a vector of TH1D* to this method. **/ - std::unique_ptr CalcCovMx(const std::vector & binSets, int firstBin=0, int lastBin=-1); + //std::unique_ptr CalcCovMx(const std::vector & binSets, int firstBin=0, int lastBin=-1); + Eigen::MatrixXd CalcCovMx(const std::vector& binSets); + + /** \brief Compute bias from a collection of sets of bin contents. + + \param nom Bins corresponding to the nominal universe from which the bias is calculated + \param binSets Collection of sets of bins from which bias from the nominal is calculated + + \returns Eigen::MatrixXD containing computed bias matrix unless binSets.size() < 2, + in which case an 0*0 matric is returned + **/ + Eigen::MatrixXd CalcBiasMx(const Eigen::ArrayXd& nom, const std::vector& binSets); + + /// Returns a TH2 to visualize matrix easily + // TH2* EigenMatrixToTH2( ) class LLPerBinFracSystErr { @@ -153,6 +167,9 @@ namespace ana TMatrixD TMatrixDFromEigenMatrixXd(const Eigen::MatrixXd& mat); + TH2F * EigenMatrixToTH2(Eigen::MatrixXd m); + + /** \brief Chi-squared calculation using a covariance matrix. \param exp Expected bin counts @@ -262,6 +279,10 @@ namespace ana Eigen::ArrayXd GetMaskArray(const Spectrum& s, double xmin=0, double xmax=-1, double ymin=0, double ymax=-1); + + /// /param frac Quantile to find, eg 0.9 + /// /param xs Values to search in -- this will be sorted + double FindQuantile(double frac, std::vector& xs); } /// \brief Like Ronseal, does exactly what it says on the tin diff --git a/CAFAna/Core/Var.h b/CAFAna/Core/Var.h index 5892ebbd..866c0fc6 100644 --- a/CAFAna/Core/Var.h +++ b/CAFAna/Core/Var.h @@ -11,13 +11,34 @@ namespace ana /// /// A Var consists of a function, taking a StandardRecord and returning the /// value of the variable (which may be some complicated function). - using Var = _Var; + typedef _Var Var; + typedef _Var TruthVar; + typedef _Var TruthPartVar; +//Commented things: I was trying so we could write loader.Interactions()[IntCut].{dlp,pandora}.RecoParticles().{dlp,pandora}[PartiCut] + // typedef _Var Var; + /// \brief Equivalent of \ref Var acting on \ref caf::SRSpill + typedef _Var SRVar; + typedef _Var NDVar; /// \brief For Vars where literally all you need is a single CAF variable /// /// eg Var myVar = SIMPLEVAR(my.var.str); /// NB lack of quotes quotes around my.var.str -#define SIMPLEVAR(CAFNAME) Var([](const caf::SRProxy* sr){return sr->CAFNAME;}) +#define SIMPLEVAR(CAFNAME) Var([](const caf::SRInteractionProxy* sr){return sr->CAFNAME;}) + +#define SIMPLETRUTHVAR(CAFNAME) TruthVar([](const caf::SRTrueInteractionProxy* nu){return nu->CAFNAME;}) + +#define SIMPLENDVAR(CAFNAME) NDVar([](const caf::SRNDLArIntProxy* sr){return sr->CAFNAME;}) + +#define SIMPLESRVAR(CAFNAME) SRVar([](const caf::SRProxy* sr){return sr->CAFNAME;}) + + + inline Var Constant(double v){return Var([v](const caf::SRInteractionProxy*){return v;});} +// inline Var Constant(double v){return Var([v](const caf::SRInteractionBranchProxy*){return v;});} + + typedef _Var RecoPartVar; + +#define SIMPLEPARTVAR(CAFNAME) RecoPartVar([](const caf::SRRecoParticleProxy* sr){return sr->CAFNAME;}) + - inline Var Constant(double v){return Var([v](const caf::SRProxy*){return v;});} } diff --git a/CAFAna/Core/Weight.h b/CAFAna/Core/Weight.h index 4dd326d2..8eecf64f 100644 --- a/CAFAna/Core/Weight.h +++ b/CAFAna/Core/Weight.h @@ -4,11 +4,26 @@ #include "duneanaobj/StandardRecord/Proxy/FwdDeclare.h" +//namespace ana +//{ +// using Weight = _Weight; +// +//#define SIMPLEWEIGHT(CAFNAME) Weight([](const caf::SRProxy* sr){return sr->CAFNAME;}) +// +// const Weight kUnweighted = Unweighted(); +//} + namespace ana { - using Weight = _Weight; + typedef _Weight SRWeight; + + /// \brief Equivalent of \ref Weight acting on \ref caf::SRSpill + typedef _Weight Weight; + // typedef _Weight NuTruthWeight; + + /// The simplest possible Weight, always 1. Used as a default weight. + const SRWeight kSRUnweighted = Unweighted(); + const Weight kUnweighted = Unweighted(); -#define SIMPLEWEIGHT(CAFNAME) Weight([](const caf::SRProxy* sr){return sr->CAFNAME;}) - const Weight kUnweighted = Unweighted(); -} +} // namespace \ No newline at end of file diff --git a/CAFAna/Cuts/AnaCuts.cxx b/CAFAna/Cuts/AnaCuts.cxx index ab055654..6fe113ff 100644 --- a/CAFAna/Cuts/AnaCuts.cxx +++ b/CAFAna/Cuts/AnaCuts.cxx @@ -4,6 +4,7 @@ namespace ana { + /* const Cut kPassFD_CVN_NUE( [](const caf::SRProxy* sr) { @@ -41,4 +42,6 @@ const Cut kPassND_RHC_NUMU( // sr->reco_q == +1 && sr->Ehad_veto<30); }); + */ + } diff --git a/CAFAna/Cuts/AnaCuts.h b/CAFAna/Cuts/AnaCuts.h index 3e2fc05e..1791d9bb 100644 --- a/CAFAna/Cuts/AnaCuts.h +++ b/CAFAna/Cuts/AnaCuts.h @@ -4,13 +4,13 @@ namespace ana { - extern const Cut kPassFD_CVN_NUE; - - extern const Cut kPassFD_CVN_NUMU; - - extern const Cut kPassFD_CVN_NUTAU; - - extern const Cut kPassND_FHC_NUMU; - - extern const Cut kPassND_RHC_NUMU; +// extern const Cut kPassFD_CVN_NUE; +// +// extern const Cut kPassFD_CVN_NUMU; +// +// extern const Cut kPassFD_CVN_NUTAU; +// +// extern const Cut kPassND_FHC_NUMU; +// +// extern const Cut kPassND_RHC_NUMU; } diff --git a/CAFAna/Cuts/TruthCuts.cxx b/CAFAna/Cuts/TruthCuts.cxx index d410e2c5..d0b33d27 100644 --- a/CAFAna/Cuts/TruthCuts.cxx +++ b/CAFAna/Cuts/TruthCuts.cxx @@ -1,4 +1,61 @@ #include "CAFAna/Cuts/TruthCuts.h" - +#include "duneanaobj/StandardRecord/Proxy/SRProxy.h" +#include // Just make sure that the cuts get built on a regular basis. Could contain // more complex cut logic in the future. +namespace ana +{ + +// NOvA cuts + const Cut kIsNC([](const caf::SRProxy* sr) + { + if(sr->mc.nnu == 0) return false; + assert(sr->mc.nnu == 1); + return !sr->mc.nu[0].iscc; + }); + + const Cut kIsNue([](const caf::SRProxy* sr){ + return (sr->mc.nnu == 1 && abs(sr->mc.nu[0].pdg) ==12);}); + + const Cut kIsNumu([](const caf::SRProxy* sr){ + return (sr->mc.nnu == 1 && abs(sr->mc.nu[0].pdg) ==14);}); + + + bool CCFlavSel::operator()(const caf::SRProxy* sr) const + { + if(sr->mc.nnu == 0) return false; + assert(sr->mc.nnu == 1); + return (sr->mc.nu[0].iscc && + abs(sr->mc.nu[0].pdg) == fPdg && + abs(sr->mc.nu[0].pdgorig) == fPdgOrig); + } + + + const Cut kIsAntiNu([](const caf::SRProxy* sr) + { + if(sr->mc.nnu == 0) return false; + assert(sr->mc.nnu == 1); + return sr->mc.nu[0].pdg < 0; + }); + + const Cut kIsNu([](const caf::SRProxy* sr) + { + if(sr->mc.nnu == 0) return false; + assert(sr->mc.nnu == 1); + return sr->mc.nu[0].pdg > 0; + }); + + const Cut kHasNu([](const caf::SRProxy* sr) + { + if(sr->mc.nnu == 0) return false; + assert(sr->mc.nnu == 1); + return true; + }); + + const Cut kHasNeutrino( + [](const caf::SRProxy* sr) + { return (sr->mc.nnu != 0); } + ); + + +} \ No newline at end of file diff --git a/CAFAna/Cuts/TruthCuts.h b/CAFAna/Cuts/TruthCuts.h index 54475ab5..d02151c2 100644 --- a/CAFAna/Cuts/TruthCuts.h +++ b/CAFAna/Cuts/TruthCuts.h @@ -1,23 +1,57 @@ #pragma once #include "CAFAna/Core/Cut.h" -#include "duneanaobj/StandardRecord/Proxy/SRProxy.h" + namespace ana { + + + /// \brief Is this a Neutral %Current event? /// /// We use uniform-initializer syntax to concisely pass the list of necessary /// branches. In this case the selection function is simple enough that we /// can include it inline as a lambda function. - const Cut kIsNC([](const caf::SRProxy* sr) - { - return !sr->isCC; - }); - - //---------------------------------------------------------------------- - /// Helper for defining true CC event cuts +// const Cut kIsNC([](const caf::SRProxy* sr) +// { +// return !sr->isCC; +// }); + + extern const Cut kIsNC; + extern const Cut kIsNue; + extern const Cut kIsNumu; + +// const NuTruthCut kIsTau_NT([](const caf::SRNeutrinoProxy* truth){ +// return (abs(truth->pdg) == 16);}); +// +// const Cut kIsTau = CutFromNuTruthCut(kIsTau_NT); +// +// const NuTruthCut kIsNC_NT([](const caf::SRNeutrinoProxy* truth) +// { +// return !truth->iscc; +// }); + + +// //---------------------------------------------------------------------- +// /// Helper for defining true CC event cuts +// class CCFlavSel +// { +// public: +// CCFlavSel(int pdg, int pdgorig) : fPdg(pdg), fPdgOrig(pdgorig) +// { +// } +// +// bool operator()(const caf::SRProxy* sr) const +// { +// return sr->isCC && abs(sr->nuPDGunosc) == fPdgOrig && abs(sr->nuPDG) == fPdg; +// } +// protected: +// int fPdg, fPdgOrig; +// }; + +// Nova version class CCFlavSel { public: @@ -25,10 +59,7 @@ namespace ana { } - bool operator()(const caf::SRProxy* sr) const - { - return sr->isCC && abs(sr->nuPDGunosc) == fPdgOrig && abs(sr->nuPDG) == fPdg; - } + bool operator()(const caf::SRProxy* sr) const; protected: int fPdg, fPdgOrig; }; @@ -38,7 +69,7 @@ namespace ana // constants to be easily duplicated. /// Select CC \f$ \nu_\mu\to\nu_e \f$ - const Cut kIsSig (CCFlavSel(12, 14)); + const Cut kIsNueApp (CCFlavSel(12, 14)); /// Select CC \f$ \nu_\mu\to\nu_\mu \f$ const Cut kIsNumuCC (CCFlavSel(14, 14)); /// Select CC \f$ \nu_e\to\nu_e \f$ @@ -50,6 +81,23 @@ namespace ana /// Select CC \f$ \nu_e\to\nu_\tau \f$ const Cut kIsTauFromE(CCFlavSel(16, 12)); + + + +//// Commenting out DUNE cafana, and porting Nova cuts here + /// Is this truly an antineutrino? + extern const Cut kIsAntiNu; + extern const Cut kIsNu; + + extern const Cut kHasNu; + + + /// Check if MC slice has neutrino information (useful for in-and-out tests) + extern const Cut kHasNeutrino; + + + +/* /// Is this truly an antineutrino? const Cut kIsAntiNu([](const caf::SRProxy* sr) { @@ -133,5 +181,5 @@ namespace ana { return ( sr->mvanumu > -1 ); }); - +*/ } // namespace ana diff --git a/CAFAna/Decomp/CMakeLists.txt b/CAFAna/Decomp/CMakeLists.txt deleted file mode 100644 index 4535cb4a..00000000 --- a/CAFAna/Decomp/CMakeLists.txt +++ /dev/null @@ -1,21 +0,0 @@ -set(Decomp_implementation_files - IDecomp.cxx - NumuDecomp.cxx) - -set(Decomp_header_files - IDecomp.h - NumuDecomp.h) - -add_library(CAFAnaDecomp SHARED ${Decomp_implementation_files}) -target_link_libraries(CAFAnaDecomp CAFAnaCore) - -set_target_properties(CAFAnaDecomp PROPERTIES - PUBLIC_HEADER "${Decomp_header_files}") - -if(DEFINED USE_OPENMP AND USE_OPENMP) - target_compile_options(CAFAnaDecomp BEFORE PUBLIC -DUSE_PREDINTERP_OMP -fopenmp) -endif() - -install(TARGETS CAFAnaDecomp - LIBRARY DESTINATION lib/ - PUBLIC_HEADER DESTINATION include/CAFAna/Decomp/) diff --git a/CAFAna/Decomp/IDecomp.cxx b/CAFAna/Decomp/IDecomp.cxx deleted file mode 100644 index 92f85652..00000000 --- a/CAFAna/Decomp/IDecomp.cxx +++ /dev/null @@ -1,29 +0,0 @@ -#include "CAFAna/Decomp/IDecomp.h" - -#include "CAFAna/Core/LoadFromFile.h" - -#include - -#include "TDirectory.h" -#include "TObjString.h" - -// So we can implement LoadFrom() -#include "CAFAna/Decomp/NumuDecomp.h" - -namespace ana -{ - //---------------------------------------------------------------------- - // Definition to satisfy the declaration in Core/LoadFromFile.h - template<> std::unique_ptr LoadFrom(TDirectory* dir, const std::string& name) - { - TObjString* ptag = (TObjString*)dir->Get((name+"/type").c_str()); - assert(ptag); - - const TString tag = ptag->GetString(); - - if(tag == "NumuDecomp") return NumuDecomp::LoadFrom(dir, name); - - std::cerr << "Unknown Decomp type '" << tag << "'" << std::endl; - abort(); - } -} diff --git a/CAFAna/Decomp/IDecomp.h b/CAFAna/Decomp/IDecomp.h deleted file mode 100644 index e5715e98..00000000 --- a/CAFAna/Decomp/IDecomp.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#include "CAFAna/Core/Cut.h" -#include "CAFAna/Core/SpectrumLoaderBase.h" -#include "CAFAna/Core/Spectrum.h" - -class TDirectory; - -namespace ana -{ - - /// Standard interface to all decomposition techniques - class IDecomp - { - public: - virtual ~IDecomp() = default; - virtual Spectrum NCComponent() const = 0; - virtual Spectrum NumuComponent() const = 0; - virtual Spectrum AntiNumuComponent() const = 0; - virtual Spectrum NueComponent() const = 0; - virtual Spectrum AntiNueComponent() const = 0; - - virtual void SaveTo(TDirectory* dir, const std::string& name) const = 0; - }; -} diff --git a/CAFAna/Decomp/NumuDecomp.cxx b/CAFAna/Decomp/NumuDecomp.cxx deleted file mode 100644 index 57dd75c9..00000000 --- a/CAFAna/Decomp/NumuDecomp.cxx +++ /dev/null @@ -1,117 +0,0 @@ -#include "CAFAna/Decomp/NumuDecomp.h" - -#include "CAFAna/Cuts/TruthCuts.h" -#include "CAFAna/Core/Ratio.h" - -#include - -#include "TDirectory.h" -#include "TObjString.h" - -namespace ana -{ - //---------------------------------------------------------------------- - NumuDecomp::NumuDecomp(SpectrumLoaderBase& loaderMC, - SpectrumLoaderBase& loaderData, - const std::string& label, - const Binning& bins, - const Var& var, - const Cut& cut, - const SystShifts& shiftMC, - const SystShifts& shiftData, - const Weight& wei) - : NumuDecomp(loaderMC, loaderData, HistAxis(label, bins, var), - cut, shiftMC, shiftData, wei) - { - } - - //---------------------------------------------------------------------- - NumuDecomp::NumuDecomp(SpectrumLoaderBase& loaderMC, - SpectrumLoaderBase& loaderData, - const HistAxis& axis, - const Cut& cut, - const SystShifts& shiftMC, - const SystShifts& shiftData, - const Weight& wei) - : fData (loaderData, axis, cut, shiftData, wei), - fNC (loaderMC, axis, cut && kIsNC, shiftMC, wei), - fNue (loaderMC, axis, cut && kIsBeamNue&&!kIsAntiNu, shiftMC, wei), - fAntiNue (loaderMC, axis, cut && kIsBeamNue&& kIsAntiNu, shiftMC, wei), - fNumu (loaderMC, axis, cut && kIsNumuCC &&!kIsAntiNu, shiftMC, wei), - fAntiNumu(loaderMC, axis, cut && kIsNumuCC && kIsAntiNu, shiftMC, wei), - fNotNumu (loaderMC, axis, cut && !kIsNumuCC, shiftMC, wei) - { - } - - //---------------------------------------------------------------------- - NumuDecomp::NumuDecomp(Loaders& loaders, - const HistAxis& axis, - const Cut& cut, - const SystShifts& shiftMC, - const SystShifts& shiftData, - const Weight& wei) - : NumuDecomp(loaders.GetLoader(caf::kNEARDET, Loaders::kMC), - loaders.GetLoader(caf::kNEARDET, Loaders::kData), - axis, cut, shiftMC, shiftData, wei) - { - } - - //---------------------------------------------------------------------- - Spectrum NumuDecomp::NumuComponent() const - { - // Subtract backgrounds from data using MC, then split into nu/antinu - // components using MC ratio - return (fNumu/(fNumu+fAntiNumu))*(fData-fNotNumu); - } - - //---------------------------------------------------------------------- - Spectrum NumuDecomp::AntiNumuComponent() const - { - return (fAntiNumu/(fNumu+fAntiNumu))*(fData-fNotNumu); - } - - //---------------------------------------------------------------------- - void NumuDecomp::SaveTo(TDirectory* dir, const std::string& name) const - { - TDirectory* tmp = gDirectory; - - dir = dir->mkdir(name.c_str()); // switch to subdir - dir->cd(); - - TObjString("NumuDecomp").Write("type"); - - fNC.SaveTo(dir, "nc_comp"); - fData.SaveTo(dir, "data_comp"); - fNue.SaveTo(dir, "nue_comp"); - fAntiNue.SaveTo(dir, "antinue_comp"); - fNumu.SaveTo(dir, "numu_comp"); - fAntiNumu.SaveTo(dir, "antinumu_comp"); - fNotNumu.SaveTo(dir, "notnumu_comp"); - - dir->Write(); - delete dir; - - tmp->cd(); - } - - //---------------------------------------------------------------------- - std::unique_ptr NumuDecomp::LoadFrom(TDirectory* dir, const std::string& name) - { - dir = dir->GetDirectory(name.c_str()); // switch to subdir - assert(dir); - - std::unique_ptr ret(new NumuDecomp); - - ret->fNC = *Spectrum::LoadFrom(dir, "nc_comp"); - ret->fData = *Spectrum::LoadFrom(dir, "data_comp"); - ret->fNue = *Spectrum::LoadFrom(dir, "nue_comp"); - ret->fAntiNue = *Spectrum::LoadFrom(dir, "antinue_comp"); - ret->fNumu = *Spectrum::LoadFrom(dir, "numu_comp"); - ret->fAntiNumu = *Spectrum::LoadFrom(dir, "antinumu_comp"); - ret->fNotNumu = *Spectrum::LoadFrom(dir, "notnumu_comp"); - - delete dir; - - return ret; - } -} diff --git a/CAFAna/Decomp/NumuDecomp.h b/CAFAna/Decomp/NumuDecomp.h deleted file mode 100644 index 76a4da5f..00000000 --- a/CAFAna/Decomp/NumuDecomp.h +++ /dev/null @@ -1,74 +0,0 @@ -#pragma once - -#include "CAFAna/Decomp/IDecomp.h" - -#include "CAFAna/Core/Loaders.h" - -namespace ana -{ - /// Uses MC for NC and \f$ \nu_e \f$ CC components, assigns remainder of data to \f$ \nu_\mu \f$ CC - class NumuDecomp: public IDecomp - { - public: - NumuDecomp(SpectrumLoaderBase& loaderMC, - SpectrumLoaderBase& loaderData, - const std::string& label, - const Binning& bins, - const Var& var, - const Cut& cut, - const SystShifts& shiftMC = kNoShift, - const SystShifts& shiftData = kNoShift, - const Weight& wei = kUnweighted); - - NumuDecomp(SpectrumLoaderBase& loaderMC, - SpectrumLoaderBase& loaderData, - const HistAxis& axis, - const Cut& cut, - const SystShifts& shiftMC = kNoShift, - const SystShifts& shiftData = kNoShift, - const Weight& wei = kUnweighted); - - NumuDecomp(Loaders& loaders, - const HistAxis& axis, - const Cut& cut, - const SystShifts& shiftMC = kNoShift, - const SystShifts& shiftData = kNoShift, - const Weight& wei = kUnweighted); - - Spectrum NumuComponent() const override; - Spectrum AntiNumuComponent() const override; - Spectrum NCComponent() const override {return fNC;} - Spectrum NueComponent() const override {return fNue;} - Spectrum AntiNueComponent() const override {return fAntiNue;} - - virtual Spectrum MC_NumuComponent() const {return fNumu;} - virtual Spectrum MC_AntiNumuComponent() const {return fAntiNumu;} - virtual Spectrum Data_Component () const {return fData;} - - void SaveTo(TDirectory* dir, const std::string& name) const override; - static std::unique_ptr LoadFrom(TDirectory* dir, const std::string& name); - - protected: - NumuDecomp() - : fData(Spectrum::Uninitialized()), - fNC (Spectrum::Uninitialized()), - fNue (Spectrum::Uninitialized()), - fAntiNue(Spectrum::Uninitialized()), - fNumu(Spectrum::Uninitialized()), - fAntiNumu(Spectrum::Uninitialized()), - fNotNumu(Spectrum::Uninitialized()) - {}; - - Spectrum fData; - - Spectrum fNC; - - Spectrum fNue; - Spectrum fAntiNue; - - Spectrum fNumu; - Spectrum fAntiNumu; - - Spectrum fNotNumu; - }; -} diff --git a/CAFAna/Extrap/CMakeLists.txt b/CAFAna/Extrap/CMakeLists.txt index c8276dd2..fc25685a 100644 --- a/CAFAna/Extrap/CMakeLists.txt +++ b/CAFAna/Extrap/CMakeLists.txt @@ -1,14 +1,9 @@ set(Extrap_implementation_files IExtrap.cxx - ModularExtrap.cxx - ModularExtrapComponent.cxx - ModularExtrapComponentPlot.cxx TrivialExtrap.cxx) set(Extrap_header_files IExtrap.h - ModularExtrap.h - ModularExtrapComponent.h TrivialExtrap.h) add_library(CAFAnaExtrap SHARED ${Extrap_implementation_files}) diff --git a/CAFAna/Extrap/ModularExtrap.cxx b/CAFAna/Extrap/ModularExtrap.cxx deleted file mode 100644 index a95cf47b..00000000 --- a/CAFAna/Extrap/ModularExtrap.cxx +++ /dev/null @@ -1,429 +0,0 @@ -#if 0 -// Currently dead code - -#include "CAFAna/Core/LoadFromFile.h" -#include "CAFAna/Extrap/ModularExtrap.h" -#include "CAFAna/Core/Loaders.h" -#include "CAFAna/Cuts/TruthCuts.h" -#include "TObjString.h" -#include "TDirectory.h" - -namespace ana -{ - - //--------------------------------------------------------------------------- - /* - ModularExtrap ModularExtrap::Nue( - Loaders& loaders, - const IDecomp& nueDecomp, - const IDecomp& numuDecomp, - const HistAxis& axis, - const HistAxis& axisNumuND, - const Cut& fdcut, - const Cut& nueNDcut, - const Cut& numuNDcut, - const SystShifts& shiftMC, - const Weight& weight - ){ - return ModularExtrap::Nue( - loaders.GetLoader( - caf::kNEARDET, Loaders::kMC, Loaders::kNonSwap), - loaders.GetLoader( - caf::kFARDET, Loaders::kMC, Loaders::kFluxSwap), - loaders.GetLoader( - caf::kFARDET, Loaders::kMC, Loaders::kNonSwap), - loaders.GetLoader( - caf::kFARDET, Loaders::kMC, Loaders::kTauSwap), - nueDecomp, - numuDecomp, - axis, - axisNumuND, - fdcut, - nueNDcut, - numuNDcut, - shiftMC, - weight - ); - } - */ - //--------------------------------------------------------------------------- - - ModularExtrap ModularExtrap::Numu( - Loaders& loaders, - const IDecomp& numuDecomp, - const HistAxis& axis, - const Cut& fdcut, - const Cut& ndcut, - const SystShifts& shiftMC, - const Weight& weight - ){ - return ModularExtrap::Numu( - loaders.GetLoader( - caf::kNEARDET, Loaders::kMC, Loaders::kNonSwap), - loaders.GetLoader( - caf::kFARDET, Loaders::kMC, Loaders::kNonSwap), - loaders.GetLoader( - caf::kFARDET, Loaders::kMC, Loaders::kNue), - loaders.GetLoader( - caf::kFARDET, Loaders::kMC, Loaders::kTau), - loaders.GetLoader( - caf::kFARDET, Loaders::kMC, Loaders::kNC), - numuDecomp, - axis, - fdcut, - ndcut, - shiftMC, - weight - ); - } - - //--------------------------------------------------------------------------- - /* - ModularExtrap ModularExtrap::Nue( - SpectrumLoaderBase& nearMC, - SpectrumLoaderBase& farMCswap, - SpectrumLoaderBase& farMCnonswap, - SpectrumLoaderBase& farMCtauswap, - const IDecomp& nueDecomp, - const IDecomp& numuDecomp, - const HistAxis& axis, - const HistAxis& axisNumuND, - const Cut& fdcut, - const Cut& nueNDcut, - const Cut& numuNDcut, - const SystShifts& shiftMC, - const Weight& weight - ){ - - ModularExtrap extrap( - farMCswap, - farMCnonswap, - farMCtauswap, - axis, - fdcut, - shiftMC, - weight - ); - - // mu -> mu ---- - extrap.fMMextrap = std::unique_ptr( - new RecoReweight( - nearMC, axis, fdcut, shiftMC, weight, - "mu -> mu", "#nu_{#mu} #rightarrow #nu_{#mu}", - nueNDcut, nueDecomp, // nue selection in ND - DecompResult::numu, kIsNumuCC && !kIsAntiNu, // numu truth in ND - farMCnonswap, kIsNumuCC && !kIsAntiNu // mu->mu in FD - ) - ); - - // mu -> e ---- - extrap.fMEextrap = std::unique_ptr( - new TruthReweight( - nearMC, axis, axisNumuND, fdcut, shiftMC, weight, - "mu -> e", "#nu_{#mu} #rightarrow #nu_{e}", - numuNDcut, numuDecomp, // numu selection in ND - DecompResult::numu, kIsNumuCC && !kIsAntiNu, // numu truth in ND - farMCswap, kIsSig && !kIsAntiNu // mu->e in FD - ) - ); - extrap.fMEAntiextrap = std::unique_ptr( - new TruthReweight( - nearMC, axis, axisNumuND, fdcut, shiftMC, weight, - "mubar -> ebar", "#bar{#nu}_{#mu} #rightarrow #bar{#nu}_{e}", - numuNDcut, numuDecomp, // numu selection in ND - DecompResult::numubar, kIsNumuCC && kIsAntiNu, // numubar truth in ND - farMCswap, kIsSig && kIsAntiNu // mubar->ebar in FD - ) - ); - - // NC -> NC ---- - extrap.fNCextrap = std::unique_ptr( - new RecoReweight( - nearMC, axis, fdcut, shiftMC, weight, - "NC -> NC", "NC #rightarrow NC", - nueNDcut, nueDecomp, // nue selection in ND - DecompResult::NC, kIsNC, // NC truth in ND - farMCswap, kIsNC, // NC->NC in FD - farMCnonswap, farMCtauswap // extra NC stats - ) - ); - - // e -> e ---- - extrap.fEEextrap = std::unique_ptr( - new RecoReweight( - nearMC, axis, fdcut, shiftMC, weight, - "e -> e", "#nu_{e} #rightarrow #nu_{e}", - nueNDcut, nueDecomp, // nue selection in ND - DecompResult::nue, kIsBeamNue && !kIsAntiNu, // nue truth in ND - farMCnonswap, kIsBeamNue && !kIsAntiNu // e->e in FD - ) - ); - - return extrap; - - } - */ - //--------------------------------------------------------------------------- - - ModularExtrap ModularExtrap::Numu( - SpectrumLoaderBase& nearMC, - SpectrumLoaderBase& farMCnonswap, - SpectrumLoaderBase& farMCnue, - SpectrumLoaderBase& farMCnutau, - SpectrumLoaderBase& farMCnc, - const IDecomp& numuDecomp, - const HistAxis& axis, - const Cut& fdcut, - const Cut& numuNDcut, - const SystShifts& shiftMC, - const Weight& weight - ){ - - ModularExtrap extrap( - farMCnonswap, - farMCnue, - farMCnutau, - farMCnc, - axis, - fdcut, - shiftMC, - weight - ); - - // mu -> mu ---- - extrap.fMMextrap = std::unique_ptr( - new TruthReweight( - nearMC, axis, axis, fdcut, shiftMC, weight, - "mu -> mu", "#nu_{#mu} #rightarrow #nu_{#mu}", - numuNDcut, numuDecomp, // numu selection in ND - DecompResult::numu, kIsNumuCC && !kIsAntiNu, // numu truth in ND - farMCnonswap, kIsNumuCC && !kIsAntiNu // mu->mu in FD - ) - ); - extrap.fMMAntiextrap = std::unique_ptr( - new TruthReweight( - nearMC, axis, axis, fdcut, shiftMC, weight, - "mubar -> mubar", "#bar{#nu}_{#mu} #rightarrow #bar{#nu}_{#mu}", - numuNDcut, numuDecomp, // numu selection in ND - DecompResult::numubar, kIsNumuCC && kIsAntiNu, // numubar truth in ND - farMCnonswap, kIsNumuCC && kIsAntiNu // mubar->mubar in FD - ) - ); - - return extrap; - } - - //--------------------------------------------------------------------------- - - void ModularExtrap::SaveTo(TDirectory* dir) const - { - - TDirectory* tmp = gDirectory; - dir->cd(); - TObjString("ModularExtrap").Write("type"); - - fEEextrap->SaveTo(dir->mkdir("EEextrap")); - fEMextrap->SaveTo(dir->mkdir("EMextrap")); - fMEextrap->SaveTo(dir->mkdir("MEextrap")); - fMMextrap->SaveTo(dir->mkdir("MMextrap")); - fEEAntiextrap->SaveTo(dir->mkdir("EEAntiextrap")); - fEMAntiextrap->SaveTo(dir->mkdir("EMAntiextrap")); - fMEAntiextrap->SaveTo(dir->mkdir("MEAntiextrap")); - fMMAntiextrap->SaveTo(dir->mkdir("MMAntiextrap")); - fMTextrap->SaveTo(dir->mkdir("MTextrap")); - fETextrap->SaveTo(dir->mkdir("ETextrap")); - fMTAntiextrap->SaveTo(dir->mkdir("MTAntiextrap")); - fETAntiextrap->SaveTo(dir->mkdir("ETAntiextrap")); - fNCextrap->SaveTo(dir->mkdir("NCextrap")); - - tmp->cd(); - - } - - //--------------------------------------------------------------------------- - - void ModularExtrap::SavePlotsNue( TDirectory* dir, double potFD ) const - { - TDirectory* tmp = gDirectory; - dir->cd(); - fMEextrap->SavePlots( dir->mkdir("MEextrap"), potFD ); - fMEAntiextrap->SavePlots( dir->mkdir("MEAntiextrap"), potFD ); - fEEextrap->SavePlots( dir->mkdir("EEextrap"), potFD ); - fMMextrap->SavePlots( dir->mkdir("MMextrap"), potFD ); - fNCextrap->SavePlots( dir->mkdir("NCextrap"), potFD ); - tmp->cd(); - } - - //--------------------------------------------------------------------------- - - void ModularExtrap::SavePlotsNumu( TDirectory* dir, double potFD ) const - { - TDirectory* tmp = gDirectory; - dir->cd(); - fMMextrap->SavePlots( dir->mkdir("MMextrap"), potFD ); - fMMAntiextrap->SavePlots( dir->mkdir("MMAntiextrap"), potFD ); - tmp->cd(); - } - - //--------------------------------------------------------------------------- - - std::unique_ptr ModularExtrap::LoadFrom(TDirectory* dir) - { - - std::unique_ptr ret(new ModularExtrap); - - assert(dir->GetDirectory("EEextrap")); - ret->fEEextrap = ana::LoadFrom( - dir->GetDirectory("EEextrap") ); - - assert(dir->GetDirectory("EMextrap")); - ret->fEMextrap = ana::LoadFrom( - dir->GetDirectory("EMextrap") ); - - assert(dir->GetDirectory("MEextrap")); - ret->fMEextrap = ana::LoadFrom( - dir->GetDirectory("MEextrap") ); - - assert(dir->GetDirectory("MMextrap")); - ret->fMMextrap = ana::LoadFrom( - dir->GetDirectory("MMextrap") ); - - assert(dir->GetDirectory("EEAntiextrap")); - ret->fEEAntiextrap = ana::LoadFrom( - dir->GetDirectory("EEAntiextrap") ); - - assert(dir->GetDirectory("EMAntiextrap")); - ret->fEMAntiextrap = ana::LoadFrom( - dir->GetDirectory("EMAntiextrap") ); - - assert(dir->GetDirectory("MEAntiextrap")); - ret->fMEAntiextrap = ana::LoadFrom( - dir->GetDirectory("MEAntiextrap") ); - - assert(dir->GetDirectory("MMAntiextrap")); - ret->fMMAntiextrap = ana::LoadFrom( - dir->GetDirectory("MMAntiextrap") ); - - assert(dir->GetDirectory("NCextrap")); - ret->fNCextrap = ana::LoadFrom( - dir->GetDirectory("NCextrap") ); - - assert(dir->GetDirectory("MTextrap")); - ret->fMTextrap = ana::LoadFrom( - dir->GetDirectory("MTextrap") ); - - assert(dir->GetDirectory("ETextrap")); - ret->fETextrap = ana::LoadFrom( - dir->GetDirectory("ETextrap") ); - - assert(dir->GetDirectory("MTAntiextrap")); - ret->fMTAntiextrap = ana::LoadFrom( - dir->GetDirectory("MTAntiextrap") ); - - assert(dir->GetDirectory("ETAntiextrap")); - ret->fETAntiextrap = ana::LoadFrom( - dir->GetDirectory("ETAntiextrap") ); - - return ret; - - } - - //--------------------------------------------------------------------------- - - ModularExtrap::ModularExtrap( - SpectrumLoaderBase& farMCnonswap, - SpectrumLoaderBase& farMCnue, - SpectrumLoaderBase& farMCnutau, - SpectrumLoaderBase& farMCnc, - const HistAxis& axis, - const Cut& fdcut, - const SystShifts& shiftMC, - const Weight& weight - ) : - - // e -> e ---- - fEEextrap( new NoReweight( - farMCnonswap, axis, fdcut, shiftMC, weight, kIsBeamNue && !kIsAntiNu)), - fEEAntiextrap( new NoReweight( - farMCnonswap, axis, fdcut, shiftMC, weight, kIsBeamNue && kIsAntiNu)), - - // mu -> mu ---- - fMMextrap( new NoReweight( - farMCnonswap, axis, fdcut, shiftMC, weight, kIsNumuCC && !kIsAntiNu)), - fMMAntiextrap( new NoReweight( - farMCnonswap, axis, fdcut, shiftMC, weight, kIsNumuCC && kIsAntiNu)), - - // mu -> e ---- - fMEextrap( new NoReweight( - farMCnue, axis, fdcut, shiftMC, weight, kIsSig && !kIsAntiNu)), - fMEAntiextrap( new NoReweight( - farMCnue, axis, fdcut, shiftMC, weight, kIsSig && kIsAntiNu)), - - // e -> mu ---- - fEMextrap( new NoReweight( - farMCnutau, axis, fdcut, shiftMC, weight, kIsNumuApp && !kIsAntiNu)), - fEMAntiextrap( new NoReweight( - farMCnutau, axis, fdcut, shiftMC, weight, kIsNumuApp && kIsAntiNu)), - - // NC -> NC ---- - fNCextrap( new NoReweight( - farMCnc, axis, fdcut, shiftMC, weight, kIsNC)), - - // mu -> tau ---- - fMTextrap( new NoReweight( - farMCnutau, axis, fdcut, shiftMC, weight, kIsTauFromMu && !kIsAntiNu)), - fMTAntiextrap( new NoReweight( - farMCnutau, axis, fdcut, shiftMC, weight, kIsTauFromMu && kIsAntiNu)), - - // e -> tau ---- - fETextrap( new NoReweight( - farMCnue, axis, fdcut, shiftMC, weight, kIsTauFromE && !kIsAntiNu)), - fETAntiextrap( new NoReweight( - farMCnue, axis, fdcut, shiftMC, weight, kIsTauFromE && kIsAntiNu)) - - {} - - //--------------------------------------------------------------------------- - - OscillatableSpectrum ModularExtrap::NueSurvComponent() - {return fEEextrap->Return();} - - OscillatableSpectrum ModularExtrap::AntiNueSurvComponent() - {return fEEAntiextrap->Return();} - - OscillatableSpectrum ModularExtrap::NumuSurvComponent() - {return fMMextrap->Return();} - - OscillatableSpectrum ModularExtrap::AntiNumuSurvComponent() - {return fMMAntiextrap->Return();} - - OscillatableSpectrum ModularExtrap::NueAppComponent() - {return fMEextrap->Return();} - - OscillatableSpectrum ModularExtrap::AntiNueAppComponent() - {return fMEAntiextrap->Return();} - - OscillatableSpectrum ModularExtrap::NumuAppComponent() - {return fEMextrap->Return();} - - OscillatableSpectrum ModularExtrap::AntiNumuAppComponent() - {return fEMAntiextrap->Return();} - - Spectrum ModularExtrap::NCComponent() - {return fNCextrap->Return().Unoscillated();} - - OscillatableSpectrum ModularExtrap::TauFromMuComponent() - {return fMTextrap->Return();} - - OscillatableSpectrum ModularExtrap::AntiTauFromMuComponent() - {return fMTAntiextrap->Return();} - - OscillatableSpectrum ModularExtrap::TauFromEComponent() - {return fETextrap->Return();} - - OscillatableSpectrum ModularExtrap::AntiTauFromEComponent() - {return fETAntiextrap->Return();} - -} - -#endif diff --git a/CAFAna/Extrap/ModularExtrap.h b/CAFAna/Extrap/ModularExtrap.h deleted file mode 100644 index dcdde528..00000000 --- a/CAFAna/Extrap/ModularExtrap.h +++ /dev/null @@ -1,166 +0,0 @@ -#if 0 -// Currently dead code - -#pragma once - -#include "CAFAna/Core/HistAxis.h" -#include "CAFAna/Extrap/IExtrap.h" -#include "CAFAna/Extrap/ModularExtrapComponent.h" -#include - -class TDirectory; - -namespace ana -{ - - class Loaders; - class SpectrumLoaderBase; - class IDecomp; - class OscillatableSpectrum; - - /// \brief Extrapolate each component using a separate ModularExtrapComponent - /// - /// Only extrapolates one sample. - class ModularExtrap: public IExtrap - { - public: - - // /// Creates a nue-like extraploation. - // /** numuDecomp and numuNDCut are for the signal component (mu->e). - // nueDecomp and nueNDCut are for the backgound components. */ - // static ModularExtrap Nue( - // Loaders& loaders, - // const IDecomp& nueDecomp, - // const IDecomp& numuDecomp, - // const HistAxis& axis, - // const HistAxis& axisNumuND, - // const Cut& fdcut, - // const Cut& nueNDcut, - // const Cut& numuNDcut, - // const SystShifts& shiftMC = kNoShift, - // const Weight& weight = kUnweighted - // ); - - /// Creates a numu-like extrapolation. - static ModularExtrap Numu( - Loaders& loaders, - const IDecomp& numuDecomp, - const HistAxis& axis, - const Cut& fdcut, - const Cut& ndcut, - const SystShifts& shiftMC = kNoShift, - const Weight& weight = kUnweighted - ); - - // /// Creates a nue-like extraploation with individual spectrum loaders. - // /** numuDecomp and numuNDCut are for the signal component (mu->e). - // nueDecomp and nueNDCut are for the backgound components. */ - // static ModularExtrap Nue( - // SpectrumLoaderBase& nearMCLoader, - // SpectrumLoaderBase& farMCswapLoader, - // SpectrumLoaderBase& farMCnonswapLoader, - // SpectrumLoaderBase& farMCtauswapLoader, - // const IDecomp& nueDecomp, - // const IDecomp& numuDecomp, - // const HistAxis& axis, - // const HistAxis& axisNumuND, - // const Cut& fdcut, - // const Cut& nueNDcut, - // const Cut& numuNDcut, - // const SystShifts& shiftMC = kNoShift, - // const Weight& weight = kUnweighted - // ); - - /// Creates a numu-like extrapolation with individual spectrum loaders. - static ModularExtrap Numu( - SpectrumLoaderBase& nearMCLoader, - SpectrumLoaderBase& farMCnonswapLoader, - SpectrumLoaderBase& farMCnueLoader, - SpectrumLoaderBase& farMCnutauLoader, - SpectrumLoaderBase& farMCncLoader, - const IDecomp& numuDecomp, - const HistAxis& axis, - const Cut& fdcut, - const Cut& ndcut, - const SystShifts& shiftMC = kNoShift, - const Weight& weight = kUnweighted - ); - - // Prevent copying because we own objects on the free store. - ModularExtrap(const ModularExtrap&) = delete; - ModularExtrap& operator=(const ModularExtrap&) = delete; - ModularExtrap(ModularExtrap&&) = default; - ModularExtrap& operator=(ModularExtrap&&) = default; - virtual ~ModularExtrap() = default; - - void SaveTo(TDirectory* dir) const override; - void SavePlotsNue( TDirectory* dir, double potFD ) const; - void SavePlotsNumu( TDirectory* dir, double potFD ) const; - static std::unique_ptr LoadFrom(TDirectory* dir); - - // Override abstract methods. - OscillatableSpectrum NueSurvComponent() override; - OscillatableSpectrum AntiNueSurvComponent() override; - OscillatableSpectrum NumuSurvComponent() override; - OscillatableSpectrum AntiNumuSurvComponent() override; - OscillatableSpectrum NueAppComponent() override; - OscillatableSpectrum AntiNueAppComponent() override; - OscillatableSpectrum NumuAppComponent() override; - OscillatableSpectrum AntiNumuAppComponent() override; - OscillatableSpectrum TauFromMuComponent() override; - OscillatableSpectrum AntiTauFromMuComponent() override; - OscillatableSpectrum TauFromEComponent() override; - OscillatableSpectrum AntiTauFromEComponent() override; - Spectrum NCComponent() override; - - std::vector GetModExtrapComponents() const - { - return { - fEEextrap.get(), fEEAntiextrap.get(), - fMMextrap.get(), fMMAntiextrap.get(), - fMEextrap.get(), fMEAntiextrap.get(), - fEMextrap.get(), fEMAntiextrap.get(), - fNCextrap.get(), - fMTextrap.get(), fMTAntiextrap.get(), - fETextrap.get(), fETAntiextrap.get()}; - } - - protected: - - /// Sets up all components to use FD MC--internal use only. - /** Use a named constructor (the static function Nue() or Numu()) to - create a ModularExtrap. This function is protected. */ - ModularExtrap( - SpectrumLoaderBase& farMCnonswapLoader, - SpectrumLoaderBase& farMCnueLoader, - SpectrumLoaderBase& farMCnutauLoader, - SpectrumLoaderBase& farMCncLoader, - const HistAxis& axis, - const Cut& fdcut, - const SystShifts& shiftMC, - const Weight& weight - ); - - std::unique_ptr fEEextrap; - std::unique_ptr fEEAntiextrap; - std::unique_ptr fMMextrap; - std::unique_ptr fMMAntiextrap; - std::unique_ptr fMEextrap; - std::unique_ptr fMEAntiextrap; - std::unique_ptr fEMextrap; - std::unique_ptr fEMAntiextrap; - std::unique_ptr fNCextrap; - std::unique_ptr fMTextrap; - std::unique_ptr fMTAntiextrap; - std::unique_ptr fETextrap; - std::unique_ptr fETAntiextrap; - - private: - - ModularExtrap(){}; - - }; - -} - -#endif diff --git a/CAFAna/Extrap/ModularExtrapComponent.cxx b/CAFAna/Extrap/ModularExtrapComponent.cxx deleted file mode 100644 index dc232389..00000000 --- a/CAFAna/Extrap/ModularExtrapComponent.cxx +++ /dev/null @@ -1,384 +0,0 @@ -#if 0 -// Currently dead code - -#include "CAFAna/Core/LoadFromFile.h" -#include "CAFAna/Extrap/ModularExtrapComponent.h" -#include "CAFAna/Core/SpectrumLoaderBase.h" -#include "CAFAna/Decomp/IDecomp.h" -#include "CAFAna/Core/Ratio.h" -#include "CAFAna/Core/Utilities.h" - -#include "TH1.h" -#include "TDirectory.h" -#include "TObjString.h" - -namespace ana -{ - //--------------------------------------------------------------------------- - // Definition to satisfy declaration in Core/LoadFromFile.h - template<> std::unique_ptr - LoadFrom(TDirectory* dir) - { - TObjString* ptag = (TObjString*)dir->Get("type"); - assert(ptag); - - const TString tag = ptag->GetString(); - - if(tag == "NoReweight") - return NoReweight::LoadFrom(dir); - if(tag == "TruthReweight") - return TruthReweight::LoadFrom(dir); - if(tag == "RecoReweight") - return RecoReweight::LoadFrom(dir); - - std::cerr << "Unknown Component Extrapolation type '" - << tag << "'" << std::endl; - abort(); - } - - //--------------------------------------------------------------------------- - - ModularExtrapComponent::DivByZeroCounter::~DivByZeroCounter() - { - if (fQuiet) - return; - - if (this->fBins.size() == 0) - return; - - std::cerr << "\nWARNING: There were attempted divisions by empty bins (for which a fallback to no reweighting was used)" - << "\n during extrapolation in the following bins (check your MC stats):" - << std::endl; - for (const auto & tuple : this->fBins) - { - std::cerr << " Channel: " << std::get<0>(tuple) - << " Location: " << std::get<1>(tuple) - << " Bin Center: " << std::get<2>(tuple) - << "\n" << std::endl; - } - - } - - //--------------------------------------------------------------------------- - - const OscillatableSpectrum& ModularExtrapComponent::Return() const - { - if (!fEvaluated) - { - fCache = Eval(); - fEvaluated = true; - } - return fCache; - } - - //--------------------------------------------------------------------------- - - Spectrum ModularExtrapComponent::GetDecompResult( - const IDecomp& decomp, - const DecompResult dr - ){ - switch (dr){ - case DecompResult::nue : return decomp.NueComponent(); - case DecompResult::numu : return decomp.NumuComponent(); - case DecompResult::nuebar : return decomp.AntiNueComponent(); - case DecompResult::numubar : return decomp.AntiNumuComponent(); - case DecompResult::NC : return decomp.NCComponent(); - } - assert( 0 && "Bad DecompResult" ); - } - - //--------------------------------------------------------------------------- - - std::string ModularExtrapComponent::DRToString( - const DecompResult dr - ){ - switch (dr){ - case DecompResult::nue : return "Nue"; - case DecompResult::numu : return "Numu"; - case DecompResult::nuebar : return "NueBar"; - case DecompResult::numubar : return "NumuBar"; - case DecompResult::NC : return "NC"; - } - assert( 0 && "Bad DecompResult" ); - } - - //--------------------------------------------------------------------------- - - DecompResult ModularExtrapComponent::StringToDR( - const std::string str - ){ - if (str=="Nue") return DecompResult::nue; - else if (str=="Numu") return DecompResult::numu; - else if (str=="NueBar") return DecompResult::nuebar; - else if (str=="NumuBar") return DecompResult::numubar; - else if (str=="NC") return DecompResult::NC; - else assert( 0 && "Bad DecompResult String" ); - } - - //--------------------------------------------------------------------------- - - Ratio ModularExtrapComponent::FormSmartRatio( - const Spectrum& num, - const Spectrum& denom, - const std::string component, - const std::string location, - const Spectrum& mult - ){ - - DontAddDirectory guard; - - // TODO do this with Eigen or possibly the Ratio class? - std::unique_ptr numh(num.ToTH1(1e20)); - std::unique_ptr denomh(denom.ToTH1(1e20)); - std::unique_ptr multh(mult.ToTH1(1e20)); - - std::unique_ptr ratioh((TH1D*)numh->Clone( UniqueName().c_str() )); - ratioh->Reset(); - - int nbins = numh->GetNbinsX(); - assert( (nbins == denomh->GetNbinsX()) && "Bin Mismatch" ); - assert( (nbins == multh->GetNbinsX()) && "Bin Mismatch" ); - - static DivByZeroCounter counter; - for (int bin(0); bin<=nbins+1; ++bin) - { - if ( denomh->GetBinContent(bin) != 0 ){ - ratioh->SetBinContent( bin, numh->GetBinContent(bin) - / denomh->GetBinContent(bin) ); - } else { - ratioh->SetBinContent( bin, 1. ); - if ( numh->GetBinContent(bin) != 0 - || multh->GetBinContent(bin) != 0 ) - counter.fBins.insert(std::make_tuple(component, location, denomh->GetBinCenter(bin))); - } - } - - return Ratio( ratioh.get() ); - } - - bool ModularExtrapComponent::fQuiet = false; - - //--------------------------------------------------------------------------- - - NoReweight::NoReweight( - SpectrumLoaderBase& loader, - const HistAxis& axis, - const Cut& fdcut, - const SystShifts& shiftMC, - const Weight& weight, - const Cut& flavors ) - : fRecoFD( loader, axis, fdcut && flavors, shiftMC, weight ) - { - } - - OscillatableSpectrum NoReweight::Eval() const - {return fRecoFD;} - - void NoReweight::SaveTo(TDirectory* dir) const - { - TDirectory* tmp = gDirectory; - dir->cd(); - TObjString("NoReweight").Write("type"); - fRecoFD.SaveTo(dir->mkdir("RecoFD")); - tmp->cd(); - } - - std::unique_ptr - NoReweight::LoadFrom(TDirectory* dir) - { - assert(dir->GetDirectory("RecoFD")); - return std::unique_ptr(new NoReweight( - *(OscillatableSpectrum::LoadFrom(dir->GetDirectory("RecoFD")).release()) - )); - } - - //--------------------------------------------------------------------------- - - TruthReweight::TruthReweight( - SpectrumLoaderBase& ndloader, - const HistAxis& axisFD, - const HistAxis& axisND, - const Cut& fdcut, - const SystShifts& shiftMC, - const Weight& weight, - std::string label, - std::string latex, - const Cut& ndcut, - const IDecomp& decomposition, - const DecompResult dr, - const Cut& ndflavor, - SpectrumLoaderBase& fdloader, - const Cut& fdflavors - ) - : fRecoToTrueND(ndloader, axisND, ndcut && ndflavor, shiftMC, weight), - fTrueToRecoFD(fdloader, axisFD, fdcut && fdflavors, shiftMC, weight), - fDecomp(decomposition), - fDecompRes(dr), - fLabel(label), - fLatex(latex) - {} - - OscillatableSpectrum TruthReweight::Eval() const - { - - //Copy to local variables because reweighting is in-place - OscillatableSpectrum recoToTrueND(fRecoToTrueND); - OscillatableSpectrum trueToRecoFD(fTrueToRecoFD); - - //Get ND data from Decomp - Spectrum decompresult(GetDecompResult(fDecomp,fDecompRes)); - - //Compute Data/MC Ratio in reco energy bins to get divide-by-zero warnings - FormSmartRatio( - decompresult, fRecoToTrueND.Unoscillated(), - fLabel, "MC ND Reco", - fRecoToTrueND.Unoscillated() ); - - //ND Reco->True - recoToTrueND.ReweightToRecoSpectrum( decompresult ); - - //Compute Data/MC Ratio in true energy bins - Ratio dataMCtrue = FormSmartRatio( - recoToTrueND.TrueEnergy(), fRecoToTrueND.TrueEnergy(), - fLabel, "MC ND Truth", - fTrueToRecoFD.TrueEnergy() ); - - // Multiply by Data/MC Ratio and add in FD truth information - trueToRecoFD.ReweightToTrueSpectrum( fTrueToRecoFD.TrueEnergy() - * dataMCtrue ); - - return trueToRecoFD; - - } - - void TruthReweight::SaveTo(TDirectory* dir) const - { - TDirectory* tmp = gDirectory; - dir->cd(); - TObjString("TruthReweight").Write("type"); - fRecoToTrueND.SaveTo(dir->mkdir("RecoToTrueND")); - fTrueToRecoFD.SaveTo(dir->mkdir("TrueToRecoFD")); - fDecomp.SaveTo(dir->mkdir("Decomp")); - TObjString(DRToString(fDecompRes).c_str()).Write("DecompRes"); - TObjString(fLabel.c_str()).Write("Label"); - TObjString(fLatex.c_str()).Write("Latex"); - tmp->cd(); - } - - std::unique_ptr - TruthReweight::LoadFrom(TDirectory* dir) - { - - assert(dir->GetDirectory("RecoToTrueND")); - assert(dir->GetDirectory("TrueToRecoFD")); - assert(dir->GetDirectory("Decomp")); - TObjString* dr = (TObjString*)dir->Get("DecompRes"); - assert(dr); - TObjString* label = (TObjString*)dir->Get("Label"); - TObjString* latex = (TObjString*)dir->Get("Latex"); - assert(label); - assert(latex); - - return std::unique_ptr(new TruthReweight( - *(OscillatableSpectrum::LoadFrom(dir->GetDirectory("RecoToTrueND"))), - *(OscillatableSpectrum::LoadFrom(dir->GetDirectory("TrueToRecoFD"))), - *(ana::LoadFrom( - dir->GetDirectory("Decomp")).release()), //leaks! - StringToDR(dr->GetString().Data()), - label->GetString().Data(), - latex->GetString().Data() - )); - - } - - //--------------------------------------------------------------------------- - - RecoReweight::RecoReweight( - SpectrumLoaderBase& ndloader, - const HistAxis& axis, - const Cut& fdcut, - const SystShifts& shiftMC, - const Weight& weight, - std::string label, - std::string latex, - const Cut& ndcut, - const IDecomp& decomposition, - const DecompResult dr, - const Cut& ndflavor, - SpectrumLoaderBase& fdloader, - const Cut& fdflavors - ) - : fRecoND(ndloader, axis, ndcut && ndflavor, shiftMC, weight), - fTrueToRecoFD(fdloader, axis, fdcut && fdflavors, shiftMC, weight), - fDecomp(&decomposition), - fDecompRes(dr), - fLabel(label), - fLatex(latex) - { - } - - OscillatableSpectrum RecoReweight::Eval() const - { - - //Copy to local variable because reweighting is in-place - OscillatableSpectrum result(fTrueToRecoFD); - - //Get ND data from Decomp - Spectrum decompresult(GetDecompResult(*fDecomp,fDecompRes)); - - //Compute Data/MC Ratio - Ratio dataMC = FormSmartRatio( - decompresult, fRecoND, - fLabel, "MC ND Reco", - fTrueToRecoFD.Unoscillated() ); - - // Multiply by Data/MC Ratio and add in FD truth information - result.ReweightToRecoSpectrum( fTrueToRecoFD.Unoscillated() * dataMC ); - - return result; - - } - - void RecoReweight::SaveTo(TDirectory* dir) const - { - TDirectory* tmp = gDirectory; - dir->cd(); - TObjString("RecoReweight").Write("type"); - fRecoND.SaveTo(dir->mkdir("RecoND")); - fTrueToRecoFD.SaveTo(dir->mkdir("TrueToRecoFD")); - fDecomp->SaveTo(dir->mkdir("Decomp")); - TObjString(DRToString(fDecompRes).c_str()).Write("DecompRes"); - TObjString(fLabel.c_str()).Write("Label"); - TObjString(fLatex.c_str()).Write("Latex"); - tmp->cd(); - } - - std::unique_ptr - RecoReweight::LoadFrom(TDirectory* dir) - { - - assert(dir->GetDirectory("RecoND")); - assert(dir->GetDirectory("TrueToRecoFD")); - assert(dir->GetDirectory("Decomp")); - TObjString* dr = (TObjString*)dir->Get("DecompRes"); - assert(dr); - TObjString* label = (TObjString*)dir->Get("Label"); - TObjString* latex = (TObjString*)dir->Get("Latex"); - assert(label); - assert(latex); - - return std::unique_ptr(new RecoReweight( - *(Spectrum::LoadFrom(dir->GetDirectory("RecoND"))), - *(OscillatableSpectrum::LoadFrom(dir->GetDirectory("TrueToRecoFD"))), - *(ana::LoadFrom( - dir->GetDirectory("Decomp")).release()), //leaks! - StringToDR(dr->GetString().Data()), - label->GetString().Data(), - latex->GetString().Data() - )); - - } - -} - -#endif diff --git a/CAFAna/Extrap/ModularExtrapComponent.h b/CAFAna/Extrap/ModularExtrapComponent.h deleted file mode 100644 index ddedcb29..00000000 --- a/CAFAna/Extrap/ModularExtrapComponent.h +++ /dev/null @@ -1,230 +0,0 @@ -#if 0 -// Currently dead code - -#pragma once - -#include "CAFAna/Core/HistAxis.h" -#include "CAFAna/Core/OscillatableSpectrum.h" -#include "CAFAna/Core/Ratio.h" -#include "CAFAna/Core/SpectrumLoaderBase.h" - -class TDirectory; -class TH1; - -namespace ana -{ - - class IDecomp; - - /// Simple way to remember what to ask the decomposition for. - enum class DecompResult {nue, numu, NC, nuebar, numubar}; - - /// Base class for component extrapolation. - class ModularExtrapComponent - { - public: - - ModularExtrapComponent() : fEvaluated(false), fCache(nullptr, {}, {}, 0, 0) {} - virtual ~ModularExtrapComponent() {}; - virtual void SaveTo(TDirectory* dir) const = 0; - virtual void SavePlots(TDirectory* dir, double potFD) const = 0; - static void SetQuiet(bool quiet = true){ fQuiet = quiet; } - - /// Interface so that result of Eval() is called only once and cached. - const OscillatableSpectrum& Return() const; - - virtual const IDecomp* GetDecomp() const = 0; - - protected: - - /// Core extrapolation math. - virtual OscillatableSpectrum Eval() const = 0; - - /// Helper function to pick out single Spectrum from a decomposition. - static Spectrum GetDecompResult(const IDecomp&, DecompResult); - - /// Helper function to turn a DecompResult into a string (for storage). - static std::string DRToString(DecompResult); - - /// Helper function to turn a string into a DecompResult (for loading). - static DecompResult StringToDR(std::string); - - /// Form Ratio, but be aware of zero division. - /** Necessary because root thinks n/0==0, so we lose events when - low stats cause empty bins. If zero division occurs, ratio is set to - 1 and warning is issued. If numerator is 0 and ratio will be - multiplied by 0 later, the warning is suppressed. */ - static Ratio FormSmartRatio( - const Spectrum& num, - const Spectrum& denom, - std::string component, - std::string location, - const Spectrum& mult - ); - - static void ComparisonPlot( - Spectrum mc, - Spectrum notMC, - double pot, - std::string notMCLabel, - int notMCColor, - std::string latex, - std::string title, - std::string saveAs, - bool restrictRange = false - ); - - private: - mutable bool fEvaluated; - mutable OscillatableSpectrum fCache; - static bool fQuiet; - - class DivByZeroCounter - { - public: - DivByZeroCounter(bool quiet = false) - : fQuiet(quiet) - {} - ~DivByZeroCounter(); - - std::set> fBins; - - private: - bool fQuiet; - - }; - - }; - - /// "Extrapolates" component by returning FD Monte Carlo. - class NoReweight: public ModularExtrapComponent - { - - public: - NoReweight( - SpectrumLoaderBase& loader, - const HistAxis& axis, - const Cut& fdcut, - const SystShifts& shiftMC, - const Weight& weight, - const Cut& flavors - ); - OscillatableSpectrum Eval() const override; - void SaveTo(TDirectory* dir) const override; - void SavePlots(TDirectory* dir, double potFD) const override; - static std::unique_ptr LoadFrom(TDirectory* dir); - - const IDecomp* GetDecomp() const override {return 0;} - private: - NoReweight(OscillatableSpectrum recoFD) : fRecoFD(recoFD) {} - - OscillatableSpectrum fRecoFD; - - }; - - /// Extrapolates component using truth-over-truth method. - class TruthReweight: public ModularExtrapComponent - { - - public: - TruthReweight( - SpectrumLoaderBase& ndloader, - const HistAxis& axisFD, - const HistAxis& axisND, - const Cut& fdcut, - const SystShifts& shiftMC, - const Weight& weight, - std::string label, - std::string latex, - const Cut& ndcut, - const IDecomp& decomposition, - const DecompResult dr, - const Cut& ndflavor, - SpectrumLoaderBase& fdloader, - const Cut& fdflavors - ); - OscillatableSpectrum Eval() const override; - void SaveTo(TDirectory* dir) const override; - void SavePlots(TDirectory* dir, double potFD) const override; - static std::unique_ptr LoadFrom(TDirectory* dir); - - const IDecomp* GetDecomp() const override {return &fDecomp;} - private: - TruthReweight( - OscillatableSpectrum recoToTrueND, - OscillatableSpectrum trueToRecoFD, - const IDecomp& decomp, - const DecompResult decompRes, - std::string label, - std::string latex - ) : fRecoToTrueND(recoToTrueND), fTrueToRecoFD(trueToRecoFD), - fDecomp(decomp), fDecompRes(decompRes), - fLabel(label), fLatex(latex) {} - - OscillatableSpectrum fRecoToTrueND; - OscillatableSpectrum fTrueToRecoFD; - const IDecomp& fDecomp; - const DecompResult fDecompRes; - std::string fLabel; - std::string fLatex; - - }; - - /// Extrapolates using reco-over-reco method. - class RecoReweight: public ModularExtrapComponent - { - - public: - RecoReweight( - SpectrumLoaderBase& ndloader, - const HistAxis& axis, - const Cut& fdcut, - const SystShifts& shiftMC, - const Weight& weight, - std::string label, - std::string latex, - const Cut& ndcut, - const IDecomp& decomposition, - const DecompResult dr, - const Cut& ndflavor, - SpectrumLoaderBase& fdloader, - const Cut& fdflavors - ); - OscillatableSpectrum Eval() const override; - void SaveTo(TDirectory* dir) const override; - void SavePlots(TDirectory* dir, double potFD) const override; - static std::unique_ptr LoadFrom(TDirectory* dir); - - /// Uses MC spectra and target MC stats to estimate optimal binning. - TH1* OptimalBinning( double potMCFD, double potMCND ) const; - /// Fits gaussians to FD and ND MC to estimate optimal binning - TH1* OptimalBinningFit( double potMCFD, double potMCND ) const; - static TH1* OptimalBinningHelper( TH1*, TH1* ); - - const IDecomp* GetDecomp() const override {return fDecomp;} - - friend class ModularExtrap; - private: - RecoReweight( - Spectrum recoND, - OscillatableSpectrum trueToRecoFD, - const IDecomp& decomp, - const DecompResult decompRes, - std::string label, - std::string latex - ) : fRecoND(recoND), fTrueToRecoFD(trueToRecoFD), - fDecomp(&decomp), fDecompRes(decompRes), - fLabel(label), fLatex(latex) {} - - Spectrum fRecoND; - OscillatableSpectrum fTrueToRecoFD; - const IDecomp* fDecomp; - const DecompResult fDecompRes; - std::string fLabel; - std::string fLatex; - - }; - -} - -#endif diff --git a/CAFAna/Extrap/ModularExtrapComponentPlot.cxx b/CAFAna/Extrap/ModularExtrapComponentPlot.cxx deleted file mode 100644 index 2e2ba453..00000000 --- a/CAFAna/Extrap/ModularExtrapComponentPlot.cxx +++ /dev/null @@ -1,329 +0,0 @@ -#if 0 -// Currently dead code - -#include "CAFAna/Extrap/ModularExtrapComponent.h" -#include "CAFAna/Core/Ratio.h" -#include "CAFAna/Core/Utilities.h" - -#include "TCanvas.h" -#include "TDirectory.h" -#include "TLegend.h" -#include "TF1.h" -#include "TH1.h" -#include "TH2.h" - -namespace ana -{ - - //--------------------------------------------------------------------------- - - void ModularExtrapComponent::ComparisonPlot( - Spectrum mc, - Spectrum notMC, - double pot, - std::string notMCLabel, - int notMCColor, - std::string latex, - std::string title, - std::string saveAs, - bool restrictRange - ){ - TH1* histMC( mc.ToTH1(pot) ); - TH1* histNotMC( notMC.ToTH1(pot) ); - histMC->SetLineColor( kRed ); - histNotMC->SetLineColor( notMCColor ); - TCanvas c; - histMC->SetMaximum( 1.5 * histMC->GetMaximum() ); - if (restrictRange) histMC->GetXaxis()->SetRangeUser( 0.5, 3.5); - histMC->SetTitle( (latex+" "+title).c_str() ); - histMC->Draw("hist"); - histNotMC->Draw("same"); - TLegend legend( .15, .7, .4, .85 ); - legend.SetTextSize(0.05); - legend.AddEntry( histNotMC, notMCLabel.c_str() ); - legend.AddEntry( histMC, "MC" ); - legend.SetFillStyle(0); - legend.Draw(); - c.Write( saveAs.c_str() ); - delete histMC; - delete histNotMC; - } - - //--------------------------------------------------------------------------- - - void NoReweight::SavePlots(TDirectory* dir, double potFD) const - { - TDirectory* tmp = gDirectory; - dir->cd(); - - TH1* hist( fRecoFD.Unoscillated().ToTH1(potFD) ); - hist->SetLineColor( kRed ); - TCanvas c; - hist->SetMaximum( 1.5 * hist->GetMaximum() ); - hist->SetTitle( "FD Reco Spectrum" ); - hist->Draw("hist"); - c.Write("MC"); - delete hist; - - tmp->cd(); - } - - //--------------------------------------------------------------------------- - - void TruthReweight::SavePlots(TDirectory* dir, double potFD) const - { - TDirectory* tmp = gDirectory; - dir->cd(); - - Spectrum decompresult( GetDecompResult(fDecomp,fDecompRes) ); - double potND( decompresult.POT() ); - - ComparisonPlot( - fRecoToTrueND.Unoscillated(), decompresult, potND, - "Data", kBlack, fLatex, "ND Reco Spectrum", "NDReco" ); - - TH2* histNDrtt( fRecoToTrueND.ToTH2(potND) ); - TCanvas cNDrtt; - histNDrtt->GetYaxis()->SetRangeUser( 0.5, 3.5 ); - histNDrtt->SetTitle( (fLatex+" ND Reco to True Spectrum (MC)").c_str() ); - histNDrtt->Draw("colz"); - cNDrtt.Write("NDRecoToTrue"); - delete histNDrtt; - - OscillatableSpectrum recoToTrueND( fRecoToTrueND ); - recoToTrueND.ReweightToRecoSpectrum( decompresult ); - ComparisonPlot( - fRecoToTrueND.TrueEnergy(), recoToTrueND.TrueEnergy(), potND, - "Reweighted", kBlue, fLatex, "ND True Energy Spectrum", "NDTrue", - true ); - - ComparisonPlot( - fTrueToRecoFD.TrueEnergy(), Return().TrueEnergy(), potFD, - "Extrapolated", kBlue, fLatex, "FD True Energy Spectrum", "FDTrue", - true ); - - TH2* histFDttr( fTrueToRecoFD.ToTH2(potFD) ); - TCanvas cFDttr; - histFDttr->GetYaxis()->SetRangeUser( 0.5, 3.5 ); - histFDttr->SetTitle( (fLatex+" FD True To Reco Spectrum (MC)").c_str() ); - histFDttr->Draw("colz"); - cFDttr.Write("FDTrueToReco"); - delete histFDttr; - - ComparisonPlot( - fTrueToRecoFD.Unoscillated(), Return().Unoscillated(), potFD, - "Extrapolated", kBlue, fLatex, "FD Reco Spectrum", "FDReco" ); - - TH1* histNDDatReco = decompresult.ToTH1(potND); - TH1* histNDRwtTrue = recoToTrueND.TrueEnergy().ToTH1(potND); - TH1* histFDExtTrue = Return().TrueEnergy().ToTH1(potFD); - TH1* histFDExtReco = Return().Unoscillated().ToTH1(potFD); - - TH1* histNDMCReco = fRecoToTrueND.Unoscillated().ToTH1(potND); - TH1* histNDMCTrue = fRecoToTrueND.TrueEnergy().ToTH1(potND); - TH1* histFDMCTrue = fTrueToRecoFD.TrueEnergy().ToTH1(potFD); - TH1* histFDMCReco = fTrueToRecoFD.Unoscillated().ToTH1(potFD); - - histNDDatReco->Write("NDDatReco"); - histNDRwtTrue->Write("NDRwtTrue"); - histFDExtTrue->Write("FDExtTrue"); - histFDExtReco->Write("FDExtReco"); - - histNDMCReco->Write("NDMCReco"); - histNDMCTrue->Write("NDMCTrue"); - histFDMCTrue->Write("FDMCTrue"); - histFDMCReco->Write("FDMCReco"); - - delete histNDDatReco; - delete histNDRwtTrue; - delete histFDExtTrue; - delete histFDExtReco; - - delete histNDMCReco; - delete histNDMCTrue; - delete histFDMCTrue; - delete histFDMCReco; - - tmp->cd(); - } - - //--------------------------------------------------------------------------- - - void RecoReweight::SavePlots(TDirectory* dir, double potFD) const - { - TDirectory* tmp = gDirectory; - dir->cd(); - - Spectrum fdMCReco( fTrueToRecoFD.Unoscillated() ); - Spectrum fdExtReco( Return().Unoscillated() ); - - Spectrum decompresult( GetDecompResult(*fDecomp,fDecompRes) ); - double potND( decompresult.POT() ); - - ComparisonPlot( - fRecoND, decompresult, potND, - "Data", kBlack, fLatex, "ND Reco Spectrum", "ND" ); - - ComparisonPlot( - fdMCReco, fdExtReco, potFD, - "Extrapolated", kBlue, fLatex, "FD Reco Spectrum", "FD" ); - - TH1* histDvMCND( (decompresult/fRecoND).ToTH1() ); - TH1* histEvMCFD( (fdExtReco / fdMCReco).ToTH1() ); - histDvMCND->SetLineColor( kRed ); - histEvMCFD->SetLineColor( kBlue ); - histEvMCFD->SetLineWidth( 4 ); - histEvMCFD->SetLineStyle( 2 ); - TCanvas cDvMC; - histDvMCND->SetMaximum( 1.5 * histDvMCND->GetMaximum() ); - histDvMCND->SetTitle( (fLatex+" Data/MC Ratio").c_str() ); - histDvMCND->GetYaxis()->SetTitle("Ratio"); - histDvMCND->Draw("hist"); - histEvMCFD->Draw("same""hist"); - TLegend legendDvMC( .15, .7, .4, .85 ); - legendDvMC.SetTextSize(0.05); - legendDvMC.AddEntry( histEvMCFD, "FD (Extrapolated)" ); - legendDvMC.AddEntry( histDvMCND, "ND" ); - legendDvMC.SetFillStyle(0); - legendDvMC.Draw(); - cDvMC.Write("DataOverMC"); - delete histDvMCND; - delete histEvMCFD; - - TH1* histFoNMC( (fdMCReco/fRecoND).ToTH1() ); - TH1* histFoNDE( (fdExtReco/decompresult).ToTH1() ); - histFoNMC->SetLineColor( kRed ); - histFoNDE->SetLineColor( kBlue ); - histFoNDE->SetLineWidth( 4 ); - histFoNDE->SetLineStyle( 2 ); - TCanvas cFoN; - histFoNMC->SetMaximum( 1.5 * histFoNMC->GetMaximum() ); - histFoNMC->SetTitle( (fLatex+" Far/Near Ratio").c_str() ); - histFoNMC->GetYaxis()->SetTitle("Ratio"); - histFoNMC->Draw("hist"); - histFoNDE->Draw("same""hist"); - TLegend legendFoN( .15, .7, .4, .85 ); - legendFoN.SetTextSize(0.05); - legendFoN.AddEntry( histFoNDE, "Extrapolation/Data" ); - legendFoN.AddEntry( histFoNMC, "MC" ); - legendFoN.SetFillStyle(0); - legendFoN.Draw(); - cFoN.Write("FarOverNear"); - delete histFoNMC; - delete histFoNDE; - - TH1* histNDDat = decompresult.ToTH1(potND); - TH1* histFDExt = fdExtReco.ToTH1(potFD); - TH1* histNDMC = fRecoND.ToTH1(potND); - TH1* histFDMC = fdMCReco.ToTH1(potFD); - - histNDDat->Write("NDDat"); - histFDExt->Write("FDExt"); - histNDMC->Write("NDMC"); - histFDMC->Write("FDMC"); - - delete histNDDat; - delete histFDExt; - delete histNDMC; - delete histFDMC; - - tmp->cd(); - } - - //--------------------------------------------------------------------------- - - TH1* RecoReweight::OptimalBinning( - double potMCFD, - double potMCND - ) const { - - TH1* fd = fTrueToRecoFD.Unoscillated().ToTH1(potMCFD); - TH1* nd = fRecoND.ToTH1(potMCND); - - TH1* ob = OptimalBinningHelper( fd, nd ); - - delete fd; - delete nd; - - return ob; - - } - - //--------------------------------------------------------------------------- - - TH1* RecoReweight::OptimalBinningFit( - double potMCFD, - double potMCND - ) const { - - TH1* fd = fTrueToRecoFD.Unoscillated().ToTH1(potMCFD); - TH1* nd = fRecoND.ToTH1(potMCND); - - const double lower( fd->GetXaxis()->GetXmin() ); - const double upper( fd->GetXaxis()->GetXmax() ); - - TF1* fdGauss = new TF1( UniqueName().c_str() ,"gaus(0)", lower, upper ); - TF1* ndGauss = new TF1( UniqueName().c_str() ,"gaus(0)", lower, upper ); - - fdGauss->SetParameters( 100., 2., .5 ); - ndGauss->SetParameters( 100., 2., .5 ); - - fd->Fit( fdGauss, "WW" ); - nd->Fit( ndGauss, "WW" ); - - TH1* fdFine = new TH1D(UniqueName().c_str(),"fdFine",100,lower,upper); - TH1* ndFine = new TH1D(UniqueName().c_str(),"ndFine",100,lower,upper); - - fdFine->Eval(fdGauss); - ndFine->Eval(ndGauss); - - const double binScale = fdFine->GetBinWidth(1) / fd->GetBinWidth(1); - - fdFine->Scale(binScale); - ndFine->Scale(binScale); - - TH1* ob(OptimalBinningHelper(fdFine,ndFine)); - - delete fd; - delete nd; - - return ob; - - } - - //--------------------------------------------------------------------------- - - TH1* RecoReweight::OptimalBinningHelper( TH1* fd, TH1* nd) - { - - TH1* ob( (TH1*)fd->Clone() ); - - int nbins = fd->GetNbinsX(); - assert( (nbins == nd->GetNbinsX()) && "Bin Mismatch" ); - - for (int bin(1); bin<=nbins; ++bin) - { - double invdensFD( fd->GetBinWidth(bin) / fd->GetBinContent(bin) ); - double invdensND( nd->GetBinWidth(bin) / nd->GetBinContent(bin) ); - double ratio( fd->GetBinContent(bin) / nd->GetBinContent(bin) ); - double ratioPrev( fd->GetBinContent(bin-1) / nd->GetBinContent(bin-1) ); - double ratioNext( fd->GetBinContent(bin+1) / nd->GetBinContent(bin+1) ); - double deltaRatio( ratioNext - ratioPrev ); - double deltaVar( fd->GetBinCenter(bin+1) - fd->GetBinCenter(bin-1) ); - double invslope( deltaVar / deltaRatio ); - double widthCubed( 6. * ( ratio*ratio * invslope*invslope ) - * ( invdensFD + invdensND ) ); - double optbin( pow(widthCubed, 1./3.) ); - if ( std::isfinite(optbin) ) ob->SetBinContent( bin, optbin ); - else ob->SetBinContent( bin, 0. ); - } - ob->SetBinContent( 0, 0. ); - ob->SetBinContent( nbins+1, 0. ); - - return ob; - - } - -} - -#endif diff --git a/CAFAna/Extrap/TrivialExtrap.cxx b/CAFAna/Extrap/TrivialExtrap.cxx index 37237d25..ead2e358 100644 --- a/CAFAna/Extrap/TrivialExtrap.cxx +++ b/CAFAna/Extrap/TrivialExtrap.cxx @@ -13,78 +13,46 @@ namespace ana { REGISTER_LOADFROM("TrivialExtrap", IExtrap, TrivialExtrap); + namespace{ + const Var kTrueE([](const caf::SRProxy* sr){return sr->Ev;}); + } + //---------------------------------------------------------------------- - TrivialExtrap::TrivialExtrap(SpectrumLoaderBase& loaderNonswap, - SpectrumLoaderBase& loaderNue, - SpectrumLoaderBase& loaderNuTau, - const HistAxis& axis, - const Cut& cut, - const SystShifts& shift, - const Weight& wei) + TrivialExtrap::TrivialExtrap(IRecordSource& nonswapSrc, + IRecordSource& nueSrc, + IRecordSource& tauSrc, + const HistAxis& axis) : - fNueApp (loaderNue, axis, cut && kIsSig && !kIsAntiNu, shift, wei), - fNueAppAnti (loaderNue, axis, cut && kIsSig && kIsAntiNu, shift, wei), - - fNumuSurv (loaderNonswap, axis, cut && kIsNumuCC && !kIsAntiNu, shift, wei), - fNumuSurvAnti (loaderNonswap, axis, cut && kIsNumuCC && kIsAntiNu, shift, wei), - - fNumuApp (loaderNuTau, axis, cut && kIsNumuApp && !kIsAntiNu, shift, wei), - fNumuAppAnti (loaderNuTau, axis, cut && kIsNumuApp && kIsAntiNu, shift, wei), - - fNueSurv (loaderNonswap, axis, cut && kIsBeamNue && !kIsAntiNu, shift, wei), - fNueSurvAnti (loaderNonswap, axis, cut && kIsBeamNue && kIsAntiNu, shift, wei), - - fTauFromE (loaderNue, axis, cut && kIsTauFromE && !kIsAntiNu, shift, wei), - fTauFromEAnti (loaderNue, axis, cut && kIsTauFromE && kIsAntiNu, shift, wei), - - fTauFromMu (loaderNuTau, axis, cut && kIsTauFromMu && !kIsAntiNu, shift, wei), - fTauFromMuAnti(loaderNuTau, axis, cut && kIsTauFromMu && kIsAntiNu, shift, wei), - - fNCTot (loaderNonswap, axis, cut && kIsNC , shift, wei), - fNC (loaderNonswap, axis, cut && kIsNC && !kIsAntiNu, shift, wei), - fNCAnti (loaderNonswap, axis, cut && kIsNC && kIsAntiNu, shift, wei) + fNueApp (nueSrc [kIsNueApp && !kIsAntiNu], axis), + fNueAppAnti (nueSrc [kIsNueApp && kIsAntiNu], axis), + fNumuSurv (nonswapSrc[kIsNumuCC && !kIsAntiNu], axis), + fNumuSurvAnti (nonswapSrc[kIsNumuCC && kIsAntiNu], axis), + fNumuApp (tauSrc [kIsNumuApp && !kIsAntiNu], axis), + fNumuAppAnti (tauSrc [kIsNumuApp && kIsAntiNu], axis), + fNueSurv (nonswapSrc[kIsBeamNue && !kIsAntiNu], axis), + fNueSurvAnti (nonswapSrc[kIsBeamNue && kIsAntiNu], axis), + fTauFromE (nueSrc [kIsTauFromE && !kIsAntiNu], axis), + fTauFromEAnti (nueSrc [kIsTauFromE && kIsAntiNu], axis), + fTauFromMu (tauSrc [kIsTauFromMu && !kIsAntiNu], axis), + fTauFromMuAnti(tauSrc [kIsTauFromMu && kIsAntiNu], axis), + fNCTot (nonswapSrc[kIsNC ], axis), + fNC (nonswapSrc[kIsNC && !kIsAntiNu], axis), + fNCAnti (nonswapSrc[kIsNC && kIsAntiNu], axis) { // All swapped files are equally valid as a source of NCs. This // approximately doubles/triples our statistics. SpectrumLoader just adds // events and POT for both cases, which is the right thing to do. - loaderNue .AddSpectrum(fNCTot , axis.GetVar1D(), cut && kIsNC , shift, wei); - loaderNue .AddSpectrum(fNC , axis.GetVar1D(), cut && kIsNC && !kIsAntiNu, shift, wei); - loaderNue .AddSpectrum(fNCAnti, axis.GetVar1D(), cut && kIsNC && kIsAntiNu, shift, wei); - loaderNuTau.AddSpectrum(fNCTot , axis.GetVar1D(), cut && kIsNC , shift, wei); - loaderNuTau.AddSpectrum(fNC , axis.GetVar1D(), cut && kIsNC && !kIsAntiNu, shift, wei); - loaderNuTau.AddSpectrum(fNCAnti, axis.GetVar1D(), cut && kIsNC && kIsAntiNu, shift, wei); - } + nueSrc[kIsNC].GetVar(axis.GetVar1D()).Register(&fNCTot); + nueSrc[kIsNC && !kIsAntiNu].GetVar(axis.GetVar1D()).Register(&fNC); + nueSrc[kIsNC && kIsAntiNu].GetVar(axis.GetVar1D()).Register(&fNCAnti); - //---------------------------------------------------------------------- - TrivialExtrap::TrivialExtrap(SpectrumLoaderBase& loaderNonswap, - SpectrumLoaderBase& loaderNue, - SpectrumLoaderBase& loaderNuTau, - std::string label, - const Binning& bins, - const Var& var, - const Cut& cut, - const SystShifts& shift, - const Weight& wei) - : - TrivialExtrap(loaderNonswap, loaderNue, loaderNuTau, - HistAxis(label, bins, var), - cut, shift, wei) - { - } - - //---------------------------------------------------------------------- - TrivialExtrap::TrivialExtrap(Loaders& loaders, - std::string label, - const Binning& bins, - const Var& var, - const Cut& cut, - const SystShifts& shift, - const Weight& wei) - : TrivialExtrap(loaders, HistAxis(label, bins, var), cut, shift, wei) - { + tauSrc[kIsNC].GetVar(axis.GetVar1D()).Register(&fNCTot); + tauSrc[kIsNC && !kIsAntiNu].GetVar(axis.GetVar1D()).Register(&fNC); + tauSrc[kIsNC && kIsAntiNu].GetVar(axis.GetVar1D()).Register(&fNCAnti); } + /* //---------------------------------------------------------------------- TrivialExtrap::TrivialExtrap(Loaders& loaders, const HistAxis& axis, @@ -94,9 +62,10 @@ namespace ana : TrivialExtrap(loaders.GetLoader(caf::kFARDET, Loaders::kMC, Loaders::kNonSwap), loaders.GetLoader(caf::kFARDET, Loaders::kMC, Loaders::kNueSwap), loaders.GetLoader(caf::kFARDET, Loaders::kMC, Loaders::kNuTauSwap), - axis, cut, shift, wei) + axis) { } + */ //---------------------------------------------------------------------- void TrivialExtrap::SaveTo(TDirectory* dir, const std::string& name) const diff --git a/CAFAna/Extrap/TrivialExtrap.h b/CAFAna/Extrap/TrivialExtrap.h index a73c6c49..ef74234f 100644 --- a/CAFAna/Extrap/TrivialExtrap.h +++ b/CAFAna/Extrap/TrivialExtrap.h @@ -2,6 +2,8 @@ #include "CAFAna/Extrap/IExtrap.h" +#include "CAFAna/Core/IRecordSource.h" + namespace ana { class Loaders; @@ -10,38 +12,12 @@ namespace ana class TrivialExtrap: public IExtrap { public: - // This is the DUNE constructor - TrivialExtrap(SpectrumLoaderBase& loaderNonswap, - SpectrumLoaderBase& loaderNue, - SpectrumLoaderBase& loaderNuTau, - const HistAxis& axis, - const Cut& cut, - const SystShifts& shift, - const Weight& wei); - - TrivialExtrap(SpectrumLoaderBase& loaderNonswap, - SpectrumLoaderBase& loaderNue, - SpectrumLoaderBase& loaderNuTau, - std::string label, - const Binning& bins, - const Var& var, - const Cut& cut, - const SystShifts& shift, - const Weight& wei); - - TrivialExtrap(Loaders& loaders, - std::string label, - const Binning& bins, - const Var& var, - const Cut& cut, - const SystShifts& shift = kNoShift, - const Weight& wei = kUnweighted); - - TrivialExtrap(Loaders& loaders, - const HistAxis& axis, - const Cut& cut, - const SystShifts& shift = kNoShift, - const Weight& wei = kUnweighted); + TrivialExtrap(IRecordSource& nonswapSrc, + IRecordSource& nueSrc, + IRecordSource& tauSrc, + const HistAxis& axis); + + // TrivialExtrap(SliceSources& srcs, const HistAxis& axis); virtual OscillatableSpectrum NueSurvComponent() override {return fNueSurv;} virtual OscillatableSpectrum AntiNueSurvComponent() override {return fNueSurvAnti;} diff --git a/CAFAna/Prediction/CMakeLists.txt b/CAFAna/Prediction/CMakeLists.txt index e0f7ee5a..55b92a28 100644 --- a/CAFAna/Prediction/CMakeLists.txt +++ b/CAFAna/Prediction/CMakeLists.txt @@ -25,7 +25,7 @@ set(Prediction_header_files #PredictionsForPRISM.h) add_library(CAFAnaPrediction SHARED ${Prediction_implementation_files}) -target_link_libraries(CAFAnaPrediction CAFAnaExtrap CAFAnaPRISM) +target_link_libraries(CAFAnaPrediction CAFAnaExtrap) # CAFAnaPRISM) set_target_properties(CAFAnaPrediction PROPERTIES PUBLIC_HEADER "${Prediction_header_files}") diff --git a/CAFAna/Prediction/PredictionGenerator.cxx b/CAFAna/Prediction/PredictionGenerator.cxx index 1d42e824..a627033a 100644 --- a/CAFAna/Prediction/PredictionGenerator.cxx +++ b/CAFAna/Prediction/PredictionGenerator.cxx @@ -5,7 +5,7 @@ namespace ana { //-------------------------------------------------------------------------- - + /* TODO TODO think about generators NoExtrapGenerator::NoExtrapGenerator( const HistAxis axis, const Cut cut, @@ -19,5 +19,5 @@ namespace ana return std::unique_ptr( new PredictionNoExtrap( loaders, fAxis, fCut, shiftMC, fWei ) ); } - + */ } diff --git a/CAFAna/Prediction/PredictionNoExtrap.cxx b/CAFAna/Prediction/PredictionNoExtrap.cxx index 16044ccb..5d4091e2 100644 --- a/CAFAna/Prediction/PredictionNoExtrap.cxx +++ b/CAFAna/Prediction/PredictionNoExtrap.cxx @@ -15,30 +15,11 @@ namespace ana REGISTER_LOADFROM("PredictionNoExtrap", IPrediction, PredictionNoExtrap); //---------------------------------------------------------------------- - PredictionNoExtrap::PredictionNoExtrap(SpectrumLoaderBase& loaderNonswap, - SpectrumLoaderBase& loaderNue, - SpectrumLoaderBase& loaderNuTau, - const std::string& label, - const Binning& bins, - const Var& var, - const Cut& cut, - const SystShifts& shift, - const Weight& wei) - : PredictionExtrap(new TrivialExtrap(loaderNonswap, loaderNue, loaderNuTau, - label, bins, var, cut, shift, wei)) - { - } - - //---------------------------------------------------------------------- - PredictionNoExtrap::PredictionNoExtrap(SpectrumLoaderBase& loaderNonswap, - SpectrumLoaderBase& loaderNue, - SpectrumLoaderBase& loaderNuTau, - const HistAxis& axis, - const Cut& cut, - const SystShifts& shift, - const Weight& wei) - : PredictionExtrap(new TrivialExtrap(loaderNonswap, loaderNue, loaderNuTau, - axis, cut, shift, wei)) + PredictionNoExtrap::PredictionNoExtrap(IRecordSource& srcNonswap, + IRecordSource& srcNue, + IRecordSource& srcNuTau, + const HistAxis& axis) + : PredictionExtrap(new TrivialExtrap(srcNonswap, srcNue, srcNuTau, axis)) { } @@ -47,18 +28,7 @@ namespace ana { } - //---------------------------------------------------------------------- - PredictionNoExtrap::PredictionNoExtrap(Loaders& loaders, - const std::string& label, - const Binning& bins, - const Var& var, - const Cut& cut, - const SystShifts& shift, - const Weight& wei) - : PredictionNoExtrap(loaders, HistAxis(label, bins, var), cut, shift, wei) - { - } - + /* //---------------------------------------------------------------------- PredictionNoExtrap::PredictionNoExtrap(Loaders& loaders, const HistAxis& axis, @@ -68,6 +38,7 @@ namespace ana : PredictionExtrap(new TrivialExtrap(loaders, axis, cut, shift, wei)) { } + */ //---------------------------------------------------------------------- void PredictionNoExtrap::SaveTo(TDirectory* dir, const std::string& name) const diff --git a/CAFAna/Prediction/PredictionNoExtrap.h b/CAFAna/Prediction/PredictionNoExtrap.h index 66973e77..69de3bde 100644 --- a/CAFAna/Prediction/PredictionNoExtrap.h +++ b/CAFAna/Prediction/PredictionNoExtrap.h @@ -4,6 +4,8 @@ #include "CAFAna/Prediction/PredictionGenerator.h" +#include "CAFAna/Core/IRecordSource.h" + namespace ana { class Loaders; @@ -13,28 +15,12 @@ class PredictionNoExtrap : public PredictionExtrap { PredictionNoExtrap(PredictionExtrap *pred); PredictionNoExtrap(IExtrap *extrap); - // This is the DUNE constructor - PredictionNoExtrap(SpectrumLoaderBase &loaderNonswap, - SpectrumLoaderBase &loaderNue, - SpectrumLoaderBase &loaderNuTau, const std::string &label, - const Binning &bins, const Var &var, const Cut &cut, - const SystShifts &shift = kNoShift, - const Weight &wei = kUnweighted); - - PredictionNoExtrap(SpectrumLoaderBase &loaderNonswap, - SpectrumLoaderBase &loaderNue, - SpectrumLoaderBase &loaderNuTau, const HistAxis &axis, - const Cut &cut, const SystShifts &shift = kNoShift, - const Weight &wei = kUnweighted); - - PredictionNoExtrap(Loaders &loaders, const std::string &label, - const Binning &bins, const Var &var, const Cut &cut, - const SystShifts &shift = kNoShift, - const Weight &wei = kUnweighted); + PredictionNoExtrap(IRecordSource& loaderNonswap, + IRecordSource& loaderNue, + IRecordSource& loaderNuTau, + const HistAxis& axis); - PredictionNoExtrap(Loaders &loaders, const HistAxis &axis, const Cut &cut, - const SystShifts &shift = kNoShift, - const Weight &wei = kUnweighted); + // PredictionNoExtrap(Loaders &loaders, const HistAxis &axis); virtual ~PredictionNoExtrap(); @@ -42,6 +28,7 @@ class PredictionNoExtrap : public PredictionExtrap { virtual void SaveTo(TDirectory *dir, const std::string& name) const override; }; + /* TODO think about generators class NoExtrapPredictionGenerator : public IPredictionGenerator { public: NoExtrapPredictionGenerator(HistAxis axis, Cut cut, Weight wei = kUnweighted) @@ -60,5 +47,6 @@ class NoExtrapPredictionGenerator : public IPredictionGenerator { Cut fCut; Weight fWei; }; + */ } // namespace ana diff --git a/CAFAna/Prediction/PredictionNoOsc.cxx b/CAFAna/Prediction/PredictionNoOsc.cxx index 3e8cb5e9..393b8f1b 100644 --- a/CAFAna/Prediction/PredictionNoOsc.cxx +++ b/CAFAna/Prediction/PredictionNoOsc.cxx @@ -16,31 +16,15 @@ namespace ana REGISTER_LOADFROM("PredictionNoOsc", IPrediction, PredictionNoOsc); //---------------------------------------------------------------------- - PredictionNoOsc::PredictionNoOsc(SpectrumLoaderBase& loader, - const std::string& label, - const Binning& bins, - const Var& var, - const Cut& cut, - const SystShifts& shift, - const Weight& wei) - : PredictionNoOsc(loader, HistAxis(label, bins, var), cut, shift, wei) - { - } - - //---------------------------------------------------------------------- - PredictionNoOsc::PredictionNoOsc(SpectrumLoaderBase& loader, - const HistAxis& axis, - const Cut& cut, - const SystShifts& shift, - const Weight& wei) - : fSpectrum( loader, axis, cut , shift, wei), - fSpectrumNCTot( loader, axis, cut && kIsNC , shift, wei), - fSpectrumNC( loader, axis, cut && kIsNC && !kIsAntiNu, shift, wei), - fSpectrumNCAnti( loader, axis, cut && kIsNC && kIsAntiNu, shift, wei), - fSpectrumNumu( loader, axis, cut && !kIsNC && kIsNumuCC && !kIsAntiNu, shift, wei), - fSpectrumNumubar(loader, axis, cut && !kIsNC && kIsNumuCC && kIsAntiNu, shift, wei), - fSpectrumNue( loader, axis, cut && !kIsNC && kIsBeamNue && !kIsAntiNu, shift, wei), - fSpectrumNuebar( loader, axis, cut && !kIsNC && kIsBeamNue && kIsAntiNu, shift, wei) + PredictionNoOsc::PredictionNoOsc(IRecordSource& src, const HistAxis& axis) + : fSpectrum (src, axis), + fSpectrumNCTot (src[ kIsNC], axis), + fSpectrumNC (src[ kIsNC][!kIsAntiNu], axis), + fSpectrumNCAnti(src[ kIsNC][ kIsAntiNu], axis), + fSpectrumNumu (src[!kIsNC][kIsNumuCC ][!kIsAntiNu], axis), + fSpectrumNumubar(src[!kIsNC][kIsNumuCC ][ kIsAntiNu], axis), + fSpectrumNue (src[!kIsNC][kIsBeamNue][!kIsAntiNu], axis), + fSpectrumNuebar (src[!kIsNC][kIsBeamNue][ kIsAntiNu], axis) { } diff --git a/CAFAna/Prediction/PredictionNoOsc.h b/CAFAna/Prediction/PredictionNoOsc.h index 277b6445..271b76aa 100644 --- a/CAFAna/Prediction/PredictionNoOsc.h +++ b/CAFAna/Prediction/PredictionNoOsc.h @@ -4,19 +4,13 @@ #include "CAFAna/Prediction/PredictionGenerator.h" #include "CAFAna/Core/Loaders.h" +#include "CAFAna/Core/IRecordSource.h" namespace ana { /// Prediction that wraps a simple Spectrum class PredictionNoOsc : public IPrediction { public: - PredictionNoOsc(SpectrumLoaderBase &loader, const HistAxis &axis, - const Cut &cut, const SystShifts &shift = kNoShift, - const Weight &wei = kUnweighted); - - PredictionNoOsc(SpectrumLoaderBase &loader, const std::string &label, - const Binning &bins, const Var &var, const Cut &cut, - const SystShifts &shift = kNoShift, - const Weight &wei = kUnweighted); + PredictionNoOsc(IRecordSource& src, const HistAxis& axis); static std::unique_ptr LoadFrom(TDirectory *dir, const std::string& name); virtual void SaveTo(TDirectory *dir, const std::string& name) const override; @@ -75,6 +69,7 @@ class PredictionNoOsc : public IPrediction { Spectrum fSpectrumNuebar; }; + /* TODO think about generators class NoOscPredictionGenerator : public IPredictionGenerator { public: NoOscPredictionGenerator(HistAxis axis, Cut cut, Weight wei = kUnweighted) @@ -94,5 +89,6 @@ class NoOscPredictionGenerator : public IPredictionGenerator { Cut fCut; Weight fWei; }; + */ } // namespace ana diff --git a/CAFAna/Prediction/PredictionNuOnE.cxx b/CAFAna/Prediction/PredictionNuOnE.cxx index 98fdf19a..43699e5c 100644 --- a/CAFAna/Prediction/PredictionNuOnE.cxx +++ b/CAFAna/Prediction/PredictionNuOnE.cxx @@ -30,14 +30,12 @@ namespace ana const Weight kNCScaleFactor([](const caf::SRProxy* sr){return .1;}); // -------------------------------------------------------------------------- - PredictionNuOnE::PredictionNuOnE(SpectrumLoaderBase& sigLoader, - SpectrumLoaderBase& ccBkgLoader, - SpectrumLoaderBase& ncBkgLoader, - const SystShifts& shift, - const Weight& wei) - : fSig ( sigLoader, kNuOnEaxis, kNuOnECut, shift, wei), - fCCBkg(ccBkgLoader, kNuOnEaxis, kNuOnECut, shift, wei), - fNCBkg(ncBkgLoader, kNuOnEaxis, kNuOnECut, shift, wei * kNCScaleFactor) + PredictionNuOnE::PredictionNuOnE(IRecordSource& sigSrc, + IRecordSource& ccBkgSrc, + IRecordSource& ncBkgSrc) + : fSig ( sigSrc[kNuOnECut], kNuOnEaxis), + fCCBkg(ccBkgSrc[kNuOnECut], kNuOnEaxis), + fNCBkg(ncBkgSrc[kNuOnECut].Weighted(kNCScaleFactor), kNuOnEaxis) { } @@ -110,6 +108,7 @@ namespace ana return std::unique_ptr(ret); } + /* TODO TODO //---------------------------------------------------------------------- std::unique_ptr PredictionNuOnEGenerator:: Generate(Loaders& loaders, const SystShifts& shiftMC) const @@ -124,5 +123,5 @@ namespace ana (new PredictionNuOnE(noel->Signal(), noel->CCBkg(), noel->NCBkg(), shiftMC, fWei)); } - + */ } diff --git a/CAFAna/Prediction/PredictionNuOnE.h b/CAFAna/Prediction/PredictionNuOnE.h index c1a52ead..3a70cf59 100644 --- a/CAFAna/Prediction/PredictionNuOnE.h +++ b/CAFAna/Prediction/PredictionNuOnE.h @@ -4,45 +4,40 @@ #include "CAFAna/Prediction/PredictionGenerator.h" -#include "CAFAna/Core/Loaders.h" +#include "CAFAna/Core/IRecordSource.h" namespace ana { /// Jam the necessary loaders into approximately the expected structure - class NuOnELoaders: public Loaders + class NuOnELoaders // : public Loaders { public: - NuOnELoaders(SpectrumLoaderBase& sig, - SpectrumLoaderBase& ccBkg, - SpectrumLoaderBase& ncBkg) + NuOnELoaders(IRecordSource& sig, + IRecordSource& ccBkg, + IRecordSource& ncBkg) : fSig(sig), fCCBkg(ccBkg), fNCBkg(ncBkg) { } - SpectrumLoaderBase& Signal() {return fSig;} - SpectrumLoaderBase& CCBkg() {return fCCBkg;} - SpectrumLoaderBase& NCBkg() {return fNCBkg;} + IRecordSource& Signal() {return fSig;} + IRecordSource& CCBkg() {return fCCBkg;} + IRecordSource& NCBkg() {return fNCBkg;} - void Go() {fSig.Go(); fCCBkg.Go(); fNCBkg.Go();} + // TODO TODO TODO void Go() {fSig.Go(); fCCBkg.Go(); fNCBkg.Go();} protected: - SpectrumLoaderBase &fSig, &fCCBkg, &fNCBkg; + IRecordSource &fSig, &fCCBkg, &fNCBkg; }; class PredictionNuOnE: public IPrediction { public: - PredictionNuOnE(SpectrumLoaderBase& sigLoader, - SpectrumLoaderBase& ccBkgLoader, - SpectrumLoaderBase& ncBkgLoader, - const SystShifts& shift = kNoShift, - const Weight& wei = kUnweighted); - - PredictionNuOnE(NuOnELoaders& loaders, - const SystShifts& shift = kNoShift, - const Weight& wei = kUnweighted) - : PredictionNuOnE(loaders.Signal(), loaders.CCBkg(), loaders.NCBkg(), - shift, wei) + PredictionNuOnE(IRecordSource& sigSrc, + IRecordSource& ccBkgSrc, + IRecordSource& ncBkgSrc); + + PredictionNuOnE(NuOnELoaders& loaders) + : PredictionNuOnE(loaders.Signal(), loaders.CCBkg(), loaders.NCBkg()) { } @@ -67,7 +62,7 @@ namespace ana Spectrum fSig, fCCBkg, fNCBkg; }; - + /* TODO think about generators class PredictionNuOnEGenerator: public IPredictionGenerator { public: @@ -82,4 +77,5 @@ namespace ana protected: Weight fWei; }; + */ } diff --git a/CAFAna/Prediction/PredictionScaleComp.cxx b/CAFAna/Prediction/PredictionScaleComp.cxx index b26b509d..9876596c 100644 --- a/CAFAna/Prediction/PredictionScaleComp.cxx +++ b/CAFAna/Prediction/PredictionScaleComp.cxx @@ -1,3 +1,5 @@ +#if 0 // TODO TODO TODO + #include "CAFAna/Prediction/PredictionScaleComp.h" #include "CAFAna/Core/Cut.h" @@ -209,3 +211,5 @@ namespace ana } } + +#endif diff --git a/CAFAna/README.md b/CAFAna/README.md new file mode 100644 index 00000000..342789d0 --- /dev/null +++ b/CAFAna/README.md @@ -0,0 +1,85 @@ + +# Making your first plots in CAFAna + +This is a simplified guide on how to install and run `CAFAna` to make your first plot . A lot more information can be found in [this tutorial](https://github.com/chenel/dune-nd-lar-reco/blob/main/tute/2021-12-02%20CAFAna-NDLAr-Howto.md) by Jeremy Wolcott. + +Also some information is duplicated from a directory above, but gathered here for your easy access. + +## Setup a container + +As you may know, we are living now in AL9 world, but I don't know how to use spack to build CAFAna. Instead you can setup this standard container provided for us as in https://wiki.dunescience.org/wiki/SL7_to_Alma9_conversion + +``` +/cvmfs/oasis.opensciencegrid.org/mis/apptainer/current/bin/apptainer shell --shell=/bin/bash \ +-B /cvmfs,/exp,/nashome,/pnfs/dune,/opt,/run/user,/etc/hostname,/etc/hosts,/etc/krb5.conf --ipc --pid \ +/cvmfs/singularity.opensciencegrid.org/fermilab/fnal-dev-sl7:latest +``` +The reccommendation is that you use `dunebuild03` instead of a gpvm to build your code. Remove `/pnfs/dune/` when setting up the container, otherwise it will complain. Later on, you can run code and access `pnfs` on a regular gpvm. + +``` +# before anything else, set up UPS +source /cvmfs/dune.opensciencegrid.org/products/dune/setup_dune.sh +``` +Now you can go ahead and install. + +## How to install + +Clone this branch of the repository: +``` +git clone git@github.com:DUNE/lblpwgtools.git +cd lblpwgtools +checkout feature/source-sink-overhaul +``` + +We currently don't have official versions of `cafanacore` ,`duneanaobj`,`osclib`, and `srproxy` , that have truth-reco matching, so we need this extra step to fetch working versions (eventually these should be published): +``` +export PRODUCTS="/exp/dune/app/users/jwolcott/ups:$PRODUCTS" +export PRODUCTS="/exp/dune/app/users/mcasales/ups:$PRODUCTS" +``` + +A helper build script lives in this `CAFAna` subdirectory. You can build and install the code like: + +``` +cd CAFAna +./standalone_configure_and_build.sh -r +``` + +If you are in a DUNE `gpvm` and therefore have `cvmfs` access, you can rely on relevant dependencies from FNAL scisoft by add in the `-u` option: + +``` +./standalone_configure_and_build.sh -r -u -j 4 +``` + +Once CAFAna has been built, to set up the environment you will need to `source /path/to/install/CAFAnaEnv.sh`. If `standalone_configure_and_build.sh` was not passed a `-I` argument, then this will be `/path/to/repo/CAFAna/build/Linux/CAFAnaEnv.sh` by default. + +## Examples + +Once CAFAna is built and the environment setup, proceed to run an example script doing: +``` +cafe tute/demo0b.C +``` +``` +cafe -l 10 tute/demo0b.C +``` +The `-l` option limits the number of files read by the script so you can obtain plots faster. See other options with `cafe --help`. + +The three example scripts in the `tute` directory have the following content: + +### demo0b +Basic distributions in 1D and 2D of variables from the ` SRCommonRecoBranch`. + +### demo1b +More distributions, more manipulations of variables/cuts, now of variables from the `SRTruthBranch`. Also showing how to open/read files. + +### demo0eb +Examples of systematic variations applied to distributions from ` SRCommonRecoBranch` variables. + +## To do's / caveats / wishlist +- Systematic variations are not implemented in truth branches yet +- More realistic examples of systematics +- Note: If you run into issues accessing files, which looks like ```Error in : [FATAL] Auth failed: No protocols left to try```, you probably need to `setup duneutil v09_89_01d01 -q e26:prof` in order to do `setup_fnal_security`. You might need to re-build after doing this. I am working on adding a detailed instruction on this. Remember to source `CAFAnaEnv.sh` after building. +## + +Last updated September 4, 2024, by Maria Martinez-Casales (mcasales@fnal.gov) + + diff --git a/CAFAna/Systs/AnaSysts.cxx b/CAFAna/Systs/AnaSysts.cxx index face8b44..dca3e2c8 100644 --- a/CAFAna/Systs/AnaSysts.cxx +++ b/CAFAna/Systs/AnaSysts.cxx @@ -72,6 +72,7 @@ namespace ana std::vector systs = {}; +/* std::vector fdEScalelist = GetEnergySysts(); std::vector fdlist = GetFDRecoSysts(); std::vector ndEScalelist = GetRecoENDSysts(); @@ -100,10 +101,10 @@ namespace ana // TO DO: Only add the dials to actually use and avoid the need of RemoveSysts // Then we won't have to worry about systs addition ordering RemoveSysts(systs, GetDoNotIncludeSystNames()); - +*/ return systs; } - +/* std::vector getFakeDataSysts(bool fluxXsecPenalties){ std::vector systs = GetCrazyFluxSysts(); @@ -169,7 +170,8 @@ namespace ana if (systString == "fakedata") { return GetListOfSysts(false, false, false, false, false, false, - true /*add fake data*/, false, false); + true, //add fake data + false, false); } // Now defaults to true! @@ -191,8 +193,9 @@ namespace ana // 1) Get a default list with everything std::vector namedList = GetListOfSysts(true, true, true, useND, useFD, useNueOnE, - false /*no fake data*/, true /*Get CDR flux systs*/, - true /*Get Sept 21 flux systs*/); + false, //no fake data + true, //Get CDR flux systs + true );//Get Sept 21 flux systs // for (auto & syst : namedList) std::cout << syst->ShortName() << // std::endl; 2) Interpret the list of short names std::vector systs = SplitString(systString, ':'); @@ -371,6 +374,7 @@ namespace ana retlist.emplace_back(s); } return retlist; + } - +*/ } diff --git a/CAFAna/Systs/AnaSysts.h b/CAFAna/Systs/AnaSysts.h index 244d9bfa..584f164e 100644 --- a/CAFAna/Systs/AnaSysts.h +++ b/CAFAna/Systs/AnaSysts.h @@ -21,28 +21,28 @@ namespace ana /// Get a vector of all the analysis group systs std::vector getDetectorSysts(bool useFD=true, bool useND=false, bool useNueOneE=false); - std::vector getReducedXSecSysts(bool fluxXsecPenalties); - - std::vector getFakeDataSysts(bool fluxXsecPenaltiess); - - std::vector GetListOfSysts(bool fluxsyst_Nov17 = true, bool xsecsyst = true, - bool detsyst = true, bool useND = true, bool useFD = true, - bool useNueOnE = false, bool useFakeDataDials = true, - bool fluxsyst_CDR = true, bool fluxsyst_Sept21 = false, - int NFluxSysts = NFluxParametersToAddToStatefile, - bool removeFDNonFitDials = false); - - std::vector GetListOfSysts(std::string systString, - bool useND = true, - bool useFD = true, - bool useNueOnE = false); - - std::vector GetListOfSysts(char const *systCString, - bool useND = true, - bool useFD = true, - bool useNueOnE = false); - - /// Put a list of systematics in the 'standard' order - std::vector OrderListOfSysts(std::vector const &systlist); +// std::vector getReducedXSecSysts(bool fluxXsecPenalties); +// +// std::vector getFakeDataSysts(bool fluxXsecPenaltiess); +// +// std::vector GetListOfSysts(bool fluxsyst_Nov17 = true, bool xsecsyst = true, +// bool detsyst = true, bool useND = true, bool useFD = true, +// bool useNueOnE = false, bool useFakeDataDials = true, +// bool fluxsyst_CDR = true, bool fluxsyst_Sept21 = false, +// int NFluxSysts = NFluxParametersToAddToStatefile, +// bool removeFDNonFitDials = false); +// +// std::vector GetListOfSysts(std::string systString, +// bool useND = true, +// bool useFD = true, +// bool useNueOnE = false); +// +// std::vector GetListOfSysts(char const *systCString, +// bool useND = true, +// bool useFD = true, +// bool useNueOnE = false); +// +// /// Put a list of systematics in the 'standard' order +// std::vector OrderListOfSysts(std::vector const &systlist); } diff --git a/CAFAna/Systs/CrazyFluxFakeData.cxx b/CAFAna/Systs/CrazyFluxFakeData.cxx index 33f17f55..77b34e1b 100644 --- a/CAFAna/Systs/CrazyFluxFakeData.cxx +++ b/CAFAna/Systs/CrazyFluxFakeData.cxx @@ -3,62 +3,62 @@ #include "duneanaobj/StandardRecord/Proxy/SRProxy.h" namespace ana { - - std::vector GetCrazyFluxDialNames(){ - static std::vector ret = {"CrazyFlux_FHC", - "CrazyFlux_RHC", - "CrazyFlux_BOTH"}; - return ret; - } - - bool IsCrazyFluxSyst(std::string name){ - return (std::find(GetCrazyFluxDialNames().begin(), GetCrazyFluxDialNames().end(), name) != - GetCrazyFluxDialNames().end()); - } - - - void CrazyFluxDial::Shift(double sigma, - caf::SRProxy *sr, - double &weight) const { - // Play it safe - if (fabs(sigma) < 1E-5) return; - - // This is a bit hacky... simply because ND files with this fix haven't been made yet - if (!sr->isFD) return; - - // Make sure weights are only applied when appropriate - if (fName == GetCrazyFluxDialNames()[0] && !sr->isFHC){ - return; - } - if (fName == GetCrazyFluxDialNames()[1] && sr->isFHC){ - return; - } - - // If you get this far, apply a weight - // All values in the array except [3], the nominal, should be the same - weight *= sr->wgt_CrazyFlux[0]; - } - - - CrazyFluxDial::CrazyFluxDial(std::string name, bool applyPenalty) - : ISyst(name, name, applyPenalty), - fName(name) {} - - std::vector GetCrazyFluxSysts(std::vector names, - bool applyPenalty) { - static std::vector ret; - - if (names.empty()) { - names = GetCrazyFluxDialNames(); - } - - if (ret.empty()) { - for (auto &it : names) { - ret.push_back(new CrazyFluxDial(it, applyPenalty)); - } - } - return ret; - } +// +// std::vector GetCrazyFluxDialNames(){ +// static std::vector ret = {"CrazyFlux_FHC", +// "CrazyFlux_RHC", +// "CrazyFlux_BOTH"}; +// return ret; +// } +// +// bool IsCrazyFluxSyst(std::string name){ +// return (std::find(GetCrazyFluxDialNames().begin(), GetCrazyFluxDialNames().end(), name) != +// GetCrazyFluxDialNames().end()); +// } +// +// +// void CrazyFluxDial::Shift(double sigma, +// caf::SRProxy *sr, +// double &weight) const { +// // Play it safe +// if (fabs(sigma) < 1E-5) return; +// +// // This is a bit hacky... simply because ND files with this fix haven't been made yet +// if (!sr->isFD) return; +// +// // Make sure weights are only applied when appropriate +// if (fName == GetCrazyFluxDialNames()[0] && !sr->isFHC){ +// return; +// } +// if (fName == GetCrazyFluxDialNames()[1] && sr->isFHC){ +// return; +// } +// +// // If you get this far, apply a weight +// // All values in the array except [3], the nominal, should be the same +// weight *= sr->wgt_CrazyFlux[0]; +// } +// +// +// CrazyFluxDial::CrazyFluxDial(std::string name, bool applyPenalty) +// : ISyst(name, name, applyPenalty), +// fName(name) {} +// +// std::vector GetCrazyFluxSysts(std::vector names, +// bool applyPenalty) { +// static std::vector ret; +// +// if (names.empty()) { +// names = GetCrazyFluxDialNames(); +// } +// +// if (ret.empty()) { +// for (auto &it : names) { +// ret.push_back(new CrazyFluxDial(it, applyPenalty)); +// } +// } +// return ret; +// } } diff --git a/CAFAna/Systs/CrazyFluxFakeData.h b/CAFAna/Systs/CrazyFluxFakeData.h index 07f78660..79142aab 100644 --- a/CAFAna/Systs/CrazyFluxFakeData.h +++ b/CAFAna/Systs/CrazyFluxFakeData.h @@ -9,28 +9,28 @@ namespace ana { -class CrazyFluxDial : public ISyst { - public: - - virtual ~CrazyFluxDial(){}; - - void Shift(double sigma, caf::SRProxy *sr, - double &weight) const override; - - protected: - CrazyFluxDial(std::string name, bool applyPenalty = false); - - friend std::vector GetCrazyFluxSysts(std::vector, bool); - - std::string fName; - - }; - - std::vector GetCrazyFluxDialNames(); - - bool IsCrazyFluxSyst(std::string name); - - std::vector - GetCrazyFluxSysts(std::vector names = {}, bool applyPenalty = false); +//class CrazyFluxDial : public ISyst { +// public: +// +// virtual ~CrazyFluxDial(){}; +// +// void Shift(double sigma, caf::SRProxy *sr, +// double &weight) const override; +// +// protected: +// CrazyFluxDial(std::string name, bool applyPenalty = false); +// +// friend std::vector GetCrazyFluxSysts(std::vector, bool); +// +// std::string fName; +// +// }; +// +// std::vector GetCrazyFluxDialNames(); +// +// bool IsCrazyFluxSyst(std::string name); +// +// std::vector +// GetCrazyFluxSysts(std::vector names = {}, bool applyPenalty = false); } // namespace ana diff --git a/CAFAna/Systs/DUNEFluxSysts.cxx b/CAFAna/Systs/DUNEFluxSysts.cxx index e3141ed7..21eb63a8 100644 --- a/CAFAna/Systs/DUNEFluxSysts.cxx +++ b/CAFAna/Systs/DUNEFluxSysts.cxx @@ -22,202 +22,202 @@ static ana::NewOffAxisFluxUncertainty2022Helper const *fNewOffAxisFluxUncertaint #include namespace ana { -const DUNEFluxSystVector kFluxSysts = GetDUNEFluxSysts(30); - -//---------------------------------------------------------------------- -DUNEFluxSyst::~DUNEFluxSyst() { - for (int i : {0, 1}) - for (int j : {0, 1}) - for (int k : {0, 1}) - for (int l : {0, 1}) - delete fScale[i][j][k][l]; -} - -//---------------------------------------------------------------------- -void DUNEFluxSyst::Shift(double sigma, - caf::SRProxy *sr, double &weight) const { - - if (abs(sr->nuPDGunosc) == 16) { - return; - } - -#ifdef USE_TH2JAGGED - if (fUseCDR) { - std::cout - << "[ERROR]: Off axis flux uncertainties did not exist for the CDR." - << std::endl; - abort(); - } - - bool isSpecHCRun(false); - if (std::abs(sr->SpecialHCRunId) != 293) isSpecHCRun = true; - - if (sr->OffAxisFluxBin == -1) { - if (fUseSept21) { - sr->OffAxisFluxBin = ana::NewOffAxisFluxUncertainty2022Helper::Get().GetBin( - sr->nuPDGunosc, sr->Ev, sr->abspos_x * 1E-2, fIdx, !sr->isFD, - sr->isFHC, isSpecHCRun); - } else { - sr->OffAxisFluxBin = ana::OffAxisFluxUncertaintyHelper::Get().GetBin( - sr->nuPDGunosc, sr->Ev, sr->abspos_x * 1E-2, 0, !sr->isFD, - sr->isFHC, isSpecHCRun); - } - } - - if (sr->OffAxisFluxConfig == -1) { - if (fUseSept21) { - sr->OffAxisFluxConfig = - ana::NewOffAxisFluxUncertainty2022Helper::Get().GetNuConfig_checked( - sr->nuPDGunosc, sr->Ev, sr->abspos_x * 1E-2, fIdx, !sr->isFD, - sr->isFHC, isSpecHCRun); - } else { - sr->OffAxisFluxConfig = - ana::OffAxisFluxUncertaintyHelper::Get().GetNuConfig_checked( - sr->nuPDGunosc, sr->Ev, sr->abspos_x * 1E-2, 0, !sr->isFD, - sr->isFHC, isSpecHCRun); - } - } - - if (fUseSept21) { - weight = fNewOffAxisFluxUncertainty2022Helper->GetFluxWeight( - fIdx, sigma, sr->abspos_x * 1E-2, sr->OffAxisFluxBin, sr->OffAxisFluxConfig); - } else { - weight = fOffAxisFluxParamHelper->GetFluxWeight( - fIdx, sigma, sr->OffAxisFluxBin, sr->OffAxisFluxConfig); - } -#else - if (!fScale[0][0][0][0]) { - std::string InputFileName; - if (fUseCDR) { - // CDROpt flux - InputFileName = "flux_shifts_CDR.root"; - } else { - // Nov17 opt engineered - InputFileName = "flux_shifts_Nov17.root"; - } - - TFile f((FindCAFAnaDir() + "/Systs/" + InputFileName).c_str()); - assert(!f.IsZombie()); - - for (int det : {0, 1}) { - const std::string detStr = (det == 0) ? "ND" : "FD"; - for (int pdg : {0, 1}) { - std::string pdgStr = (pdg == 0) ? "nue" : "numu"; - for (bool anti : {false, true}) { - if (anti) - pdgStr += "bar"; - - for (int hc : {0, 1}) { - const std::string hcStr = (hc == 0) ? "FHC" : "RHC"; - - TH1 *&h = fScale[det][pdg][anti][hc]; - - h = (TH1 *)f.Get(TString::Format("syst%d/%s_%s_%s", fIdx, - detStr.c_str(), pdgStr.c_str(), - hcStr.c_str()) - .Data()); - h = (TH1 *)h->Clone(UniqueName().c_str()); - assert(h); - h->SetDirectory(0); - } - } - } - } - } // end if - - if (abs(sr->nuPDGunosc) == 16) - return; - - double /*const*/ rel_weight = 1; - double const enu = sr->Ev; - - const int det = sr->isFD ? 0 : 1; - const int pdg = (abs(sr->nuPDGunosc) == 12) ? 0 : 1; - const int anti = (sr->nuPDGunosc > 0) ? 0 : 1; - const int hc = sr->isFHC ? 0 : 1; - - TH1 *h = fScale[det][pdg][anti][hc]; - assert(h); - - const int bin = h->FindBin(enu); - - if (bin == 0 || bin == h->GetNbinsX() + 1) { - return; - } - rel_weight = h->GetBinContent(bin); - - weight *= 1 + rel_weight * sigma; -#endif -} - -//---------------------------------------------------------------------- -const DUNEFluxSyst *GetDUNEFluxSyst(unsigned int i, bool applyPenalty, - bool useCDR, bool useSept21) { - // Make sure we always give the same one back - static std::vector cache_CDR; - static std::vector cache_Nov17; - - auto c = useCDR ? &cache_CDR : &cache_Nov17; - if (i >= c->size()) { - c->resize(i + 1); - } - if (!c->at(i)) { - c->at(i) = new DUNEFluxSyst(i, applyPenalty, useCDR, useSept21); - } - return c->at(i); -} - -//---------------------------------------------------------------------- -DUNEFluxSystVector GetDUNEFluxSysts(unsigned int N, bool applyPenalty, - bool useCDR, bool useSept21) { - -#ifdef USE_TH2JAGGED - if (!fOffAxisFluxParamHelper) { - fOffAxisFluxParamHelper = &ana::OffAxisFluxUncertaintyHelper::Get(); - } - if (!fNewOffAxisFluxUncertainty2022Helper) { - fNewOffAxisFluxUncertainty2022Helper = - &ana::NewOffAxisFluxUncertainty2022Helper::Get(); - } -#endif - - DUNEFluxSystVector ret; - for (unsigned int i = 0; i < N; ++i) { - ret.push_back(GetDUNEFluxSyst(i, applyPenalty, useCDR, useSept21)); - } - return ret; -} - -SystShifts FilterFluxSystShifts(SystShifts shift) { - SystShifts outs; - std::vector fsysts = - ana::GetDUNEFluxSysts(ana::kFluxSysts.size(), true, false, false); - std::vector fsysts_sept21 = - ana::GetDUNEFluxSysts(ana::kFluxSysts.size(), true, false, true); - fsysts.insert(fsysts.end(), fsysts_sept21.begin(), fsysts_sept21.end()); - - for (auto syst : shift.ActiveSysts()) { - if (std::find(fsysts.begin(), fsysts.end(), syst) != fsysts.end()) { - outs.SetShift(syst, shift.GetShift(syst)); - } - } - return outs; -} - -size_t GetFluxSystIndex(const ana::ISyst *syst) { - std::vector fsysts = - ana::GetDUNEFluxSysts(ana::kFluxSysts.size(), true, false, false); - std::vector fsysts_sept21 = - ana::GetDUNEFluxSysts(ana::kFluxSysts.size(), true, false, true); - fsysts.insert(fsysts.end(), fsysts_sept21.begin(), fsysts_sept21.end()); - - for (size_t i = 0; i < fsysts.size(); ++i) { - if (fsysts[i] == syst) { - return i; - } - } - - return kNotValidFluxSyst; -} +//const DUNEFluxSystVector kFluxSysts = GetDUNEFluxSysts(30); +// +////---------------------------------------------------------------------- +//DUNEFluxSyst::~DUNEFluxSyst() { +// for (int i : {0, 1}) +// for (int j : {0, 1}) +// for (int k : {0, 1}) +// for (int l : {0, 1}) +// delete fScale[i][j][k][l]; +//} +// +////---------------------------------------------------------------------- +//void DUNEFluxSyst::Shift(double sigma, +// caf::SRProxy *sr, double &weight) const { +// +// if (abs(sr->nuPDGunosc) == 16) { +// return; +// } +// +//#ifdef USE_TH2JAGGED +// if (fUseCDR) { +// std::cout +// << "[ERROR]: Off axis flux uncertainties did not exist for the CDR." +// << std::endl; +// abort(); +// } +// +// bool isSpecHCRun(false); +// if (std::abs(sr->SpecialHCRunId) != 293) isSpecHCRun = true; +// +// if (sr->OffAxisFluxBin == -1) { +// if (fUseSept21) { +// sr->OffAxisFluxBin = ana::NewOffAxisFluxUncertainty2022Helper::Get().GetBin( +// sr->nuPDGunosc, sr->Ev, sr->abspos_x * 1E-2, fIdx, !sr->isFD, +// sr->isFHC, isSpecHCRun); +// } else { +// sr->OffAxisFluxBin = ana::OffAxisFluxUncertaintyHelper::Get().GetBin( +// sr->nuPDGunosc, sr->Ev, sr->abspos_x * 1E-2, 0, !sr->isFD, +// sr->isFHC, isSpecHCRun); +// } +// } +// +// if (sr->OffAxisFluxConfig == -1) { +// if (fUseSept21) { +// sr->OffAxisFluxConfig = +// ana::NewOffAxisFluxUncertainty2022Helper::Get().GetNuConfig_checked( +// sr->nuPDGunosc, sr->Ev, sr->abspos_x * 1E-2, fIdx, !sr->isFD, +// sr->isFHC, isSpecHCRun); +// } else { +// sr->OffAxisFluxConfig = +// ana::OffAxisFluxUncertaintyHelper::Get().GetNuConfig_checked( +// sr->nuPDGunosc, sr->Ev, sr->abspos_x * 1E-2, 0, !sr->isFD, +// sr->isFHC, isSpecHCRun); +// } +// } +// +// if (fUseSept21) { +// weight = fNewOffAxisFluxUncertainty2022Helper->GetFluxWeight( +// fIdx, sigma, sr->abspos_x * 1E-2, sr->OffAxisFluxBin, sr->OffAxisFluxConfig); +// } else { +// weight = fOffAxisFluxParamHelper->GetFluxWeight( +// fIdx, sigma, sr->OffAxisFluxBin, sr->OffAxisFluxConfig); +// } +//#else +// if (!fScale[0][0][0][0]) { +// std::string InputFileName; +// if (fUseCDR) { +// // CDROpt flux +// InputFileName = "flux_shifts_CDR.root"; +// } else { +// // Nov17 opt engineered +// InputFileName = "flux_shifts_Nov17.root"; +// } +// +// TFile f((FindCAFAnaDir() + "/Systs/" + InputFileName).c_str()); +// assert(!f.IsZombie()); +// +// for (int det : {0, 1}) { +// const std::string detStr = (det == 0) ? "ND" : "FD"; +// for (int pdg : {0, 1}) { +// std::string pdgStr = (pdg == 0) ? "nue" : "numu"; +// for (bool anti : {false, true}) { +// if (anti) +// pdgStr += "bar"; +// +// for (int hc : {0, 1}) { +// const std::string hcStr = (hc == 0) ? "FHC" : "RHC"; +// +// TH1 *&h = fScale[det][pdg][anti][hc]; +// +// h = (TH1 *)f.Get(TString::Format("syst%d/%s_%s_%s", fIdx, +// detStr.c_str(), pdgStr.c_str(), +// hcStr.c_str()) +// .Data()); +// h = (TH1 *)h->Clone(UniqueName().c_str()); +// assert(h); +// h->SetDirectory(0); +// } +// } +// } +// } +// } // end if +// +// if (abs(sr->nuPDGunosc) == 16) +// return; +// +// double /*const*/ rel_weight = 1; +// double const enu = sr->Ev; +// +// const int det = sr->isFD ? 0 : 1; +// const int pdg = (abs(sr->nuPDGunosc) == 12) ? 0 : 1; +// const int anti = (sr->nuPDGunosc > 0) ? 0 : 1; +// const int hc = sr->isFHC ? 0 : 1; +// +// TH1 *h = fScale[det][pdg][anti][hc]; +// assert(h); +// +// const int bin = h->FindBin(enu); +// +// if (bin == 0 || bin == h->GetNbinsX() + 1) { +// return; +// } +// rel_weight = h->GetBinContent(bin); +// +// weight *= 1 + rel_weight * sigma; +//#endif +//} +// +////---------------------------------------------------------------------- +//const DUNEFluxSyst *GetDUNEFluxSyst(unsigned int i, bool applyPenalty, +// bool useCDR, bool useSept21) { +// // Make sure we always give the same one back +// static std::vector cache_CDR; +// static std::vector cache_Nov17; +// +// auto c = useCDR ? &cache_CDR : &cache_Nov17; +// if (i >= c->size()) { +// c->resize(i + 1); +// } +// if (!c->at(i)) { +// c->at(i) = new DUNEFluxSyst(i, applyPenalty, useCDR, useSept21); +// } +// return c->at(i); +//} +// +////---------------------------------------------------------------------- +//DUNEFluxSystVector GetDUNEFluxSysts(unsigned int N, bool applyPenalty, +// bool useCDR, bool useSept21) { +// +//#ifdef USE_TH2JAGGED +// if (!fOffAxisFluxParamHelper) { +// fOffAxisFluxParamHelper = &ana::OffAxisFluxUncertaintyHelper::Get(); +// } +// if (!fNewOffAxisFluxUncertainty2022Helper) { +// fNewOffAxisFluxUncertainty2022Helper = +// &ana::NewOffAxisFluxUncertainty2022Helper::Get(); +// } +//#endif +// +// DUNEFluxSystVector ret; +// for (unsigned int i = 0; i < N; ++i) { +// ret.push_back(GetDUNEFluxSyst(i, applyPenalty, useCDR, useSept21)); +// } +// return ret; +//} +// +//SystShifts FilterFluxSystShifts(SystShifts shift) { +// SystShifts outs; +// std::vector fsysts = +// ana::GetDUNEFluxSysts(ana::kFluxSysts.size(), true, false, false); +// std::vector fsysts_sept21 = +// ana::GetDUNEFluxSysts(ana::kFluxSysts.size(), true, false, true); +// fsysts.insert(fsysts.end(), fsysts_sept21.begin(), fsysts_sept21.end()); +// +// for (auto syst : shift.ActiveSysts()) { +// if (std::find(fsysts.begin(), fsysts.end(), syst) != fsysts.end()) { +// outs.SetShift(syst, shift.GetShift(syst)); +// } +// } +// return outs; +//} +// +//size_t GetFluxSystIndex(const ana::ISyst *syst) { +// std::vector fsysts = +// ana::GetDUNEFluxSysts(ana::kFluxSysts.size(), true, false, false); +// std::vector fsysts_sept21 = +// ana::GetDUNEFluxSysts(ana::kFluxSysts.size(), true, false, true); +// fsysts.insert(fsysts.end(), fsysts_sept21.begin(), fsysts_sept21.end()); +// +// for (size_t i = 0; i < fsysts.size(); ++i) { +// if (fsysts[i] == syst) { +// return i; +// } +// } +// +// return kNotValidFluxSyst; +//} } // namespace ana diff --git a/CAFAna/Systs/DUNEFluxSysts.h b/CAFAna/Systs/DUNEFluxSysts.h index d67bfd9c..fce2048b 100644 --- a/CAFAna/Systs/DUNEFluxSysts.h +++ b/CAFAna/Systs/DUNEFluxSysts.h @@ -8,58 +8,58 @@ class TH1; class TH2; namespace ana { -class SystShifts; - -class DUNEFluxSyst : public ISyst { -public: - virtual ~DUNEFluxSyst(); - - virtual void Shift(double sigma, caf::SRProxy *sr, - double &weight) const override; - -protected: - friend const DUNEFluxSyst *GetDUNEFluxSyst(unsigned int, bool, bool, bool); - DUNEFluxSyst(int i, bool applyPenalty, bool useCDR, bool useSept21) - : ISyst(TString::Format("flux_%s_%i", - useCDR ? "CDR" : - (useSept21 ? "Sept21" : "Nov17"), i).Data(), - TString::Format("Flux #%i (%s)", i, - useCDR ? "CDR" : - (useSept21 ? "Sept21" : "Nov17")).Data(), - applyPenalty), - fIdx(i), fScale(), fUseCDR(useCDR), fUseSept21(useSept21) {} - - int fIdx; - - mutable TH1 *fScale[2][2][2][2]; // ND/FD, numu/nue, bar, FHC/RHC - - bool fUseCDR; - bool fUseSept21; -}; - -const DUNEFluxSyst *GetDUNEFluxSyst(unsigned int i, bool applyPenalty = true, - bool useCDR = true, bool useSept21 = false); - -// Because vector won't automatically convert to vector even when U -// inherits from V. -struct DUNEFluxSystVector : public std::vector { - operator std::vector() { - return std::vector(begin(), end()); - } -}; - -DUNEFluxSystVector GetDUNEFluxSysts(unsigned int N, bool applyPenalty = true, - bool useCDR = true, bool useSept21 = false); - -// instantiate them all at global scope so that they can be found in the -// Registry -extern const DUNEFluxSystVector kFluxSysts; - -// Given a SystShifts, extract only those that are flux shifts -SystShifts FilterFluxSystShifts(SystShifts); - -// Get the index of a given Flux syst -static const size_t kNotValidFluxSyst = std::numeric_limits::max(); -size_t GetFluxSystIndex(const ana::ISyst *syst); +//class SystShifts; +// +//class DUNEFluxSyst : public ISyst { +//public: +// virtual ~DUNEFluxSyst(); +// +// virtual void Shift(double sigma, caf::SRProxy *sr, +// double &weight) const override; +// +//protected: +// friend const DUNEFluxSyst *GetDUNEFluxSyst(unsigned int, bool, bool, bool); +// DUNEFluxSyst(int i, bool applyPenalty, bool useCDR, bool useSept21) +// : ISyst(TString::Format("flux_%s_%i", +// useCDR ? "CDR" : +// (useSept21 ? "Sept21" : "Nov17"), i).Data(), +// TString::Format("Flux #%i (%s)", i, +// useCDR ? "CDR" : +// (useSept21 ? "Sept21" : "Nov17")).Data(), +// applyPenalty), +// fIdx(i), fScale(), fUseCDR(useCDR), fUseSept21(useSept21) {} +// +// int fIdx; +// +// mutable TH1 *fScale[2][2][2][2]; // ND/FD, numu/nue, bar, FHC/RHC +// +// bool fUseCDR; +// bool fUseSept21; +//}; +// +//const DUNEFluxSyst *GetDUNEFluxSyst(unsigned int i, bool applyPenalty = true, +// bool useCDR = true, bool useSept21 = false); +// +//// Because vector won't automatically convert to vector even when U +//// inherits from V. +//struct DUNEFluxSystVector : public std::vector { +// operator std::vector() { +// return std::vector(begin(), end()); +// } +//}; +// +//DUNEFluxSystVector GetDUNEFluxSysts(unsigned int N, bool applyPenalty = true, +// bool useCDR = true, bool useSept21 = false); +// +//// instantiate them all at global scope so that they can be found in the +//// Registry +//extern const DUNEFluxSystVector kFluxSysts; +// +//// Given a SystShifts, extract only those that are flux shifts +//SystShifts FilterFluxSystShifts(SystShifts); +// +//// Get the index of a given Flux syst +//static const size_t kNotValidFluxSyst = std::numeric_limits::max(); +//size_t GetFluxSystIndex(const ana::ISyst *syst); } // namespace ana diff --git a/CAFAna/Systs/DUNENDSysts.cxx b/CAFAna/Systs/DUNENDSysts.cxx index f27d43bb..4b9af894 100644 --- a/CAFAna/Systs/DUNENDSysts.cxx +++ b/CAFAna/Systs/DUNENDSysts.cxx @@ -2,6 +2,6 @@ namespace ana { - const DUNENDEvSyst kNDEvSyst; - const DUNENDPIDSyst kNDPIDSyst; +// const DUNENDEvSyst kNDEvSyst; +// const DUNENDPIDSyst kNDPIDSyst; } // namespace diff --git a/CAFAna/Systs/DUNENDSysts.h b/CAFAna/Systs/DUNENDSysts.h index 56a11ca9..7eefd621 100644 --- a/CAFAna/Systs/DUNENDSysts.h +++ b/CAFAna/Systs/DUNENDSysts.h @@ -7,56 +7,56 @@ namespace ana { - class DUNENDEvSyst: public ISyst - { - public: - DUNENDEvSyst() : ISyst("NDEv", "Near Detector reco Ev") {} - - void Shift(double sigma, - caf::SRProxy* sr, - double& weight) const override - { - double scale = pow( 1. + sr->sigma_Ev_reco, sigma ); - sr->Ev_reco *= scale; - sr->Ev_reco_numu *= scale; - sr->Ev_reco_nue *= scale; - } - }; - - extern const DUNENDEvSyst kNDEvSyst; - - class DUNENDPIDSyst: public ISyst - { - public: - DUNENDPIDSyst() : ISyst("NDPID", "Near Detector lepton PID") {} - - void Shift(double sigma, - caf::SRProxy* sr, - double& weight) const override - { - bool numu = ( sigma > sr->sigma_numu_pid ); - bool nue = ( sigma > sr->sigma_nue_pid ); - - // theoretically it is possible for both to be true in the same event, though this is highly unlikely. - // in these rare cases, use the one with the smaller sigma - if( numu && nue ) { // very rare - if( sr->sigma_numu_pid < sr->sigma_nue_pid ) nue = false; - else numu = false; - } - - if( numu ) { - sr->numu_pid = 1.; - sr->nue_pid = -1.; - } else if( nue ) { - sr->numu_pid = -1.; - sr->nue_pid = 1.; - } else { // NC event - sr->numu_pid = -1.; - sr->nue_pid = -1.; - } - - } - }; - - extern const DUNENDPIDSyst kNDPIDSyst; +// class DUNENDEvSyst: public ISyst +// { +// public: +// DUNENDEvSyst() : ISyst("NDEv", "Near Detector reco Ev") {} +// +// void Shift(double sigma, +// caf::SRProxy* sr, +// double& weight) const override +// { +// double scale = pow( 1. + sr->sigma_Ev_reco, sigma ); +// sr->Ev_reco *= scale; +// sr->Ev_reco_numu *= scale; +// sr->Ev_reco_nue *= scale; +// } +// }; +// +// extern const DUNENDEvSyst kNDEvSyst; +// +// class DUNENDPIDSyst: public ISyst +// { +// public: +// DUNENDPIDSyst() : ISyst("NDPID", "Near Detector lepton PID") {} +// +// void Shift(double sigma, +// caf::SRProxy* sr, +// double& weight) const override +// { +// bool numu = ( sigma > sr->sigma_numu_pid ); +// bool nue = ( sigma > sr->sigma_nue_pid ); +// +// // theoretically it is possible for both to be true in the same event, though this is highly unlikely. +// // in these rare cases, use the one with the smaller sigma +// if( numu && nue ) { // very rare +// if( sr->sigma_numu_pid < sr->sigma_nue_pid ) nue = false; +// else numu = false; +// } +// +// if( numu ) { +// sr->numu_pid = 1.; +// sr->nue_pid = -1.; +// } else if( nue ) { +// sr->numu_pid = -1.; +// sr->nue_pid = 1.; +// } else { // NC event +// sr->numu_pid = -1.; +// sr->nue_pid = -1.; +// } +// +// } +// }; +// +// extern const DUNENDPIDSyst kNDPIDSyst; } diff --git a/CAFAna/Systs/DUNEXSecSysts.cxx b/CAFAna/Systs/DUNEXSecSysts.cxx index e903216b..2d8d6fd9 100644 --- a/CAFAna/Systs/DUNEXSecSysts.cxx +++ b/CAFAna/Systs/DUNEXSecSysts.cxx @@ -100,12 +100,12 @@ namespace ana //---------------------------------------------------------------------- EVALORCategory GetVALORCategory(const caf::SRProxy* sr) { - int lep = sr->LepPDG; - int scat = sr->mode; - const int npiz = sr->nipi0; - const int npic = sr->nipip + sr->nipim; - const float Enu = sr->Ev; - const float Q2 = sr->Q2; + int lep = sr->mc.nu[0].pdg;// this is probs wrong LepPDG; + int scat = sr->mc.nu[0].mode;//mode; + const int npiz = sr->mc.nu[0].npi0;//nipi0; + const int npic = sr->mc.nu[0].npip+sr->mc.nu[0].npim;//nipip + sr->nipim; + const float Enu = sr->mc.nu[0].E;//Ev; + const float Q2 = sr->mc.nu[0].Q2;//Q2; // These are the FD codes // kUnknownMode = -1 @@ -142,7 +142,7 @@ namespace ana // 14 IMD annihilation // Different conventions ND (weird (new?)) and FD (like NOvA) - if(sr->isFD){ + /*if(sr->isFD){ switch(scat){ case 0: scat = 1; break; // QE -> QE case 1: scat = 4; break; // RES -> RES @@ -161,7 +161,7 @@ namespace ana std::cout << "Unhandled GENIE FD code " << scat << std::endl; abort(); } - } + }*/ // Treat nutaus as if they were numus for now if(lep == -16) lep = -14; diff --git a/CAFAna/Systs/EnergySysts.cxx b/CAFAna/Systs/EnergySysts.cxx index 12c77b17..13803f78 100644 --- a/CAFAna/Systs/EnergySysts.cxx +++ b/CAFAna/Systs/EnergySysts.cxx @@ -1,435 +1,435 @@ #include "CAFAna/Systs/EnergySysts.h" namespace ana { - - void EnergyScaleFD::Shift(double sigma, - caf::SRProxy* sr, double& weight) const { - - double scale = .02 * sigma; - if (sr->isFD) { - if (sr->RecoHadEnNue < 0.) sr->RecoHadEnNue = 0.; - if (sr->Ev_reco_nue < 0.) sr->Ev_reco_nue = 0.; - sr->Ev_reco_numu += scale * sr->RecoHadEnNumu; - sr->Ev_reco_nue += scale * sr->RecoHadEnNue; - sr->EVisReco_numu += scale * sr->HadEVisReco_FD; - sr->EVisReco_nue += scale * sr->HadEVisReco_FD; - sr->RecoHadEnNumu *= 1. + scale; - sr->RecoHadEnNue *= 1. + scale; - sr->HadEVisReco_FD*= 1. + scale; - if ( !(sr->isCC==1 && abs(sr->nuPDG) == 14) ) { - sr->Ev_reco_nue += scale * sr->RecoLepEnNue; - sr->EVisReco_nue += scale * sr->RecoLepEnNue; - sr->RecoLepEnNue *= 1. + scale; - } - } - } - - const EnergyScaleFD kEnergyScaleFD; - - void UncorrFDTotSqrt::Shift(double sigma, - caf::SRProxy* sr, double& weight) const { - - const double scale = .01 * sigma; - if (sr->isFD) { - if (sr->RecoHadEnNue < 0.) sr->RecoHadEnNue = 0.; - sr->Ev_reco_numu += scale*pow(sr->RecoHadEnNumu, 0.5)*sr->RecoHadEnNumu; - sr->Ev_reco_nue += scale*pow(sr->RecoHadEnNue, 0.5)*sr->RecoHadEnNue; - sr->EVisReco_numu += scale*pow(sr->HadEVisReco_FD, 0.5)*sr->HadEVisReco_FD; - sr->EVisReco_nue += scale*pow(sr->HadEVisReco_FD, 0.5)*sr->HadEVisReco_FD; - sr->RecoHadEnNumu += scale*pow(sr->RecoHadEnNumu, 0.5)*sr->RecoHadEnNumu; - sr->RecoHadEnNue += scale*pow(sr->RecoHadEnNue, 0.5)*sr->RecoHadEnNue; - sr->HadEVisReco_FD+= scale*pow(sr->HadEVisReco_FD, 0.5)*sr->HadEVisReco_FD; - if ( !(sr->isCC==1 && abs(sr->nuPDG) == 14) ) { - sr->Ev_reco_nue += scale*pow(sr->RecoLepEnNue, 0.5)*sr->RecoLepEnNue; - sr->EVisReco_nue += scale*pow(sr->RecoLepEnNue, 0.5)*sr->RecoLepEnNue; - sr->RecoLepEnNue += scale*pow(sr->RecoLepEnNue, 0.5)*sr->RecoLepEnNue; - } - } - } - - const UncorrFDTotSqrt kUncorrFDTotSqrt; - - void UncorrFDTotInvSqrt::Shift(double sigma, - caf::SRProxy* sr, double& weight) const { - - if (sr->isFD) { - if (sr->RecoHadEnNue < 0.) sr->RecoHadEnNue = 0.; - const double scale = .02 * sigma; - sr->Ev_reco_numu += sr->RecoHadEnNumu*scale*pow(sr->RecoHadEnNumu+0.1, -0.5); - sr->Ev_reco_nue += sr->RecoHadEnNue*scale*pow(sr->RecoHadEnNue+0.1, -0.5); - sr->EVisReco_numu += sr->HadEVisReco_FD*scale*pow(sr->HadEVisReco_FD+0.1, -0.5); - sr->RecoHadEnNumu += sr->RecoHadEnNumu*scale*pow(sr->RecoHadEnNumu+0.1, -0.5); - sr->RecoHadEnNue += sr->RecoHadEnNue*scale*pow(sr->RecoHadEnNue+0.1, -0.5); - sr->HadEVisReco_FD+= sr->HadEVisReco_FD*scale*pow(sr->HadEVisReco_FD+0.1, -0.5); - if ( !(sr->isCC==1 && abs(sr->nuPDG) == 14) ) { - sr->Ev_reco_nue += sr->RecoLepEnNue * scale * pow(sr->RecoLepEnNue+0.1, -0.5); - sr->EVisReco_nue += sr->RecoLepEnNue * scale * pow(sr->RecoLepEnNue+0.1, -0.5); - sr->RecoLepEnNue += sr->RecoLepEnNue * scale * pow(sr->RecoLepEnNue+0.1, -0.5); - } - } - } - - const UncorrFDTotInvSqrt kUncorrFDTotInvSqrt; - - void UncorrFDHadSqrt::Shift(double sigma, - caf::SRProxy* sr, double& weight) const { - - const double scale = .05 * sigma; - if (sr->isFD) { - if (sr->RecoHadEnNue < 0.) sr->RecoHadEnNue = 0.; - if (sr->eRecoP < 0) sr->eRecoP = 0.; - if (sr->eRecoPim < 0) sr->eRecoPim = 0.; - if (sr->eRecoPip < 0) sr->eRecoPip = 0.; - double sumE = sr->eRecoP + sr->eRecoPip + sr->eRecoPim; - double sumEdep = sr->eDepP + sr->eDepPip + sr->eDepPim; - sr->eRecoP += sr->eRecoP * scale * pow(sumE, 0.5); - sr->eRecoPim += sr->eRecoPim * scale * pow(sumE, 0.5); - sr->eRecoPip += sr->eRecoPip * scale * pow(sumE, 0.5); - sr->Ev_reco_numu += sumE * scale * pow(sumE, 0.5); - sr->Ev_reco_nue += sumE * scale * pow(sumE, 0.5); - sr->EVisReco_numu+= sumEdep * scale * pow(sumEdep, 0.5); - sr->EVisReco_numu+= sumEdep * scale * pow(sumEdep, 0.5); - sr->RecoHadEnNumu += sumE * scale * pow(sumE, 0.5); - sr->RecoHadEnNue += sumE * scale * pow(sumE, 0.5); - sr->HadEVisReco_FD+= sumEdep * scale * pow(sumEdep, 0.5); - } - } - - const UncorrFDHadSqrt kUncorrFDHadSqrt; - - void UncorrFDHadInvSqrt::Shift(double sigma, - caf::SRProxy* sr, double& weight) const { - - const double scale = .05 * sigma; - if (sr->isFD) { - if (sr->RecoHadEnNue < 0.) sr->RecoHadEnNue = 0.; - if (sr->eRecoP < 0) sr->eRecoP = 0.; - if (sr->eRecoPim < 0) sr->eRecoPim = 0.; - if (sr->eRecoPip < 0) sr->eRecoPip = 0.; - double sumE = sr->eRecoP + sr->eRecoPip + sr->eRecoPim; - double sumEdep = sr->eDepP + sr->eDepPip + sr->eDepPim; - sr->Ev_reco_numu += sumE * scale * pow(sumE+0.1, -0.5); - sr->Ev_reco_nue += sumE * scale * pow(sumE+0.1, -0.5); - sr->EVisReco_numu+= sumEdep * scale * pow(sumEdep+0.1, -0.5); - sr->EVisReco_nue+= sumEdep * scale * pow(sumEdep+0.1, -0.5); - sr->eRecoP += sr->eRecoP * scale * pow(sumE+0.1, -0.5); - sr->eRecoPim += sr->eRecoPim * scale * pow(sumE+0.1, -0.5); - sr->eRecoPip += sr->eRecoPip * scale * pow(sumE+0.1, -0.5); - sr->RecoHadEnNumu += sumE * scale * pow(sumE+0.1, -0.5); - sr->RecoHadEnNue += sumE * scale * pow(sumE+0.1, -0.5); - sr->HadEVisReco_FD+= sumEdep * scale * pow(sumEdep+0.1, -0.5); - } - } - - const UncorrFDHadInvSqrt kUncorrFDHadInvSqrt; - - void UncorrFDMuSqrt::Shift(double sigma, - caf::SRProxy* sr, double& weight) const { - - if (sr->isFD && sr->isCC==1 && abs(sr->nuPDG)==14) { - const double scale = .005 * sigma; - sr->Ev_reco_numu += sr->RecoLepEnNumu * pow(sr->RecoLepEnNumu, 0.5) * scale; - sr->EVisReco_numu += sr->RecoLepEnNumu * pow(sr->RecoLepEnNumu, 0.5) * scale; - sr->RecoLepEnNumu += sr->RecoLepEnNumu * pow(sr->RecoLepEnNumu, 0.5) * scale; - } - } - - const UncorrFDMuSqrt kUncorrFDMuSqrt; - - void UncorrFDMuInvSqrt::Shift(double sigma, - caf::SRProxy* sr, double& weight) const { - - if (sr->isFD && sr->isCC==1 && abs(sr->nuPDG)==14) { - const double scale = .02 * sigma; - sr->Ev_reco_numu += sr->RecoLepEnNumu * scale * pow(sr->RecoLepEnNumu+0.1, -0.5); - sr->EVisReco_numu += sr->RecoLepEnNumu * scale * pow(sr->RecoLepEnNumu+0.1, -0.5); - sr->RecoLepEnNumu += sr->RecoLepEnNumu * scale * pow(sr->RecoLepEnNumu+0.1, -0.5); - } - } - - const UncorrFDMuInvSqrt kUncorrFDMuInvSqrt; - - void UncorrFDNSqrt::Shift(double sigma, - caf::SRProxy* sr, double& weight) const { - - const double scale = .3 * sigma; - if (sr->isFD) { - if (sr->eRecoN < 0.) { sr->eRecoN = 0.; } - sr->Ev_reco_numu += sr->eRecoN * pow(sr->eRecoN, 0.5) * scale; - sr->Ev_reco_nue += sr->eRecoN * pow(sr->eRecoN, 0.5) * scale; - sr->RecoHadEnNumu += sr->eRecoN * pow(sr->eRecoN, 0.5) * scale; - sr->RecoHadEnNue += sr->eRecoN * pow(sr->eRecoN, 0.5) * scale; - } - } - - const UncorrFDNSqrt kUncorrFDNSqrt; - - void UncorrFDNInvSqrt::Shift(double sigma, - caf::SRProxy* sr, double& weight) const { - - const double scale = .3 * sigma; - if (sr->isFD) { - if (sr->eRecoN < 0.) { sr->eRecoN = 0.; } - sr->Ev_reco_numu += sr->eRecoN * scale * pow(sr->eRecoN+0.1, -0.5); - sr->Ev_reco_nue += sr->eRecoN * scale * pow(sr->eRecoN+0.1, -0.5); - sr->RecoHadEnNumu += sr->eRecoN * scale * pow(sr->eRecoN+0.1, -0.5); - sr->RecoHadEnNue += sr->eRecoN * scale * pow(sr->eRecoN+0.1, -0.5); - } - } - - const UncorrFDNInvSqrt kUncorrFDNInvSqrt; - - void UncorrFDEMSqrt::Shift(double sigma, - caf::SRProxy* sr, double& weight) const { - - const double scale = .025 * sigma; - if (sr->isFD) { - if (sr->RecoHadEnNue < 0.) sr->RecoHadEnNue = 0.; - if (sr->eRecoPi0 < 0) sr->eRecoPi0 = 0.; - sr->Ev_reco_numu += sr->eRecoPi0 * pow(sr->eRecoPi0, 0.5) * scale; - sr->Ev_reco_nue += sr->eRecoPi0 * pow(sr->eRecoPi0, 0.5) * scale; - sr->EVisReco_numu+= sr->eDepPi0 * pow(sr->eDepPi0, 0.5) * scale; - sr->EVisReco_nue += sr->eDepPi0 * pow(sr->eDepPi0, 0.5) * scale; - sr->RecoHadEnNumu += sr->eRecoPi0 * pow(sr->eRecoPi0, 0.5) * scale; - sr->RecoHadEnNue += sr->eRecoPi0 * pow(sr->eRecoPi0, 0.5) * scale; - sr->HadEVisReco_FD+= sr->eDepPi0 * pow(sr->eDepPi0, 0.5) * scale; - sr->eRecoPi0 += sr->eRecoPi0 * pow(sr->eRecoPi0, 0.5) * scale; - if (sr->eRecoPi0 < 0) sr->eRecoPi0 = 0.; - if (sr->isCC==1 && abs(sr->nuPDG)==12) { - sr->Ev_reco_nue += sr->RecoLepEnNue*pow(sr->RecoLepEnNue, 0.5)*scale; - sr->EVisReco_nue += sr->RecoLepEnNue*pow(sr->RecoLepEnNue, 0.5)*scale; - sr->RecoLepEnNue += sr->RecoLepEnNue*pow(sr->RecoLepEnNue, 0.5)*scale; - } - } - } - - const UncorrFDEMSqrt kUncorrFDEMSqrt; - - - void UncorrFDEMInvSqrt::Shift(double sigma, - caf::SRProxy* sr, double& weight) const { - - const double scale = .025 * sigma; - if (sr->isFD) { - if (sr->RecoHadEnNue < 0.) sr->RecoHadEnNue = 0.; - if (sr->eRecoPi0 < 0) sr->eRecoPi0 = 0.; - sr->Ev_reco_numu += sr->eRecoPi0 * scale * pow(sr->eRecoPi0+0.1, -0.5); - sr->Ev_reco_nue += sr->eRecoPi0 * scale * pow(sr->eRecoPi0+0.1, -0.5); - sr->EVisReco_numu+= sr->eDepPi0 * scale * pow(sr->eDepPi0+0.1, -0.5); - sr->EVisReco_nue += sr->eDepPi0 * scale * pow(sr->eDepPi0+0.1, -0.5); - sr->RecoHadEnNumu += sr->eRecoPi0 * scale * pow(sr->eRecoPi0+0.1, -0.5); - sr->RecoHadEnNue += sr->eRecoPi0 * scale * pow(sr->eRecoPi0+0.1, -0.5); - sr->HadEVisReco_FD+= sr->eDepPi0 * scale * pow(sr->eDepPi0+0.1, -0.5); - sr->eRecoPi0 += sr->eRecoPi0 * scale * pow(sr->eRecoPi0+0.1, -0.5); - if (sr->isCC==1 && abs(sr->nuPDG)==12) { - sr->Ev_reco_nue += sr->RecoLepEnNue * scale * pow(sr->RecoLepEnNue+0.1, -0.5); - sr->EVisReco_nue += sr->RecoLepEnNue * scale * pow(sr->RecoLepEnNue+0.1, -0.5); - sr->RecoLepEnNue += sr->RecoLepEnNue * scale * pow(sr->RecoLepEnNue+0.1, -0.5); - } - } - } - - const UncorrFDEMInvSqrt kUncorrFDEMInvSqrt; - - void EScaleMuLArFD::Shift(double sigma, - caf::SRProxy* sr, double& weight) const { - - const double scale = .02 * sigma; - // Checks if FD and select only CC muon neutrino events - if(sr->isFD && abs(sr->nuPDG) == 14 && sr->isCC == 1){ - sr->Ev_reco_numu += sr->RecoLepEnNumu * scale; - sr->EVisReco_numu += sr->RecoLepEnNumu * scale; - sr->RecoLepEnNumu *= 1. + scale; - } - } - - const EScaleMuLArFD kEScaleMuLArFD; - - void ChargedHadUncorrFD::Shift(double sigma, - caf::SRProxy* sr, double& weight) const { - - const double scale = .05 * sigma; - if(sr->isFD) { - if (sr->RecoHadEnNue < 0.) sr->RecoHadEnNue = 0.; - if (sr->eRecoP < 0) sr->eRecoP = 0.; - if (sr->eRecoPim < 0) sr->eRecoPim = 0.; - if (sr->eRecoPip < 0) sr->eRecoPip = 0.; - const double sumE = sr->eRecoP + sr->eRecoPim + sr->eRecoPip; - const double sumEdep = sr->eDepP + sr->eDepPip + sr->eDepPim; - sr->eRecoP += sr->eRecoP * scale; - sr->eRecoPim += sr->eRecoPim * scale; - sr->eRecoPip += sr->eRecoPip * scale; - sr->Ev_reco_numu += sumE * scale; - sr->Ev_reco_nue += sumE * scale; - sr->EVisReco_numu += sumEdep * scale; - sr->EVisReco_nue += sumEdep * scale; - sr->RecoHadEnNumu += sumE * scale; - sr->RecoHadEnNue += sumE * scale; - sr->HadEVisReco_FD += sumEdep * scale; - } - } - - const ChargedHadUncorrFD kChargedHadUncorrFD; - - void NUncorrFD::Shift(double sigma, - caf::SRProxy* sr, double& weight) const { - - const double scale = .20 * sigma; - if(sr->isFD) { - if (sr->RecoHadEnNue < 0.) sr->RecoHadEnNue = 0.; - if (sr->eRecoN < 0.) sr->eRecoN = 0.; - sr->Ev_reco_numu += sr->eRecoN * scale; - sr->Ev_reco_nue += sr->eRecoN * scale; - sr->RecoHadEnNumu += sr->eRecoN * scale; - sr->RecoHadEnNue += sr->eRecoN * scale; - sr->eRecoN += sr->eRecoN * scale; - } - } - - const NUncorrFD kNUncorrFD; - - void EMUncorrFD::Shift(double sigma, - caf::SRProxy* sr, double& weight) const { - - const double scale = 0.025 * sigma; - if (sr->isFD) { - if (sr->RecoHadEnNue < 0.) sr->RecoHadEnNue = 0.; - if (sr->eRecoPi0 < 0.) sr->eRecoPi0 = 0.; - sr->Ev_reco_nue += sr->eRecoPi0 * scale; - sr->Ev_reco_numu += sr->eRecoPi0 * scale; - sr->EVisReco_numu += sr->eDepPi0 * scale; - sr->EVisReco_nue += sr->eDepPi0 * scale; - sr->RecoHadEnNue += sr->eRecoPi0 * scale; - sr->RecoHadEnNumu += sr->eRecoPi0 * scale; - sr->HadEVisReco_FD += sr->eDepPi0 * scale; - sr->eRecoPi0 += sr->eRecoPi0 * scale; - if (sr->isCC && abs(sr->nuPDG) == 12) { - sr->Ev_reco_nue += sr->RecoLepEnNue * scale; - sr->EVisReco_nue += sr->RecoLepEnNue * scale; - sr->RecoLepEnNue += sr->RecoLepEnNue * scale; - } - } - } - - const EMUncorrFD kEMUncorrFD; - - void MuonResFD::Shift(double sigma, - caf::SRProxy* sr, double& weight) const { - - const double scale = .02*sigma; - // FD charged current numus only - if (sr->isFD && sr->isCC && abs(sr->nuPDG)==14) { - sr->Ev_reco_numu += (sr->LepE - sr->RecoLepEnNumu) * scale; - sr->EVisReco_numu += (sr->LepE - sr->RecoLepEnNumu) * scale; - sr->RecoLepEnNumu += (sr->LepE - sr->RecoLepEnNumu) * scale; - } - } - - const MuonResFD kMuonResFD; - - void EMResFD::Shift(double sigma, - caf::SRProxy* sr, double& weight) const { - - const double scale = .02*sigma; - if (sr->isFD){ - if (sr->RecoHadEnNue < 0.) sr->RecoHadEnNue = 0.; - if (sr->eRecoPi0 < 0.) sr->eRecoPi0 = 0.; - sr->Ev_reco_nue += (sr->ePi0 - sr->eRecoPi0) * scale; - sr->Ev_reco_numu += (sr->ePi0 - sr->eRecoPi0) * scale; - sr->EVisReco_nue += (sr->ePi0 - sr->eDepPi0) * scale; - sr->EVisReco_numu += (sr->ePi0 - sr->eDepPi0) * scale; - sr->RecoHadEnNumu += (sr->ePi0 - sr->eRecoPi0) * scale; - sr->RecoHadEnNue += (sr->ePi0 - sr->eRecoPi0) * scale; - sr->HadEVisReco_FD+= (sr->ePi0 - sr->eDepPi0) * scale; - sr->eRecoPi0 += (sr->ePi0 - sr->eRecoPi0) * scale; - if (sr->isCC && abs(sr->nuPDG)==12) { - sr->Ev_reco_nue += (sr->LepE - sr->RecoLepEnNue) * scale; - sr->EVisReco_nue += (sr->LepE - sr->RecoLepEnNue) * scale; - sr->RecoLepEnNue += (sr->LepE - sr->RecoLepEnNue) * scale; - } - } - } - - const EMResFD kEMResFD; - - void ChargedHadResFD::Shift(double sigma, - caf::SRProxy* sr, double& weight) const { - - const double scale = .02*sigma; - if (sr->isFD) { - if (sr->RecoHadEnNue < 0.) sr->RecoHadEnNue = 0.; - if (sr->eRecoP < 0.) sr->eRecoP = 0.; - if (sr->eRecoPip < 0.) sr->eRecoPip = 0.; - if (sr->eRecoPim < 0.) sr->eRecoPim = 0.; - const double trueSum = sr->ePip + sr->ePim + sr->eP; - const double recoSum = sr->eRecoPip + sr->eRecoPim + sr->eRecoP; - const double depSum = sr->eDepP + sr->eDepPip + sr->eDepPim; - sr->Ev_reco_nue += (trueSum - recoSum) * scale; - sr->Ev_reco_numu += (trueSum - recoSum) * scale; - sr->EVisReco_nue += (trueSum - depSum) * scale; - sr->EVisReco_numu += (trueSum - depSum) * scale; - sr->RecoHadEnNue += (trueSum - recoSum) * scale; - sr->RecoHadEnNumu += (trueSum - recoSum) * scale; - sr->HadEVisReco_FD+= (trueSum - depSum) * scale; - } - } - - const ChargedHadResFD kChargedHadResFD; - - void NResFD::Shift(double sigma, - caf::SRProxy* sr, double& weight) const { - - const double scale = .1*sigma; - // FD charged current numus only - if (sr->isFD) { - if (sr->RecoHadEnNue < 0.) sr->RecoHadEnNue = 0.; - if (sr->eRecoN < 0.) sr->eRecoN = 0.; - sr->Ev_reco_nue += (sr->eN - sr->eRecoN) * scale; - sr->Ev_reco_numu += (sr->eN - sr->eRecoN) * scale; - sr->RecoHadEnNue += (sr->eN - sr->eRecoN) * scale; - sr->RecoHadEnNumu += (sr->eN - sr->eRecoN) * scale; - sr->eRecoN += (sr->eN - sr->eRecoN) * scale; - } - } - - const NResFD kNResFD; - - std::vector GetEnergySysts() { - - std::vector vec; - vec.push_back(&kEnergyScaleFD); - vec.push_back(&kUncorrFDTotSqrt);//v4 - vec.push_back(&kUncorrFDTotInvSqrt);//v4 - vec.push_back(&kUncorrFDHadSqrt);//v4 - vec.push_back(&kUncorrFDHadInvSqrt);//v4 - vec.push_back(&kUncorrFDMuSqrt);//v4 - vec.push_back(&kUncorrFDMuInvSqrt);//v4 - vec.push_back(&kUncorrFDNSqrt);//v4 - vec.push_back(&kUncorrFDNInvSqrt);//v4 - vec.push_back(&kUncorrFDEMSqrt);//v4 - vec.push_back(&kUncorrFDEMInvSqrt);//v4 - vec.push_back(&kEScaleMuLArFD); - vec.push_back(&kChargedHadUncorrFD);//v4 - vec.push_back(&kNUncorrFD); - vec.push_back(&kEMUncorrFD); - vec.push_back(&kMuonResFD); - vec.push_back(&kEMResFD); - vec.push_back(&kChargedHadResFD); - vec.push_back(&kNResFD); - - return vec; - } - - std::vector FilterOutFDSysts(std::vector systs) { - std::vector outs; - std::vector fsysts = GetEnergySysts(); - - for (auto syst : systs) { - if (std::find(fsysts.begin(), fsysts.end(), syst) == fsysts.end()) { - outs.emplace_back(syst); - } - } - return outs; - } - +// +// void EnergyScaleFD::Shift(double sigma, +// caf::SRProxy* sr, double& weight) const { +// +// double scale = .02 * sigma; +// if (sr->isFD) { +// if (sr->RecoHadEnNue < 0.) sr->RecoHadEnNue = 0.; +// if (sr->Ev_reco_nue < 0.) sr->Ev_reco_nue = 0.; +// sr->Ev_reco_numu += scale * sr->RecoHadEnNumu; +// sr->Ev_reco_nue += scale * sr->RecoHadEnNue; +// sr->EVisReco_numu += scale * sr->HadEVisReco_FD; +// sr->EVisReco_nue += scale * sr->HadEVisReco_FD; +// sr->RecoHadEnNumu *= 1. + scale; +// sr->RecoHadEnNue *= 1. + scale; +// sr->HadEVisReco_FD*= 1. + scale; +// if ( !(sr->isCC==1 && abs(sr->nuPDG) == 14) ) { +// sr->Ev_reco_nue += scale * sr->RecoLepEnNue; +// sr->EVisReco_nue += scale * sr->RecoLepEnNue; +// sr->RecoLepEnNue *= 1. + scale; +// } +// } +// } +// +// const EnergyScaleFD kEnergyScaleFD; +// +// void UncorrFDTotSqrt::Shift(double sigma, +// caf::SRProxy* sr, double& weight) const { +// +// const double scale = .01 * sigma; +// if (sr->isFD) { +// if (sr->RecoHadEnNue < 0.) sr->RecoHadEnNue = 0.; +// sr->Ev_reco_numu += scale*pow(sr->RecoHadEnNumu, 0.5)*sr->RecoHadEnNumu; +// sr->Ev_reco_nue += scale*pow(sr->RecoHadEnNue, 0.5)*sr->RecoHadEnNue; +// sr->EVisReco_numu += scale*pow(sr->HadEVisReco_FD, 0.5)*sr->HadEVisReco_FD; +// sr->EVisReco_nue += scale*pow(sr->HadEVisReco_FD, 0.5)*sr->HadEVisReco_FD; +// sr->RecoHadEnNumu += scale*pow(sr->RecoHadEnNumu, 0.5)*sr->RecoHadEnNumu; +// sr->RecoHadEnNue += scale*pow(sr->RecoHadEnNue, 0.5)*sr->RecoHadEnNue; +// sr->HadEVisReco_FD+= scale*pow(sr->HadEVisReco_FD, 0.5)*sr->HadEVisReco_FD; +// if ( !(sr->isCC==1 && abs(sr->nuPDG) == 14) ) { +// sr->Ev_reco_nue += scale*pow(sr->RecoLepEnNue, 0.5)*sr->RecoLepEnNue; +// sr->EVisReco_nue += scale*pow(sr->RecoLepEnNue, 0.5)*sr->RecoLepEnNue; +// sr->RecoLepEnNue += scale*pow(sr->RecoLepEnNue, 0.5)*sr->RecoLepEnNue; +// } +// } +// } +// +// const UncorrFDTotSqrt kUncorrFDTotSqrt; +// +// void UncorrFDTotInvSqrt::Shift(double sigma, +// caf::SRProxy* sr, double& weight) const { +// +// if (sr->isFD) { +// if (sr->RecoHadEnNue < 0.) sr->RecoHadEnNue = 0.; +// const double scale = .02 * sigma; +// sr->Ev_reco_numu += sr->RecoHadEnNumu*scale*pow(sr->RecoHadEnNumu+0.1, -0.5); +// sr->Ev_reco_nue += sr->RecoHadEnNue*scale*pow(sr->RecoHadEnNue+0.1, -0.5); +// sr->EVisReco_numu += sr->HadEVisReco_FD*scale*pow(sr->HadEVisReco_FD+0.1, -0.5); +// sr->RecoHadEnNumu += sr->RecoHadEnNumu*scale*pow(sr->RecoHadEnNumu+0.1, -0.5); +// sr->RecoHadEnNue += sr->RecoHadEnNue*scale*pow(sr->RecoHadEnNue+0.1, -0.5); +// sr->HadEVisReco_FD+= sr->HadEVisReco_FD*scale*pow(sr->HadEVisReco_FD+0.1, -0.5); +// if ( !(sr->isCC==1 && abs(sr->nuPDG) == 14) ) { +// sr->Ev_reco_nue += sr->RecoLepEnNue * scale * pow(sr->RecoLepEnNue+0.1, -0.5); +// sr->EVisReco_nue += sr->RecoLepEnNue * scale * pow(sr->RecoLepEnNue+0.1, -0.5); +// sr->RecoLepEnNue += sr->RecoLepEnNue * scale * pow(sr->RecoLepEnNue+0.1, -0.5); +// } +// } +// } +// +// const UncorrFDTotInvSqrt kUncorrFDTotInvSqrt; +// +// void UncorrFDHadSqrt::Shift(double sigma, +// caf::SRProxy* sr, double& weight) const { +// +// const double scale = .05 * sigma; +// if (sr->isFD) { +// if (sr->RecoHadEnNue < 0.) sr->RecoHadEnNue = 0.; +// if (sr->eRecoP < 0) sr->eRecoP = 0.; +// if (sr->eRecoPim < 0) sr->eRecoPim = 0.; +// if (sr->eRecoPip < 0) sr->eRecoPip = 0.; +// double sumE = sr->eRecoP + sr->eRecoPip + sr->eRecoPim; +// double sumEdep = sr->eDepP + sr->eDepPip + sr->eDepPim; +// sr->eRecoP += sr->eRecoP * scale * pow(sumE, 0.5); +// sr->eRecoPim += sr->eRecoPim * scale * pow(sumE, 0.5); +// sr->eRecoPip += sr->eRecoPip * scale * pow(sumE, 0.5); +// sr->Ev_reco_numu += sumE * scale * pow(sumE, 0.5); +// sr->Ev_reco_nue += sumE * scale * pow(sumE, 0.5); +// sr->EVisReco_numu+= sumEdep * scale * pow(sumEdep, 0.5); +// sr->EVisReco_numu+= sumEdep * scale * pow(sumEdep, 0.5); +// sr->RecoHadEnNumu += sumE * scale * pow(sumE, 0.5); +// sr->RecoHadEnNue += sumE * scale * pow(sumE, 0.5); +// sr->HadEVisReco_FD+= sumEdep * scale * pow(sumEdep, 0.5); +// } +// } +// +// const UncorrFDHadSqrt kUncorrFDHadSqrt; +// +// void UncorrFDHadInvSqrt::Shift(double sigma, +// caf::SRProxy* sr, double& weight) const { +// +// const double scale = .05 * sigma; +// if (sr->isFD) { +// if (sr->RecoHadEnNue < 0.) sr->RecoHadEnNue = 0.; +// if (sr->eRecoP < 0) sr->eRecoP = 0.; +// if (sr->eRecoPim < 0) sr->eRecoPim = 0.; +// if (sr->eRecoPip < 0) sr->eRecoPip = 0.; +// double sumE = sr->eRecoP + sr->eRecoPip + sr->eRecoPim; +// double sumEdep = sr->eDepP + sr->eDepPip + sr->eDepPim; +// sr->Ev_reco_numu += sumE * scale * pow(sumE+0.1, -0.5); +// sr->Ev_reco_nue += sumE * scale * pow(sumE+0.1, -0.5); +// sr->EVisReco_numu+= sumEdep * scale * pow(sumEdep+0.1, -0.5); +// sr->EVisReco_nue+= sumEdep * scale * pow(sumEdep+0.1, -0.5); +// sr->eRecoP += sr->eRecoP * scale * pow(sumE+0.1, -0.5); +// sr->eRecoPim += sr->eRecoPim * scale * pow(sumE+0.1, -0.5); +// sr->eRecoPip += sr->eRecoPip * scale * pow(sumE+0.1, -0.5); +// sr->RecoHadEnNumu += sumE * scale * pow(sumE+0.1, -0.5); +// sr->RecoHadEnNue += sumE * scale * pow(sumE+0.1, -0.5); +// sr->HadEVisReco_FD+= sumEdep * scale * pow(sumEdep+0.1, -0.5); +// } +// } +// +// const UncorrFDHadInvSqrt kUncorrFDHadInvSqrt; +// +// void UncorrFDMuSqrt::Shift(double sigma, +// caf::SRProxy* sr, double& weight) const { +// +// if (sr->isFD && sr->isCC==1 && abs(sr->nuPDG)==14) { +// const double scale = .005 * sigma; +// sr->Ev_reco_numu += sr->RecoLepEnNumu * pow(sr->RecoLepEnNumu, 0.5) * scale; +// sr->EVisReco_numu += sr->RecoLepEnNumu * pow(sr->RecoLepEnNumu, 0.5) * scale; +// sr->RecoLepEnNumu += sr->RecoLepEnNumu * pow(sr->RecoLepEnNumu, 0.5) * scale; +// } +// } +// +// const UncorrFDMuSqrt kUncorrFDMuSqrt; +// +// void UncorrFDMuInvSqrt::Shift(double sigma, +// caf::SRProxy* sr, double& weight) const { +// +// if (sr->isFD && sr->isCC==1 && abs(sr->nuPDG)==14) { +// const double scale = .02 * sigma; +// sr->Ev_reco_numu += sr->RecoLepEnNumu * scale * pow(sr->RecoLepEnNumu+0.1, -0.5); +// sr->EVisReco_numu += sr->RecoLepEnNumu * scale * pow(sr->RecoLepEnNumu+0.1, -0.5); +// sr->RecoLepEnNumu += sr->RecoLepEnNumu * scale * pow(sr->RecoLepEnNumu+0.1, -0.5); +// } +// } +// +// const UncorrFDMuInvSqrt kUncorrFDMuInvSqrt; +// +// void UncorrFDNSqrt::Shift(double sigma, +// caf::SRProxy* sr, double& weight) const { +// +// const double scale = .3 * sigma; +// if (sr->isFD) { +// if (sr->eRecoN < 0.) { sr->eRecoN = 0.; } +// sr->Ev_reco_numu += sr->eRecoN * pow(sr->eRecoN, 0.5) * scale; +// sr->Ev_reco_nue += sr->eRecoN * pow(sr->eRecoN, 0.5) * scale; +// sr->RecoHadEnNumu += sr->eRecoN * pow(sr->eRecoN, 0.5) * scale; +// sr->RecoHadEnNue += sr->eRecoN * pow(sr->eRecoN, 0.5) * scale; +// } +// } +// +// const UncorrFDNSqrt kUncorrFDNSqrt; +// +// void UncorrFDNInvSqrt::Shift(double sigma, +// caf::SRProxy* sr, double& weight) const { +// +// const double scale = .3 * sigma; +// if (sr->isFD) { +// if (sr->eRecoN < 0.) { sr->eRecoN = 0.; } +// sr->Ev_reco_numu += sr->eRecoN * scale * pow(sr->eRecoN+0.1, -0.5); +// sr->Ev_reco_nue += sr->eRecoN * scale * pow(sr->eRecoN+0.1, -0.5); +// sr->RecoHadEnNumu += sr->eRecoN * scale * pow(sr->eRecoN+0.1, -0.5); +// sr->RecoHadEnNue += sr->eRecoN * scale * pow(sr->eRecoN+0.1, -0.5); +// } +// } +// +// const UncorrFDNInvSqrt kUncorrFDNInvSqrt; +// +// void UncorrFDEMSqrt::Shift(double sigma, +// caf::SRProxy* sr, double& weight) const { +// +// const double scale = .025 * sigma; +// if (sr->isFD) { +// if (sr->RecoHadEnNue < 0.) sr->RecoHadEnNue = 0.; +// if (sr->eRecoPi0 < 0) sr->eRecoPi0 = 0.; +// sr->Ev_reco_numu += sr->eRecoPi0 * pow(sr->eRecoPi0, 0.5) * scale; +// sr->Ev_reco_nue += sr->eRecoPi0 * pow(sr->eRecoPi0, 0.5) * scale; +// sr->EVisReco_numu+= sr->eDepPi0 * pow(sr->eDepPi0, 0.5) * scale; +// sr->EVisReco_nue += sr->eDepPi0 * pow(sr->eDepPi0, 0.5) * scale; +// sr->RecoHadEnNumu += sr->eRecoPi0 * pow(sr->eRecoPi0, 0.5) * scale; +// sr->RecoHadEnNue += sr->eRecoPi0 * pow(sr->eRecoPi0, 0.5) * scale; +// sr->HadEVisReco_FD+= sr->eDepPi0 * pow(sr->eDepPi0, 0.5) * scale; +// sr->eRecoPi0 += sr->eRecoPi0 * pow(sr->eRecoPi0, 0.5) * scale; +// if (sr->eRecoPi0 < 0) sr->eRecoPi0 = 0.; +// if (sr->isCC==1 && abs(sr->nuPDG)==12) { +// sr->Ev_reco_nue += sr->RecoLepEnNue*pow(sr->RecoLepEnNue, 0.5)*scale; +// sr->EVisReco_nue += sr->RecoLepEnNue*pow(sr->RecoLepEnNue, 0.5)*scale; +// sr->RecoLepEnNue += sr->RecoLepEnNue*pow(sr->RecoLepEnNue, 0.5)*scale; +// } +// } +// } +// +// const UncorrFDEMSqrt kUncorrFDEMSqrt; +// +// +// void UncorrFDEMInvSqrt::Shift(double sigma, +// caf::SRProxy* sr, double& weight) const { +// +// const double scale = .025 * sigma; +// if (sr->isFD) { +// if (sr->RecoHadEnNue < 0.) sr->RecoHadEnNue = 0.; +// if (sr->eRecoPi0 < 0) sr->eRecoPi0 = 0.; +// sr->Ev_reco_numu += sr->eRecoPi0 * scale * pow(sr->eRecoPi0+0.1, -0.5); +// sr->Ev_reco_nue += sr->eRecoPi0 * scale * pow(sr->eRecoPi0+0.1, -0.5); +// sr->EVisReco_numu+= sr->eDepPi0 * scale * pow(sr->eDepPi0+0.1, -0.5); +// sr->EVisReco_nue += sr->eDepPi0 * scale * pow(sr->eDepPi0+0.1, -0.5); +// sr->RecoHadEnNumu += sr->eRecoPi0 * scale * pow(sr->eRecoPi0+0.1, -0.5); +// sr->RecoHadEnNue += sr->eRecoPi0 * scale * pow(sr->eRecoPi0+0.1, -0.5); +// sr->HadEVisReco_FD+= sr->eDepPi0 * scale * pow(sr->eDepPi0+0.1, -0.5); +// sr->eRecoPi0 += sr->eRecoPi0 * scale * pow(sr->eRecoPi0+0.1, -0.5); +// if (sr->isCC==1 && abs(sr->nuPDG)==12) { +// sr->Ev_reco_nue += sr->RecoLepEnNue * scale * pow(sr->RecoLepEnNue+0.1, -0.5); +// sr->EVisReco_nue += sr->RecoLepEnNue * scale * pow(sr->RecoLepEnNue+0.1, -0.5); +// sr->RecoLepEnNue += sr->RecoLepEnNue * scale * pow(sr->RecoLepEnNue+0.1, -0.5); +// } +// } +// } +// +// const UncorrFDEMInvSqrt kUncorrFDEMInvSqrt; +// +// void EScaleMuLArFD::Shift(double sigma, +// caf::SRProxy* sr, double& weight) const { +// +// const double scale = .02 * sigma; +// // Checks if FD and select only CC muon neutrino events +// if(sr->isFD && abs(sr->nuPDG) == 14 && sr->isCC == 1){ +// sr->Ev_reco_numu += sr->RecoLepEnNumu * scale; +// sr->EVisReco_numu += sr->RecoLepEnNumu * scale; +// sr->RecoLepEnNumu *= 1. + scale; +// } +// } +// +// const EScaleMuLArFD kEScaleMuLArFD; +// +// void ChargedHadUncorrFD::Shift(double sigma, +// caf::SRProxy* sr, double& weight) const { +// +// const double scale = .05 * sigma; +// if(sr->isFD) { +// if (sr->RecoHadEnNue < 0.) sr->RecoHadEnNue = 0.; +// if (sr->eRecoP < 0) sr->eRecoP = 0.; +// if (sr->eRecoPim < 0) sr->eRecoPim = 0.; +// if (sr->eRecoPip < 0) sr->eRecoPip = 0.; +// const double sumE = sr->eRecoP + sr->eRecoPim + sr->eRecoPip; +// const double sumEdep = sr->eDepP + sr->eDepPip + sr->eDepPim; +// sr->eRecoP += sr->eRecoP * scale; +// sr->eRecoPim += sr->eRecoPim * scale; +// sr->eRecoPip += sr->eRecoPip * scale; +// sr->Ev_reco_numu += sumE * scale; +// sr->Ev_reco_nue += sumE * scale; +// sr->EVisReco_numu += sumEdep * scale; +// sr->EVisReco_nue += sumEdep * scale; +// sr->RecoHadEnNumu += sumE * scale; +// sr->RecoHadEnNue += sumE * scale; +// sr->HadEVisReco_FD += sumEdep * scale; +// } +// } +// +// const ChargedHadUncorrFD kChargedHadUncorrFD; +// +// void NUncorrFD::Shift(double sigma, +// caf::SRProxy* sr, double& weight) const { +// +// const double scale = .20 * sigma; +// if(sr->isFD) { +// if (sr->RecoHadEnNue < 0.) sr->RecoHadEnNue = 0.; +// if (sr->eRecoN < 0.) sr->eRecoN = 0.; +// sr->Ev_reco_numu += sr->eRecoN * scale; +// sr->Ev_reco_nue += sr->eRecoN * scale; +// sr->RecoHadEnNumu += sr->eRecoN * scale; +// sr->RecoHadEnNue += sr->eRecoN * scale; +// sr->eRecoN += sr->eRecoN * scale; +// } +// } +// +// const NUncorrFD kNUncorrFD; +// +// void EMUncorrFD::Shift(double sigma, +// caf::SRProxy* sr, double& weight) const { +// +// const double scale = 0.025 * sigma; +// if (sr->isFD) { +// if (sr->RecoHadEnNue < 0.) sr->RecoHadEnNue = 0.; +// if (sr->eRecoPi0 < 0.) sr->eRecoPi0 = 0.; +// sr->Ev_reco_nue += sr->eRecoPi0 * scale; +// sr->Ev_reco_numu += sr->eRecoPi0 * scale; +// sr->EVisReco_numu += sr->eDepPi0 * scale; +// sr->EVisReco_nue += sr->eDepPi0 * scale; +// sr->RecoHadEnNue += sr->eRecoPi0 * scale; +// sr->RecoHadEnNumu += sr->eRecoPi0 * scale; +// sr->HadEVisReco_FD += sr->eDepPi0 * scale; +// sr->eRecoPi0 += sr->eRecoPi0 * scale; +// if (sr->isCC && abs(sr->nuPDG) == 12) { +// sr->Ev_reco_nue += sr->RecoLepEnNue * scale; +// sr->EVisReco_nue += sr->RecoLepEnNue * scale; +// sr->RecoLepEnNue += sr->RecoLepEnNue * scale; +// } +// } +// } +// +// const EMUncorrFD kEMUncorrFD; +// +// void MuonResFD::Shift(double sigma, +// caf::SRProxy* sr, double& weight) const { +// +// const double scale = .02*sigma; +// // FD charged current numus only +// if (sr->isFD && sr->isCC && abs(sr->nuPDG)==14) { +// sr->Ev_reco_numu += (sr->LepE - sr->RecoLepEnNumu) * scale; +// sr->EVisReco_numu += (sr->LepE - sr->RecoLepEnNumu) * scale; +// sr->RecoLepEnNumu += (sr->LepE - sr->RecoLepEnNumu) * scale; +// } +// } +// +// const MuonResFD kMuonResFD; +// +// void EMResFD::Shift(double sigma, +// caf::SRProxy* sr, double& weight) const { +// +// const double scale = .02*sigma; +// if (sr->isFD){ +// if (sr->RecoHadEnNue < 0.) sr->RecoHadEnNue = 0.; +// if (sr->eRecoPi0 < 0.) sr->eRecoPi0 = 0.; +// sr->Ev_reco_nue += (sr->ePi0 - sr->eRecoPi0) * scale; +// sr->Ev_reco_numu += (sr->ePi0 - sr->eRecoPi0) * scale; +// sr->EVisReco_nue += (sr->ePi0 - sr->eDepPi0) * scale; +// sr->EVisReco_numu += (sr->ePi0 - sr->eDepPi0) * scale; +// sr->RecoHadEnNumu += (sr->ePi0 - sr->eRecoPi0) * scale; +// sr->RecoHadEnNue += (sr->ePi0 - sr->eRecoPi0) * scale; +// sr->HadEVisReco_FD+= (sr->ePi0 - sr->eDepPi0) * scale; +// sr->eRecoPi0 += (sr->ePi0 - sr->eRecoPi0) * scale; +// if (sr->isCC && abs(sr->nuPDG)==12) { +// sr->Ev_reco_nue += (sr->LepE - sr->RecoLepEnNue) * scale; +// sr->EVisReco_nue += (sr->LepE - sr->RecoLepEnNue) * scale; +// sr->RecoLepEnNue += (sr->LepE - sr->RecoLepEnNue) * scale; +// } +// } +// } +// +// const EMResFD kEMResFD; +// +// void ChargedHadResFD::Shift(double sigma, +// caf::SRProxy* sr, double& weight) const { +// +// const double scale = .02*sigma; +// if (sr->isFD) { +// if (sr->RecoHadEnNue < 0.) sr->RecoHadEnNue = 0.; +// if (sr->eRecoP < 0.) sr->eRecoP = 0.; +// if (sr->eRecoPip < 0.) sr->eRecoPip = 0.; +// if (sr->eRecoPim < 0.) sr->eRecoPim = 0.; +// const double trueSum = sr->ePip + sr->ePim + sr->eP; +// const double recoSum = sr->eRecoPip + sr->eRecoPim + sr->eRecoP; +// const double depSum = sr->eDepP + sr->eDepPip + sr->eDepPim; +// sr->Ev_reco_nue += (trueSum - recoSum) * scale; +// sr->Ev_reco_numu += (trueSum - recoSum) * scale; +// sr->EVisReco_nue += (trueSum - depSum) * scale; +// sr->EVisReco_numu += (trueSum - depSum) * scale; +// sr->RecoHadEnNue += (trueSum - recoSum) * scale; +// sr->RecoHadEnNumu += (trueSum - recoSum) * scale; +// sr->HadEVisReco_FD+= (trueSum - depSum) * scale; +// } +// } +// +// const ChargedHadResFD kChargedHadResFD; +// +// void NResFD::Shift(double sigma, +// caf::SRProxy* sr, double& weight) const { +// +// const double scale = .1*sigma; +// // FD charged current numus only +// if (sr->isFD) { +// if (sr->RecoHadEnNue < 0.) sr->RecoHadEnNue = 0.; +// if (sr->eRecoN < 0.) sr->eRecoN = 0.; +// sr->Ev_reco_nue += (sr->eN - sr->eRecoN) * scale; +// sr->Ev_reco_numu += (sr->eN - sr->eRecoN) * scale; +// sr->RecoHadEnNue += (sr->eN - sr->eRecoN) * scale; +// sr->RecoHadEnNumu += (sr->eN - sr->eRecoN) * scale; +// sr->eRecoN += (sr->eN - sr->eRecoN) * scale; +// } +// } +// +// const NResFD kNResFD; +// +// std::vector GetEnergySysts() { +// +// std::vector vec; +// vec.push_back(&kEnergyScaleFD); +// vec.push_back(&kUncorrFDTotSqrt);//v4 +// vec.push_back(&kUncorrFDTotInvSqrt);//v4 +// vec.push_back(&kUncorrFDHadSqrt);//v4 +// vec.push_back(&kUncorrFDHadInvSqrt);//v4 +// vec.push_back(&kUncorrFDMuSqrt);//v4 +// vec.push_back(&kUncorrFDMuInvSqrt);//v4 +// vec.push_back(&kUncorrFDNSqrt);//v4 +// vec.push_back(&kUncorrFDNInvSqrt);//v4 +// vec.push_back(&kUncorrFDEMSqrt);//v4 +// vec.push_back(&kUncorrFDEMInvSqrt);//v4 +// vec.push_back(&kEScaleMuLArFD); +// vec.push_back(&kChargedHadUncorrFD);//v4 +// vec.push_back(&kNUncorrFD); +// vec.push_back(&kEMUncorrFD); +// vec.push_back(&kMuonResFD); +// vec.push_back(&kEMResFD); +// vec.push_back(&kChargedHadResFD); +// vec.push_back(&kNResFD); +// +// return vec; +// } +// +// std::vector FilterOutFDSysts(std::vector systs) { +// std::vector outs; +// std::vector fsysts = GetEnergySysts(); +// +// for (auto syst : systs) { +// if (std::find(fsysts.begin(), fsysts.end(), syst) == fsysts.end()) { +// outs.emplace_back(syst); +// } +// } +// return outs; +// } +// } // namespace ana diff --git a/CAFAna/Systs/EnergySysts.h b/CAFAna/Systs/EnergySysts.h index e434bc44..92add23d 100644 --- a/CAFAna/Systs/EnergySysts.h +++ b/CAFAna/Systs/EnergySysts.h @@ -12,222 +12,222 @@ namespace ana { - // FD global energy scale syst - // Don't shift muon energies with this - class EnergyScaleFD: public ISyst { - public: - EnergyScaleFD() : ISyst("EnergyScaleFD", "Global FD Energy Scale Syst") {} - void Shift(double sigma, - caf::SRProxy* sr, double& weight) const override; - }; - - extern const EnergyScaleFD kEnergyScaleFD; - - // Total energy scale shape systematics - class UncorrFDTotSqrt: public ISyst { - public: - UncorrFDTotSqrt() : ISyst("UncorrFDTotSqrt", "Uncorrelated FD Sqrt Total Syst") {} - void Shift(double sigma, - caf::SRProxy* sr, double& weight) const override; - }; - - extern const UncorrFDTotSqrt kUncorrFDTotSqrt; - - class UncorrFDTotInvSqrt: public ISyst { - public: - UncorrFDTotInvSqrt() : ISyst("UncorrFDTotInvSqrt", "Uncorrelated FD Inverse Sqrt Total Syst") {} - void Shift(double sigma, - caf::SRProxy* sr, double& weight) const override; - }; - - extern const UncorrFDTotInvSqrt kUncorrFDTotInvSqrt; - - //------------------------------------------------------------------------------------------------ - - // FD three parameter systematics to match ND ones - // Slope energy scale systematics - // Charged hadrons - class UncorrFDHadSqrt: public ISyst { - public: - UncorrFDHadSqrt() : ISyst("UncorrFDHadSqrt", "Uncorrelated FD Sqrt Hadron Syst") {} - void Shift(double sigma, - caf::SRProxy* sr, double& weight) const override; - }; - - extern const UncorrFDHadSqrt kUncorrFDHadSqrt; - - class UncorrFDHadInvSqrt: public ISyst { - public: - UncorrFDHadInvSqrt() : ISyst("UncorrFDHadInvSqrt", "Uncorrelated FD Inv Sqrt Hadron Syst") {} - void Shift(double sigma, - caf::SRProxy* sr, double& weight) const override; - }; - - extern const UncorrFDHadInvSqrt kUncorrFDHadInvSqrt; - - //------------------------------------------------------------------------------------ - - // Muons - class UncorrFDMuSqrt: public ISyst { - public: - UncorrFDMuSqrt() : ISyst("UncorrFDMuSqrt", "Uncorrelated FD Sqrt Muon Syst") {} - void Shift(double sigma, - caf::SRProxy* sr, double& weight) const override; - }; - - extern const UncorrFDMuSqrt kUncorrFDMuSqrt; - - class UncorrFDMuInvSqrt: public ISyst { - public: - UncorrFDMuInvSqrt() : ISyst("UncorrFDMuInvSqrt", "Uncorrelated FD Inv Sqrt Muon Syst") {} - void Shift(double sigma, - caf::SRProxy* sr, double& weight) const override; - }; - - extern const UncorrFDMuInvSqrt kUncorrFDMuInvSqrt; - - //------------------------------------------------------------------------------------ - - //Neutrons - - class UncorrFDNSqrt: public ISyst { - public: - UncorrFDNSqrt() : ISyst("UncorrFDNSqrt", "Uncorrelated FD Sqrt Neutron Syst") {} - void Shift(double sigma, - caf::SRProxy* sr, double& weight) const override; - }; - - extern const UncorrFDNSqrt kUncorrFDNSqrt; - - class UncorrFDNInvSqrt: public ISyst { - public: - UncorrFDNInvSqrt() : ISyst("UncorrFDNInvSqrt", "Uncorrelated FD Inv Sqrt Neutron Syst") {} - void Shift(double sigma, - caf::SRProxy* sr, double& weight) const override; - }; - - extern const UncorrFDNInvSqrt kUncorrFDNInvSqrt; - - //------------------------------------------------------------------------------------ - - // Electromagnetic - class UncorrFDEMSqrt: public ISyst { - public: - UncorrFDEMSqrt() : ISyst("UncorrFDEMSqrt", "Uncorrelated FD Sqrt EM Syst") {} - void Shift(double sigma, - caf::SRProxy* sr, double& weight) const override; - }; - - extern const UncorrFDEMSqrt kUncorrFDEMSqrt; - - class UncorrFDEMInvSqrt: public ISyst { - public: - UncorrFDEMInvSqrt() : ISyst("UncorrFDEMInvSqrt", "Uncorrelated FD Inv Sqrt EM Syst") {} - void Shift(double sigma, - caf::SRProxy* sr, double& weight) const override; - }; - - extern const UncorrFDEMInvSqrt kUncorrFDEMInvSqrt; - - // FD muon LAr systematic - // 2% on CC numu events - class EScaleMuLArFD: public ISyst { - public: - EScaleMuLArFD() : ISyst("EScaleMuLArFD", "Muon Energy Scale LAr Far Detector") {} - - void Shift(double sigma, - caf::SRProxy* sr, double& weight) const override; - }; - - extern const EScaleMuLArFD kEScaleMuLArFD; - - // 5% uncorrelated FD syst for charged hadrons - class ChargedHadUncorrFD: public ISyst { - public: - ChargedHadUncorrFD() : ISyst("ChargedHadUncorrFD", "Charged Hadron Uncorrelated FD Syst") {} - - void Shift(double sigma, - caf::SRProxy* sr, double& weight) const override; - }; - - extern const ChargedHadUncorrFD kChargedHadUncorrFD; - - // Neutron energy scale - // 20% on visible energy - class NUncorrFD: public ISyst { - public: - NUncorrFD() : ISyst("NUncorrFD", "Neutron Energy Scale FD") {} - - void Shift(double sigma, - caf::SRProxy* sr, double& weight) const override; - }; - - extern const NUncorrFD kNUncorrFD; - - // FD systematic correlated for pi0s and electrons - // 2.5% on reco energy for electrons and pi0s - class EMUncorrFD: public ISyst { - public: - EMUncorrFD() : ISyst("EMUncorrFD", "Electromagnetic shower FD Syst") {} - void Shift(double sigma, - caf::SRProxy* sr, double& weight) const override; - }; - - extern const EMUncorrFD kEMUncorrFD; - - //////////////////////////////////////////////////////////////////////////////////////////////// - // Resolution systematics - // Muon energy resolution - class MuonResFD: public ISyst { - public: - MuonResFD() : ISyst("MuonResFD", "Muon Far Detector Resolution Syst") {} - void Shift(double sigma, - caf::SRProxy* sr, double& weight) const override; - }; - - extern const MuonResFD kMuonResFD; - - // Electron/pi0 energy resolution - class EMResFD: public ISyst { - public: - EMResFD() : ISyst("EMResFD", "EM shower Far Detector Resolution Syst") {} - void Shift(double sigma, - caf::SRProxy* sr, double& weight) const override; - }; - - extern const EMResFD kEMResFD; - - // Charged hadron energy resolution - class ChargedHadResFD: public ISyst { - public: - ChargedHadResFD() : ISyst("ChargedHadResFD", "Charged Hadron Far Detector Resolution Syst") {} - void Shift(double sigma, - caf::SRProxy* sr, double& weight) const override; - }; - - extern const ChargedHadResFD kChargedHadResFD; - - // Neutron energy resolution - class NResFD: public ISyst { - public: - NResFD() : ISyst("NResFD", "Neutron Far Detector Resolution Syst") {} - void Shift(double sigma, - caf::SRProxy* sr, double& weight) const override; - }; - - extern const NResFD kNResFD; - -/* - /// why have a structure (yet) if not needed - /// make things simpler - // Vector of energy scale systematics - struct EnergySystVector: public std::vector - { - }; - EnergySystVector GetEnergySysts(); -*/ - - std::vector GetEnergySysts(); - - std::vector FilterOutFDSysts(std::vector systs); +// // FD global energy scale syst +// // Don't shift muon energies with this +// class EnergyScaleFD: public ISyst { +// public: +// EnergyScaleFD() : ISyst("EnergyScaleFD", "Global FD Energy Scale Syst") {} +// void Shift(double sigma, +// caf::SRProxy* sr, double& weight) const override; +// }; +// +// extern const EnergyScaleFD kEnergyScaleFD; +// +// // Total energy scale shape systematics +// class UncorrFDTotSqrt: public ISyst { +// public: +// UncorrFDTotSqrt() : ISyst("UncorrFDTotSqrt", "Uncorrelated FD Sqrt Total Syst") {} +// void Shift(double sigma, +// caf::SRProxy* sr, double& weight) const override; +// }; +// +// extern const UncorrFDTotSqrt kUncorrFDTotSqrt; +// +// class UncorrFDTotInvSqrt: public ISyst { +// public: +// UncorrFDTotInvSqrt() : ISyst("UncorrFDTotInvSqrt", "Uncorrelated FD Inverse Sqrt Total Syst") {} +// void Shift(double sigma, +// caf::SRProxy* sr, double& weight) const override; +// }; +// +// extern const UncorrFDTotInvSqrt kUncorrFDTotInvSqrt; +// +// //------------------------------------------------------------------------------------------------ +// +// // FD three parameter systematics to match ND ones +// // Slope energy scale systematics +// // Charged hadrons +// class UncorrFDHadSqrt: public ISyst { +// public: +// UncorrFDHadSqrt() : ISyst("UncorrFDHadSqrt", "Uncorrelated FD Sqrt Hadron Syst") {} +// void Shift(double sigma, +// caf::SRProxy* sr, double& weight) const override; +// }; +// +// extern const UncorrFDHadSqrt kUncorrFDHadSqrt; +// +// class UncorrFDHadInvSqrt: public ISyst { +// public: +// UncorrFDHadInvSqrt() : ISyst("UncorrFDHadInvSqrt", "Uncorrelated FD Inv Sqrt Hadron Syst") {} +// void Shift(double sigma, +// caf::SRProxy* sr, double& weight) const override; +// }; +// +// extern const UncorrFDHadInvSqrt kUncorrFDHadInvSqrt; +// +// //------------------------------------------------------------------------------------ +// +// // Muons +// class UncorrFDMuSqrt: public ISyst { +// public: +// UncorrFDMuSqrt() : ISyst("UncorrFDMuSqrt", "Uncorrelated FD Sqrt Muon Syst") {} +// void Shift(double sigma, +// caf::SRProxy* sr, double& weight) const override; +// }; +// +// extern const UncorrFDMuSqrt kUncorrFDMuSqrt; +// +// class UncorrFDMuInvSqrt: public ISyst { +// public: +// UncorrFDMuInvSqrt() : ISyst("UncorrFDMuInvSqrt", "Uncorrelated FD Inv Sqrt Muon Syst") {} +// void Shift(double sigma, +// caf::SRProxy* sr, double& weight) const override; +// }; +// +// extern const UncorrFDMuInvSqrt kUncorrFDMuInvSqrt; +// +// //------------------------------------------------------------------------------------ +// +// //Neutrons +// +// class UncorrFDNSqrt: public ISyst { +// public: +// UncorrFDNSqrt() : ISyst("UncorrFDNSqrt", "Uncorrelated FD Sqrt Neutron Syst") {} +// void Shift(double sigma, +// caf::SRProxy* sr, double& weight) const override; +// }; +// +// extern const UncorrFDNSqrt kUncorrFDNSqrt; +// +// class UncorrFDNInvSqrt: public ISyst { +// public: +// UncorrFDNInvSqrt() : ISyst("UncorrFDNInvSqrt", "Uncorrelated FD Inv Sqrt Neutron Syst") {} +// void Shift(double sigma, +// caf::SRProxy* sr, double& weight) const override; +// }; +// +// extern const UncorrFDNInvSqrt kUncorrFDNInvSqrt; +// +// //------------------------------------------------------------------------------------ +// +// // Electromagnetic +// class UncorrFDEMSqrt: public ISyst { +// public: +// UncorrFDEMSqrt() : ISyst("UncorrFDEMSqrt", "Uncorrelated FD Sqrt EM Syst") {} +// void Shift(double sigma, +// caf::SRProxy* sr, double& weight) const override; +// }; +// +// extern const UncorrFDEMSqrt kUncorrFDEMSqrt; +// +// class UncorrFDEMInvSqrt: public ISyst { +// public: +// UncorrFDEMInvSqrt() : ISyst("UncorrFDEMInvSqrt", "Uncorrelated FD Inv Sqrt EM Syst") {} +// void Shift(double sigma, +// caf::SRProxy* sr, double& weight) const override; +// }; +// +// extern const UncorrFDEMInvSqrt kUncorrFDEMInvSqrt; +// +// // FD muon LAr systematic +// // 2% on CC numu events +// class EScaleMuLArFD: public ISyst { +// public: +// EScaleMuLArFD() : ISyst("EScaleMuLArFD", "Muon Energy Scale LAr Far Detector") {} +// +// void Shift(double sigma, +// caf::SRProxy* sr, double& weight) const override; +// }; +// +// extern const EScaleMuLArFD kEScaleMuLArFD; +// +// // 5% uncorrelated FD syst for charged hadrons +// class ChargedHadUncorrFD: public ISyst { +// public: +// ChargedHadUncorrFD() : ISyst("ChargedHadUncorrFD", "Charged Hadron Uncorrelated FD Syst") {} +// +// void Shift(double sigma, +// caf::SRProxy* sr, double& weight) const override; +// }; +// +// extern const ChargedHadUncorrFD kChargedHadUncorrFD; +// +// // Neutron energy scale +// // 20% on visible energy +// class NUncorrFD: public ISyst { +// public: +// NUncorrFD() : ISyst("NUncorrFD", "Neutron Energy Scale FD") {} +// +// void Shift(double sigma, +// caf::SRProxy* sr, double& weight) const override; +// }; +// +// extern const NUncorrFD kNUncorrFD; +// +// // FD systematic correlated for pi0s and electrons +// // 2.5% on reco energy for electrons and pi0s +// class EMUncorrFD: public ISyst { +// public: +// EMUncorrFD() : ISyst("EMUncorrFD", "Electromagnetic shower FD Syst") {} +// void Shift(double sigma, +// caf::SRProxy* sr, double& weight) const override; +// }; +// +// extern const EMUncorrFD kEMUncorrFD; +// +// //////////////////////////////////////////////////////////////////////////////////////////////// +// // Resolution systematics +// // Muon energy resolution +// class MuonResFD: public ISyst { +// public: +// MuonResFD() : ISyst("MuonResFD", "Muon Far Detector Resolution Syst") {} +// void Shift(double sigma, +// caf::SRProxy* sr, double& weight) const override; +// }; +// +// extern const MuonResFD kMuonResFD; +// +// // Electron/pi0 energy resolution +// class EMResFD: public ISyst { +// public: +// EMResFD() : ISyst("EMResFD", "EM shower Far Detector Resolution Syst") {} +// void Shift(double sigma, +// caf::SRProxy* sr, double& weight) const override; +// }; +// +// extern const EMResFD kEMResFD; +// +// // Charged hadron energy resolution +// class ChargedHadResFD: public ISyst { +// public: +// ChargedHadResFD() : ISyst("ChargedHadResFD", "Charged Hadron Far Detector Resolution Syst") {} +// void Shift(double sigma, +// caf::SRProxy* sr, double& weight) const override; +// }; +// +// extern const ChargedHadResFD kChargedHadResFD; +// +// // Neutron energy resolution +// class NResFD: public ISyst { +// public: +// NResFD() : ISyst("NResFD", "Neutron Far Detector Resolution Syst") {} +// void Shift(double sigma, +// caf::SRProxy* sr, double& weight) const override; +// }; +// +// extern const NResFD kNResFD; +// +///* +// /// why have a structure (yet) if not needed +// /// make things simpler +// // Vector of energy scale systematics +// struct EnergySystVector: public std::vector +// { +// }; +// EnergySystVector GetEnergySysts(); +//*/ +// +// std::vector GetEnergySysts(); +// +// std::vector FilterOutFDSysts(std::vector systs); } diff --git a/CAFAna/Systs/FDRecoSysts.cxx b/CAFAna/Systs/FDRecoSysts.cxx index 168c0d01..042ebf40 100644 --- a/CAFAna/Systs/FDRecoSysts.cxx +++ b/CAFAna/Systs/FDRecoSysts.cxx @@ -6,19 +6,19 @@ namespace ana { - const FDRecoNumuSyst kFDRecoNumuSyst; - const FDRecoNueSyst kFDRecoNueSyst; - const FVNumuFDSyst kFVNumuFDSyst; - const FVNueFDSyst kFVNueFDSyst; - - std::vector GetFDRecoSysts() - { - std::vector vec = {}; - vec.push_back(&kFDRecoNumuSyst); - vec.push_back(&kFDRecoNueSyst); - vec.push_back(&kFVNumuFDSyst); - vec.push_back(&kFVNueFDSyst); - return vec; - } +// const FDRecoNumuSyst kFDRecoNumuSyst; +// const FDRecoNueSyst kFDRecoNueSyst; +// const FVNumuFDSyst kFVNumuFDSyst; +// const FVNueFDSyst kFVNueFDSyst; +// +// std::vector GetFDRecoSysts() +// { +// std::vector vec = {}; +// vec.push_back(&kFDRecoNumuSyst); +// vec.push_back(&kFDRecoNueSyst); +// vec.push_back(&kFVNumuFDSyst); +// vec.push_back(&kFVNueFDSyst); +// return vec; +// } } diff --git a/CAFAna/Systs/FDRecoSysts.h b/CAFAna/Systs/FDRecoSysts.h index 85d044fe..6425f25b 100644 --- a/CAFAna/Systs/FDRecoSysts.h +++ b/CAFAna/Systs/FDRecoSysts.h @@ -16,136 +16,139 @@ namespace ana { - class FDRecoNumuSyst: public ISyst - { - public: - FDRecoNumuSyst() : ISyst("FDRecoNumuSyst", "Far Detector Numu Reconstruction Syst") {} - - void Shift(double sigma, - caf::SRProxy* sr, - double& weight) const override - { - // Load histograms if they have not been loaded already - if (!hist) { - TFile f((FindCAFAnaDir()+"/Systs/modelComp.root").c_str()); - assert(!f.IsZombie()); - hist = (TH2*)f.Get("hYratio_neutfhc_geniefhc"); - hist->SetDirectory(0); - assert(hist); - } - // Passes FD selection cut - if (sr->isFD && kPassFD_CVN_NUMU(sr)) { - int EBin = hist->GetXaxis()->FindBin(sr->Ev); - int VarBin = hist->GetYaxis()->FindBin(sr->Y); - double w = hist->GetBinContent(EBin, VarBin); - weight *= 1. + sigma * (1. - w) ; - } - } - - protected: - mutable TH2* hist; - }; - - extern const FDRecoNumuSyst kFDRecoNumuSyst; - - // Nue reco syst - class FDRecoNueSyst: public ISyst - { - public: - FDRecoNueSyst() : ISyst("FDRecoNueSyst", "Far Detector Nue Reconstruction Syst") {} - - void Shift(double sigma, - caf::SRProxy* sr, - double& weight) const override - { - // Load histograms if they have not been loaded already - if (!hist) { - TFile f((FindCAFAnaDir()+"/Systs/modelComp.root").c_str()); - assert(!f.IsZombie()); - hist = (TH2*)f.Get("hYratio_neutfhc_geniefhc"); - hist->SetDirectory(0); - assert(hist); - } - // Passes FD nue selection - if (sr->isFD && kPassFD_CVN_NUE(sr)) { - int EBin = hist->GetXaxis()->FindBin(sr->Ev); - int VarBin = hist->GetYaxis()->FindBin(sr->Y); - double w = hist->GetBinContent(EBin, VarBin); - weight *= 1. + sigma * (1. - w) ; - } - } - - protected: - mutable TH2* hist; - }; - - extern const FDRecoNueSyst kFDRecoNueSyst; - - // Fiducial volume normalization for nues - class FVNueFDSyst: public ISyst - { - public: - FVNueFDSyst() : ISyst("FVNueFD", "Far Detector Nue Fiducial Volume") {} - void Shift(double sigma, - caf::SRProxy* sr, - double& weight) const override - { - const double scale = 1. + 0.01 * sigma; - if (sr->isFD && kPassFD_CVN_NUE(sr)) { - weight *= scale; - } - } - }; - - extern const FVNueFDSyst kFVNueFDSyst; - - // Fiducial volume normalization for numus - class FVNumuFDSyst: public ISyst - { - public: - FVNumuFDSyst() : ISyst("FVNumuFD", "Far Detector Numu Fiducial Volume") {} - void Shift(double sigma, - caf::SRProxy* sr, - double& weight) const override - { - const double scale = 1. + 0.01 * sigma; - if (sr->isFD && kPassFD_CVN_NUMU(sr)) { - weight *= scale; - } - } - }; - - extern const FVNumuFDSyst kFVNumuFDSyst; - - // Fiducial volume normalization - // Correlated between nues and numus - class FVCorrFDSyst: public ISyst - { - public: - FVCorrFDSyst() : ISyst("FVCorrFD", "Far Detector Correlated Fiducial Volume") {} - void Shift(double sigma, - caf::SRProxy* sr, - double& weight) const override - { - const double scale = 1. + 0.01 * sigma; - if (sr->isFD && (kPassFD_CVN_NUMU(sr) || kPassFD_CVN_NUMU(sr))) { - weight *= scale; - } - } - }; - - extern const FVCorrFDSyst kFVCorrFDSyst; - - -/* - /// why have a structure (yet) if not needed - /// make things simpler - struct FDRecoSystVector: public std::vector - { - }; - FDRecoSystVector GetFDRecoSysts(); -*/ - - std::vector GetFDRecoSysts(); +// class FDRecoNumuSyst: public ISyst +// { +// public: +// FDRecoNumuSyst() : ISyst("FDRecoNumuSyst", "Far Detector Numu Reconstruction Syst") {} +// +// void Shift(double sigma, +// caf::SRProxy* sr, +// double& weight) const override +// { +// // Load histograms if they have not been loaded already +// if (!hist) { +// TFile f((FindCAFAnaDir()+"/Systs/modelComp.root").c_str()); +// assert(!f.IsZombie()); +// hist = (TH2*)f.Get("hYratio_neutfhc_geniefhc"); +// hist->SetDirectory(0); +// assert(hist); +// } +// // Passes FD selection cut +// if (sr->isFD && kPassFD_CVN_NUMU(sr)) { +// int EBin = hist->GetXaxis()->FindBin(sr->mc.nu[0].E);//Ev); +// int VarBin = hist->GetYaxis()->FindBin(sr->mc.nu[0].inelasticity);//Y); +// double w = hist->GetBinContent(EBin, VarBin); +// weight *= 1. + sigma * (1. - w) ; +// } +// } +// +// protected: +// mutable TH2* hist; +// }; +// +// extern const FDRecoNumuSyst kFDRecoNumuSyst; +// +// // Nue reco syst +// class FDRecoNueSyst: public ISyst +// { +// public: +// FDRecoNueSyst() : ISyst("FDRecoNueSyst", "Far Detector Nue Reconstruction Syst") {} +// +// void Shift(double sigma, +// caf::SRProxy* sr, +// double& weight) const override +// { +// // Load histograms if they have not been loaded already +// if (!hist) { +// TFile f((FindCAFAnaDir()+"/Systs/modelComp.root").c_str()); +// assert(!f.IsZombie()); +// hist = (TH2*)f.Get("hYratio_neutfhc_geniefhc"); +// hist->SetDirectory(0); +// assert(hist); +// } +// // Passes FD nue selection +// if (sr->isFD && kPassFD_CVN_NUE(sr)) { +// int EBin = hist->GetXaxis()->FindBin(sr->mc.nu[0].E);//Ev); +// int VarBin = hist->GetYaxis()->FindBin(sr->mc.nu[0].inelasticity);//Y); +// double w = hist->GetBinContent(EBin, VarBin); +// weight *= 1. + sigma * (1. - w) ; +// } +// } +// +// protected: +// mutable TH2* hist; +// }; +// +// extern const FDRecoNueSyst kFDRecoNueSyst; +// +// // Fiducial volume normalization for nues +// class FVNueFDSyst: public ISyst +// { +// public: +// FVNueFDSyst() : ISyst("FVNueFD", "Far Detector Nue Fiducial Volume") {} +// void Shift(double sigma, +// caf::SRProxy* sr, +// double& weight) const override +// { +// const double scale = 1. + 0.01 * sigma; +//// if (sr->isFD && kPassFD_CVN_NUE(sr)) { +//// weight *= scale; +//// } +// weight *= 1 + .05*sigma; +// } +// }; +// +// extern const FVNueFDSyst kFVNueFDSyst; +// +// // Fiducial volume normalization for numus +// class FVNumuFDSyst: public ISyst +// { +// public: +// FVNumuFDSyst() : ISyst("FVNumuFD", "Far Detector Numu Fiducial Volume") {} +// void Shift(double sigma, +// caf::SRProxy* sr, +// double& weight) const override +// { +// const double scale = 1. + 0.01 * sigma; +//// if (sr->isFD && kPassFD_CVN_NUMU(sr)) { +//// weight *= scale; +//// } +// weight *= 1 + .05*sigma; +// } +// }; +// +// extern const FVNumuFDSyst kFVNumuFDSyst; +// +// // Fiducial volume normalization +// // Correlated between nues and numus +// class FVCorrFDSyst: public ISyst +// { +// public: +// FVCorrFDSyst() : ISyst("FVCorrFD", "Far Detector Correlated Fiducial Volume") {} +// void Shift(double sigma, +// caf::SRProxy* sr, +// double& weight) const override +// { +// const double scale = 1. + 0.01 * sigma; +//// if (sr->isFD && (kPassFD_CVN_NUMU(sr) || kPassFD_CVN_NUMU(sr))) { +//// weight *= scale; +//// } +// weight *= 1 + .05*sigma; +// } +// }; +// +// extern const FVCorrFDSyst kFVCorrFDSyst; +// +// +///* +// /// why have a structure (yet) if not needed +// /// make things simpler +// struct FDRecoSystVector: public std::vector +// { +// }; +// FDRecoSystVector GetFDRecoSysts(); +//*/ +// +// std::vector GetFDRecoSysts(); } diff --git a/CAFAna/Systs/MissingProtonFakeData.h b/CAFAna/Systs/MissingProtonFakeData.h index d8aae91e..b9a8dd7f 100644 --- a/CAFAna/Systs/MissingProtonFakeData.h +++ b/CAFAna/Systs/MissingProtonFakeData.h @@ -13,101 +13,101 @@ #include #include #include - -class MissingProtonFakeDataGenerator : public ana::ISyst { -public: - virtual ~MissingProtonFakeDataGenerator(){}; - - std::vector bdt_reweighter; - - bool fDoWeight; - - void Shift(double sigma, caf::SRProxy *sr, - double &weight) const override { - - if (!sr->isCC) { - return; - } - - if (sigma != 1) { - return; - } - - if (sr->isFD) { - sr->eRec_FromDep -= EpFrac * sr->eDepP; - sr->EVisReco_numu -= EpFrac * sr->eDepP; - sr->EVisReco_nue -= EpFrac * sr->eDepP; - sr->VisTrue_NDFD -= EpFrac * sr->eP; - sr->HadEVisReco_FD -= EpFrac * sr->eDepP; - sr->HadE -= EpFrac * sr->eP; - } else { - sr->eRec_FromDep -= EpFrac * sr->eRecoP; - sr->EVisReco_ND -= EpFrac * sr->eRecoP; - sr->VisTrue_NDFD -= EpFrac * sr->eP; - sr->HadEVisReco_FD -= EpFrac *sr->eRecoP; - sr->HadE -= EpFrac * sr->eP; - } - - double eother = 0; - if (std::isnormal(sr->eOther)) { - eother = sr->eOther; - } - sr->eRecProxy = sr->LepE + (1.0 - EpFrac) * sr->eP + - sr->ePip + sr->ePim + sr->ePi0 + - 0.135 * sr->nipi0 + eother; - - if (!fDoWeight) { - return; - } - - union BDTReweighter::BDTReweighterFeature features[8]; - - features[5].fvalue = sr->Ev; // Etrue - features[6].fvalue = sr->eP; // True proton kinetic energy - features[7].fvalue = 1 - sr->LepE / sr->Ev; // ytrue - - for (int i = 0; i < 5; i++) - features[i].fvalue = 0; - - bool foundMode = true; - switch (sr->GENIE_ScatteringMode) { - case 1: - features[0].fvalue = 1.; - break; - case 3: - features[1].fvalue = 1.; - break; - case 4: - features[2].fvalue = 1.; - break; - case 5: - features[3].fvalue = 1.; - break; - case 10: - features[4].fvalue = 1.; - break; - default: - foundMode = false; - } - - if (foundMode) { - double wght_val = - bdt_reweighter[sr->nuPDG > 0 ? 0 : 1]->GetWeight(features, 1); - weight *= wght_val; - } - } - -public: - MissingProtonFakeDataGenerator(bool DoWeight = true, double epfrac = 0.2) - : ana::ISyst(DoWeight ? "MissingProtonFakeDataGenerator" - : "MissingProtonEnergyGenerator", - DoWeight ? "MissingProtonFakeDataGenerator" - : "MissingProtonEnergyGenerator", - false, 0, 1), - fDoWeight(DoWeight), EpFrac(epfrac) { - - bdt_reweighter.push_back(new MissingProtonFakeData_BDTRW_FHC()); - bdt_reweighter.push_back(new MissingProtonFakeData_BDTRW_RHC()); - } - double EpFrac; -}; +// +//class MissingProtonFakeDataGenerator : public ana::ISyst { +//public: +// virtual ~MissingProtonFakeDataGenerator(){}; +// +// std::vector bdt_reweighter; +// +// bool fDoWeight; +// +// void Shift(double sigma, caf::SRProxy *sr, +// double &weight) const override { +// +// if (!sr->isCC) { +// return; +// } +// +// if (sigma != 1) { +// return; +// } +// +// if (sr->isFD) { +// sr->eRec_FromDep -= EpFrac * sr->eDepP; +// sr->EVisReco_numu -= EpFrac * sr->eDepP; +// sr->EVisReco_nue -= EpFrac * sr->eDepP; +// sr->VisTrue_NDFD -= EpFrac * sr->eP; +// sr->HadEVisReco_FD -= EpFrac * sr->eDepP; +// sr->HadE -= EpFrac * sr->eP; +// } else { +// sr->eRec_FromDep -= EpFrac * sr->eRecoP; +// sr->EVisReco_ND -= EpFrac * sr->eRecoP; +// sr->VisTrue_NDFD -= EpFrac * sr->eP; +// sr->HadEVisReco_FD -= EpFrac *sr->eRecoP; +// sr->HadE -= EpFrac * sr->eP; +// } +// +// double eother = 0; +// if (std::isnormal(sr->eOther)) { +// eother = sr->eOther; +// } +// sr->eRecProxy = sr->LepE + (1.0 - EpFrac) * sr->eP + +// sr->ePip + sr->ePim + sr->ePi0 + +// 0.135 * sr->nipi0 + eother; +// +// if (!fDoWeight) { +// return; +// } +// +// union BDTReweighter::BDTReweighterFeature features[8]; +// +// features[5].fvalue = sr->Ev; // Etrue +// features[6].fvalue = sr->eP; // True proton kinetic energy +// features[7].fvalue = 1 - sr->LepE / sr->Ev; // ytrue +// +// for (int i = 0; i < 5; i++) +// features[i].fvalue = 0; +// +// bool foundMode = true; +// switch (sr->GENIE_ScatteringMode) { +// case 1: +// features[0].fvalue = 1.; +// break; +// case 3: +// features[1].fvalue = 1.; +// break; +// case 4: +// features[2].fvalue = 1.; +// break; +// case 5: +// features[3].fvalue = 1.; +// break; +// case 10: +// features[4].fvalue = 1.; +// break; +// default: +// foundMode = false; +// } +// +// if (foundMode) { +// double wght_val = +// bdt_reweighter[sr->nuPDG > 0 ? 0 : 1]->GetWeight(features, 1); +// weight *= wght_val; +// } +// } +// +//public: +// MissingProtonFakeDataGenerator(bool DoWeight = true, double epfrac = 0.2) +// : ana::ISyst(DoWeight ? "MissingProtonFakeDataGenerator" +// : "MissingProtonEnergyGenerator", +// DoWeight ? "MissingProtonFakeDataGenerator" +// : "MissingProtonEnergyGenerator", +// false, 0, 1), +// fDoWeight(DoWeight), EpFrac(epfrac) { +// +// bdt_reweighter.push_back(new MissingProtonFakeData_BDTRW_FHC()); +// bdt_reweighter.push_back(new MissingProtonFakeData_BDTRW_RHC()); +// } +// double EpFrac; +//}; diff --git a/CAFAna/Systs/NDRecoSysts.cxx b/CAFAna/Systs/NDRecoSysts.cxx index 1f48301a..4e097686 100644 --- a/CAFAna/Systs/NDRecoSysts.cxx +++ b/CAFAna/Systs/NDRecoSysts.cxx @@ -11,91 +11,91 @@ namespace ana { - const RecoNCSyst kRecoNCSyst; - const LeptonAccSyst kLeptonAccSyst; - const HadronAccSyst kHadronAccSyst; - const FVNumuNDSyst kFVNumuNDSyst; - - //---------------------------------------------------------------------- - void RecoNCSyst::Shift(double sigma, - caf::SRProxy* sr, - double& weight) const - { - // Is ND - if(!sr->isFD) { - // CC event selection but is NC - /*if((sr->reco_numu || sr->reco_nue) && (sr->muon_contained || sr->muon_tracker) && (sr->reco_q == -1 || sr->reco_q == 1) && sr->Ehad_veto<30 && !sr->isCC) { - weight *= 1 + .2*sigma; - }*/ - if((sr->reco_numu || sr->reco_nue) && (sr->muon_contained || sr->muon_tracker) && sr->Ehad_veto<30 && !sr->isCC) { - weight *= 1 + .2*sigma; - } - } - } - - //---------------------------------------------------------------------- - void LeptonAccSyst::Shift(double sigma, - caf::SRProxy* sr, - double& weight) const - { - // Load hist if it hasn't been loaded already - const double m_mu = 0.105658; - if (!fHist) { - #ifdef USE_FQ_HARDCODED_SYST_PATHS - TFile f("/app/users/marshalc/ND_syst/ND_eff_syst.root", "read"); - #else - TFile f((FindCAFAnaDir()+"/Systs/ND_eff_syst.root").c_str()); - #endif - assert(!f.IsZombie()); - fHist = (TH2*)f.Get("unc"); - fHist->SetDirectory(0); - } - - // Is ND and is a true numu CC event - if (!sr->isFD && sr->isCC && abs(sr->nuPDG) == 14) { - double LepE = sr->LepE; - int bin = fHist->FindBin(sqrt(LepE*LepE - m_mu*m_mu) * cos(sr->LepNuAngle), sqrt(LepE*LepE - m_mu*m_mu) * sin(sr->LepNuAngle)); - double w = fHist->GetBinContent(bin); - weight *= 1. + w*sigma; - } - } - - //---------------------------------------------------------------------- - void HadronAccSyst::Shift(double sigma, - caf::SRProxy* sr, - double& weight) const - { - // Load hist if it hasn't been loaded already - if (!fHist) { - #ifdef USE_FQ_HARDCODED_SYST_PATHS - TFile f("/app/users/marshalc/ND_syst/ND_eff_syst.root", "read"); - #else - TFile f((FindCAFAnaDir()+"/Systs/ND_eff_syst.root").c_str()); - #endif - assert(!f.IsZombie()); - fHist = (TH1*)f.Get("hunc"); - fHist->SetDirectory(0); - } - - // Is ND - if (!sr->isFD) { - double HadE = sr->Ev - sr->LepE; - if (HadE > 5.) { - HadE = 5.; - } - int bin = fHist->FindBin(HadE); - double w = fHist->GetBinContent(bin); - weight *= 1. + w*sigma; - } - } - - //---------------------------------------------------------------------- - std::vector GetNDRecoSysts() - { - std::vector vec; - vec.push_back(&kRecoNCSyst); - vec.push_back(&kFVNumuNDSyst); - return vec; - } +// const RecoNCSyst kRecoNCSyst; +// const LeptonAccSyst kLeptonAccSyst; +// const HadronAccSyst kHadronAccSyst; +// const FVNumuNDSyst kFVNumuNDSyst; +// +// //---------------------------------------------------------------------- +// void RecoNCSyst::Shift(double sigma, +// caf::SRProxy* sr, +// double& weight) const +// { +// // Is ND +// if(!sr->isFD) { +// // CC event selection but is NC +// /*if((sr->reco_numu || sr->reco_nue) && (sr->muon_contained || sr->muon_tracker) && (sr->reco_q == -1 || sr->reco_q == 1) && sr->Ehad_veto<30 && !sr->isCC) { +// weight *= 1 + .2*sigma; +// }*/ +// if((sr->reco_numu || sr->reco_nue) && (sr->muon_contained || sr->muon_tracker) && sr->Ehad_veto<30 && !sr->isCC) { +// weight *= 1 + .2*sigma; +// } +// } +// } +// +// //---------------------------------------------------------------------- +// void LeptonAccSyst::Shift(double sigma, +// caf::SRProxy* sr, +// double& weight) const +// { +// // Load hist if it hasn't been loaded already +// const double m_mu = 0.105658; +// if (!fHist) { +// #ifdef USE_FQ_HARDCODED_SYST_PATHS +// TFile f("/app/users/marshalc/ND_syst/ND_eff_syst.root", "read"); +// #else +// TFile f((FindCAFAnaDir()+"/Systs/ND_eff_syst.root").c_str()); +// #endif +// assert(!f.IsZombie()); +// fHist = (TH2*)f.Get("unc"); +// fHist->SetDirectory(0); +// } +// +// // Is ND and is a true numu CC event +// if (!sr->isFD && sr->isCC && abs(sr->nuPDG) == 14) { +// double LepE = sr->LepE; +// int bin = fHist->FindBin(sqrt(LepE*LepE - m_mu*m_mu) * cos(sr->LepNuAngle), sqrt(LepE*LepE - m_mu*m_mu) * sin(sr->LepNuAngle)); +// double w = fHist->GetBinContent(bin); +// weight *= 1. + w*sigma; +// } +// } +// +// //---------------------------------------------------------------------- +// void HadronAccSyst::Shift(double sigma, +// caf::SRProxy* sr, +// double& weight) const +// { +// // Load hist if it hasn't been loaded already +// if (!fHist) { +// #ifdef USE_FQ_HARDCODED_SYST_PATHS +// TFile f("/app/users/marshalc/ND_syst/ND_eff_syst.root", "read"); +// #else +// TFile f((FindCAFAnaDir()+"/Systs/ND_eff_syst.root").c_str()); +// #endif +// assert(!f.IsZombie()); +// fHist = (TH1*)f.Get("hunc"); +// fHist->SetDirectory(0); +// } +// +// // Is ND +// if (!sr->isFD) { +// double HadE = sr->Ev - sr->LepE; +// if (HadE > 5.) { +// HadE = 5.; +// } +// int bin = fHist->FindBin(HadE); +// double w = fHist->GetBinContent(bin); +// weight *= 1. + w*sigma; +// } +// } +// +// //---------------------------------------------------------------------- +// std::vector GetNDRecoSysts() +// { +// std::vector vec; +// vec.push_back(&kRecoNCSyst); +// vec.push_back(&kFVNumuNDSyst); +// return vec; +// } } diff --git a/CAFAna/Systs/NDRecoSysts.h b/CAFAna/Systs/NDRecoSysts.h index fc1d20c4..a7b5e487 100644 --- a/CAFAna/Systs/NDRecoSysts.h +++ b/CAFAna/Systs/NDRecoSysts.h @@ -14,70 +14,70 @@ class TH2; namespace ana { - /// Take ND events which pass the CC selection cuts but are NC and reweight - /// by 20% - class RecoNCSyst: public ISyst - { - public: - RecoNCSyst() : ISyst("RecoNCSyst", "ND Neutral Current Reconstruction Syst") {} - void Shift(double sigma, - caf::SRProxy* sr, double& weight) const override; - }; - extern const RecoNCSyst kRecoNCSyst; - - /// Systematic designed to mimic effect of lepton acceptance in the ND - class LeptonAccSyst: public ISyst - { - public: - LeptonAccSyst() : ISyst("LeptonAccSyst", "ND Lepton Acceptance Syst"), fHist(0) {} - - void Shift(double sigma, - caf::SRProxy* sr, double& weight) const override; - protected: - mutable TH2* fHist; - }; - extern const LeptonAccSyst kLeptonAccSyst; - - /// Systematic designed to mimic effect of hadron acceptance in the ND - class HadronAccSyst: public ISyst - { - public: - HadronAccSyst() : ISyst("HadronAccSyst", "ND Hadron Acceptance Syst"), fHist(0) {} - - void Shift(double sigma, - caf::SRProxy* sr, double& weight) const override; - protected: - mutable TH1* fHist; - }; - extern const HadronAccSyst kHadronAccSyst; - - // Fiducial volume normalization for numus - class FVNumuNDSyst: public ISyst - { - public: - FVNumuNDSyst() : ISyst("FVNumuND", "Near Detector Numu Fiducial Volume") {} - void Shift(double sigma, - caf::SRProxy* sr, - double& weight) const override - { - const double scale = 1. + 0.01 * sigma; - if (!sr->isFD && (kPassND_FHC_NUMU(sr) || kPassND_RHC_NUMU(sr))) { - weight *= scale; - } - } - }; - - extern const FVNumuNDSyst kFVNumuNDSyst; - -/* - /// why have a structure (yet) if not needed - /// make things simpler - struct NDRecoSystVector: public std::vector - { - }; - NDRecoSystVector GetNDRecoSysts(); -*/ - - std::vector GetNDRecoSysts(); - +// /// Take ND events which pass the CC selection cuts but are NC and reweight +// /// by 20% +// class RecoNCSyst: public ISyst +// { +// public: +// RecoNCSyst() : ISyst("RecoNCSyst", "ND Neutral Current Reconstruction Syst") {} +// void Shift(double sigma, +// caf::SRProxy* sr, double& weight) const override; +// }; +// extern const RecoNCSyst kRecoNCSyst; +// +// /// Systematic designed to mimic effect of lepton acceptance in the ND +// class LeptonAccSyst: public ISyst +// { +// public: +// LeptonAccSyst() : ISyst("LeptonAccSyst", "ND Lepton Acceptance Syst"), fHist(0) {} +// +// void Shift(double sigma, +// caf::SRProxy* sr, double& weight) const override; +// protected: +// mutable TH2* fHist; +// }; +// extern const LeptonAccSyst kLeptonAccSyst; +// +// /// Systematic designed to mimic effect of hadron acceptance in the ND +// class HadronAccSyst: public ISyst +// { +// public: +// HadronAccSyst() : ISyst("HadronAccSyst", "ND Hadron Acceptance Syst"), fHist(0) {} +// +// void Shift(double sigma, +// caf::SRProxy* sr, double& weight) const override; +// protected: +// mutable TH1* fHist; +// }; +// extern const HadronAccSyst kHadronAccSyst; +// +// // Fiducial volume normalization for numus +// class FVNumuNDSyst: public ISyst +// { +// public: +// FVNumuNDSyst() : ISyst("FVNumuND", "Near Detector Numu Fiducial Volume") {} +// void Shift(double sigma, +// caf::SRProxy* sr, +// double& weight) const override +// { +// const double scale = 1. + 0.01 * sigma; +// if (!sr->isFD && (kPassND_FHC_NUMU(sr) || kPassND_RHC_NUMU(sr))) { +// weight *= scale; +// } +// } +// }; +// +// extern const FVNumuNDSyst kFVNumuNDSyst; +// +///* +// /// why have a structure (yet) if not needed +// /// make things simpler +// struct NDRecoSystVector: public std::vector +// { +// }; +// NDRecoSystVector GetNDRecoSysts(); +//*/ +// +// std::vector GetNDRecoSysts(); +// } diff --git a/CAFAna/Systs/NuOnESysts.cxx b/CAFAna/Systs/NuOnESysts.cxx index 6ee02a60..43f8561f 100644 --- a/CAFAna/Systs/NuOnESysts.cxx +++ b/CAFAna/Systs/NuOnESysts.cxx @@ -1,17 +1,17 @@ #include "CAFAna/Systs/NuOnESysts.h" namespace ana { - const NuOnECCBkgSyst kNuOnECCBkgSyst; - const NuOnENCBkgSyst kNuOnENCBkgSyst; - const NuOnERecoEffSyst kNuOnERecoEffSyst; - - std::vector GetNuOnESysts() - { - std::vector vec; - vec.push_back(&kNuOnECCBkgSyst); - vec.push_back(&kNuOnENCBkgSyst); - vec.push_back(&kNuOnERecoEffSyst); - return vec; - } +// const NuOnECCBkgSyst kNuOnECCBkgSyst; +// const NuOnENCBkgSyst kNuOnENCBkgSyst; +// const NuOnERecoEffSyst kNuOnERecoEffSyst; +// +// std::vector GetNuOnESysts() +// { +// std::vector vec; +// vec.push_back(&kNuOnECCBkgSyst); +// vec.push_back(&kNuOnENCBkgSyst); +// vec.push_back(&kNuOnERecoEffSyst); +// return vec; +// } } diff --git a/CAFAna/Systs/NuOnESysts.h b/CAFAna/Systs/NuOnESysts.h index d0b2d0b9..536edbf1 100644 --- a/CAFAna/Systs/NuOnESysts.h +++ b/CAFAna/Systs/NuOnESysts.h @@ -10,76 +10,76 @@ namespace ana { - // Expect ~20% shape uncertainty on nu_e CC background to nu+e --> nu+e - class NuOnECCBkgSyst: public ISyst - { - public: - NuOnECCBkgSyst() : ISyst("NuOnECCBkgSyst", "nu_e CC background to nu+e") {} - void Shift(double sigma, - caf::SRProxy* sr, double& weight) const override - { - if(!sr->isFD) { // ND only - // apply unc. only to nu_e CC background, not NC gamma background - if( (sr->nuPDG == 12 || sr->nuPDG == -12) && sr->isCC && sr->mode != 7 ) { - // apply it to everything? or just selected? - //double reco_ehad = sr->Ehad_veto; // re-using this variable for "extra energy" cut in nu+e - //double eth2 = sr->Elep_reco * sr->Elep_reco * sr->reco_theta; // E * theta^2 - //if( sr->reco_nue && reco_ehad < 20. && eth2 < 0.002 ) { - weight *= (1 + .2*sigma); // 20% uncertainty on shape (norm is constrained by sideband) - } - } - } - }; - extern const NuOnECCBkgSyst kNuOnECCBkgSyst; - - // Expect ~20% shape uncertainty on nu_e CC background to nu+e --> nu+e - class NuOnENCBkgSyst: public ISyst - { - public: - NuOnENCBkgSyst() : ISyst("NuOnENCBkgSyst", "NC pi0 background to nu+e") {} - void Shift(double sigma, - caf::SRProxy* sr, double& weight) const override - { - if(!sr->isFD) { // ND only - // apply unc. only to NC gamma background (and not nu-on-e) - if( !sr->isCC && sr->mode != 7) { - // apply it to everything? or just selected? - //double reco_ehad = sr->Ehad_veto; // re-using this variable for "extra energy" cut in nu+e - //double eth2 = sr->Elep_reco * sr->Elep_reco * sr->reco_theta; // E * theta^2 - //if( sr->reco_nue && reco_ehad < 20. && eth2 < 0.002 ) { - weight *= (1 + .1*sigma); // 10% uncertainty on shape (norm is constrained by sideband) - } - } - } - }; - extern const NuOnENCBkgSyst kNuOnENCBkgSyst; - - // Signal reconstruction efficiency systematic - class NuOnERecoEffSyst: public ISyst - { - public: - NuOnERecoEffSyst() : ISyst("NuOnERecoEffSyst", "nu+e signal reconstruction") {} - void Shift(double sigma, - caf::SRProxy* sr, double& weight) const override - { - if(!sr->isFD) { // ND only - if( sr->mode == 7 ) { - weight *= (1 + 0.01*sigma); // 1% uncertainty on reco eff - } - } - } - }; - extern const NuOnERecoEffSyst kNuOnERecoEffSyst; - -/* - /// why have a structure (yet) if not needed - /// make things simpler - struct NuOnESystVector: public std::vector - { - }; - NuOnESystVector GetNuOnESysts(); -*/ - - std::vector GetNuOnESysts(); +/// // Expect ~20% shape uncertainty on nu_e CC background to nu+e --> nu+e +/// class NuOnECCBkgSyst: public ISyst +/// { +/// public: +/// NuOnECCBkgSyst() : ISyst("NuOnECCBkgSyst", "nu_e CC background to nu+e") {} +/// void Shift(double sigma, +/// caf::SRProxy* sr, double& weight) const override +/// { +/// if(!sr->isFD) { // ND only +/// // apply unc. only to nu_e CC background, not NC gamma background +/// if( (sr->nuPDG == 12 || sr->nuPDG == -12) && sr->isCC && sr->mode != 7 ) { +/// // apply it to everything? or just selected? +/// //double reco_ehad = sr->Ehad_veto; // re-using this variable for "extra energy" cut in nu+e +/// //double eth2 = sr->Elep_reco * sr->Elep_reco * sr->reco_theta; // E * theta^2 +/// //if( sr->reco_nue && reco_ehad < 20. && eth2 < 0.002 ) { +/// weight *= (1 + .2*sigma); // 20% uncertainty on shape (norm is constrained by sideband) +/// } +/// } +/// } +/// }; +/// extern const NuOnECCBkgSyst kNuOnECCBkgSyst; +/// +/// // Expect ~20% shape uncertainty on nu_e CC background to nu+e --> nu+e +/// class NuOnENCBkgSyst: public ISyst +/// { +/// public: +/// NuOnENCBkgSyst() : ISyst("NuOnENCBkgSyst", "NC pi0 background to nu+e") {} +/// void Shift(double sigma, +/// caf::SRProxy* sr, double& weight) const override +/// { +/// if(!sr->isFD) { // ND only +/// // apply unc. only to NC gamma background (and not nu-on-e) +/// if( !sr->isCC && sr->mode != 7) { +/// // apply it to everything? or just selected? +/// //double reco_ehad = sr->Ehad_veto; // re-using this variable for "extra energy" cut in nu+e +/// //double eth2 = sr->Elep_reco * sr->Elep_reco * sr->reco_theta; // E * theta^2 +/// //if( sr->reco_nue && reco_ehad < 20. && eth2 < 0.002 ) { +/// weight *= (1 + .1*sigma); // 10% uncertainty on shape (norm is constrained by sideband) +/// } +/// } +/// } +/// }; +/// extern const NuOnENCBkgSyst kNuOnENCBkgSyst; +/// +/// // Signal reconstruction efficiency systematic +/// class NuOnERecoEffSyst: public ISyst +/// { +/// public: +/// NuOnERecoEffSyst() : ISyst("NuOnERecoEffSyst", "nu+e signal reconstruction") {} +/// void Shift(double sigma, +/// caf::SRProxy* sr, double& weight) const override +/// { +/// if(!sr->isFD) { // ND only +/// if( sr->mode == 7 ) { +/// weight *= (1 + 0.01*sigma); // 1% uncertainty on reco eff +/// } +/// } +/// } +/// }; +/// extern const NuOnERecoEffSyst kNuOnERecoEffSyst; +/// +////* +/// /// why have a structure (yet) if not needed +/// /// make things simpler +/// struct NuOnESystVector: public std::vector +/// { +/// }; +/// NuOnESystVector GetNuOnESysts(); +///*/ +/// +/// std::vector GetNuOnESysts(); } diff --git a/CAFAna/Systs/NuWroReweightFakeData.cxx b/CAFAna/Systs/NuWroReweightFakeData.cxx index 9b3feef5..d4affe3d 100644 --- a/CAFAna/Systs/NuWroReweightFakeData.cxx +++ b/CAFAna/Systs/NuWroReweightFakeData.cxx @@ -14,137 +14,137 @@ #include #include -NuWroReweightFakeDataGenerator::NuWroReweightFakeDataGenerator() - : ana::ISyst("NuWroReweightFakeDataGenerator", - "NuWroReweightFakeDataGenerator", false, 0, 1) -{ - bdt_reweighters.emplace_back(new GeneratorReweight_nue_FD_FHC()); // 0 nue_FD_FHC - bdt_reweighters.emplace_back(new GeneratorReweight_nue_FD_RHC()); // 1 nue_FD_RHC - bdt_reweighters.emplace_back(new GeneratorReweight_nuebar_FD_RHC()); // 2 nuebar_FD_RHC - bdt_reweighters.emplace_back(new GeneratorReweight_numu_FD_FHC()); // 3 numu_FD_FHC - bdt_reweighters.emplace_back(new GeneratorReweight_numu_FD_RHC()); // 4 numu_FD_RHC - bdt_reweighters.emplace_back(new GeneratorReweight_numubar_FD_RHC()); // 5 numubar_FD_RHC - bdt_reweighters.emplace_back(new GeneratorReweight_numu_ND_FHC()); // 6 numu_ND_FHC - bdt_reweighters.emplace_back(new GeneratorReweight_numu_ND_RHC()); // 7 numu_ND_RHC - bdt_reweighters.emplace_back(new GeneratorReweight_numubar_ND_RHC()); // 8 numubar_ND_RHC -} - -NuWroReweightFakeDataGenerator::~NuWroReweightFakeDataGenerator() -{ - for(BDTReweighter* rw: bdt_reweighters) delete rw; -} - -void NuWroReweightFakeDataGenerator::Shift(double sigma, - caf::SRProxy* sr, - double& weight) const -{ - if(!sr->isCC) return; // only reweight CC's - - // To be on the safe side. BDT does not know about taus. - if(abs(sr->nuPDG) == 16) return; - - // Reweighting only applied up to 8 GeV - if(sr->Ev > 8.) return; - - if(sigma != 1) return; - - union BDTReweighter::BDTReweighterFeature features[22]; - - features[0].fvalue = sr->Ev; - features[1].fvalue = sr->LepE; - features[2].fvalue = sr->LepNuAngle; - features[3].fvalue = sr->Q2; - features[4].fvalue = sr->W; - features[5].fvalue = sr->X; - features[6].fvalue = sr->Y; - - features[7].fvalue = sr->nP; - features[8].fvalue = sr->nN; - features[9].fvalue = sr->nipip; - features[10].fvalue = sr->nipim; - features[11].fvalue = sr->nipi0; - features[12].fvalue = sr->niem; - - features[13].fvalue = sr->eP; - features[14].fvalue = sr->eN; - features[15].fvalue = sr->ePip; - features[16].fvalue = sr->ePim; - features[17].fvalue = sr->ePi0; - - // These last 4 are legacy of an initial attempt and I don't think the BDT is using them but let's fill them properly to be on the safe side. - features[18].fvalue = (sr->isFD == 0 ? 1 : 0); // FD files have isFD = 999 - features[19].fvalue = sr->isFHC; - features[20].fvalue = (sr->nuPDG > 0 ? 1 : 0); // Is a neutrino, as opposed to antineutrino - features[21].fvalue = (abs(sr->nuPDG) == 14 ? 1 : 0); // Is (anti)numu, as opposed to (anti)nue - - // BDT_norm_weight normalizes weights predicted by the BDT to Genie absolute normalization - double BDT_norm_weight = 1.; - // absolute_NuWro_over_Genie_weight gives the absolute normalization difference between Genie and NuWro, i.e., the inclusive xsec ratio integrated over the respective fluxes. - double absolute_NuWro_over_Genie_weight = 1.; - // Calibration parameters for BDT output (Platt scaling) - double plattA = -1.; - double plattB = 0.; - // Pointer to BDT to use - BDTReweighter * thisReweighter = 0; - - if(sr->isFD == 0 && sr->isFHC && abs(sr->nuPDG) == 14 && sr->nuPDG > 0){ - BDT_norm_weight = 1.035; - absolute_NuWro_over_Genie_weight = 1.013; - plattA = -1.24585102; - plattB = -0.01783353; - thisReweighter = bdt_reweighters[6]; // 6 numu_ND_FHC - } else if(sr->isFD == 0 && !sr->isFHC && abs(sr->nuPDG) == 14 && sr->nuPDG > 0){ - BDT_norm_weight = 1.046; - absolute_NuWro_over_Genie_weight = 0.917; - plattA = -1.22806734; - plattB = -0.01548346; - thisReweighter = bdt_reweighters[7]; // 7 numu_ND_RHC - } else if(sr->isFD == 0 && !sr->isFHC && abs(sr->nuPDG) == 14 && sr->nuPDG <= 0){ - BDT_norm_weight = 1.019; - absolute_NuWro_over_Genie_weight = 0.917; - plattA = -1.3029002; - plattB = -0.0314188; - thisReweighter = bdt_reweighters[8]; // 8 numubar_ND_RHC - } else if(sr->isFD != 0 && sr->isFHC && abs(sr->nuPDG) == 14 && sr->nuPDG > 0){ - BDT_norm_weight = 1.042; - absolute_NuWro_over_Genie_weight = 1.011; - plattA = -1.21073292; - plattB = -0.02231727; - thisReweighter = bdt_reweighters[3]; // 3 numu_FD_FHC - } else if(sr->isFD != 0 && !sr->isFHC && abs(sr->nuPDG) == 14 && sr->nuPDG > 0){ - BDT_norm_weight = 1.040; - absolute_NuWro_over_Genie_weight = 0.981; - plattA = -1.21420542; - plattB = -0.02423824; - thisReweighter = bdt_reweighters[4]; // 4 numu_FD_RHC - } else if(sr->isFD != 0 && !sr->isFHC && abs(sr->nuPDG) == 14 && sr->nuPDG <= 0){ - BDT_norm_weight = 1.036; - absolute_NuWro_over_Genie_weight = 0.904; - plattA = -1.24604201; - plattB = -0.03690337; - thisReweighter = bdt_reweighters[5]; // 5 numubar_FD_RHC - } else if(sr->isFD != 0 && sr->isFHC && abs(sr->nuPDG) != 14 && sr->nuPDG > 0){ - BDT_norm_weight = 1.041; - absolute_NuWro_over_Genie_weight = 1.038; - plattA = -1.22058287; - plattB = -0.01992826; - thisReweighter = bdt_reweighters[0]; // 0 nue_FD_FHC - } else if(sr->isFD != 0 && !sr->isFHC && abs(sr->nuPDG) != 14 && sr->nuPDG > 0){ - BDT_norm_weight = 1.056; - absolute_NuWro_over_Genie_weight = 0.988; - plattA = -1.17760748; - plattB = -0.02129378; - thisReweighter = bdt_reweighters[1]; // 1 nue_FD_RHC - } else if(sr->isFD != 0 && !sr->isFHC && abs(sr->nuPDG) != 14 && sr->nuPDG <= 0){ - BDT_norm_weight = 1.029; - absolute_NuWro_over_Genie_weight = 0.912; - plattA = -1.27055928; - plattB = -0.0294727; - thisReweighter = bdt_reweighters[2]; // 2 nuebar_FD_RHC - } - - if(thisReweighter) { - weight *= absolute_NuWro_over_Genie_weight*BDT_norm_weight*exp(plattA*thisReweighter->predict(features,1) + plattB); - } - -} +//NuWroReweightFakeDataGenerator::NuWroReweightFakeDataGenerator() +// : ana::ISyst("NuWroReweightFakeDataGenerator", +// "NuWroReweightFakeDataGenerator", false, 0, 1) +//{ +// bdt_reweighters.emplace_back(new GeneratorReweight_nue_FD_FHC()); // 0 nue_FD_FHC +// bdt_reweighters.emplace_back(new GeneratorReweight_nue_FD_RHC()); // 1 nue_FD_RHC +// bdt_reweighters.emplace_back(new GeneratorReweight_nuebar_FD_RHC()); // 2 nuebar_FD_RHC +// bdt_reweighters.emplace_back(new GeneratorReweight_numu_FD_FHC()); // 3 numu_FD_FHC +// bdt_reweighters.emplace_back(new GeneratorReweight_numu_FD_RHC()); // 4 numu_FD_RHC +// bdt_reweighters.emplace_back(new GeneratorReweight_numubar_FD_RHC()); // 5 numubar_FD_RHC +// bdt_reweighters.emplace_back(new GeneratorReweight_numu_ND_FHC()); // 6 numu_ND_FHC +// bdt_reweighters.emplace_back(new GeneratorReweight_numu_ND_RHC()); // 7 numu_ND_RHC +// bdt_reweighters.emplace_back(new GeneratorReweight_numubar_ND_RHC()); // 8 numubar_ND_RHC +//} +// +//NuWroReweightFakeDataGenerator::~NuWroReweightFakeDataGenerator() +//{ +// for(BDTReweighter* rw: bdt_reweighters) delete rw; +//} +// +//void NuWroReweightFakeDataGenerator::Shift(double sigma, +// caf::SRProxy* sr, +// double& weight) const +//{ +// if(!sr->mc.nu[0].iscc /*isCC*/) return; // only reweight CC's +// +// // To be on the safe side. BDT does not know about taus. +// if(abs(sr->mc.nu[0].pdg /*nuPDG*/) == 16) return; +// +// // Reweighting only applied up to 8 GeV +// if(sr->Ev > 8.) return; +// +// if(sigma != 1) return; +// +// union BDTReweighter::BDTReweighterFeature features[22]; +// +// features[0].fvalue = sr->Ev; +// features[1].fvalue = sr->LepE; +// features[2].fvalue = sr->LepNuAngle; +// features[3].fvalue = sr->Q2; +// features[4].fvalue = sr->W; +// features[5].fvalue = sr->X; +// features[6].fvalue = sr->Y; +// +// features[7].fvalue = sr->nP; +// features[8].fvalue = sr->nN; +// features[9].fvalue = sr->nipip; +// features[10].fvalue = sr->nipim; +// features[11].fvalue = sr->nipi0; +// features[12].fvalue = sr->niem; +// +// features[13].fvalue = sr->eP; +// features[14].fvalue = sr->eN; +// features[15].fvalue = sr->ePip; +// features[16].fvalue = sr->ePim; +// features[17].fvalue = sr->ePi0; +// +// // These last 4 are legacy of an initial attempt and I don't think the BDT is using them but let's fill them properly to be on the safe side. +// features[18].fvalue = (sr->isFD == 0 ? 1 : 0); // FD files have isFD = 999 +// features[19].fvalue = sr->isFHC; +// features[20].fvalue = (sr->nuPDG > 0 ? 1 : 0); // Is a neutrino, as opposed to antineutrino +// features[21].fvalue = (abs(sr->nuPDG) == 14 ? 1 : 0); // Is (anti)numu, as opposed to (anti)nue +// +// // BDT_norm_weight normalizes weights predicted by the BDT to Genie absolute normalization +// double BDT_norm_weight = 1.; +// // absolute_NuWro_over_Genie_weight gives the absolute normalization difference between Genie and NuWro, i.e., the inclusive xsec ratio integrated over the respective fluxes. +// double absolute_NuWro_over_Genie_weight = 1.; +// // Calibration parameters for BDT output (Platt scaling) +// double plattA = -1.; +// double plattB = 0.; +// // Pointer to BDT to use +// BDTReweighter * thisReweighter = 0; +// +// if(sr->isFD == 0 && sr->isFHC && abs(sr->nuPDG) == 14 && sr->nuPDG > 0){ +// BDT_norm_weight = 1.035; +// absolute_NuWro_over_Genie_weight = 1.013; +// plattA = -1.24585102; +// plattB = -0.01783353; +// thisReweighter = bdt_reweighters[6]; // 6 numu_ND_FHC +// } else if(sr->isFD == 0 && !sr->isFHC && abs(sr->nuPDG) == 14 && sr->nuPDG > 0){ +// BDT_norm_weight = 1.046; +// absolute_NuWro_over_Genie_weight = 0.917; +// plattA = -1.22806734; +// plattB = -0.01548346; +// thisReweighter = bdt_reweighters[7]; // 7 numu_ND_RHC +// } else if(sr->isFD == 0 && !sr->isFHC && abs(sr->nuPDG) == 14 && sr->nuPDG <= 0){ +// BDT_norm_weight = 1.019; +// absolute_NuWro_over_Genie_weight = 0.917; +// plattA = -1.3029002; +// plattB = -0.0314188; +// thisReweighter = bdt_reweighters[8]; // 8 numubar_ND_RHC +// } else if(sr->isFD != 0 && sr->isFHC && abs(sr->nuPDG) == 14 && sr->nuPDG > 0){ +// BDT_norm_weight = 1.042; +// absolute_NuWro_over_Genie_weight = 1.011; +// plattA = -1.21073292; +// plattB = -0.02231727; +// thisReweighter = bdt_reweighters[3]; // 3 numu_FD_FHC +// } else if(sr->isFD != 0 && !sr->isFHC && abs(sr->nuPDG) == 14 && sr->nuPDG > 0){ +// BDT_norm_weight = 1.040; +// absolute_NuWro_over_Genie_weight = 0.981; +// plattA = -1.21420542; +// plattB = -0.02423824; +// thisReweighter = bdt_reweighters[4]; // 4 numu_FD_RHC +// } else if(sr->isFD != 0 && !sr->isFHC && abs(sr->nuPDG) == 14 && sr->nuPDG <= 0){ +// BDT_norm_weight = 1.036; +// absolute_NuWro_over_Genie_weight = 0.904; +// plattA = -1.24604201; +// plattB = -0.03690337; +// thisReweighter = bdt_reweighters[5]; // 5 numubar_FD_RHC +// } else if(sr->isFD != 0 && sr->isFHC && abs(sr->nuPDG) != 14 && sr->nuPDG > 0){ +// BDT_norm_weight = 1.041; +// absolute_NuWro_over_Genie_weight = 1.038; +// plattA = -1.22058287; +// plattB = -0.01992826; +// thisReweighter = bdt_reweighters[0]; // 0 nue_FD_FHC +// } else if(sr->isFD != 0 && !sr->isFHC && abs(sr->nuPDG) != 14 && sr->nuPDG > 0){ +// BDT_norm_weight = 1.056; +// absolute_NuWro_over_Genie_weight = 0.988; +// plattA = -1.17760748; +// plattB = -0.02129378; +// thisReweighter = bdt_reweighters[1]; // 1 nue_FD_RHC +// } else if(sr->isFD != 0 && !sr->isFHC && abs(sr->nuPDG) != 14 && sr->nuPDG <= 0){ +// BDT_norm_weight = 1.029; +// absolute_NuWro_over_Genie_weight = 0.912; +// plattA = -1.27055928; +// plattB = -0.0294727; +// thisReweighter = bdt_reweighters[2]; // 2 nuebar_FD_RHC +// } +// +// if(thisReweighter) { +// weight *= absolute_NuWro_over_Genie_weight*BDT_norm_weight*exp(plattA*thisReweighter->predict(features,1) + plattB); +// } +// +//} diff --git a/CAFAna/Systs/NuWroReweightFakeData.h b/CAFAna/Systs/NuWroReweightFakeData.h index 3fcf17c7..da2f049b 100644 --- a/CAFAna/Systs/NuWroReweightFakeData.h +++ b/CAFAna/Systs/NuWroReweightFakeData.h @@ -8,17 +8,17 @@ #include "CAFAna/Systs/BDTReweighter.h" #include - -class NuWroReweightFakeDataGenerator : public ana::ISyst { -public: - NuWroReweightFakeDataGenerator(); - virtual ~NuWroReweightFakeDataGenerator(); - - void Shift(double sigma, caf::SRProxy *sr, - double &weight) const override; - -protected: - NuWroReweightFakeDataGenerator(const NuWroReweightFakeDataGenerator&) = delete; - - std::vector bdt_reweighters; -}; +// +//class NuWroReweightFakeDataGenerator : public ana::ISyst { +//public: +// NuWroReweightFakeDataGenerator(); +// virtual ~NuWroReweightFakeDataGenerator(); +// +// void Shift(double sigma, caf::SRProxy *sr, +// double &weight) const override; +// +//protected: +// NuWroReweightFakeDataGenerator(const NuWroReweightFakeDataGenerator&) = delete; +// +// std::vector bdt_reweighters; +//}; diff --git a/CAFAna/Systs/RecoEnergyNDSysts.cxx b/CAFAna/Systs/RecoEnergyNDSysts.cxx index cb52776a..3b84770a 100644 --- a/CAFAna/Systs/RecoEnergyNDSysts.cxx +++ b/CAFAna/Systs/RecoEnergyNDSysts.cxx @@ -4,352 +4,352 @@ namespace ana { - void RecoEnergyScaleND::Shift(double sigma, - caf::SRProxy* sr, - double& weight) const { - - const double scale = 0.02 * sigma; - if (!sr->isFD) { - // To match FD: - // Whether NC or CC, Numu or Nue, we want to shift total "reconstructed neutrino energy" - // by the "reconstructed hadronic energy". - sr->EVisReco_ND += (sr->EVisReco_ND - sr->Elep_reco) * scale; - // Also shift the hadronic energy variable, if we don't do this then shifted - // plots of the reconstructed hadronic energy will not be different to nominal. - sr->HadEVisReco_ND *= 1. + scale; - // If it isn't Numu-CC, also shift the "reconstructed neutrino energy" by the - // "reconstructed leptonic energy". - // Also shift the reconstructed leptonic energy itself. - if (!(sr->isCC && abs(sr->nuPDG) == 14)) { - sr->EVisReco_ND += sr->Elep_reco * scale; - sr->Elep_reco *= 1. + scale; - } - } - } - - const RecoEnergyScaleND kRecoEnergyScaleND; - - void RecoEnergySqrtND::Shift(double sigma, - caf::SRProxy* sr, - double& weight) const { - - const double scale = 0.01 * sigma; - if (!sr->isFD) { - // To match LBL TDR: - // Whether NC or CC, Numu or Nue, we want to shift total "reconstructed neutrino energy" - // by the "reconstructed hadronic energy". - sr->EVisReco_ND += (sr->EVisReco_ND - sr->Elep_reco) * scale * - pow((sr->EVisReco_ND - sr->Elep_reco), 0.5); - // Also shift the hadronic energy variable, if we don't do this then shifted - // plots of the reconstructed hadronic energy will not be different to nominal. - sr->HadEVisReco_ND += sr->HadEVisReco_ND * scale * pow(sr->HadEVisReco_ND, 0.5); - // If it isn't Numu-CC, also shift the "reconstructed neutrino energy" by the - // "reconstructed leptonic energy". - // Also shift the reconstructed leptonic energy itself. - if (!(sr->isCC && abs(sr->nuPDG) == 14)) { - sr->EVisReco_ND += sr->Elep_reco * scale * pow(sr->Elep_reco, 0.5); - sr->Elep_reco += sr->Elep_reco * scale * pow(sr->Elep_reco, 0.5); - } - } - } - - const RecoEnergySqrtND kRecoEnergySqrtND; - - void RecoEnergyInvSqrtND::Shift(double sigma, - caf::SRProxy* sr, - double& weight) const { - - const double scale = 0.02 * sigma; - if (!sr->isFD) { - // To match LBL TDR: - // Whether NC or CC, Numu or Nue, we want to shift total "reconstructed neutrino energy" - // by the "reconstructed hadronic energy". - sr->EVisReco_ND += (sr->EVisReco_ND - sr->Elep_reco) * scale * - pow((sr->EVisReco_ND - sr->Elep_reco+0.1), -0.5); - // Also shift the hadronic energy variable, if we don't do this then shifted - // plots of the reconstructed hadronic energy will not be different to nominal. - sr->HadEVisReco_ND += sr->HadEVisReco_ND * scale * pow(sr->HadEVisReco_ND+0.1, -0.5); - // If it isn't Numu-CC, also shift the "reconstructed neutrino energy" by the - // "reconstructed leptonic energy". - // Also shift the reconstructed leptonic energy itself. - if (!(sr->isCC && abs(sr->nuPDG) == 14)) { - sr->EVisReco_ND += sr->Elep_reco * scale * pow(sr->Elep_reco+0.1, -0.5); - sr->Elep_reco += sr->Elep_reco * scale * pow(sr->Elep_reco+0.1, -0.5); - } - } - } - - const RecoEnergyInvSqrtND kRecoEnergyInvSqrtND; - - - void EMRecoUncorrND::Shift(double sigma, - caf::SRProxy* sr, - double& weight) const { - - const double scale = 0.025 * sigma; - if (!sr->isFD) { // in the ND - sr->eRecoPi0 += sr->eRecoPi0 * scale; - sr->EVisReco_ND += sr->eRecoPi0 * scale; - if (sr->isCC && abs(sr->nuPDG) == 12) { - sr->Elep_reco += sr->Elep_reco * scale; - sr->EVisReco_ND += sr->Elep_reco * scale; - } - } - } - - const EMRecoUncorrND kEMRecoUncorrND; - - void EMRecoUncorrSqrtND::Shift(double sigma, - caf::SRProxy* sr, - double& weight) const { - - const double scale = 0.025 * sigma; - if (!sr->isFD) { // in the ND - sr->eRecoPi0 += sr->eRecoPi0 * scale * pow(sr->eRecoPi0, 0.5); - sr->EVisReco_ND += sr->eRecoPi0 * scale * pow(sr->eRecoPi0, 0.5); - if (sr->isCC && abs(sr->nuPDG) == 12) { - sr->Elep_reco += sr->Elep_reco * scale * pow(sr->Elep_reco, 0.5); - sr->EVisReco_ND += sr->Elep_reco * scale * pow(sr->Elep_reco, 0.5); - } - } - } - - const EMRecoUncorrSqrtND kEMRecoUncorrSqrtND; - - void EMRecoUncorrInvSqrtND::Shift(double sigma, - caf::SRProxy* sr, - double& weight) const { - - const double scale = 0.025 * sigma; - if (!sr->isFD) { // in the ND - sr->eRecoPi0 += sr->eRecoPi0 * scale * pow(sr->eRecoPi0+0.1, -0.5); - sr->EVisReco_ND += sr->eRecoPi0 * scale * pow(sr->eRecoPi0+0.1, -0.5); - if (sr->isCC && abs(sr->nuPDG) == 12) { - sr->Elep_reco += sr->Elep_reco * scale * pow(sr->Elep_reco+0.1, -0.5); - sr->EVisReco_ND += sr->Elep_reco * scale * pow(sr->Elep_reco+0.1, -0.5); - } - } - } - - const EMRecoUncorrInvSqrtND kEMRecoUncorrInvSqrtND; - - void ChargedHadRecoUncorrND::Shift(double sigma, - caf::SRProxy* sr, - double& weight) const { - - const double scale = 0.05 * sigma; - if (!sr->isFD) { // in the ND - if (sr->eRecoP < 0) sr->eRecoP = 0.; - if (sr->eRecoPim < 0) sr->eRecoPim = 0.; - if (sr->eRecoPip < 0) sr->eRecoPip = 0.; - const double sumE = sr->eRecoP + sr->eRecoPim + sr->eRecoPip; - sr->eRecoPip += sr->eRecoPip * scale; - sr->eRecoPim += sr->eRecoPim * scale; - sr->eRecoP += sr->eRecoP * scale; - sr->EVisReco_ND += sumE * scale; - sr->HadEVisReco_ND += sumE * scale; - } - } - - const ChargedHadRecoUncorrND kChargedHadRecoUncorrND; - - void ChargedHadRecoUncorrSqrtND::Shift(double sigma, - caf::SRProxy* sr, - double& weight) const { - - const double scale = 0.05 * sigma; - if (!sr->isFD) { // in the ND - if (sr->eRecoP < 0) sr->eRecoP = 0.; - if (sr->eRecoPim < 0) sr->eRecoPim = 0.; - if (sr->eRecoPip < 0) sr->eRecoPip = 0.; - const double sumE = sr->eRecoPip + sr->eRecoPim + sr->eRecoP; - sr->eRecoPip += sr->eRecoPip * scale * pow(sr->eRecoPip, 0.5); - sr->eRecoPim += sr->eRecoPim * scale * pow(sr->eRecoPim, 0.5); - sr->eRecoP += sr->eRecoP * scale * pow(sr->eRecoP, 0.5); - sr->EVisReco_ND += sumE * scale * pow(sumE, 0.5); - sr->HadEVisReco_ND += sumE * scale * pow(sumE, 0.5); - } - } - - const ChargedHadRecoUncorrSqrtND kChargedHadRecoUncorrSqrtND; - - void ChargedHadRecoUncorrInvSqrtND::Shift(double sigma, - caf::SRProxy* sr, - double& weight) const { - - const double scale = 0.05 * sigma; - if (!sr->isFD) { // in the ND - if (sr->eRecoP < 0) sr->eRecoP = 0.; - if (sr->eRecoPim < 0) sr->eRecoPim = 0.; - if (sr->eRecoPip < 0) sr->eRecoPip = 0.; - const double sumE = sr->eRecoPip + sr->eRecoPim + sr->eRecoP; - sr->eRecoPip += sr->eRecoPip * scale * pow(sr->eRecoPip+0.1, -0.5); - sr->eRecoPim += sr->eRecoPim * scale * pow(sr->eRecoPim+0.1, -0.5); - sr->eRecoP += sr->eRecoP * scale * pow(sr->eRecoP+0.1, -0.5); - sr->EVisReco_ND += sumE * scale * pow(sumE+0.1, -0.5); - sr->HadEVisReco_ND += sumE * scale * pow(sumE+0.1, -0.5); - } - } - - const ChargedHadRecoUncorrInvSqrtND kChargedHadRecoUncorrInvSqrtND; - - void ERecoScaleMuLArND::Shift(double sigma, - caf::SRProxy* sr, - double& weight) const { - - // Different EScale uncertainty for reconstruction by range or in - // GAr tracker - double var(0); - if (sr->muon_contained) var = 0.02; - else if (sr->muon_tracker) var = 0.01; - else var = 0.02; // selection requires muon to be inLAr or GAr so never get here - const double scale = var * sigma; - if (!sr->isFD) { // in the ND - if (sr->isCC && abs(sr->nuPDG) == 14) { - sr->Elep_reco += sr->Elep_reco * scale; - sr->EVisReco_ND += sr->Elep_reco * scale; - } - } - } - - const ERecoScaleMuLArND kERecoScaleMuLArND; - - void ERecoScaleMuLArSqrtND::Shift(double sigma, - caf::SRProxy* sr, - double& weight) const { - - double var(0); - if (sr->muon_contained) var = 0.02; - else if (sr->muon_tracker) var = 0.01; - else var = 0.02; // selection requires muon to be inLAr or GAr so never get here - const double scale = var * sigma; // is 0.005 in FD - if (!sr->isFD) { // in the ND - if (sr->isCC && abs(sr->nuPDG) == 14) { - sr->Elep_reco += sr->Elep_reco * scale * pow(sr->Elep_reco, 0.5); - sr->EVisReco_ND += sr->Elep_reco * scale * pow(sr->Elep_reco, 0.5); - } - } - } - - const ERecoScaleMuLArSqrtND kERecoScaleMuLArSqrtND; - - void ERecoScaleMuLArInvSqrtND::Shift(double sigma, - caf::SRProxy* sr, - double& weight) const { - - double var(0); - if (sr->muon_contained) var = 0.02; - else if (sr->muon_tracker) var = 0.01; - else var = 0.02; // selection requires muon to be inLAr or GAr so never get here - const double scale = var * sigma; - if (!sr->isFD) { // in the ND - if (sr->isCC && abs(sr->nuPDG) == 14) { - sr->Elep_reco += sr->Elep_reco * scale * pow(sr->Elep_reco+0.1, -0.5); - sr->EVisReco_ND += sr->Elep_reco * scale * pow(sr->Elep_reco+0.1, -0.5); - } - } - } - - const ERecoScaleMuLArInvSqrtND kERecoScaleMuLArInvSqrtND; - - // Resolution Syst - - void MuonRecoResND::Shift(double sigma, - caf::SRProxy* sr, - double& weight) const { - - const double scale = 0.02 * sigma; - if (!sr->isFD) { // in the ND - sr->Elep_reco += (sr->LepE - sr->Elep_reco) * scale; - sr->EVisReco_ND += (sr->LepE - sr->Elep_reco) * scale; - } - } - - const MuonRecoResND kMuonRecoResND; - - void EMRecoResND::Shift(double sigma, - caf::SRProxy* sr, - double& weight) const { - - const double scale = .02*sigma; - if (!sr->isFD){ - sr->EVisReco_ND += (sr->ePi0 - sr->eRecoPi0) * scale; - sr->eRecoPi0 += (sr->ePi0 - sr->eRecoPi0) * scale; - if (sr->isCC && abs(sr->nuPDG)==12) { - sr->EVisReco_ND += (sr->LepE - sr->Elep_reco) * scale; - sr->Elep_reco += (sr->LepE - sr->Elep_reco) * scale; - } - } - } - - const EMRecoResND kEMRecoResND; - - - void ChargedHadRecoResND::Shift(double sigma, - caf::SRProxy* sr, - double& weight) const { - - const double scale = .02*sigma; - if (!sr->isFD) { - if (sr->eRecoP < 0.) sr->eRecoP = 0.; - if (sr->eRecoPip < 0.) sr->eRecoPip = 0.; - if (sr->eRecoPim < 0.) sr->eRecoPim = 0.; - const double trueSum = sr->ePip + sr->ePim + sr->eP; - const double recoSum = sr->eRecoPip + sr->eRecoPim + sr->eRecoP; - sr->eRecoPip += (sr->ePip - sr->eRecoPip) * scale; - sr->eRecoPim += (sr->ePim - sr->eRecoPim) * scale; - sr->eRecoP += (sr->eP - sr->eRecoP) * scale; - sr->EVisReco_ND += (trueSum - recoSum) * scale; - sr->HadEVisReco_ND += (trueSum - recoSum) * scale; - } - } - - const ChargedHadRecoResND kChargedHadRecoResND; - - RecoEnergyNDSystVector GetRecoENDSysts() { - - RecoEnergyNDSystVector vec; - vec.push_back(&kRecoEnergyScaleND); - vec.push_back(&kRecoEnergySqrtND); - vec.push_back(&kRecoEnergyInvSqrtND); - vec.push_back(&kEMRecoUncorrND); - vec.push_back(&kEMRecoUncorrSqrtND); - vec.push_back(&kEMRecoUncorrInvSqrtND); - vec.push_back(&kChargedHadRecoUncorrND); - vec.push_back(&kChargedHadRecoUncorrSqrtND); - vec.push_back(&kChargedHadRecoUncorrInvSqrtND); - vec.push_back(&kERecoScaleMuLArND); - vec.push_back(&kERecoScaleMuLArSqrtND); - vec.push_back(&kERecoScaleMuLArInvSqrtND); - vec.push_back(&kMuonRecoResND); - vec.push_back(&kEMRecoResND); - vec.push_back(&kChargedHadRecoResND); - - return vec; - } - - bool IsNDdetRecoSyst(std::string name) { - - std::vector syst_names; - for (const auto &syst : GetRecoENDSysts()) { - syst_names.emplace_back(syst->ShortName()); - } - - return (std::find(syst_names.begin(), - syst_names.end(), name) != - syst_names.end()); - } - - std::vector FilterOutNDSysts(std::vector systs) { - std::vector outs; - std::vector fsysts = GetRecoENDSysts(); - - for (auto syst : systs) { - if (std::find(fsysts.begin(), fsysts.end(), syst) == fsysts.end()) { - outs.emplace_back(syst); - } - } - return outs; - } +// void RecoEnergyScaleND::Shift(double sigma, +// caf::SRProxy* sr, +// double& weight) const { +// +// const double scale = 0.02 * sigma; +// if (!sr->isFD) { +// // To match FD: +// // Whether NC or CC, Numu or Nue, we want to shift total "reconstructed neutrino energy" +// // by the "reconstructed hadronic energy". +// sr->EVisReco_ND += (sr->EVisReco_ND - sr->Elep_reco) * scale; +// // Also shift the hadronic energy variable, if we don't do this then shifted +// // plots of the reconstructed hadronic energy will not be different to nominal. +// sr->HadEVisReco_ND *= 1. + scale; +// // If it isn't Numu-CC, also shift the "reconstructed neutrino energy" by the +// // "reconstructed leptonic energy". +// // Also shift the reconstructed leptonic energy itself. +// if (!(sr->isCC && abs(sr->nuPDG) == 14)) { +// sr->EVisReco_ND += sr->Elep_reco * scale; +// sr->Elep_reco *= 1. + scale; +// } +// } +// } +// +// const RecoEnergyScaleND kRecoEnergyScaleND; +// +// void RecoEnergySqrtND::Shift(double sigma, +// caf::SRProxy* sr, +// double& weight) const { +// +// const double scale = 0.01 * sigma; +// if (!sr->isFD) { +// // To match LBL TDR: +// // Whether NC or CC, Numu or Nue, we want to shift total "reconstructed neutrino energy" +// // by the "reconstructed hadronic energy". +// sr->EVisReco_ND += (sr->EVisReco_ND - sr->Elep_reco) * scale * +// pow((sr->EVisReco_ND - sr->Elep_reco), 0.5); +// // Also shift the hadronic energy variable, if we don't do this then shifted +// // plots of the reconstructed hadronic energy will not be different to nominal. +// sr->HadEVisReco_ND += sr->HadEVisReco_ND * scale * pow(sr->HadEVisReco_ND, 0.5); +// // If it isn't Numu-CC, also shift the "reconstructed neutrino energy" by the +// // "reconstructed leptonic energy". +// // Also shift the reconstructed leptonic energy itself. +// if (!(sr->isCC && abs(sr->nuPDG) == 14)) { +// sr->EVisReco_ND += sr->Elep_reco * scale * pow(sr->Elep_reco, 0.5); +// sr->Elep_reco += sr->Elep_reco * scale * pow(sr->Elep_reco, 0.5); +// } +// } +// } +// +// const RecoEnergySqrtND kRecoEnergySqrtND; +// +// void RecoEnergyInvSqrtND::Shift(double sigma, +// caf::SRProxy* sr, +// double& weight) const { +// +// const double scale = 0.02 * sigma; +// if (!sr->isFD) { +// // To match LBL TDR: +// // Whether NC or CC, Numu or Nue, we want to shift total "reconstructed neutrino energy" +// // by the "reconstructed hadronic energy". +// sr->EVisReco_ND += (sr->EVisReco_ND - sr->Elep_reco) * scale * +// pow((sr->EVisReco_ND - sr->Elep_reco+0.1), -0.5); +// // Also shift the hadronic energy variable, if we don't do this then shifted +// // plots of the reconstructed hadronic energy will not be different to nominal. +// sr->HadEVisReco_ND += sr->HadEVisReco_ND * scale * pow(sr->HadEVisReco_ND+0.1, -0.5); +// // If it isn't Numu-CC, also shift the "reconstructed neutrino energy" by the +// // "reconstructed leptonic energy". +// // Also shift the reconstructed leptonic energy itself. +// if (!(sr->isCC && abs(sr->nuPDG) == 14)) { +// sr->EVisReco_ND += sr->Elep_reco * scale * pow(sr->Elep_reco+0.1, -0.5); +// sr->Elep_reco += sr->Elep_reco * scale * pow(sr->Elep_reco+0.1, -0.5); +// } +// } +// } +// +// const RecoEnergyInvSqrtND kRecoEnergyInvSqrtND; +// +// +// void EMRecoUncorrND::Shift(double sigma, +// caf::SRProxy* sr, +// double& weight) const { +// +// const double scale = 0.025 * sigma; +// if (!sr->isFD) { // in the ND +// sr->eRecoPi0 += sr->eRecoPi0 * scale; +// sr->EVisReco_ND += sr->eRecoPi0 * scale; +// if (sr->isCC && abs(sr->nuPDG) == 12) { +// sr->Elep_reco += sr->Elep_reco * scale; +// sr->EVisReco_ND += sr->Elep_reco * scale; +// } +// } +// } +// +// const EMRecoUncorrND kEMRecoUncorrND; +// +// void EMRecoUncorrSqrtND::Shift(double sigma, +// caf::SRProxy* sr, +// double& weight) const { +// +// const double scale = 0.025 * sigma; +// if (!sr->isFD) { // in the ND +// sr->eRecoPi0 += sr->eRecoPi0 * scale * pow(sr->eRecoPi0, 0.5); +// sr->EVisReco_ND += sr->eRecoPi0 * scale * pow(sr->eRecoPi0, 0.5); +// if (sr->isCC && abs(sr->nuPDG) == 12) { +// sr->Elep_reco += sr->Elep_reco * scale * pow(sr->Elep_reco, 0.5); +// sr->EVisReco_ND += sr->Elep_reco * scale * pow(sr->Elep_reco, 0.5); +// } +// } +// } +// +// const EMRecoUncorrSqrtND kEMRecoUncorrSqrtND; +// +// void EMRecoUncorrInvSqrtND::Shift(double sigma, +// caf::SRProxy* sr, +// double& weight) const { +// +// const double scale = 0.025 * sigma; +// if (!sr->isFD) { // in the ND +// sr->eRecoPi0 += sr->eRecoPi0 * scale * pow(sr->eRecoPi0+0.1, -0.5); +// sr->EVisReco_ND += sr->eRecoPi0 * scale * pow(sr->eRecoPi0+0.1, -0.5); +// if (sr->isCC && abs(sr->nuPDG) == 12) { +// sr->Elep_reco += sr->Elep_reco * scale * pow(sr->Elep_reco+0.1, -0.5); +// sr->EVisReco_ND += sr->Elep_reco * scale * pow(sr->Elep_reco+0.1, -0.5); +// } +// } +// } +// +// const EMRecoUncorrInvSqrtND kEMRecoUncorrInvSqrtND; +// +// void ChargedHadRecoUncorrND::Shift(double sigma, +// caf::SRProxy* sr, +// double& weight) const { +// +// const double scale = 0.05 * sigma; +// if (!sr->isFD) { // in the ND +// if (sr->eRecoP < 0) sr->eRecoP = 0.; +// if (sr->eRecoPim < 0) sr->eRecoPim = 0.; +// if (sr->eRecoPip < 0) sr->eRecoPip = 0.; +// const double sumE = sr->eRecoP + sr->eRecoPim + sr->eRecoPip; +// sr->eRecoPip += sr->eRecoPip * scale; +// sr->eRecoPim += sr->eRecoPim * scale; +// sr->eRecoP += sr->eRecoP * scale; +// sr->EVisReco_ND += sumE * scale; +// sr->HadEVisReco_ND += sumE * scale; +// } +// } +// +// const ChargedHadRecoUncorrND kChargedHadRecoUncorrND; +// +// void ChargedHadRecoUncorrSqrtND::Shift(double sigma, +// caf::SRProxy* sr, +// double& weight) const { +// +// const double scale = 0.05 * sigma; +// if (!sr->isFD) { // in the ND +// if (sr->eRecoP < 0) sr->eRecoP = 0.; +// if (sr->eRecoPim < 0) sr->eRecoPim = 0.; +// if (sr->eRecoPip < 0) sr->eRecoPip = 0.; +// const double sumE = sr->eRecoPip + sr->eRecoPim + sr->eRecoP; +// sr->eRecoPip += sr->eRecoPip * scale * pow(sr->eRecoPip, 0.5); +// sr->eRecoPim += sr->eRecoPim * scale * pow(sr->eRecoPim, 0.5); +// sr->eRecoP += sr->eRecoP * scale * pow(sr->eRecoP, 0.5); +// sr->EVisReco_ND += sumE * scale * pow(sumE, 0.5); +// sr->HadEVisReco_ND += sumE * scale * pow(sumE, 0.5); +// } +// } +// +// const ChargedHadRecoUncorrSqrtND kChargedHadRecoUncorrSqrtND; +// +// void ChargedHadRecoUncorrInvSqrtND::Shift(double sigma, +// caf::SRProxy* sr, +// double& weight) const { +// +// const double scale = 0.05 * sigma; +// if (!sr->isFD) { // in the ND +// if (sr->eRecoP < 0) sr->eRecoP = 0.; +// if (sr->eRecoPim < 0) sr->eRecoPim = 0.; +// if (sr->eRecoPip < 0) sr->eRecoPip = 0.; +// const double sumE = sr->eRecoPip + sr->eRecoPim + sr->eRecoP; +// sr->eRecoPip += sr->eRecoPip * scale * pow(sr->eRecoPip+0.1, -0.5); +// sr->eRecoPim += sr->eRecoPim * scale * pow(sr->eRecoPim+0.1, -0.5); +// sr->eRecoP += sr->eRecoP * scale * pow(sr->eRecoP+0.1, -0.5); +// sr->EVisReco_ND += sumE * scale * pow(sumE+0.1, -0.5); +// sr->HadEVisReco_ND += sumE * scale * pow(sumE+0.1, -0.5); +// } +// } +// +// const ChargedHadRecoUncorrInvSqrtND kChargedHadRecoUncorrInvSqrtND; +// +// void ERecoScaleMuLArND::Shift(double sigma, +// caf::SRProxy* sr, +// double& weight) const { +// +// // Different EScale uncertainty for reconstruction by range or in +// // GAr tracker +// double var(0); +// if (sr->muon_contained) var = 0.02; +// else if (sr->muon_tracker) var = 0.01; +// else var = 0.02; // selection requires muon to be inLAr or GAr so never get here +// const double scale = var * sigma; +// if (!sr->isFD) { // in the ND +// if (sr->isCC && abs(sr->nuPDG) == 14) { +// sr->Elep_reco += sr->Elep_reco * scale; +// sr->EVisReco_ND += sr->Elep_reco * scale; +// } +// } +// } +// +// const ERecoScaleMuLArND kERecoScaleMuLArND; +// +// void ERecoScaleMuLArSqrtND::Shift(double sigma, +// caf::SRProxy* sr, +// double& weight) const { +// +// double var(0); +// if (sr->muon_contained) var = 0.02; +// else if (sr->muon_tracker) var = 0.01; +// else var = 0.02; // selection requires muon to be inLAr or GAr so never get here +// const double scale = var * sigma; // is 0.005 in FD +// if (!sr->isFD) { // in the ND +// if (sr->isCC && abs(sr->nuPDG) == 14) { +// sr->Elep_reco += sr->Elep_reco * scale * pow(sr->Elep_reco, 0.5); +// sr->EVisReco_ND += sr->Elep_reco * scale * pow(sr->Elep_reco, 0.5); +// } +// } +// } +// +// const ERecoScaleMuLArSqrtND kERecoScaleMuLArSqrtND; +// +// void ERecoScaleMuLArInvSqrtND::Shift(double sigma, +// caf::SRProxy* sr, +// double& weight) const { +// +// double var(0); +// if (sr->muon_contained) var = 0.02; +// else if (sr->muon_tracker) var = 0.01; +// else var = 0.02; // selection requires muon to be inLAr or GAr so never get here +// const double scale = var * sigma; +// if (!sr->isFD) { // in the ND +// if (sr->isCC && abs(sr->nuPDG) == 14) { +// sr->Elep_reco += sr->Elep_reco * scale * pow(sr->Elep_reco+0.1, -0.5); +// sr->EVisReco_ND += sr->Elep_reco * scale * pow(sr->Elep_reco+0.1, -0.5); +// } +// } +// } +// +// const ERecoScaleMuLArInvSqrtND kERecoScaleMuLArInvSqrtND; +// +// // Resolution Syst +// +// void MuonRecoResND::Shift(double sigma, +// caf::SRProxy* sr, +// double& weight) const { +// +// const double scale = 0.02 * sigma; +// if (!sr->isFD) { // in the ND +// sr->Elep_reco += (sr->LepE - sr->Elep_reco) * scale; +// sr->EVisReco_ND += (sr->LepE - sr->Elep_reco) * scale; +// } +// } +// +// const MuonRecoResND kMuonRecoResND; +// +// void EMRecoResND::Shift(double sigma, +// caf::SRProxy* sr, +// double& weight) const { +// +// const double scale = .02*sigma; +// if (!sr->isFD){ +// sr->EVisReco_ND += (sr->ePi0 - sr->eRecoPi0) * scale; +// sr->eRecoPi0 += (sr->ePi0 - sr->eRecoPi0) * scale; +// if (sr->isCC && abs(sr->nuPDG)==12) { +// sr->EVisReco_ND += (sr->LepE - sr->Elep_reco) * scale; +// sr->Elep_reco += (sr->LepE - sr->Elep_reco) * scale; +// } +// } +// } +// +// const EMRecoResND kEMRecoResND; +// +// +// void ChargedHadRecoResND::Shift(double sigma, +// caf::SRProxy* sr, +// double& weight) const { +// +// const double scale = .02*sigma; +// if (!sr->isFD) { +// if (sr->eRecoP < 0.) sr->eRecoP = 0.; +// if (sr->eRecoPip < 0.) sr->eRecoPip = 0.; +// if (sr->eRecoPim < 0.) sr->eRecoPim = 0.; +// const double trueSum = sr->ePip + sr->ePim + sr->eP; +// const double recoSum = sr->eRecoPip + sr->eRecoPim + sr->eRecoP; +// sr->eRecoPip += (sr->ePip - sr->eRecoPip) * scale; +// sr->eRecoPim += (sr->ePim - sr->eRecoPim) * scale; +// sr->eRecoP += (sr->eP - sr->eRecoP) * scale; +// sr->EVisReco_ND += (trueSum - recoSum) * scale; +// sr->HadEVisReco_ND += (trueSum - recoSum) * scale; +// } +// } +// +// const ChargedHadRecoResND kChargedHadRecoResND; +// +// RecoEnergyNDSystVector GetRecoENDSysts() { +// +// RecoEnergyNDSystVector vec; +// vec.push_back(&kRecoEnergyScaleND); +// vec.push_back(&kRecoEnergySqrtND); +// vec.push_back(&kRecoEnergyInvSqrtND); +// vec.push_back(&kEMRecoUncorrND); +// vec.push_back(&kEMRecoUncorrSqrtND); +// vec.push_back(&kEMRecoUncorrInvSqrtND); +// vec.push_back(&kChargedHadRecoUncorrND); +// vec.push_back(&kChargedHadRecoUncorrSqrtND); +// vec.push_back(&kChargedHadRecoUncorrInvSqrtND); +// vec.push_back(&kERecoScaleMuLArND); +// vec.push_back(&kERecoScaleMuLArSqrtND); +// vec.push_back(&kERecoScaleMuLArInvSqrtND); +// vec.push_back(&kMuonRecoResND); +// vec.push_back(&kEMRecoResND); +// vec.push_back(&kChargedHadRecoResND); +// +// return vec; +// } +// +// bool IsNDdetRecoSyst(std::string name) { +// +// std::vector syst_names; +// for (const auto &syst : GetRecoENDSysts()) { +// syst_names.emplace_back(syst->ShortName()); +// } +// +// return (std::find(syst_names.begin(), +// syst_names.end(), name) != +// syst_names.end()); +// } +// +// std::vector FilterOutNDSysts(std::vector systs) { +// std::vector outs; +// std::vector fsysts = GetRecoENDSysts(); +// +// for (auto syst : systs) { +// if (std::find(fsysts.begin(), fsysts.end(), syst) == fsysts.end()) { +// outs.emplace_back(syst); +// } +// } +// return outs; +// } } diff --git a/CAFAna/Systs/RecoEnergyNDSysts.h b/CAFAna/Systs/RecoEnergyNDSysts.h index 8ac7bf4a..6303751f 100644 --- a/CAFAna/Systs/RecoEnergyNDSysts.h +++ b/CAFAna/Systs/RecoEnergyNDSysts.h @@ -23,226 +23,226 @@ class TH2; namespace ana { - class SystShifts; - - class RecoEnergyScaleND : public ISyst { - public: - RecoEnergyScaleND() : ISyst("RecoEnergyScaleND", "Global Reco Energy Scale ND Syst") {} - void Shift(double sigma, - caf::SRProxy* sr, - double& weight) const override; - - }; - - extern const RecoEnergyScaleND kRecoEnergyScaleND; - - // Total energy scale syst varying with sqrt of the energy - class RecoEnergySqrtND: public ISyst { - public: - RecoEnergySqrtND() : ISyst("RecoEnergySqrtND", "Sqrt Reco Energy Scale ND Syst") {} - void Shift(double sigma, - caf::SRProxy* sr, - double& weight) const override; - - }; - - extern const RecoEnergySqrtND kRecoEnergySqrtND; - - // Total energy scale syst varying with inverse sqrt of the energy - class RecoEnergyInvSqrtND: public ISyst { - public: - RecoEnergyInvSqrtND() : ISyst("RecoEnergyInvSqrtND", "Inv Sqrt Total Energy Scale ND Syst") {} - void Shift(double sigma, - caf::SRProxy* sr, - double& weight) const override; - - }; - - extern const RecoEnergyInvSqrtND kRecoEnergyInvSqrtND; - - //------------------------------------------------------------------------------ - // Electromagnetic - - // Systematic for pi0s and electrons - // 2.5% on true energy of electrons and pi0s - class EMRecoUncorrND : public ISyst { - public: - EMRecoUncorrND() : ISyst("EMRecoUncorrND", "EM Shower Uncorrelated ND Syst") {} - - void Shift(double sigma, - caf::SRProxy* sr, - double& weight) const override; - - }; - - extern const EMRecoUncorrND kEMRecoUncorrND; - - // 2.5% systematic on EM energy for sqrt parameter - // - class EMRecoUncorrSqrtND : public ISyst { - public: - EMRecoUncorrSqrtND() : ISyst("EMRecoUncorrSqrtND", "EM Shower Uncorrelated ND Syst Sqrt") {} - - void Shift(double sigma, - caf::SRProxy* sr, - double& weight) const override; - - }; - - extern const EMRecoUncorrSqrtND kEMRecoUncorrSqrtND; - - // 2.5% syst on EM energy for inv sqrt param - // - class EMRecoUncorrInvSqrtND : public ISyst { - public: - EMRecoUncorrInvSqrtND() : ISyst("EMRecoUncorrInvSqrtND", "EM Shower Uncorrelated ND Syst Inv Sqrt") {} - - void Shift(double sigma, - caf::SRProxy* sr, - double& weight) const override; - - }; - - extern const EMRecoUncorrInvSqrtND kEMRecoUncorrInvSqrtND; - - //--------------------------------------------------------------------- - // Charged Hadrons - - // Systematic for charged hadrons: p, pi+, pi- - // 5% on true energy of charged pions and protons - class ChargedHadRecoUncorrND : public ISyst { - public: - ChargedHadRecoUncorrND() : ISyst("ChargedHadRecoUncorrND", "Charged Hadron Uncorrelated ND Syst") {} - - void Shift(double sigma, - caf::SRProxy* sr, - double& weight) const override; - - }; - - extern const ChargedHadRecoUncorrND kChargedHadRecoUncorrND; - - // 5% syst for charged hadrons sqrt param - // - class ChargedHadRecoUncorrSqrtND : public ISyst { - public: - ChargedHadRecoUncorrSqrtND() : ISyst("ChargedHadRecoUncorrSqrtND", "Charged Had Uncorrelated Sqrt ND Syst") {} - - void Shift(double sigma, - caf::SRProxy* sr, - double& weight) const override; - - }; - - extern const ChargedHadRecoUncorrSqrtND kChargedHadRecoUncorrSqrtND; - - // 5% syst for charged hadrons inv sqrt param - // - class ChargedHadRecoUncorrInvSqrtND : public ISyst { - public: - ChargedHadRecoUncorrInvSqrtND() : ISyst("ChargedHadRecoUncorrInvSqrtND", "Charged Had Uncorrelated Inv Sqrt ND Syst") {} - - void Shift(double sigma, - caf::SRProxy* sr, - double& weight) const override; - - }; - - extern const ChargedHadRecoUncorrInvSqrtND kChargedHadRecoUncorrInvSqrtND; - - //------------------------------------------------------------------- - // Muons - - // Systematic for Muon - // 2% on true energy of muon from CC numu event - class ERecoScaleMuLArND : public ISyst { - public: - ERecoScaleMuLArND() : ISyst("ERecoScaleMuLArND", "Muon Energy Scale ND Syst") {} - - void Shift(double sigma, - caf::SRProxy* sr, - double& weight) const override; - - }; - - extern const ERecoScaleMuLArND kERecoScaleMuLArND; - - // true energy of muon from CC numu event - // Sqrt param 2% for LArTPC - class ERecoScaleMuLArSqrtND : public ISyst { - public: - ERecoScaleMuLArSqrtND() : ISyst("ERecoScaleMuLArSqrtND", "Muon E Scale Sqrt ND Syst") {} - - void Shift(double sigma, - caf::SRProxy* sr, - double& weight) const override; - - }; - - extern const ERecoScaleMuLArSqrtND kERecoScaleMuLArSqrtND; - - // 2% on true energy of muon from CC numu event - // Inv Sqrt param - class ERecoScaleMuLArInvSqrtND : public ISyst { - public: - ERecoScaleMuLArInvSqrtND() : ISyst("ERecoScaleMuLArInvSqrtND", "Muon E Scale Inv Sqrt ND Syst") {} - - void Shift(double sigma, - caf::SRProxy* sr, - double& weight) const override; - - }; - - extern const ERecoScaleMuLArInvSqrtND kERecoScaleMuLArInvSqrtND; - - //--------------------------------------------------------------------------------- - - // Resolution systematics for Muon - class MuonRecoResND : public ISyst { - public: - MuonRecoResND() : ISyst("MuonRecoResND", "Muon Near Detector Resolution") {} - - void Shift(double sigma, - caf::SRProxy* sr, - double& weight) const override; - - }; - - extern const MuonRecoResND kMuonRecoResND; - - // Electron/pi0 energy resolution - class EMRecoResND: public ISyst - { - public: - EMRecoResND() : ISyst("EMRecoResND", "EM shower Near Detector Resolution Syst") {} - void Shift(double sigma, - caf::SRProxy* sr, double& weight) const override; - - }; - - extern const EMRecoResND kEMRecoResND; - - // Charged hadron energy resolution - class ChargedHadRecoResND: public ISyst - { - public: - ChargedHadRecoResND() : ISyst("ChargedHadRecoResND", "Charged Hadron Near Detector Resolution Syst") {} - void Shift(double sigma, - caf::SRProxy* sr, double& weight) const override; - - }; - - extern const ChargedHadRecoResND kChargedHadRecoResND; - - //--------------------------------------------------------------------------------- - - // Vector of the reco energy scale systematics - struct RecoEnergyNDSystVector : public std::vector {}; - - RecoEnergyNDSystVector GetRecoENDSysts(); - - bool IsNDdetRecoSyst(std::string); - - std::vector FilterOutNDSysts(std::vector systs); +// class SystShifts; +// +// class RecoEnergyScaleND : public ISyst { +// public: +// RecoEnergyScaleND() : ISyst("RecoEnergyScaleND", "Global Reco Energy Scale ND Syst") {} +// void Shift(double sigma, +// caf::SRProxy* sr, +// double& weight) const override; +// +// }; +// +// extern const RecoEnergyScaleND kRecoEnergyScaleND; +// +// // Total energy scale syst varying with sqrt of the energy +// class RecoEnergySqrtND: public ISyst { +// public: +// RecoEnergySqrtND() : ISyst("RecoEnergySqrtND", "Sqrt Reco Energy Scale ND Syst") {} +// void Shift(double sigma, +// caf::SRProxy* sr, +// double& weight) const override; +// +// }; +// +// extern const RecoEnergySqrtND kRecoEnergySqrtND; +// +// // Total energy scale syst varying with inverse sqrt of the energy +// class RecoEnergyInvSqrtND: public ISyst { +// public: +// RecoEnergyInvSqrtND() : ISyst("RecoEnergyInvSqrtND", "Inv Sqrt Total Energy Scale ND Syst") {} +// void Shift(double sigma, +// caf::SRProxy* sr, +// double& weight) const override; +// +// }; +// +// extern const RecoEnergyInvSqrtND kRecoEnergyInvSqrtND; +// +// //------------------------------------------------------------------------------ +// // Electromagnetic +// +// // Systematic for pi0s and electrons +// // 2.5% on true energy of electrons and pi0s +// class EMRecoUncorrND : public ISyst { +// public: +// EMRecoUncorrND() : ISyst("EMRecoUncorrND", "EM Shower Uncorrelated ND Syst") {} +// +// void Shift(double sigma, +// caf::SRProxy* sr, +// double& weight) const override; +// +// }; +// +// extern const EMRecoUncorrND kEMRecoUncorrND; +// +// // 2.5% systematic on EM energy for sqrt parameter +// // +// class EMRecoUncorrSqrtND : public ISyst { +// public: +// EMRecoUncorrSqrtND() : ISyst("EMRecoUncorrSqrtND", "EM Shower Uncorrelated ND Syst Sqrt") {} +// +// void Shift(double sigma, +// caf::SRProxy* sr, +// double& weight) const override; +// +// }; +// +// extern const EMRecoUncorrSqrtND kEMRecoUncorrSqrtND; +// +// // 2.5% syst on EM energy for inv sqrt param +// // +// class EMRecoUncorrInvSqrtND : public ISyst { +// public: +// EMRecoUncorrInvSqrtND() : ISyst("EMRecoUncorrInvSqrtND", "EM Shower Uncorrelated ND Syst Inv Sqrt") {} +// +// void Shift(double sigma, +// caf::SRProxy* sr, +// double& weight) const override; +// +// }; +// +// extern const EMRecoUncorrInvSqrtND kEMRecoUncorrInvSqrtND; +// +// //--------------------------------------------------------------------- +// // Charged Hadrons +// +// // Systematic for charged hadrons: p, pi+, pi- +// // 5% on true energy of charged pions and protons +// class ChargedHadRecoUncorrND : public ISyst { +// public: +// ChargedHadRecoUncorrND() : ISyst("ChargedHadRecoUncorrND", "Charged Hadron Uncorrelated ND Syst") {} +// +// void Shift(double sigma, +// caf::SRProxy* sr, +// double& weight) const override; +// +// }; +// +// extern const ChargedHadRecoUncorrND kChargedHadRecoUncorrND; +// +// // 5% syst for charged hadrons sqrt param +// // +// class ChargedHadRecoUncorrSqrtND : public ISyst { +// public: +// ChargedHadRecoUncorrSqrtND() : ISyst("ChargedHadRecoUncorrSqrtND", "Charged Had Uncorrelated Sqrt ND Syst") {} +// +// void Shift(double sigma, +// caf::SRProxy* sr, +// double& weight) const override; +// +// }; +// +// extern const ChargedHadRecoUncorrSqrtND kChargedHadRecoUncorrSqrtND; +// +// // 5% syst for charged hadrons inv sqrt param +// // +// class ChargedHadRecoUncorrInvSqrtND : public ISyst { +// public: +// ChargedHadRecoUncorrInvSqrtND() : ISyst("ChargedHadRecoUncorrInvSqrtND", "Charged Had Uncorrelated Inv Sqrt ND Syst") {} +// +// void Shift(double sigma, +// caf::SRProxy* sr, +// double& weight) const override; +// +// }; +// +// extern const ChargedHadRecoUncorrInvSqrtND kChargedHadRecoUncorrInvSqrtND; +// +// //------------------------------------------------------------------- +// // Muons +// +// // Systematic for Muon +// // 2% on true energy of muon from CC numu event +// class ERecoScaleMuLArND : public ISyst { +// public: +// ERecoScaleMuLArND() : ISyst("ERecoScaleMuLArND", "Muon Energy Scale ND Syst") {} +// +// void Shift(double sigma, +// caf::SRProxy* sr, +// double& weight) const override; +// +// }; +// +// extern const ERecoScaleMuLArND kERecoScaleMuLArND; +// +// // true energy of muon from CC numu event +// // Sqrt param 2% for LArTPC +// class ERecoScaleMuLArSqrtND : public ISyst { +// public: +// ERecoScaleMuLArSqrtND() : ISyst("ERecoScaleMuLArSqrtND", "Muon E Scale Sqrt ND Syst") {} +// +// void Shift(double sigma, +// caf::SRProxy* sr, +// double& weight) const override; +// +// }; +// +// extern const ERecoScaleMuLArSqrtND kERecoScaleMuLArSqrtND; +// +// // 2% on true energy of muon from CC numu event +// // Inv Sqrt param +// class ERecoScaleMuLArInvSqrtND : public ISyst { +// public: +// ERecoScaleMuLArInvSqrtND() : ISyst("ERecoScaleMuLArInvSqrtND", "Muon E Scale Inv Sqrt ND Syst") {} +// +// void Shift(double sigma, +// caf::SRProxy* sr, +// double& weight) const override; +// +// }; +// +// extern const ERecoScaleMuLArInvSqrtND kERecoScaleMuLArInvSqrtND; +// +// //--------------------------------------------------------------------------------- +// +// // Resolution systematics for Muon +// class MuonRecoResND : public ISyst { +// public: +// MuonRecoResND() : ISyst("MuonRecoResND", "Muon Near Detector Resolution") {} +// +// void Shift(double sigma, +// caf::SRProxy* sr, +// double& weight) const override; +// +// }; +// +// extern const MuonRecoResND kMuonRecoResND; +// +// // Electron/pi0 energy resolution +// class EMRecoResND: public ISyst +// { +// public: +// EMRecoResND() : ISyst("EMRecoResND", "EM shower Near Detector Resolution Syst") {} +// void Shift(double sigma, +// caf::SRProxy* sr, double& weight) const override; +// +// }; +// +// extern const EMRecoResND kEMRecoResND; +// +// // Charged hadron energy resolution +// class ChargedHadRecoResND: public ISyst +// { +// public: +// ChargedHadRecoResND() : ISyst("ChargedHadRecoResND", "Charged Hadron Near Detector Resolution Syst") {} +// void Shift(double sigma, +// caf::SRProxy* sr, double& weight) const override; +// +// }; +// +// extern const ChargedHadRecoResND kChargedHadRecoResND; +// +// //--------------------------------------------------------------------------------- +// +// // Vector of the reco energy scale systematics +// struct RecoEnergyNDSystVector : public std::vector {}; +// +// RecoEnergyNDSystVector GetRecoENDSysts(); +// +// bool IsNDdetRecoSyst(std::string); +// +// std::vector FilterOutNDSysts(std::vector systs); } diff --git a/CAFAna/Systs/Systs.h b/CAFAna/Systs/Systs.h index 47e88f15..b02171bf 100644 --- a/CAFAna/Systs/Systs.h +++ b/CAFAna/Systs/Systs.h @@ -10,6 +10,9 @@ namespace ana { + +// Just leaving everything at a flat 5% normalization shift because I'm too lazy to actually update these + ///ETW Rework of Normalization Systematics //Signal normalization @@ -23,7 +26,9 @@ namespace ana void Shift(double sigma, caf::SRProxy* sr, double& weight) const override { - if(sr->isCC && abs(sr->nuPDG)==14 && sr->run==20000001) weight *= 1 + .05*sigma; + //if(sr->isCC && abs(sr->nuPDG)==14 && sr->run==20000001) weight *= 1 + .05*sigma; + // if(sr->mc.nu[0].iscc && abs(sr->mc.nu[0].pdg)==14 && sr->run==20000001) weight *= 1 + .05*sigma; + weight *= 1 + .05*sigma; } }; @@ -38,7 +43,8 @@ namespace ana void Shift(double sigma, caf::SRProxy* sr, double& weight) const override { - if(sr->isCC && abs(sr->nuPDG)==14 && sr->run==20000004) weight *= 1 + .05*sigma; + //if(sr->isCC && abs(sr->nuPDG)==14 && sr->run==20000004) weight *= 1 + .05*sigma; + weight *= 1 + .05*sigma; } }; @@ -53,7 +59,8 @@ namespace ana void Shift(double sigma, caf::SRProxy* sr, double& weight) const override { - if(sr->isCC && abs(sr->nuPDG)==12 && sr->run==20000002) weight *= 1 + .02*sigma; + //if(sr->isCC && abs(sr->nuPDG)==12 && sr->run==20000002) weight *= 1 + .02*sigma; + weight *= 1 + .05*sigma; } }; @@ -68,7 +75,8 @@ namespace ana void Shift(double sigma, caf::SRProxy* sr, double& weight) const override { - if(sr->isCC && abs(sr->nuPDG)==12 && sr->run==20000005) weight *= 1 + .02*sigma; + //if(sr->isCC && abs(sr->nuPDG)==12 && sr->run==20000005) weight *= 1 + .02*sigma; + weight *= 1 + .05*sigma; } }; @@ -85,7 +93,8 @@ namespace ana void Shift(double sigma, caf::SRProxy* sr, double& weight) const override { - if(!sr->isCC && sr->cvnnumu > 0.5 && sr->cvnnue < 0.5) weight *= 1 + .1*sigma; + //if(!sr->isCC && sr->cvnnumu > 0.5 && sr->cvnnue < 0.5) weight *= 1 + .1*sigma; + weight *= 1 + .05*sigma; } }; @@ -100,7 +109,8 @@ namespace ana void Shift(double sigma, caf::SRProxy* sr, double& weight) const override { - if((!sr->isCC && sr->cvnnue > 0.5 && sr->cvnnumu < 0.5) || (sr->isCC && abs(sr->nuPDG)==14)) weight *= 1 + .05*sigma; + //if((!sr->isCC && sr->cvnnue > 0.5 && sr->cvnnumu < 0.5) || (sr->isCC && abs(sr->nuPDG)==14)) weight *= 1 + .05*sigma; + weight *= 1 + .05*sigma; } }; @@ -115,7 +125,8 @@ namespace ana void Shift(double sigma, caf::SRProxy* sr, double& weight) const override { - if(sr->isCC && abs(sr->nuPDG)==16) weight *= 1 + .2*sigma; + //if(sr->isCC && abs(sr->nuPDG)==16) weight *= 1 + .2*sigma; + weight *= 1 + .05*sigma; } }; @@ -130,7 +141,8 @@ namespace ana void Shift(double sigma, caf::SRProxy* sr, double& weight) const override { - if(sr->isCC && abs(sr->nuPDG) == 12 && abs(sr->nuPDGunosc) == 12 && sr->run<20000004) weight *= 1 + .05*sigma; + //if(sr->isCC && abs(sr->nuPDG) == 12 && abs(sr->nuPDGunosc) == 12 && sr->run<20000004) weight *= 1 + .05*sigma; + weight *= 1 + .05*sigma; } }; @@ -145,7 +157,8 @@ namespace ana void Shift(double sigma, caf::SRProxy* sr, double& weight) const override { - if(sr->isCC && abs(sr->nuPDG) == 12 && abs(sr->nuPDGunosc) == 12 && !(sr->run<20000004)) weight *= 1 + .05*sigma; + //if(sr->isCC && abs(sr->nuPDG) == 12 && abs(sr->nuPDGunosc) == 12 && !(sr->run<20000004)) weight *= 1 + .05*sigma; + weight *= 1 + .05*sigma; } }; diff --git a/CAFAna/Systs/XSecSystList.cxx b/CAFAna/Systs/XSecSystList.cxx index a678f123..c5f48c6d 100644 --- a/CAFAna/Systs/XSecSystList.cxx +++ b/CAFAna/Systs/XSecSystList.cxx @@ -7,150 +7,150 @@ #include namespace ana { -const std::vector kAllXsecSysts = GetXSecSysts(); - -///\\\///\\\///\\\/// Get a specific list -std::vector GetXSecSystNames(std::string const &inputCategg) { - - if (inputCategg == "All") { - return GetFitSystNames(); - } - - std::vector XSecSystNames; - XSecCategg thisCategg = kNahMate; - if (inputCategg == "QELike") - thisCategg = kQELike; - if (inputCategg == "RES") - thisCategg = kRES; - if (inputCategg == "DIS") - thisCategg = kDIS; - if (inputCategg == "FSI") - thisCategg = kFSI; - if (inputCategg == "Ratios") - thisCategg = kRatios; - if (inputCategg == "NC") - thisCategg = kNC; - if (inputCategg == "Other") - thisCategg = kOther; - - static auto XSecDials = GetAllXSecDials(); - for (auto const &s : XSecDials) { - if (s.IsFitSyst != kFitSyst) { - continue; - } - if (s.Categg == thisCategg) { - XSecSystNames.push_back(s.Name); - } // Just for you Luke ;p - } - - return XSecSystNames; -} - -/// All dials used as freedoms in standard fits -std::vector const &GetFitSystNames() { - static std::vector XSecSystNames; - static bool first = true; - if (first) { - first = false; - for (auto const &s : GetAllXSecDials()) { - if (s.IsFitSyst == kFitSyst) { - XSecSystNames.push_back(s.Name); - } - } - } - - return XSecSystNames; -} - -/// Dials which have an extrapolated response outside of 0->1 -std::vector const &GetExtrapolateOffToOnSystNames() { - static std::vector XSecSystNames; - static bool first = true; - if (first) { - first = false; - for (auto const &s : GetAllXSecDials()) { - if (s.IsExtrapolateOffToOnSyst == kExtrapolated) { - XSecSystNames.push_back(s.Name); - } - } - } - - return XSecSystNames; -} -/// Dials used to generate fake data sets when set to 1, should not be fit. -std::vector const &GetFakeDataGenerationSystNames() { - static std::vector XSecSystNames; - static bool first = true; - if (first) { - first = false; - for (auto const &s : GetAllXSecDials()) { - if (s.IsFitSyst == kUsedAsFakeData) { - XSecSystNames.push_back(s.Name); - } - } - } - - return XSecSystNames; -} - -int GetXSecSystIndex(std::string const &name) { - static auto XSecDials = GetAllXSecDials(); - - static std::map cache; - if (!cache.count(name)) { - int found = -1; - for (size_t it = 0; it < XSecDials.size(); ++it) { - if (XSecDials[it].Name == name) { - found = it; - break; - } - } - assert(found > -1); - cache[name] = found; - } - return cache[name]; -} - -/// Convenience method for checking if a dial is -bool IsExtrapolateOffToOnSyst(std::string const &name) { - static std::unordered_map cache; - if (!cache.count(name)) { - cache[name] = SystNameIsInList(name, GetExtrapolateOffToOnSystNames()); - } - return cache[name]; -} -bool IsExtrapolateOffToOnSyst(int index) { - static std::unordered_map cache; - if (!cache.count(index)) { - cache[index] = IsExtrapolateOffToOnSyst(GetXSecSystName(index)); - } - return cache[index]; -} - -bool IsFakeDataGenerationSyst(std::string const &name) { - static std::unordered_map cache; - if (!cache.count(name)) { - cache[name] = SystNameIsInList(name, GetFakeDataGenerationSystNames()); - } - return cache[name]; -} -bool IsFakeDataGenerationSyst(int index) { - static std::unordered_map cache; - if (!cache.count(index)) { - cache[index] = IsFakeDataGenerationSyst(GetXSecSystName(index)); - } - return cache[index]; -} - -std::pair GetXSecSystLimits(int index) { - static auto XSecDials = GetAllXSecDials(); - assert((index >= 0) && (index < int(XSecDials.size()))); - return XSecDials[index].FitLimits; -} -std::pair GetXSecSystLimits(const std::string &name) { - return GetXSecSystLimits(GetXSecSystIndex(name)); -} -double GetXSecSystMax(int index) { return GetXSecSystLimits(index).second; } -double GetXSecSystMin(int index) { return GetXSecSystLimits(index).first; } +//const std::vector kAllXsecSysts = GetXSecSysts(); +// +/////\\\///\\\///\\\/// Get a specific list +//std::vector GetXSecSystNames(std::string const &inputCategg) { +// +// if (inputCategg == "All") { +// return GetFitSystNames(); +// } +// +// std::vector XSecSystNames; +// XSecCategg thisCategg = kNahMate; +// if (inputCategg == "QELike") +// thisCategg = kQELike; +// if (inputCategg == "RES") +// thisCategg = kRES; +// if (inputCategg == "DIS") +// thisCategg = kDIS; +// if (inputCategg == "FSI") +// thisCategg = kFSI; +// if (inputCategg == "Ratios") +// thisCategg = kRatios; +// if (inputCategg == "NC") +// thisCategg = kNC; +// if (inputCategg == "Other") +// thisCategg = kOther; +// +// static auto XSecDials = GetAllXSecDials(); +// for (auto const &s : XSecDials) { +// if (s.IsFitSyst != kFitSyst) { +// continue; +// } +// if (s.Categg == thisCategg) { +// XSecSystNames.push_back(s.Name); +// } // Just for you Luke ;p +// } +// +// return XSecSystNames; +//} +// +///// All dials used as freedoms in standard fits +//std::vector const &GetFitSystNames() { +// static std::vector XSecSystNames; +// static bool first = true; +// if (first) { +// first = false; +// for (auto const &s : GetAllXSecDials()) { +// if (s.IsFitSyst == kFitSyst) { +// XSecSystNames.push_back(s.Name); +// } +// } +// } +// +// return XSecSystNames; +//} +// +///// Dials which have an extrapolated response outside of 0->1 +//std::vector const &GetExtrapolateOffToOnSystNames() { +// static std::vector XSecSystNames; +// static bool first = true; +// if (first) { +// first = false; +// for (auto const &s : GetAllXSecDials()) { +// if (s.IsExtrapolateOffToOnSyst == kExtrapolated) { +// XSecSystNames.push_back(s.Name); +// } +// } +// } +// +// return XSecSystNames; +//} +///// Dials used to generate fake data sets when set to 1, should not be fit. +//std::vector const &GetFakeDataGenerationSystNames() { +// static std::vector XSecSystNames; +// static bool first = true; +// if (first) { +// first = false; +// for (auto const &s : GetAllXSecDials()) { +// if (s.IsFitSyst == kUsedAsFakeData) { +// XSecSystNames.push_back(s.Name); +// } +// } +// } +// +// return XSecSystNames; +//} +// +//int GetXSecSystIndex(std::string const &name) { +// static auto XSecDials = GetAllXSecDials(); +// +// static std::map cache; +// if (!cache.count(name)) { +// int found = -1; +// for (size_t it = 0; it < XSecDials.size(); ++it) { +// if (XSecDials[it].Name == name) { +// found = it; +// break; +// } +// } +// assert(found > -1); +// cache[name] = found; +// } +// return cache[name]; +//} +// +///// Convenience method for checking if a dial is +//bool IsExtrapolateOffToOnSyst(std::string const &name) { +// static std::unordered_map cache; +// if (!cache.count(name)) { +// cache[name] = SystNameIsInList(name, GetExtrapolateOffToOnSystNames()); +// } +// return cache[name]; +//} +//bool IsExtrapolateOffToOnSyst(int index) { +// static std::unordered_map cache; +// if (!cache.count(index)) { +// cache[index] = IsExtrapolateOffToOnSyst(GetXSecSystName(index)); +// } +// return cache[index]; +//} +// +//bool IsFakeDataGenerationSyst(std::string const &name) { +// static std::unordered_map cache; +// if (!cache.count(name)) { +// cache[name] = SystNameIsInList(name, GetFakeDataGenerationSystNames()); +// } +// return cache[name]; +//} +//bool IsFakeDataGenerationSyst(int index) { +// static std::unordered_map cache; +// if (!cache.count(index)) { +// cache[index] = IsFakeDataGenerationSyst(GetXSecSystName(index)); +// } +// return cache[index]; +//} +// +//std::pair GetXSecSystLimits(int index) { +// static auto XSecDials = GetAllXSecDials(); +// assert((index >= 0) && (index < int(XSecDials.size()))); +// return XSecDials[index].FitLimits; +//} +//std::pair GetXSecSystLimits(const std::string &name) { +// return GetXSecSystLimits(GetXSecSystIndex(name)); +//} +//double GetXSecSystMax(int index) { return GetXSecSystLimits(index).second; } +//double GetXSecSystMin(int index) { return GetXSecSystLimits(index).first; } } // namespace ana diff --git a/CAFAna/Systs/XSecSystList.h b/CAFAna/Systs/XSecSystList.h index d881a6fc..6a845f79 100644 --- a/CAFAna/Systs/XSecSystList.h +++ b/CAFAna/Systs/XSecSystList.h @@ -9,299 +9,299 @@ #include namespace ana { -class ISyst; - -enum FitSyst { - kFitSyst, - kRemovedOverconstraint, - kRemovedOddResponse, - kRemovedOther, - kUsedAsFakeData -}; - -enum XSecCategg { kQELike, kRES, kDIS, kFSI, kRatios, kNC, kOther, kNahMate }; - -enum ExtrapolatedSyst { kExtrapolated, kContinuous }; - -static std::pair const kStandardRange{-3, 3}; -static std::pair const kFakeDataRange{0, 1}; - -struct XSecDialDescriptor { - std::string Name; - FitSyst IsFitSyst; - ExtrapolatedSyst IsExtrapolateOffToOnSyst; - std::pair FitLimits; - XSecCategg Categg; -}; - -/// All dial names that should go into a state file -inline std::vector const &GetAllXSecDials() { - static std::vector XSecSystDials; - static bool first = true; - if (first) { - - first = false; - XSecSystDials = { - {"MaCCQE", kFitSyst, kContinuous, kStandardRange, kQELike}, - {"VecFFCCQEshape", kFitSyst, kExtrapolated, kStandardRange, kQELike}, - {"MaNCEL", kUsedAsFakeData, kContinuous, kStandardRange, kNC}, - {"EtaNCEL", kRemovedOverconstraint, kContinuous, kStandardRange, kNC}, - {"MaCCRES", kFitSyst, kContinuous, kStandardRange, kRES}, - {"MvCCRES", kFitSyst, kContinuous, kStandardRange, kRES}, - {"MaNCRES", kFitSyst, kContinuous, kStandardRange, kNC}, - {"MvNCRES", kFitSyst, kContinuous, kStandardRange, kNC}, - {"RDecBR1gamma", kRemovedOverconstraint, kContinuous, {-2, 3}, kRES}, - {"RDecBR1eta", kRemovedOverconstraint, kContinuous, {-2, 3}, kRES}, - {"Theta_Delta2Npi", kFitSyst, kExtrapolated, kStandardRange, kDIS}, - {"AhtBY", kFitSyst, kContinuous, kStandardRange, kDIS}, - {"BhtBY", kFitSyst, kContinuous, kStandardRange, kDIS}, - {"CV1uBY", kFitSyst, kContinuous, kStandardRange, kDIS}, - {"CV2uBY", kFitSyst, kContinuous, kStandardRange, kDIS}, - {"FormZone", kUsedAsFakeData, kContinuous, {-2, 2}, kFSI}, - {"MFP_pi", kUsedAsFakeData, kContinuous, {-2, 2}, kFSI}, - {"FrCEx_pi", kFitSyst, kContinuous, {-2, 2}, kFSI}, - {"FrElas_pi", kFitSyst, kContinuous, {-2, 2}, kFSI}, - {"FrInel_pi", kFitSyst, kContinuous, {-2, 2}, kFSI}, - {"FrAbs_pi", kFitSyst, kContinuous, {-2, 2}, kFSI}, - {"FrPiProd_pi", kFitSyst, kContinuous, {-2, 2}, kFSI}, - {"MFP_N", kUsedAsFakeData, kContinuous, {-2, 2}, kFSI}, - {"FrCEx_N", kFitSyst, kContinuous, {-2, 2}, kFSI}, - {"FrElas_N", kFitSyst, kContinuous, {-2, 2}, kFSI}, - {"FrInel_N", kFitSyst, kContinuous, {-2, 2}, kFSI}, - {"FrAbs_N", kFitSyst, kContinuous, {-2, 2}, kFSI}, - {"FrPiProd_N", kFitSyst, kContinuous, {-2, 2}, kFSI}, - {"CCQEPauliSupViaKF", kFitSyst, kExtrapolated, kStandardRange, kQELike}, - // Must be here to fill branch in SpectrumLoader but shouldn't be used - // as the dials below separate out the responses into multiple fake data - // sets. - {"Mnv2p2hGaussEnhancement", - kRemovedOther, - kContinuous, - {0, 0}, - kQELike}, - {"Mnv2p2hGaussEnhancement_NN", kUsedAsFakeData, kContinuous, - kFakeDataRange, kQELike}, - {"Mnv2p2hGaussEnhancement_2p2h", kUsedAsFakeData, kContinuous, - kFakeDataRange, kQELike}, - {"Mnv2p2hGaussEnhancement_1p1h", kUsedAsFakeData, kContinuous, - kFakeDataRange, kQELike}, - {"MKSPP_ReWeight", kUsedAsFakeData, kContinuous, kFakeDataRange, kRES}, - {"E2p2h_A_nu", kFitSyst, kExtrapolated, kStandardRange, kQELike}, - {"E2p2h_B_nu", kFitSyst, kExtrapolated, kStandardRange, kQELike}, - {"E2p2h_A_nubar", kFitSyst, kExtrapolated, kStandardRange, kQELike}, - {"E2p2h_B_nubar", kFitSyst, kExtrapolated, kStandardRange, kQELike}, - {"NR_nu_n_CC_2Pi", kFitSyst, kContinuous, {-2, 3}, kDIS}, - {"NR_nu_n_CC_3Pi", kFitSyst, kContinuous, {-2, 3}, kDIS}, - {"NR_nu_p_CC_2Pi", kFitSyst, kContinuous, {-2, 3}, kDIS}, - {"NR_nu_p_CC_3Pi", kFitSyst, kContinuous, {-2, 3}, kDIS}, - {"NR_nu_np_CC_1Pi", kFitSyst, kContinuous, kStandardRange, kDIS}, - {"NR_nu_n_NC_1Pi", kFitSyst, kContinuous, {-2, 3}, kNC}, - {"NR_nu_n_NC_2Pi", kFitSyst, kContinuous, {-2, 3}, kNC}, - {"NR_nu_n_NC_3Pi", kFitSyst, kContinuous, {-2, 3}, kNC}, - {"NR_nu_p_NC_1Pi", kFitSyst, kContinuous, {-2, 3}, kNC}, - {"NR_nu_p_NC_2Pi", kFitSyst, kContinuous, {-2, 3}, kNC}, - {"NR_nu_p_NC_3Pi", kFitSyst, kContinuous, {-2, 3}, kNC}, - {"NR_nubar_n_CC_1Pi", kFitSyst, kContinuous, {-2, 3}, kDIS}, - {"NR_nubar_n_CC_2Pi", kFitSyst, kContinuous, {-2, 3}, kDIS}, - {"NR_nubar_n_CC_3Pi", kFitSyst, kContinuous, {-2, 3}, kDIS}, - {"NR_nubar_p_CC_1Pi", kFitSyst, kContinuous, {-2, 3}, kDIS}, - {"NR_nubar_p_CC_2Pi", kFitSyst, kContinuous, {-2, 3}, kDIS}, - {"NR_nubar_p_CC_3Pi", kFitSyst, kContinuous, {-2, 3}, kDIS}, - {"NR_nubar_n_NC_1Pi", kFitSyst, kContinuous, {-2, 3}, kNC}, - {"NR_nubar_n_NC_2Pi", kFitSyst, kContinuous, {-2, 3}, kNC}, - {"NR_nubar_n_NC_3Pi", kFitSyst, kContinuous, {-2, 3}, kNC}, - {"NR_nubar_p_NC_1Pi", kFitSyst, kContinuous, {-2, 3}, kNC}, - {"NR_nubar_p_NC_2Pi", kFitSyst, kContinuous, {-2, 3}, kNC}, - {"NR_nubar_p_NC_3Pi", kFitSyst, kContinuous, {-2, 3}, kNC}, - {"BeRPA_A", kFitSyst, kContinuous, kStandardRange, kQELike}, - {"BeRPA_B", kFitSyst, kContinuous, kStandardRange, kQELike}, - {"BeRPA_D", kFitSyst, kContinuous, kStandardRange, kQELike}, - {"BeRPA_E", kUsedAsFakeData, kContinuous, kStandardRange, kQELike}, - {"C12ToAr40_2p2hScaling_nu", kFitSyst, kExtrapolated, kStandardRange, - kQELike}, - {"C12ToAr40_2p2hScaling_nubar", kFitSyst, kExtrapolated, kStandardRange, - kQELike}, - {"nuenuebar_xsec_ratio", kFitSyst, kExtrapolated, kStandardRange, - kRatios}, - {"nuenumu_xsec_ratio", kFitSyst, kExtrapolated, kStandardRange, - kRatios}, - {"SPPLowQ2Suppression", kUsedAsFakeData, kContinuous, kFakeDataRange, - kRES}, - {"FSILikeEAvailSmearing", kUsedAsFakeData, kContinuous, kFakeDataRange, - kFSI}, - {"MissingProtonFakeData", kUsedAsFakeData, kContinuous, kFakeDataRange, - kOther}, - {"NuWroReweightFakeData", kUsedAsFakeData, kContinuous, kFakeDataRange, - kOther}}; - - static auto AnaV = GetAnaVersion(); - if (AnaV == kV3) { - std::string dial_name; - auto sel = [&](XSecDialDescriptor const &d) -> bool { - return d.Name == dial_name; - }; - - dial_name = "Mnv2p2hGaussEnhancement"; - auto mnv_dial = - std::find_if(XSecSystDials.begin(), XSecSystDials.end(), sel); - mnv_dial->IsFitSyst = kFitSyst; - mnv_dial->IsExtrapolateOffToOnSyst = kExtrapolated; - mnv_dial->FitLimits = kStandardRange; - - dial_name = "Mnv2p2hGaussEnhancement_NN"; - auto mnv_dial_NN = - std::find_if(XSecSystDials.begin(), XSecSystDials.end(), sel); - mnv_dial_NN->IsFitSyst = kRemovedOther; - mnv_dial_NN->FitLimits = {0, 0}; - - dial_name = "Mnv2p2hGaussEnhancement_2p2h"; - auto mnv_dial_2p2h = - std::find_if(XSecSystDials.begin(), XSecSystDials.end(), sel); - mnv_dial_2p2h->IsFitSyst = kRemovedOther; - mnv_dial_2p2h->FitLimits = {0, 0}; - - dial_name = "Mnv2p2hGaussEnhancement_1p1h"; - auto mnv_dial_1p1h = - std::find_if(XSecSystDials.begin(), XSecSystDials.end(), sel); - mnv_dial_1p1h->IsFitSyst = kRemovedOther; - mnv_dial_1p1h->FitLimits = {0, 0}; - - dial_name = "MKSPP_ReWeight"; - auto mk_dial = - std::find_if(XSecSystDials.begin(), XSecSystDials.end(), sel); - mk_dial->IsFitSyst = kFitSyst; - mk_dial->IsExtrapolateOffToOnSyst = kExtrapolated; - mk_dial->FitLimits = kStandardRange; - - dial_name = "SPPLowQ2Suppression"; - auto spplowq2 = - std::find_if(XSecSystDials.begin(), XSecSystDials.end(), sel); - spplowq2->IsFitSyst = kFitSyst; - spplowq2->IsExtrapolateOffToOnSyst = kExtrapolated; - spplowq2->FitLimits = kStandardRange; - - dial_name = "FSILikeEAvailSmearing"; - auto fslilikesmear = - std::find_if(XSecSystDials.begin(), XSecSystDials.end(), sel); - fslilikesmear->IsFitSyst = kFitSyst; - fslilikesmear->IsExtrapolateOffToOnSyst = kExtrapolated; - fslilikesmear->FitLimits = kStandardRange; - } - } - - return XSecSystDials; -} - -/// All dial names that should go into a state file -inline std::vector const &GetAllXSecSystNames() { - static std::vector XSecSystNames; - static bool first = true; - if (first) { - first = false; - for (auto const &s : GetAllXSecDials()) { - XSecSystNames.push_back(s.Name); - } - } - - return XSecSystNames; -} -/// Return a specific category of XSEC systs -std::vector -GetXSecSystNames(std::string const &inputCategg = "All"); -/// All dials used as freedoms in standard fits -std::vector const &GetFitSystNames(); -/// Dials which should not be used as freedoms (CV weights if they exist removed -/// in SpectrumLoader) -inline std::vector const &GetDoNotIncludeSystNames() { - static std::vector XSecSystNames; - static bool first = true; - if (first) { - first = false; - for (auto const &s : GetAllXSecDials()) { - if (s.IsFitSyst != kFitSyst) { - XSecSystNames.push_back(s.Name); - } - } - } - - return XSecSystNames; -} -/// Dials which have an extrapolated response outside of 0->1 -std::vector const &GetExtrapolateOffToOnSystNames(); -/// Dials used to generate fake data sets when set to 1, should not be fit. -std::vector const &GetFakeDataGenerationSystNames(); - -int GetXSecSystIndex(std::string const &name); -inline std::string GetXSecSystName(int index) { - static auto XSecDials = GetAllXSecDials(); - assert((index >= 0) && (index < int(XSecDials.size()))); - return XSecDials[index].Name; -} - -/// Check if a dial name is in a list -inline bool SystNameIsInList(std::string const &name, - std::vector const &listOfNames) { - return (std::find(listOfNames.begin(), listOfNames.end(), name) != - listOfNames.end()); -} - -/// Convenience method for checking if a dial name is -bool IsExtrapolateOffToOnSyst(std::string const &); -bool IsExtrapolateOffToOnSyst(int); - -inline bool IsDoNotIncludeSyst(std::string const &name) { - static std::map cache; - if (!cache.count(name)) { - cache[name] = SystNameIsInList(name, GetDoNotIncludeSystNames()); - } - return cache[name]; -} - -inline bool IsDoNotIncludeSyst(unsigned int index) -{ - // This function is very hot from FixupRecord(), and since we know all the - // indices are small, this arrangement is more efficient than using any sort - // of map. - - enum class Tristate{ - kUnknown = 0, // must be zero so it's the default - kTrue, - kFalse - }; - - static std::vector cache; - // Common case - if(index < cache.size() && cache[index] != Tristate::kUnknown){ - return cache[index] == Tristate::kTrue; - } - - // Otherwise, we have to look up the answer - const bool ret = IsDoNotIncludeSyst(GetXSecSystName(index)); - - // And store it in the cache for next time - if(cache.size() <= index){cache.resize(index+1);} - cache[index] = ret ? Tristate::kTrue : Tristate::kFalse; - - return ret; - - // Old, straightforward code: - /* - static std::map cache; - if (!cache.count(index)) { - cache[index] = IsDoNotIncludeSyst(GetXSecSystName(index)); - } - return cache[index]; - */ -} - -bool IsFakeDataGenerationSyst(std::string const &); -bool IsFakeDataGenerationSyst(int); - -std::pair GetXSecSystLimits(const std::string &name); -double GetXSecSystMax(int index); -double GetXSecSystMin(int index); - -// actually instantiate them so that the Registry knows about them -extern const std::vector kAllXsecSysts; +//class ISyst; +// +//enum FitSyst { +// kFitSyst, +// kRemovedOverconstraint, +// kRemovedOddResponse, +// kRemovedOther, +// kUsedAsFakeData +//}; +// +//enum XSecCategg { kQELike, kRES, kDIS, kFSI, kRatios, kNC, kOther, kNahMate }; +// +//enum ExtrapolatedSyst { kExtrapolated, kContinuous }; +// +//static std::pair const kStandardRange{-3, 3}; +//static std::pair const kFakeDataRange{0, 1}; +// +//struct XSecDialDescriptor { +// std::string Name; +// FitSyst IsFitSyst; +// ExtrapolatedSyst IsExtrapolateOffToOnSyst; +// std::pair FitLimits; +// XSecCategg Categg; +//}; +// +///// All dial names that should go into a state file +//inline std::vector const &GetAllXSecDials() { +// static std::vector XSecSystDials; +// static bool first = true; +// if (first) { +// +// first = false; +// XSecSystDials = { +// {"MaCCQE", kFitSyst, kContinuous, kStandardRange, kQELike}, +// {"VecFFCCQEshape", kFitSyst, kExtrapolated, kStandardRange, kQELike}, +// {"MaNCEL", kUsedAsFakeData, kContinuous, kStandardRange, kNC}, +// {"EtaNCEL", kRemovedOverconstraint, kContinuous, kStandardRange, kNC}, +// {"MaCCRES", kFitSyst, kContinuous, kStandardRange, kRES}, +// {"MvCCRES", kFitSyst, kContinuous, kStandardRange, kRES}, +// {"MaNCRES", kFitSyst, kContinuous, kStandardRange, kNC}, +// {"MvNCRES", kFitSyst, kContinuous, kStandardRange, kNC}, +// {"RDecBR1gamma", kRemovedOverconstraint, kContinuous, {-2, 3}, kRES}, +// {"RDecBR1eta", kRemovedOverconstraint, kContinuous, {-2, 3}, kRES}, +// {"Theta_Delta2Npi", kFitSyst, kExtrapolated, kStandardRange, kDIS}, +// {"AhtBY", kFitSyst, kContinuous, kStandardRange, kDIS}, +// {"BhtBY", kFitSyst, kContinuous, kStandardRange, kDIS}, +// {"CV1uBY", kFitSyst, kContinuous, kStandardRange, kDIS}, +// {"CV2uBY", kFitSyst, kContinuous, kStandardRange, kDIS}, +// {"FormZone", kUsedAsFakeData, kContinuous, {-2, 2}, kFSI}, +// {"MFP_pi", kUsedAsFakeData, kContinuous, {-2, 2}, kFSI}, +// {"FrCEx_pi", kFitSyst, kContinuous, {-2, 2}, kFSI}, +// {"FrElas_pi", kFitSyst, kContinuous, {-2, 2}, kFSI}, +// {"FrInel_pi", kFitSyst, kContinuous, {-2, 2}, kFSI}, +// {"FrAbs_pi", kFitSyst, kContinuous, {-2, 2}, kFSI}, +// {"FrPiProd_pi", kFitSyst, kContinuous, {-2, 2}, kFSI}, +// {"MFP_N", kUsedAsFakeData, kContinuous, {-2, 2}, kFSI}, +// {"FrCEx_N", kFitSyst, kContinuous, {-2, 2}, kFSI}, +// {"FrElas_N", kFitSyst, kContinuous, {-2, 2}, kFSI}, +// {"FrInel_N", kFitSyst, kContinuous, {-2, 2}, kFSI}, +// {"FrAbs_N", kFitSyst, kContinuous, {-2, 2}, kFSI}, +// {"FrPiProd_N", kFitSyst, kContinuous, {-2, 2}, kFSI}, +// {"CCQEPauliSupViaKF", kFitSyst, kExtrapolated, kStandardRange, kQELike}, +// // Must be here to fill branch in SpectrumLoader but shouldn't be used +// // as the dials below separate out the responses into multiple fake data +// // sets. +// {"Mnv2p2hGaussEnhancement", +// kRemovedOther, +// kContinuous, +// {0, 0}, +// kQELike}, +// {"Mnv2p2hGaussEnhancement_NN", kUsedAsFakeData, kContinuous, +// kFakeDataRange, kQELike}, +// {"Mnv2p2hGaussEnhancement_2p2h", kUsedAsFakeData, kContinuous, +// kFakeDataRange, kQELike}, +// {"Mnv2p2hGaussEnhancement_1p1h", kUsedAsFakeData, kContinuous, +// kFakeDataRange, kQELike}, +// {"MKSPP_ReWeight", kUsedAsFakeData, kContinuous, kFakeDataRange, kRES}, +// {"E2p2h_A_nu", kFitSyst, kExtrapolated, kStandardRange, kQELike}, +// {"E2p2h_B_nu", kFitSyst, kExtrapolated, kStandardRange, kQELike}, +// {"E2p2h_A_nubar", kFitSyst, kExtrapolated, kStandardRange, kQELike}, +// {"E2p2h_B_nubar", kFitSyst, kExtrapolated, kStandardRange, kQELike}, +// {"NR_nu_n_CC_2Pi", kFitSyst, kContinuous, {-2, 3}, kDIS}, +// {"NR_nu_n_CC_3Pi", kFitSyst, kContinuous, {-2, 3}, kDIS}, +// {"NR_nu_p_CC_2Pi", kFitSyst, kContinuous, {-2, 3}, kDIS}, +// {"NR_nu_p_CC_3Pi", kFitSyst, kContinuous, {-2, 3}, kDIS}, +// {"NR_nu_np_CC_1Pi", kFitSyst, kContinuous, kStandardRange, kDIS}, +// {"NR_nu_n_NC_1Pi", kFitSyst, kContinuous, {-2, 3}, kNC}, +// {"NR_nu_n_NC_2Pi", kFitSyst, kContinuous, {-2, 3}, kNC}, +// {"NR_nu_n_NC_3Pi", kFitSyst, kContinuous, {-2, 3}, kNC}, +// {"NR_nu_p_NC_1Pi", kFitSyst, kContinuous, {-2, 3}, kNC}, +// {"NR_nu_p_NC_2Pi", kFitSyst, kContinuous, {-2, 3}, kNC}, +// {"NR_nu_p_NC_3Pi", kFitSyst, kContinuous, {-2, 3}, kNC}, +// {"NR_nubar_n_CC_1Pi", kFitSyst, kContinuous, {-2, 3}, kDIS}, +// {"NR_nubar_n_CC_2Pi", kFitSyst, kContinuous, {-2, 3}, kDIS}, +// {"NR_nubar_n_CC_3Pi", kFitSyst, kContinuous, {-2, 3}, kDIS}, +// {"NR_nubar_p_CC_1Pi", kFitSyst, kContinuous, {-2, 3}, kDIS}, +// {"NR_nubar_p_CC_2Pi", kFitSyst, kContinuous, {-2, 3}, kDIS}, +// {"NR_nubar_p_CC_3Pi", kFitSyst, kContinuous, {-2, 3}, kDIS}, +// {"NR_nubar_n_NC_1Pi", kFitSyst, kContinuous, {-2, 3}, kNC}, +// {"NR_nubar_n_NC_2Pi", kFitSyst, kContinuous, {-2, 3}, kNC}, +// {"NR_nubar_n_NC_3Pi", kFitSyst, kContinuous, {-2, 3}, kNC}, +// {"NR_nubar_p_NC_1Pi", kFitSyst, kContinuous, {-2, 3}, kNC}, +// {"NR_nubar_p_NC_2Pi", kFitSyst, kContinuous, {-2, 3}, kNC}, +// {"NR_nubar_p_NC_3Pi", kFitSyst, kContinuous, {-2, 3}, kNC}, +// {"BeRPA_A", kFitSyst, kContinuous, kStandardRange, kQELike}, +// {"BeRPA_B", kFitSyst, kContinuous, kStandardRange, kQELike}, +// {"BeRPA_D", kFitSyst, kContinuous, kStandardRange, kQELike}, +// {"BeRPA_E", kUsedAsFakeData, kContinuous, kStandardRange, kQELike}, +// {"C12ToAr40_2p2hScaling_nu", kFitSyst, kExtrapolated, kStandardRange, +// kQELike}, +// {"C12ToAr40_2p2hScaling_nubar", kFitSyst, kExtrapolated, kStandardRange, +// kQELike}, +// {"nuenuebar_xsec_ratio", kFitSyst, kExtrapolated, kStandardRange, +// kRatios}, +// {"nuenumu_xsec_ratio", kFitSyst, kExtrapolated, kStandardRange, +// kRatios}, +// {"SPPLowQ2Suppression", kUsedAsFakeData, kContinuous, kFakeDataRange, +// kRES}, +// {"FSILikeEAvailSmearing", kUsedAsFakeData, kContinuous, kFakeDataRange, +// kFSI}, +// {"MissingProtonFakeData", kUsedAsFakeData, kContinuous, kFakeDataRange, +// kOther}, +// {"NuWroReweightFakeData", kUsedAsFakeData, kContinuous, kFakeDataRange, +// kOther}}; +// +// static auto AnaV = GetAnaVersion(); +// if (AnaV == kV3) { +// std::string dial_name; +// auto sel = [&](XSecDialDescriptor const &d) -> bool { +// return d.Name == dial_name; +// }; +// +// dial_name = "Mnv2p2hGaussEnhancement"; +// auto mnv_dial = +// std::find_if(XSecSystDials.begin(), XSecSystDials.end(), sel); +// mnv_dial->IsFitSyst = kFitSyst; +// mnv_dial->IsExtrapolateOffToOnSyst = kExtrapolated; +// mnv_dial->FitLimits = kStandardRange; +// +// dial_name = "Mnv2p2hGaussEnhancement_NN"; +// auto mnv_dial_NN = +// std::find_if(XSecSystDials.begin(), XSecSystDials.end(), sel); +// mnv_dial_NN->IsFitSyst = kRemovedOther; +// mnv_dial_NN->FitLimits = {0, 0}; +// +// dial_name = "Mnv2p2hGaussEnhancement_2p2h"; +// auto mnv_dial_2p2h = +// std::find_if(XSecSystDials.begin(), XSecSystDials.end(), sel); +// mnv_dial_2p2h->IsFitSyst = kRemovedOther; +// mnv_dial_2p2h->FitLimits = {0, 0}; +// +// dial_name = "Mnv2p2hGaussEnhancement_1p1h"; +// auto mnv_dial_1p1h = +// std::find_if(XSecSystDials.begin(), XSecSystDials.end(), sel); +// mnv_dial_1p1h->IsFitSyst = kRemovedOther; +// mnv_dial_1p1h->FitLimits = {0, 0}; +// +// dial_name = "MKSPP_ReWeight"; +// auto mk_dial = +// std::find_if(XSecSystDials.begin(), XSecSystDials.end(), sel); +// mk_dial->IsFitSyst = kFitSyst; +// mk_dial->IsExtrapolateOffToOnSyst = kExtrapolated; +// mk_dial->FitLimits = kStandardRange; +// +// dial_name = "SPPLowQ2Suppression"; +// auto spplowq2 = +// std::find_if(XSecSystDials.begin(), XSecSystDials.end(), sel); +// spplowq2->IsFitSyst = kFitSyst; +// spplowq2->IsExtrapolateOffToOnSyst = kExtrapolated; +// spplowq2->FitLimits = kStandardRange; +// +// dial_name = "FSILikeEAvailSmearing"; +// auto fslilikesmear = +// std::find_if(XSecSystDials.begin(), XSecSystDials.end(), sel); +// fslilikesmear->IsFitSyst = kFitSyst; +// fslilikesmear->IsExtrapolateOffToOnSyst = kExtrapolated; +// fslilikesmear->FitLimits = kStandardRange; +// } +// } +// +// return XSecSystDials; +//} +// +///// All dial names that should go into a state file +//inline std::vector const &GetAllXSecSystNames() { +// static std::vector XSecSystNames; +// static bool first = true; +// if (first) { +// first = false; +// for (auto const &s : GetAllXSecDials()) { +// XSecSystNames.push_back(s.Name); +// } +// } +// +// return XSecSystNames; +//} +///// Return a specific category of XSEC systs +//std::vector +//GetXSecSystNames(std::string const &inputCategg = "All"); +///// All dials used as freedoms in standard fits +//std::vector const &GetFitSystNames(); +///// Dials which should not be used as freedoms (CV weights if they exist removed +///// in SpectrumLoader) +//inline std::vector const &GetDoNotIncludeSystNames() { +// static std::vector XSecSystNames; +// static bool first = true; +// if (first) { +// first = false; +// for (auto const &s : GetAllXSecDials()) { +// if (s.IsFitSyst != kFitSyst) { +// XSecSystNames.push_back(s.Name); +// } +// } +// } +// +// return XSecSystNames; +//} +///// Dials which have an extrapolated response outside of 0->1 +//std::vector const &GetExtrapolateOffToOnSystNames(); +///// Dials used to generate fake data sets when set to 1, should not be fit. +//std::vector const &GetFakeDataGenerationSystNames(); +// +//int GetXSecSystIndex(std::string const &name); +//inline std::string GetXSecSystName(int index) { +// static auto XSecDials = GetAllXSecDials(); +// assert((index >= 0) && (index < int(XSecDials.size()))); +// return XSecDials[index].Name; +//} +// +///// Check if a dial name is in a list +//inline bool SystNameIsInList(std::string const &name, +// std::vector const &listOfNames) { +// return (std::find(listOfNames.begin(), listOfNames.end(), name) != +// listOfNames.end()); +//} +// +///// Convenience method for checking if a dial name is +//bool IsExtrapolateOffToOnSyst(std::string const &); +//bool IsExtrapolateOffToOnSyst(int); +// +//inline bool IsDoNotIncludeSyst(std::string const &name) { +// static std::map cache; +// if (!cache.count(name)) { +// cache[name] = SystNameIsInList(name, GetDoNotIncludeSystNames()); +// } +// return cache[name]; +//} +// +//inline bool IsDoNotIncludeSyst(unsigned int index) +//{ +// // This function is very hot from FixupRecord(), and since we know all the +// // indices are small, this arrangement is more efficient than using any sort +// // of map. +// +// enum class Tristate{ +// kUnknown = 0, // must be zero so it's the default +// kTrue, +// kFalse +// }; +// +// static std::vector cache; +// // Common case +// if(index < cache.size() && cache[index] != Tristate::kUnknown){ +// return cache[index] == Tristate::kTrue; +// } +// +// // Otherwise, we have to look up the answer +// const bool ret = IsDoNotIncludeSyst(GetXSecSystName(index)); +// +// // And store it in the cache for next time +// if(cache.size() <= index){cache.resize(index+1);} +// cache[index] = ret ? Tristate::kTrue : Tristate::kFalse; +// +// return ret; +// +// // Old, straightforward code: +// /* +// static std::map cache; +// if (!cache.count(index)) { +// cache[index] = IsDoNotIncludeSyst(GetXSecSystName(index)); +// } +// return cache[index]; +// */ +//} +// +//bool IsFakeDataGenerationSyst(std::string const &); +//bool IsFakeDataGenerationSyst(int); +// +//std::pair GetXSecSystLimits(const std::string &name); +//double GetXSecSystMax(int index); +//double GetXSecSystMin(int index); +// +//// actually instantiate them so that the Registry knows about them +//extern const std::vector kAllXsecSysts; } // namespace ana diff --git a/CAFAna/Systs/XSecSysts.cxx b/CAFAna/Systs/XSecSysts.cxx index c4db83ba..a246c727 100644 --- a/CAFAna/Systs/XSecSysts.cxx +++ b/CAFAna/Systs/XSecSysts.cxx @@ -8,164 +8,164 @@ namespace ana { -MissingProtonFakeDataGenerator mpfd; -NuWroReweightFakeDataGenerator nuwrofd; - -void XSecSyst::FakeDataDialShift(double sigma, - caf::SRProxy *sr, - double &weight) const { - - // First time hook up known fake data dial IDs, logic then in switch - // statement. - // Why is it like this?! - static int Mnv2p2hGaussEnhancement_id = 0; - static int Mnv2p2hGaussEnhancement_NN_id = 0; - static int Mnv2p2hGaussEnhancement_2p2h_id = 0; - static int Mnv2p2hGaussEnhancement_1p1h_id = 0; - static int MKSPP_ReWeight_id = 0; - static int SPPLowQ2Suppression_id = 0; - static int FSILikeEAvailSmearing_id = 0; - static int MissingProtonFakeData_id = 0; - static int NuWroReweightFakeData_id = 0; - static int BeRPA_E_id = 0; - static int FormZone_id = 0; - static int MFP_pi_id = 0; - static int MFP_N_id = 0; - static int MaNCEL_id = 0; - - static bool first = true; - if (first) { - first = false; - Mnv2p2hGaussEnhancement_id = GetXSecSystIndex("Mnv2p2hGaussEnhancement"); - Mnv2p2hGaussEnhancement_NN_id = - GetXSecSystIndex("Mnv2p2hGaussEnhancement_NN"); - Mnv2p2hGaussEnhancement_2p2h_id = - GetXSecSystIndex("Mnv2p2hGaussEnhancement_2p2h"); - Mnv2p2hGaussEnhancement_1p1h_id = - GetXSecSystIndex("Mnv2p2hGaussEnhancement_1p1h"); - MKSPP_ReWeight_id = GetXSecSystIndex("MKSPP_ReWeight"); - SPPLowQ2Suppression_id = GetXSecSystIndex("SPPLowQ2Suppression"); - FSILikeEAvailSmearing_id = GetXSecSystIndex("FSILikeEAvailSmearing"); - MissingProtonFakeData_id = GetXSecSystIndex("MissingProtonFakeData"); - NuWroReweightFakeData_id = GetXSecSystIndex("NuWroReweightFakeData"); - BeRPA_E_id = GetXSecSystIndex("BeRPA_E"); - FormZone_id = GetXSecSystIndex("FormZone"); - MFP_pi_id = GetXSecSystIndex("MFP_pi"); - MFP_N_id = GetXSecSystIndex("MFP_N"); - MaNCEL_id = GetXSecSystIndex("MaNCEL"); - } - - // This is a bit hacky, but for fake data dials which have discrete +/- values, try the +/-3 sigma values - int posneg_spline_point = 6; - if (sigma < 0) posneg_spline_point = 0; - - // Do something special with the Mnv stuff - if (fID == Mnv2p2hGaussEnhancement_NN_id) { - weight *= sr->xsSyst_wgt[Mnv2p2hGaussEnhancement_id][4]; - } else if (fID == Mnv2p2hGaussEnhancement_2p2h_id) { - weight *= sr->xsSyst_wgt[Mnv2p2hGaussEnhancement_id][3]; - } else if (fID == Mnv2p2hGaussEnhancement_1p1h_id) { - weight *= sr->xsSyst_wgt[Mnv2p2hGaussEnhancement_id][2]; - } else if (fID == MKSPP_ReWeight_id) { - weight *= sr->xsSyst_wgt[MKSPP_ReWeight_id][2]; - } else if (fID == SPPLowQ2Suppression_id) { - weight *= sr->xsSyst_wgt[SPPLowQ2Suppression_id][2]; - } else if (fID == FSILikeEAvailSmearing_id) { - weight *= sr->xsSyst_wgt[FSILikeEAvailSmearing_id][2]; - } else if (fID == MissingProtonFakeData_id) { - mpfd.Shift(sigma, sr, weight); - } else if (fID == NuWroReweightFakeData_id) { - nuwrofd.Shift(sigma, sr, weight); - } else if (fID == BeRPA_E_id) { - weight *= sr->xsSyst_wgt[BeRPA_E_id][posneg_spline_point]; - } else if (fID == FormZone_id) { - weight *= sr->xsSyst_wgt[FormZone_id][posneg_spline_point]; - } else if (fID == MFP_pi_id) { - weight *= sr->xsSyst_wgt[MFP_pi_id][posneg_spline_point]; - } else if (fID == MFP_N_id) { - weight *= sr->xsSyst_wgt[MFP_N_id][posneg_spline_point]; - } else if (fID == MaNCEL_id) { - weight *= sr->xsSyst_wgt[MaNCEL_id][posneg_spline_point]; - } -} - -void XSecSyst::Shift(double sigma,caf::SRProxy *sr, - double &weight) const { - // No xs weights in this event, skip reweighting it - if (sr->xsSyst_wgt.empty()) { - return; - } - if (sr->xsSyst_wgt[0].empty()) { - return; - } - if (fabs(sigma) < 1E-5) { - return; - } - - if (IsFakeDataGenerationSyst( - fID)) { // Separate out hard coded logic for fake data dials. - FakeDataDialShift(sigma, sr, weight); - return; - } - - assert(std::abs(sigma) <= 3 && - "XSecs responses only valid up to +/-3 sigma!"); - - bool IsExtrapolatedSyst = IsExtrapolateOffToOnSyst(fID); - - // How far apart are the points - const double spacing = 1; - - // Get the top and bottom values in the array - int low_index = std::floor(sigma / spacing) + 3; - int high_index = std::ceil(sigma / spacing) + 3; - - double fact = 1; - if (IsExtrapolatedSyst) { - - // double diff = sigma / spacing; - - double weight_at_cv = 1; - double weight_at_one_sig = sr->xsSyst_wgt[fID][4]; - - double dx = 1; - double dy = weight_at_one_sig - weight_at_cv; - - // y = m*x + c - fact = (dy / dx) * sigma + weight_at_cv; - - } else { - double diff = (sigma - double(low_index)) / spacing; - - double low_weight = sr->xsSyst_wgt[fID][low_index]; - double high_weight = sr->xsSyst_wgt[fID][high_index]; - - fact = low_weight + (high_weight - low_weight) * diff; - } - - fact = std::min(fact, 10.); - weight *= fact; -} - -XSecSyst::XSecSyst(int syst_id, bool applyPenalty) - : ISyst(GetXSecSystName(syst_id), GetXSecSystName(syst_id), applyPenalty, - GetXSecSystMin(syst_id), GetXSecSystMax(syst_id)), - fID(syst_id) {} - -std::vector GetXSecSysts(std::vector names, - bool applyPenalty) { - static std::vector ret; - - if (names.empty()) { - names = GetAllXSecSystNames(); - } - - if (ret.empty()) { - for (auto &it : names) { - ret.push_back(new XSecSyst(GetXSecSystIndex(it), applyPenalty)); - } - } - return ret; -} +//MissingProtonFakeDataGenerator mpfd; +//NuWroReweightFakeDataGenerator nuwrofd; +// +//void XSecSyst::FakeDataDialShift(double sigma, +// caf::SRProxy *sr, +// double &weight) const { +// +// // First time hook up known fake data dial IDs, logic then in switch +// // statement. +// // Why is it like this?! +// static int Mnv2p2hGaussEnhancement_id = 0; +// static int Mnv2p2hGaussEnhancement_NN_id = 0; +// static int Mnv2p2hGaussEnhancement_2p2h_id = 0; +// static int Mnv2p2hGaussEnhancement_1p1h_id = 0; +// static int MKSPP_ReWeight_id = 0; +// static int SPPLowQ2Suppression_id = 0; +// static int FSILikeEAvailSmearing_id = 0; +// static int MissingProtonFakeData_id = 0; +// static int NuWroReweightFakeData_id = 0; +// static int BeRPA_E_id = 0; +// static int FormZone_id = 0; +// static int MFP_pi_id = 0; +// static int MFP_N_id = 0; +// static int MaNCEL_id = 0; +// +// static bool first = true; +// if (first) { +// first = false; +// Mnv2p2hGaussEnhancement_id = GetXSecSystIndex("Mnv2p2hGaussEnhancement"); +// Mnv2p2hGaussEnhancement_NN_id = +// GetXSecSystIndex("Mnv2p2hGaussEnhancement_NN"); +// Mnv2p2hGaussEnhancement_2p2h_id = +// GetXSecSystIndex("Mnv2p2hGaussEnhancement_2p2h"); +// Mnv2p2hGaussEnhancement_1p1h_id = +// GetXSecSystIndex("Mnv2p2hGaussEnhancement_1p1h"); +// MKSPP_ReWeight_id = GetXSecSystIndex("MKSPP_ReWeight"); +// SPPLowQ2Suppression_id = GetXSecSystIndex("SPPLowQ2Suppression"); +// FSILikeEAvailSmearing_id = GetXSecSystIndex("FSILikeEAvailSmearing"); +// MissingProtonFakeData_id = GetXSecSystIndex("MissingProtonFakeData"); +// NuWroReweightFakeData_id = GetXSecSystIndex("NuWroReweightFakeData"); +// BeRPA_E_id = GetXSecSystIndex("BeRPA_E"); +// FormZone_id = GetXSecSystIndex("FormZone"); +// MFP_pi_id = GetXSecSystIndex("MFP_pi"); +// MFP_N_id = GetXSecSystIndex("MFP_N"); +// MaNCEL_id = GetXSecSystIndex("MaNCEL"); +// } +// +// // This is a bit hacky, but for fake data dials which have discrete +/- values, try the +/-3 sigma values +// int posneg_spline_point = 6; +// if (sigma < 0) posneg_spline_point = 0; +// +// // Do something special with the Mnv stuff +// if (fID == Mnv2p2hGaussEnhancement_NN_id) { +// weight *= sr->xsSyst_wgt[Mnv2p2hGaussEnhancement_id][4]; +// } else if (fID == Mnv2p2hGaussEnhancement_2p2h_id) { +// weight *= sr->xsSyst_wgt[Mnv2p2hGaussEnhancement_id][3]; +// } else if (fID == Mnv2p2hGaussEnhancement_1p1h_id) { +// weight *= sr->xsSyst_wgt[Mnv2p2hGaussEnhancement_id][2]; +// } else if (fID == MKSPP_ReWeight_id) { +// weight *= sr->xsSyst_wgt[MKSPP_ReWeight_id][2]; +// } else if (fID == SPPLowQ2Suppression_id) { +// weight *= sr->xsSyst_wgt[SPPLowQ2Suppression_id][2]; +// } else if (fID == FSILikeEAvailSmearing_id) { +// weight *= sr->xsSyst_wgt[FSILikeEAvailSmearing_id][2]; +// } else if (fID == MissingProtonFakeData_id) { +// mpfd.Shift(sigma, sr, weight); +// } else if (fID == NuWroReweightFakeData_id) { +// nuwrofd.Shift(sigma, sr, weight); +// } else if (fID == BeRPA_E_id) { +// weight *= sr->xsSyst_wgt[BeRPA_E_id][posneg_spline_point]; +// } else if (fID == FormZone_id) { +// weight *= sr->xsSyst_wgt[FormZone_id][posneg_spline_point]; +// } else if (fID == MFP_pi_id) { +// weight *= sr->xsSyst_wgt[MFP_pi_id][posneg_spline_point]; +// } else if (fID == MFP_N_id) { +// weight *= sr->xsSyst_wgt[MFP_N_id][posneg_spline_point]; +// } else if (fID == MaNCEL_id) { +// weight *= sr->xsSyst_wgt[MaNCEL_id][posneg_spline_point]; +// } +//} +// +//void XSecSyst::Shift(double sigma,caf::SRProxy *sr, +// double &weight) const { +// // No xs weights in this event, skip reweighting it +// if (sr->xsSyst_wgt.empty()) { +// return; +// } +// if (sr->xsSyst_wgt[0].empty()) { +// return; +// } +// if (fabs(sigma) < 1E-5) { +// return; +// } +// +// if (IsFakeDataGenerationSyst( +// fID)) { // Separate out hard coded logic for fake data dials. +// FakeDataDialShift(sigma, sr, weight); +// return; +// } +// +// assert(std::abs(sigma) <= 3 && +// "XSecs responses only valid up to +/-3 sigma!"); +// +// bool IsExtrapolatedSyst = IsExtrapolateOffToOnSyst(fID); +// +// // How far apart are the points +// const double spacing = 1; +// +// // Get the top and bottom values in the array +// int low_index = std::floor(sigma / spacing) + 3; +// int high_index = std::ceil(sigma / spacing) + 3; +// +// double fact = 1; +// if (IsExtrapolatedSyst) { +// +// // double diff = sigma / spacing; +// +// double weight_at_cv = 1; +// double weight_at_one_sig = sr->xsSyst_wgt[fID][4]; +// +// double dx = 1; +// double dy = weight_at_one_sig - weight_at_cv; +// +// // y = m*x + c +// fact = (dy / dx) * sigma + weight_at_cv; +// +// } else { +// double diff = (sigma - double(low_index)) / spacing; +// +// double low_weight = sr->xsSyst_wgt[fID][low_index]; +// double high_weight = sr->xsSyst_wgt[fID][high_index]; +// +// fact = low_weight + (high_weight - low_weight) * diff; +// } +// +// fact = std::min(fact, 10.); +// weight *= fact; +//} +// +//XSecSyst::XSecSyst(int syst_id, bool applyPenalty) +// : ISyst(GetXSecSystName(syst_id), GetXSecSystName(syst_id), applyPenalty, +// GetXSecSystMin(syst_id), GetXSecSystMax(syst_id)), +// fID(syst_id) {} +// +//std::vector GetXSecSysts(std::vector names, +// bool applyPenalty) { +// static std::vector ret; +// +// if (names.empty()) { +// names = GetAllXSecSystNames(); +// } +// +// if (ret.empty()) { +// for (auto &it : names) { +// ret.push_back(new XSecSyst(GetXSecSystIndex(it), applyPenalty)); +// } +// } +// return ret; +//} } // namespace ana diff --git a/CAFAna/Systs/XSecSysts.h b/CAFAna/Systs/XSecSysts.h index bcc7beb0..4e946c34 100644 --- a/CAFAna/Systs/XSecSysts.h +++ b/CAFAna/Systs/XSecSysts.h @@ -11,25 +11,25 @@ namespace ana { -class XSecSyst : public ISyst { -public: - virtual ~XSecSyst(){}; - - void FakeDataDialShift(double sigma, - caf::SRProxy *sr, double &weight) const; - - void Shift(double sigma, caf::SRProxy *sr, - double &weight) const override; - -protected: - XSecSyst(int syst_id, bool applyPenalty = true); - - friend std::vector GetXSecSysts(std::vector, bool); - - int fID; -}; - -std::vector -GetXSecSysts(std::vector names = {}, bool applyPenalty = true); +//class XSecSyst : public ISyst { +//public: +// virtual ~XSecSyst(){}; +// +// void FakeDataDialShift(double sigma, +// caf::SRProxy *sr, double &weight) const; +// +// void Shift(double sigma, caf::SRProxy *sr, +// double &weight) const override; +// +//protected: +// XSecSyst(int syst_id, bool applyPenalty = true); +// +// friend std::vector GetXSecSysts(std::vector, bool); +// +// int fID; +//}; +// +//std::vector +//GetXSecSysts(std::vector names = {}, bool applyPenalty = true); } // namespace ana diff --git a/CAFAna/Vars/DUNENeutNuWROReweight.cxx b/CAFAna/Vars/DUNENeutNuWROReweight.cxx index 9abbc022..67013335 100644 --- a/CAFAna/Vars/DUNENeutNuWROReweight.cxx +++ b/CAFAna/Vars/DUNENeutNuWROReweight.cxx @@ -21,10 +21,10 @@ namespace ana { if(!fHistNu && !fHist2DNu) LoadHists(); - const double x = sr->Ev; + const double x = sr->mc.nu[0].E;//sr->Ev; if(x < 0) return 1; // How? - const bool anti = (sr->nuPDG < 0); + const bool anti = ( sr->mc.nu[0].pdg<0);//(sr->nuPDG < 0); if(fVars == kEnu){ TH1* h = (anti ? fHistAnu : fHistNu); @@ -35,7 +35,7 @@ namespace ana } else{ TH2* h = (anti ? fHist2DAnu : fHist2DNu); - const double y = (fVars == kEnuQ2) ? sr->Q2 : sr->W; + const double y = (fVars == kEnuQ2) ? sr->mc.nu[0].Q2 : sr->mc.nu[0].W;//sr->Q2 : sr->W; if(x > h->GetXaxis()->GetXmax()) return 1; // overflow bin if(y < 0) return 1; // underflow bin if(y > h->GetYaxis()->GetXmax()) return 1; // overflow bin diff --git a/CAFAna/Vars/Vars.cxx b/CAFAna/Vars/Vars.cxx index afd5056e..b6049826 100644 --- a/CAFAna/Vars/Vars.cxx +++ b/CAFAna/Vars/Vars.cxx @@ -11,21 +11,21 @@ namespace ana { - // -->FD - const Var kRecoE_nue = SIMPLEVAR(Ev_reco_nue); - const Var kRecoE_numu = SIMPLEVAR(Ev_reco_numu); - const Var kRecoE_FromDep = SIMPLEVAR(eRec_FromDep); - const Var kFDNumuPid = SIMPLEVAR(cvnnumu); - const Var kFDNuePid = SIMPLEVAR(cvnnue); - const Var kMVANUMU = SIMPLEVAR(mvanumu); - - // -->ND - const Var kRecoEnergyND = SIMPLEVAR(Ev_reco); - const Var kRecoYND = (SIMPLEVAR(Ev_reco) - SIMPLEVAR(Elep_reco)) / SIMPLEVAR(Ev_reco); - const Var kRecoY_FromDep = (SIMPLEVAR(eRec_FromDep) - SIMPLEVAR(LepE)) / SIMPLEVAR(eRec_FromDep); - const Var kTrueEnergy = SIMPLEVAR(Ev); - - // CV weighting - const Weight kCVXSecWeights = SIMPLEWEIGHT(total_xsSyst_cv_wgt); // kUnweighted +// // -->FD +// const Var kRecoE_nue = SIMPLEVAR(Ev_reco_nue); +// const Var kRecoE_numu = SIMPLEVAR(Ev_reco_numu); +// const Var kRecoE_FromDep = SIMPLEVAR(eRec_FromDep); +// const Var kFDNumuPid = SIMPLEVAR(cvnnumu); +// const Var kFDNuePid = SIMPLEVAR(cvnnue); +// const Var kMVANUMU = SIMPLEVAR(mvanumu); +// +// // -->ND +// const Var kRecoEnergyND = SIMPLEVAR(Ev_reco); +// const Var kRecoYND = (SIMPLEVAR(Ev_reco) - SIMPLEVAR(Elep_reco)) / SIMPLEVAR(Ev_reco); +// const Var kRecoY_FromDep = (SIMPLEVAR(eRec_FromDep) - SIMPLEVAR(LepE)) / SIMPLEVAR(eRec_FromDep); + const Var kTrueEnergy = SIMPLEVAR(mc.nu[0].E);//Ev); +// +// // CV weighting +// const Weight kCVXSecWeights = SIMPLEWEIGHT(total_xsSyst_cv_wgt); // kUnweighted } diff --git a/CAFAna/Vars/Vars.h b/CAFAna/Vars/Vars.h index 97e45206..ce8bd306 100644 --- a/CAFAna/Vars/Vars.h +++ b/CAFAna/Vars/Vars.h @@ -10,21 +10,21 @@ namespace ana { -extern const Var kRecoE_nue; -extern const Var kRecoE_numu; -extern const Var kRecoE_FromDep; -extern const Var kFDNumuPid; -extern const Var kFDNuePid; -extern const Var kMVANUMU; - -// -->ND -extern const Var kRecoEnergyND; -extern const Var kRecoYND; -extern const Var kRecoY_FromDep; - +//extern const Var kRecoE_nue; +//extern const Var kRecoE_numu; +//extern const Var kRecoE_FromDep; +//extern const Var kFDNumuPid; +//extern const Var kFDNuePid; +//extern const Var kMVANUMU; +// +//// -->ND +//extern const Var kRecoEnergyND; +//extern const Var kRecoYND; +//extern const Var kRecoY_FromDep; +// extern const Var kTrueEnergy; - -// CV weighting -extern const Weight kCVXSecWeights; // kUnweighted +// +//// CV weighting +//extern const Weight kCVXSecWeights; // kUnweighted } // namespace diff --git a/CAFAna/cafe b/CAFAna/cafe index 8a669540..01ad28a1 100755 --- a/CAFAna/cafe +++ b/CAFAna/cafe @@ -152,6 +152,7 @@ if __name__ == '__main__': os.environ['EIGEN_INC'], os.environ['SUNDIALS_INC'], os.environ['OSCLIB_INC'], + os.environ['BOOST_INC'], os.environ['TBB_INC']] @@ -231,14 +232,15 @@ int main(int argc, char** argv) libs = ['Minuit2', 'TMVA', 'EG', 'duneanaobj_StandardRecord', 'duneanaobj_StandardRecordProxy', 'OscLib', 'CAFAnaCoreExt', - 'CAFAnaCore', 'CAFAnaVars', 'CAFAnaCuts', - 'CAFAnaExperiment', 'CAFAnaSysts', 'CAFAnaDecomp', 'CAFAnaExtrap', - 'CAFAnaPrediction', 'CAFAnaFit', 'CAFAnaAnalysis', + 'CAFAnaCore', + #'CAFAnaVars', 'CAFAnaCuts', + #'CAFAnaExperiment', 'CAFAnaSysts', 'CAFAnaExtrap', + #'CAFAnaPrediction', 'CAFAnaFit', 'CAFAnaAnalysis', 'boost_filesystem', 'boost_system'] print('Compiling macro...') incs = ' '.join(['-I '+p for p in path]) - compile_cmd = 'g++ -c -g '+d.name+'/'+fname+'.cxx -o '+d.name+'/'+fname+'.o' + ' -pthread -std=c++17 -m64 -UNDEBUG -fdiagnostics-color=auto -DDONT_USE_FQ_HARDCODED_SYST_PATHS=1 -UNDEBUG -DTBB_INTERFACE_NEW -DCAFANACORE_SPECTRUMLOADERBASE '+incs + compile_cmd = 'g++ -c -g '+d.name+'/'+fname+'.cxx -o '+d.name+'/'+fname+'.o' + ' -pthread -std=c++17 -m64 -UNDEBUG -fdiagnostics-color=auto -DDONT_USE_FQ_HARDCODED_SYST_PATHS=1 -UNDEBUG -DTBB_INTERFACE_NEW '+incs # print(compile_cmd) ret = subprocess.run(compile_cmd, shell=True).returncode if ret != 0: sys.exit(ret) diff --git a/CAFAna/cmake/FindCAFAnaCore.cmake b/CAFAna/cmake/FindCAFAnaCore.cmake index cfda0b9a..e257d283 100644 --- a/CAFAna/cmake/FindCAFAnaCore.cmake +++ b/CAFAna/cmake/FindCAFAnaCore.cmake @@ -27,7 +27,7 @@ find_path(CAFAnaCoreSAM PATHS ${CAFANACORE_INC} NO_DEFAULT_PATH) -SET(CAFAnaCore_CompileOptions "-DCAFANACORE_SPECTRUMLOADERBASE") +SET(CAFAnaCore_CompileOptions) if(NOT "${CAFAnaCoreSAM}x" STREQUAL "CAFAnaCoreSAM-NOTFOUNDx") if(DEFINED ENV{IFDHC_INC}) diff --git a/CAFAna/cmake/ups_env_setup.sh b/CAFAna/cmake/ups_env_setup.sh index 5866535b..e95bfcb3 100644 --- a/CAFAna/cmake/ups_env_setup.sh +++ b/CAFAna/cmake/ups_env_setup.sh @@ -2,21 +2,37 @@ source /cvmfs/dune.opensciencegrid.org/products/dune/setup_dune.sh +#Jeremys versions of cafanacore, osclib, duneanaobm srproxy +#export PRODUCTS="/exp/dune/app/users/jwolcott/ups:$PRODUCTS" + if [ -z "${UPS_SHELL}" ]; then echo "[ERROR]: Is UPS set up?" exit 1 fi -setup root v6_22_08d -q e20:prof:p392 || exit 1 +#setup root v6_28_10b -q e20:p3915:prof || exit 1 # v6_26_06b -q e20:p3913:prof $ +setup root v6_26_06b -q e20:p3913:prof || exit 1 setup boost v1_75_0 -q e20:prof || exit 1 setup cmake v3_22_2 || exit 1 setup jobsub_client || exit 1 -setup eigen v3_3_9a || exit 1 -setup stan v2_26_1 -q e20:prof || exit 1 -setup osclib v00.21 -q e20:prof:n311:stan || exit 1 -setup cafanacore v02.00 -q e20:prof:n311 || exit 1 -setup duneanaobj v02_02_00 -qe20:prof || exit 1 +#setup eigen v3_3_9a || exit 1 +#setup stan v2_26_1 -q e20:prof || exit 1 +#setup osclib v00.21 -q e20:prof:n311:stan || exit 1 +#setup cafanacore v02.00 -q e20:prof:n311 || exit 1 +#setup duneanaobj v03_02_01 -q e20:prof|| exit 1 #v03_02_01 v03_01_00 setup fhiclcpp v4_15_03 -q e20:prof || exit 1 # for prism +setup eigen v3_4_0 || exit 1 +setup stan v2_26_1 -q e20:prof || exit 1 +setup osclib testing -q e20:prof:stanfree || exit 1 +setup cafanacore testing -q e20:prof || exit 1 +#my v +setup duneanaobj vtestingm -q e20:debug || exit 1 +#Jeremys v +#setup duneanaobj vtesting -q e20:debug || exit 1 #v03_02_01 v03_01_00 + + + # To get setup_fnal_security which helps reading files over xrootd #setup duneutil v09_53_00d02 -q e20:prof +#setup duneutil v09_89_01d01 -q e26:prof echo "Finished ups setup." diff --git a/CAFAna/tute/TestAncestry.C b/CAFAna/tute/TestAncestry.C new file mode 100644 index 00000000..d482bc60 --- /dev/null +++ b/CAFAna/tute/TestAncestry.C @@ -0,0 +1,130 @@ +#include + +#include "duneanaobj/StandardRecord/Proxy/SRProxy.h" +#include "duneanaobj/StandardRecord/Navigate.h" +#include "duneanaobj/StandardRecord/SREnums.h" + +#include "CAFAna/Core/SpectrumLoader.h" +#include "CAFAna/Core/Spectrum.h" +#include "CAFAna/Core/Binning.h" +#include "CAFAna/Core/Var.h" +#include "CAFAna/Core/Cut.h" +#include "CAFAna/Core/HistAxis.h" + +#include "TCanvas.h" +#include "TH1.h" +#include "TLegend.h" + +using namespace ana; + + +const RecoPartVar kMatchedTruePartE([](const caf::SRRecoParticleProxy * part) -> float +{ + if (part->truth.empty()) + return -999.; + + // Ancestor() returns the closest ancestor in the SR hierarchy with the template type. + // Once we have the top-level object, we then can connect its + const caf::SRProxy * top = part->Ancestor(); + return caf::FindParticle(top->mc, part->truth[0])->p.E; +}); + +// reco particles whose best-match particle is a true muon +const RecoPartCut kMatchedToTrueMuon([](const caf::SRRecoParticleProxy * part) -> float +{ + if (part->truth.empty()) + return false; + + const caf::SRProxy * top = part->Ancestor(); + return std::abs(caf::FindParticle(top->mc, part->truth[0])->pdg) == 13; +}); + +// Select reco particles that have a pdg of muon +const RecoPartCut kIsMuon([](const caf::SRRecoParticleProxy* sr) + { + return abs(sr->pdg) == 13 ; + }); + +const Var kMatchedTrueInteractionEnergy([](const caf::SRInteractionProxy * ixn) -> float +{ + if (ixn->truth.empty()) + return -999.; + + // Ancestor() returns the closest ancestor in the SR hierarchy with the template type. + // Once we have the top-level object, we then can connect its + const caf::SRProxy * top = ixn->Ancestor(); + // should be a number... + return caf::FindInteraction(top->mc, ixn->truth[0])->E; + +}); + +// cut on true interaction mode as defined in StandardRecord/SREnums.h +const Cut kMatchedToTrueRES([](const caf::SRInteractionProxy * ixn) +{ + if (ixn->truth.empty()) + return false; + + const caf::SRProxy * top = ixn->Ancestor(); + return caf::FindInteraction(top->mc, ixn->truth[0])->mode == caf::ScatteringMode::kRes; +}); + +void TestAncestry() +{ + + const std::string fname = "/pnfs/dune/persistent/users/abooth/nd-production/MicroProdN1p2/output/run-cafmaker/MicroProdN1p2_NDLAr_1E18_RHC.caf.nu/CAF.flat/0000000/0000000/MicroProdN1p2_NDLAr_1E18_RHC.caf.nu.00000*"; + //"/exp/dune/data/users/noeroy/mywork/MiniRun5_Fixed_truth/MiniRun5_1E19_RHC.caf/CAF.flat/0000000/*.flat.root"; + + // Source of events + SpectrumLoader loader(fname); + + // Define axes for the spectra we'll make + const RecoPartHistAxis axEnergy("Best-matched true particle energy (GeV)", Binning::Simple(50, 0, 5), kMatchedTruePartE); + + Spectrum sEnergyMatched(loader.Interactions(RecoType::kDLP).RecoParticles(RecoType::kDLP)[kIsMuon], axEnergy); + Spectrum sEnergyMatchedTrueMu(loader.Interactions(RecoType::kDLP).RecoParticles(RecoType::kDLP)[kIsMuon && kMatchedToTrueMuon], axEnergy); + + const HistAxis axNuEnergy("True matched neutrino energy (GeV", Binning::Simple(50, 0, 20), kMatchedTrueInteractionEnergy); + Spectrum sNuEnergyMatched(loader.Interactions(RecoType::kDLP), axNuEnergy); + Spectrum sNuEnergyMatchedTrue(loader.Interactions(RecoType::kDLP)[kMatchedToTrueRES], axNuEnergy); + + // ~~~~**** -.-.-.-.-.-.-.-.-.-.-.- *****~~~~ + // Fill in the spectrum + loader.Go(); + + const double pot = sEnergyMatched.POT(); + //1e17; + + TCanvas c; + TLegend leg(0.6, 0.6, 0.9, 0.9); + leg.SetFillStyle(0); + leg.SetBorderSize(0); + + auto h1 = sEnergyMatched.ToTH1(pot); + h1->Draw("hist"); + leg.AddEntry(h1, "All reco muons"); + + auto h2 = sEnergyMatchedTrueMu.ToTH1(pot, kRed); + h2->Draw("hist same"); + leg.AddEntry(h2, "+ matched to true muons"); + + leg.Draw(); + + c.SaveAs("recoMu_matchedTrueE.png"); + + + TCanvas c2; + TLegend leg2(0.6, 0.6, 0.9, 0.9); + leg2.SetFillStyle(0); + leg2.SetBorderSize(0); + + auto h3 = sNuEnergyMatched.ToTH1(pot); + h3->Draw("hist"); + leg2.AddEntry(h3, "All neutrino ixn"); + + auto h4 = sNuEnergyMatchedTrue.ToTH1(pot, kRed); + h4->Draw("hist same"); + leg2.AddEntry(h2, "+ matched to RES"); + leg2.Draw(); + + c2.SaveAs("TrueE_matchedRES.png"); +} diff --git a/CAFAna/tute/demo0b.C b/CAFAna/tute/demo0b.C new file mode 100644 index 00000000..85ba9091 --- /dev/null +++ b/CAFAna/tute/demo0b.C @@ -0,0 +1,228 @@ + +#include "duneanaobj/StandardRecord/Proxy/SRProxy.h" + +#include "CAFAna/Core/SpectrumLoader.h" +#include "CAFAna/Core/Spectrum.h" +#include "CAFAna/Core/Binning.h" +#include "CAFAna/Core/Var.h" +#include "CAFAna/Core/Cut.h" +#include "CAFAna/Core/HistAxis.h" + +#include "TCanvas.h" +#include "TH1.h" +#include "TH2.h" +#include "TPad.h" +#include "TLegend.h" +#include +using namespace ana; + +// Make a few basic spectra from the cafs +// Reconstructed +// - One with Interaction Level vars/cuts +// - One with particle-level vars/cuts +// Truth +// - True interaction Level Vars/Cuts +// - True particles Level Vars/Cuts + + +void demo0b( std::string option = "flat") +{ + + std::string fname; + if(option=="caf") fname = "/exp/dune/data/users/skumara/Datafiles_2x2/CAF_rootfiles/MR5_beta2a_flash/test_flash.root"; + + if (option=="flat") fname = "/exp/dune/data/users/noeroy/mywork/MiniRun5_Fixed_truth/MiniRun5_1E19_RHC.caf/CAF.flat/0000000/*.flat.root"; + + + // Source of events + SpectrumLoader loader(fname); + + ///////////////////////////////////////////////////////////////// + // Reco-Particles (SRRecoParticleProxy) level vars and cuts + const RecoPartVar kRecoParticleEnergy = SIMPLEPARTVAR(E); + // Define axes for the spectra we'll make + const RecoPartHistAxis axEnergy("Muon energy (GeV)", Binning::Simple(50, 0, 1), kRecoParticleEnergy); + // Select particles that have a pdg of muon, + const RecoPartCut kIsMuon([](const caf::SRRecoParticleProxy* sr) + { + return abs(sr->pdg) == 13 ; + }); + + ///////////////////////////////////////////////////////////////// + // Interaction level (SRInteractionProxy) Simple vars + const Var kVtxX = SIMPLEVAR(vtx.x); + // we can also write vars with additional logic/operations + const Var kVtxZ([](const caf::SRInteractionProxy* sr) + { + double z = sr-> vtx.z;//-1300; + // you could do more operations here + return z; + }); + + // Histaxis with interaction level variables + // Note you can setup a 2D axis, you can directly write simple vars here + const HistAxis vtxPosition( "x(cm)", Binning::Simple(70,-70,70), kVtxX, + "z(cm)", Binning::Simple(70,-70,70), SIMPLEVAR(vtx.z)); //or kVtxZ + + // A simple selection cut at the level of vertices: i.e. containment + const Cut kContainedVertex([](const caf::SRInteractionProxy* sr) + { + double x = sr->vtx.x; + double y = sr->vtx.y; + double z = sr->vtx.z; + bool cont = abs(x)<50 && + abs(x)>10 && + abs(y)<50 && + abs(z)>10 && + abs(z)<50 ; + return cont; + }); + + + ///////////////////////////////////////////////////////////////// + // ~~~~**** now actually make some histograms *****~~~~ + // we use kNoCut at interactions level, meaning no selection on vertices, then with containment + // You can select RecoType::kDLP,kPandora at vtx/interaction level and kPIDA as well for particles + Spectrum sEnergyMuon( loader.Interactions(RecoType::kDLP)[kNoCut].RecoParticles( RecoType::kDLP)[kIsMuon], axEnergy); + Spectrum sEnergyMuonCont( loader.Interactions(RecoType::kDLP)[kContainedVertex].RecoParticles(RecoType::kDLP)[kIsMuon], axEnergy); + // Interaction level vars + Spectrum sVtxPositionAll( loader.Interactions(RecoType::kDLP)[kNoCut], vtxPosition); + Spectrum sVtxPositionCont(loader.Interactions(RecoType::kDLP)[kContainedVertex], vtxPosition); + + // You need the histaxis to match the Cut level (i.e: the next one will not work becausePosition is an SRInteraction entry + // but your spectrumLoader points to entries from SRRecoParticle + // Spectrum sVtxPositionCont(loader.Interactions(RecoType::kDLP)[kContainedVertex].RecoParticles(RecoType::kDLP)[kIsMuon], vtxPosition); + + ///////////////////////////////////////////////////////////////// + + const TruthVar kTrueId([](const caf::SRTrueInteractionProxy* nu){return nu->id;}); + + // lets try a reco histaxis wuth truth selection ... + const TruthCut kIsTrueNuMu ([](const caf::SRTrueInteractionProxy* nu){ + int pdg = nu->pdg; + return pdg==14; + }); + + const TruthCut kTruthContainedVertex ([](const caf::SRTrueInteractionProxy* nu){ + double x = nu->vtx.x; + double y = nu->vtx.y; + double z = nu->vtx.z; + bool cont = abs(x)<50 && + abs(x)>10 && + abs(y)<50 && + abs(z)>10 && + abs(z)<50 ; + return cont; + }); + + // This can be used for prefsi, primary or secondary particles. See spectrum constructor later. + const TruthPartVar kTruePartPDG([](const caf::SRTrueParticleProxy* part){ + int pdg = part->pdg; + // recast in a different way + //(1) muon + if ( abs(pdg)==13) return 1.; + //(2) electron + if ( abs(pdg)==11) return 2.; + //(3) proton + if ( pdg==2212) return 3.; + // (4) neutron + if ( pdg==2112) return 4.; + // (5) pi + + if ( pdg==211) return 5.; + // (6) pi - + if ( pdg==-211) return 6.; + // (7) pi0 + if ( pdg==111) return 7.; + // (8) photon + if (pdg==22) return 8.; + // (9) Any K0S, K0L K0 or K+/- + if (abs(pdg)==321 || pdg== 311|| pdg== 310|| pdg== 130) return 9.; + else{ + //std::cout< PDGlabels = {"#mu", "e","p","n","#pi^{+}","#pi^{-}","#pi^{0}","#gamma","K","other"}; + + const TruthHistAxis myHistTruthAxisPDG("true pdg", Binning::Simple(100, 0, 100), SIMPLETRUTHVAR(pdg)); + const TruthPartHistAxis myHistTruthPartAxisPDG("true particles pdg", Binning::Simple(10, 1, 11), kTruePartPDG); + + ///////////////////////////////////////////////////////////////// + // ~~~~**** now make some more histograms *****~~~~ + // this kind of an ugly plot + Spectrum PDGTrue(loader.NuTruths(), myHistTruthAxisPDG); + Spectrum sTrueNumuPDGtest(loader.NuTruths()[kIsTrueNuMu], myHistTruthAxisPDG); + + Spectrum PDGTruePrims(loader.NuTruths().TruthParticles(TruePType::kPrim)[kNoTruthPartCut], myHistTruthPartAxisPDG); + Spectrum PDGTrueSecs(loader.NuTruths()[kNoTruthCut].TruthParticles(TruePType::kSec)[kNoTruthPartCut], myHistTruthPartAxisPDG); + Spectrum PDGTruePreFSI(loader.NuTruths()[kNoTruthCut].TruthParticles(TruePType::kPreFSI)[kNoTruthPartCut], myHistTruthPartAxisPDG); + + Spectrum sTrueVtxPositionAll( loader.NuTruths(), + TruthHistAxis("Truth x(cm)", Binning::Simple(70,-70,70), SIMPLETRUTHVAR(vtx.x), + "Truth z(cm)", Binning::Simple(70,-70,70), SIMPLETRUTHVAR(vtx.z))); + Spectrum sTrueVtxPositionCont(loader.NuTruths()[kTruthContainedVertex], + TruthHistAxis("Truth x(cm)", Binning::Simple(70,-70,70), SIMPLETRUTHVAR(vtx.x), + "Truth z(cm)", Binning::Simple(70,-70,70), SIMPLETRUTHVAR(vtx.z))); + + Spectrum sTrueNumuEnergy( loader.NuTruths(), TruthHistAxis("True neutrino energy [GeV]", Binning::Simple(50,0,10),SIMPLETRUTHVAR(E)) ); + + ///////////////////////////////////////////////////////////////// + + // Fill in the spectra + loader.Go(); + + std::cout<< "Spectrum sTrueNumuPDGtest has"<< sTrueNumuPDGtest.ToTH1(sTrueNumuPDGtest.POT())->GetNbinsX() << "bins, and the axis "<< sTrueNumuPDGtest.GetBinnings()[0].NBins()<< " NBins\n"; + std::cout<< "eigen has size: "<< sTrueNumuPDGtest.GetEigen().rows() << "," << sTrueNumuPDGtest.GetEigen().cols()<Draw("hist"); + TH1 *emuCont=sEnergyMuonCont.ToTH1(pot,kMagenta+2); emuCont->Draw("hist same"); + auto *lege = new TLegend(.55,.5,.88,.88); + lege->AddEntry(emu, "All #mu energy","L"); + lege->AddEntry(emuCont, "Cont. #mu energy","L"); + lege->Draw(); + gPad->SaveAs(("demo0_sEnergyMuon"+option+".pdf").c_str()); + + new TCanvas; + PDGTrue.ToTH1(pot,kBlue)->Draw("hist same"); + sTrueNumuPDGtest.ToTH1(pot,kRed, kDashed)->Draw("hist same"); + + new TCanvas; + // you can also retrieve the TH1 * object and manipulate as usual in root + TH1* prims = PDGTruePrims.ToTH1(pot,kRed); + for (unsigned int i = 0; iGetXaxis()->SetBinLabel(i+1,PDGlabels[i].c_str()); + prims->SetTitle("True particles ID"); + prims->Draw("hist"); + TH1* secs = PDGTrueSecs.ToTH1(pot,kBlue); secs->Draw("hist same"); + TH1 *prefsi= PDGTruePreFSI.ToTH1(pot,kGreen+2); prefsi->Draw("hist same"); + auto *leg = new TLegend(.55,.7,.88,.88); + leg->AddEntry(prims, "Primaries","L"); + leg->AddEntry(secs, "Secondaries","L"); + leg->AddEntry(prefsi, "Pre-FSI","L"); + leg->SetFillStyle(0); + leg->Draw(); + gPad->SaveAs(("demo0_PDGprims_"+option+".pdf").c_str()); + + new TCanvas; + sTrueNumuEnergy.ToTH1(sTrueNumuEnergy.POT())->Draw("hist"); + + new TCanvas; + sVtxPositionAll.ToTH2(pot)->Draw("colz"); + gPad->SaveAs(("demo0_vtxPosAll_"+option+".pdf").c_str()); + new TCanvas; + sVtxPositionCont.ToTH2(pot)->Draw("colz"); + gPad->SaveAs(("demo0_vtxPosCont_"+option+".pdf").c_str()); + + + new TCanvas; + sTrueVtxPositionAll.ToTH2(sTrueVtxPositionAll.POT())->Draw("colz"); + gPad->SaveAs(("demo0_TruevtxPosAll_"+option+".pdf").c_str()); + new TCanvas; + sTrueVtxPositionCont.ToTH2(sTrueVtxPositionCont.POT())->Draw("colz"); + gPad->SaveAs(("demo0_TruevtxPosCont_"+option+".pdf").c_str()); + +} diff --git a/CAFAna/tute/demo0eb.C b/CAFAna/tute/demo0eb.C new file mode 100644 index 00000000..dd55de96 --- /dev/null +++ b/CAFAna/tute/demo0eb.C @@ -0,0 +1,434 @@ + +#include "duneanaobj/StandardRecord/Proxy/SRProxy.h" + +#include "CAFAna/Core/SpectrumLoader.h" +#include "CAFAna/Core/Spectrum.h" +#include "CAFAna/Core/Binning.h" +#include "CAFAna/Core/EnsembleSpectrum.h" +#include "CAFAna/Core/EnsembleRatio.h" +#include "CAFAna/Core/LoadFromFile.h" +#include "CAFAna/Core/Multiverse.h" +#include "CAFAna/Core/Var.h" +#include "CAFAna/Core/Cut.h" +#include "CAFAna/Core/HistAxis.h" +#include "CAFAna/Core/ISyst.h" +#include "CAFAna/Core/Utilities.h" + +#include "TFile.h" +#include "TCanvas.h" +#include "TH1.h" +#include "TH2.h" +#include "TPad.h" +#include "TColor.h" +#include + +using namespace ana; + +// Setup a dummy systematic that shifts Particle (Muon) Enegy by a +/- percent + + class EnergyScaleMu: public ISyst { + public: + EnergyScaleMu() : ISyst("EnergyScaleMu", "Muon Energy Scale Syst") {} + void Shift(double sigma, + caf::SRInteractionProxy* ixn, double& weight) const override; + }; + void EnergyScaleMu::Shift(double sigma, + caf::SRInteractionProxy* ixn, double& weight) const { + double scale = .05 * sigma; + + // loop through particles and change record to shift energy + for (int i=0; ipart.ndlp; i++){ + if ( abs(ixn->part.dlp[i].pdg)==13) { + ixn->part.dlp[i].E *= 1. + scale; + } + } + } + + const EnergyScaleMu kEnergyScaleMu; + + +//// A second dummy syst to have a multiverse with multiple systs +// A reweight systematic... multiply times [x] all events that pass [ some ] criteria + class MuonRwgtSyst : public ISyst + { + public : + MuonRwgtSyst(double scale, const std::string shortName, const std::string latexName) + : ISyst( shortName , latexName ), fScale(scale) {} + + void Shift( double sigma, caf::SRInteractionProxy* ixn, double& weight ) const override; + + private: + double fScale; + + }; + void MuonRwgtSyst::Shift( double sigma, caf::SRInteractionProxy* ixn, double& weight ) const + { + bool hasMuon = false; + // loop through particles see if theres a muon + for (int i=0; ipart.ndlp; i++){ + if ( abs(ixn->part.dlp[i].pdg)==13) { + hasMuon= true; + } + } + if (hasMuon){ + weight = 1 + sigma * fScale; + //std::cout<< " Found a Muon, wgt = "< +//{ +//public: +// MECScaleSyst(double scale, const std::string shortName, const std::string latexName) +// : ISyst(shortName, latexName), fScale(scale) {} +// +// void Shift( double sigma, caf::SRTrueInteractionProxy* ixn, double& weight) const override; +// +// private: +// double fScale; +//}; +//void MECScaleSyst::Shift(double sigma, caf::SRTrueInteractionProxy* ixn, double& weight) const +//{ +// if (ixn->mode == ScatteringMode::kMEC) +// weight = 1 + sigma * fScale; +// else +// weight=1; +//} +//const MECScaleSyst kMECScaleSyst(0.10, "MECScaleSyst", "MEC scale systematic"); +// Var that takes energy of the most energetic muon in interaction +const Var kEnergyInteractionMu([](const caf::SRInteractionProxy* ixn) + { + double e = -5.; + + int numMuons = 0; + for (int i=0; ipart.ndlp; i++){ + // check if muon + //std::cout<< "we are in particle "<< i<part.dlp[i].pdg)==13) { + numMuons ++; + //this muons energy + double tempE = ixn->part.dlp[i].E; + //std::cout<< "found muon # "<< numMuons<< ", idx "<1 ){ + // check which one has more energy + if (tempE>e) + e=tempE; // store if this muon has more energy + }else{ e = tempE;} + } + + } + return e; + }); + +// Var that sums up Energy of all tracks +// Var that takes energy of the most energetic muon in interaction +const Var kEnergyInteractionAll([](const caf::SRInteractionProxy* ixn) + { + double e = 0.; + for (int i=0; ipart.ndlp; i++){ + double tempE = ixn->part.dlp[i].E; + e = e + tempE; + }// in the weird case interaction had nothing?? + //if (e == 0) return -5.; + return e; + }); +// Var that takes energy of the most energetic muon in interaction +const Var kEnergyInteractionButMu([](const caf::SRInteractionProxy* ixn) + { + return kEnergyInteractionAll(ixn) - kEnergyInteractionMu(ixn); + }); + + + // A simple selection cut at the level of vertices: i.e. containment + const Cut kContainment([](const caf::SRInteractionProxy* ixn) + { + + double x = ixn->vtx.x; + double y = ixn->vtx.y; + double z = ixn->vtx.z; + bool cont = abs(x)<50 && + abs(x)>10 && + abs(y+310)<50 && + abs(z-1300)>10 && + abs(z-1300)<50 ; + return cont; + }); + +// Has only one muon + const Cut kHas1RecoMuon([](const caf::SRInteractionProxy* ixn) + { + int nMuons= 0; + for (int i=0; ipart.ndlp; i++){ + if ( abs(ixn->part.dlp[i].pdg)==13) { + nMuons++; + } + } + return (nMuons==1); + }); + + const RecoPartVar kRecoParticleEnergy = SIMPLEPARTVAR(E); + // Select particles that have a pdg of muon + const RecoPartCut kIsMuon([](const caf::SRRecoParticleProxy* sr) + { + return abs(sr->pdg) == 13 ; + }); + + +// Make a basic ensemble spectrum? +// based on https://github.com/SBNSoftware/sbnana/blob/feature/ext_cafanacore/sbnana/CAFAna/test/test_ensemble.C +void demo0eb() +{ + + // test multiverse + std::vector systs; //,systs2; + systs.push_back(&kEnergyScaleMu); + systs.push_back(&kMuonRwgtSyst); + //systs.push_back(&kDummyRwgtSyst); + + + // Two methods of generatig multiverse + // 100 Random values grom a gaussian distribution + // using the specific seed = 42 + const Multiverse& gas = Multiverse::RandomGas(systs, 100, 42); + // scans from -n to n sigma shifts, we'll do only the 1 sigma + const Multiverse& cross = Multiverse::Hypercross(systs,1); + + + + std::cout << gas.LatexName() << std::endl << gas.ShortName() << std::endl; + std::cout << cross.LatexName() << std::endl << cross.ShortName() << std::endl; + + std::cout << "gas has "<< gas.NUniv() << "universes from NUniv()\n"; + std::cout << "cross has "<< cross.NUniv() << "universes from NUniv()\n"; + // we can save our multiverses to file + TFile fout("test_multiverse.root", "RECREATE"); + gas.SaveTo(&fout, "gas"); + cross.SaveTo(&fout, "cross"); + fout.Close(); + + // and then retrieve multiverses from file + TFile fin("test_multiverse.root"); + const FitMultiverse& gas2 = *Multiverse::LoadFrom(&fin, "gas"); + const FitMultiverse& cross2 = *Multiverse::LoadFrom(&fin, "cross"); + +// you can print out exactly what are the values of each multiverse. +/* for (int i = 0; i< gas2.NUniv(); i++){ + for (const auto & [ key, value ] : gas2.GetUniverse(i)) { + std::cout << key->ShortName() << ": " << value << std::endl; + } + } +*/ + // you can print the hypercross universe to see what is going on + for (int i = 0; i< cross.NUniv(); i++){ + for (const auto & [ key, value ] : cross.GetUniverse(i)) { + std::cout << key->ShortName() << ": " << value << std::endl; + } + } + fin.Close(); + //----------------------------------------------------------------------// + // now make ensemble spectra + + const Binning binsEnergy = Binning::Simple(10, 0, 1); + + const HistAxis axMuEnergy("Muon energy (GeV)", binsEnergy, kEnergyInteractionMu); + const HistAxis axEnergy("Interaction energy (GeV)", binsEnergy, kEnergyInteractionAll); + const HistAxis axNoMuEnergy("non-muon energy (GeV)", binsEnergy,kEnergyInteractionButMu); + + const RecoPartHistAxis axRecoPartEnergy("Reco Particle Energy", binsEnergy, kRecoParticleEnergy); + + //std::vector weis; + //weis.reserve(101); + //weis.push_back(kUnweighted); // nominal + // TO DO: generate multiverse weights + //for(int i = 0; i < 99; ++i) weis.push_back(GetUniverseWeight("multisim_Genie", i)); + + const std::string fname = "/exp/dune/data/users/noeroy/mywork/MiniRun5_Fixed_truth/MiniRun5_1E19_RHC.caf/CAF.flat/0000000/*.flat.root"; + + // Source of events + SpectrumLoader loader(fname); + // This is another key line // dont know what is the 2nd [cut] applied to... + //EnsembleSpectrum sMuonEnsembleGauss(loader.Interactions(RecoType::kDLP).Ensemble(weis)[kContainment][kIsNumuCC], axEnergy); + // weis is a vector of weights that come from GetUniverseWeight + + // or whatever multiverse object, in this case randomly generated gaussian shifts + EnsembleSpectrum sMuonEnsembleGauss(loader.Interactions(RecoType::kDLP).Ensemble(gas)[kHas1RecoMuon], axMuEnergy); + EnsembleSpectrum sMuonEnsembleX(loader.Interactions(RecoType::kDLP).Ensemble(cross)[kHas1RecoMuon], axMuEnergy); + // Another way to access the same information from the reco particles branch + EnsembleSpectrum sMuonEnsemblePartX(loader.Interactions(RecoType::kDLP).Ensemble(cross)[kHas1RecoMuon].RecoParticles(RecoType::kDLP)[kIsMuon], axRecoPartEnergy); + // Doing the same for other particles to verify our systematic is working as expected + EnsembleSpectrum sOtherEnsemblePartX(loader.Interactions(RecoType::kDLP).Ensemble(cross)[kHas1RecoMuon].RecoParticles(RecoType::kDLP)[!kIsMuon], axRecoPartEnergy); + + + // The same but for a different variable + EnsembleSpectrum sAllEnsembleX(loader.Interactions(RecoType::kDLP).Ensemble(cross)[kHas1RecoMuon], axEnergy); + EnsembleSpectrum sNoMuEnsembleX(loader.Interactions(RecoType::kDLP).Ensemble(cross)[kHas1RecoMuon], axNoMuEnergy); + + + // some true distributions of MEC things + //EnsembleSpectrum sAllMECEnsemble(loader.NuTruths().Ensemble(crossMEC)[kIsMEC], axTrueEnergy); + //EnsembleSpectrum sAllnonMECEnsemble(loader.NuTruths().Ensemble(crossMEC)[!kIsMEC], axTrueEnergy); + + loader.Go(); + + const double pot = sMuonEnsembleGauss.POT();// 3.5 * 1.47e21 * 40/1.13; + + + //----------- save to file + TFile fout2("multiverse_ensemble_test.root", "RECREATE"); + sMuonEnsembleGauss.SaveTo(&fout2, "sMuonEnsembleGauss"); + sMuonEnsembleX.SaveTo(&fout2, "sMuonEnsembleX"); + fout2.Close(); + + + //----------- Display things in canvases for the gaussian random multiverse + // exercise load from file as well + + TFile fin2("multiverse_ensemble_test.root"); + EnsembleSpectrum sMuonEnsembleGaussFile= *EnsembleSpectrum::LoadFrom(&fin2, "sMuonEnsembleGauss"); + EnsembleSpectrum sMuonEnsembleXFile= *EnsembleSpectrum::LoadFrom(&fin2, "sMuonEnsembleX"); + + + new TCanvas; + TH1 * hsMuonEnsembleGauss = sMuonEnsembleGaussFile.Nominal().ToTH1(pot, kRed); + hsMuonEnsembleGauss->Draw("hist"); + + // a vector to store ratios to nominal + std::vector hratios; + for(unsigned int i = 0; i < sMuonEnsembleGaussFile.NUniverses(); ++i){ + hratios.push_back(sMuonEnsembleGaussFile.Universe(i).ToTH1(pot, kRed-10)); + + sMuonEnsembleGaussFile.Universe(i).ToTH1(pot, kRed-10)->Draw("hist same"); + + hratios.back()->Divide(hsMuonEnsembleGauss); + } + hsMuonEnsembleGauss->Draw("hist same"); + gPad->SaveAs("multiverse_gauss.pdf"); + + hratios[0]->SetMinimum(.6); + hratios[0]->SetMaximum(1.4); + new TCanvas; + for (unsigned int i = 0; i < sMuonEnsembleGaussFile.NUniverses(); ++i) + hratios[i]->Draw("hist same"); + gPad->SaveAs("multiverse_gauss_ratios.pdf"); + + new TCanvas; + // Error band summing in quadrature + TGraphAsymmErrors* eBand =sMuonEnsembleGaussFile.ErrorBand(pot); + DrawErrorBand(hsMuonEnsembleGauss, eBand); + + gPad->SaveAs("multiverse_ErrorBand.pdf"); + + + // Grab covariance matrix + Eigen::MatrixXd m= sMuonEnsembleGaussFile.CovarianceMatrix(pot); + std::cout << "The matrix m is of size " << m.rows() << "x" << m.cols() << std::endl; + // convert to th2 for drawing + TH2F* hCov = EigenMatrixToTH2(m); + new TCanvas; + hCov->Draw("colz"); + gPad->SaveAs("cov_mx.pdf"); + + // grab bias matrix + Eigen::MatrixXd mb= sMuonEnsembleGaussFile.BiasMatrix(pot); + TH2F* hBias = EigenMatrixToTH2(mb); + new TCanvas; + hBias->Draw("colz"); + gPad->SaveAs("bias_mx.pdf"); + + // ------- More canvases for the hypercross univ + new TCanvas; + TH1 * hsMuonEnsembleX = sMuonEnsembleXFile.Nominal().ToTH1(pot, kBlue); + hsMuonEnsembleX->SetMaximum(1.3*hsMuonEnsembleX->GetMaximum()); + hsMuonEnsembleX->Draw("hist"); + // a vector to store ratios to nominal + std::vector hratiosx; + std::cout<< "cross has "<Draw("hist same"); + hratiosx.push_back(sMuonEnsembleXFile.Universe(i).ToTH1(pot, color,kDashed)); + hratiosx.back()->Divide(hsMuonEnsembleX); + + } + hsMuonEnsembleX->Draw("hist same"); + gPad->SaveAs("multiverse_x_.pdf"); + + hratiosx[0]->SetMinimum(.6); + hratiosx[0]->SetMaximum(1.4); + new TCanvas; + for (unsigned int i = 0; i < sMuonEnsembleXFile.NUniverses(); ++i) + hratiosx[i]->Draw("hist same"); + gPad->SaveAs("multiverse_x_ratios.pdf"); + // we dont get covariance out of this one + + new TCanvas; + + TH1 * hsMuonEnsembleX2 = sMuonEnsemblePartX.Nominal().ToTH1(pot, kGreen+2); + TH1 * hsNoMuonEnsembleX2 = sOtherEnsemblePartX.Nominal().ToTH1(pot, kPink); + + + hsMuonEnsembleX2->SetMaximum(1.3*hsMuonEnsembleX2->GetMaximum()); + hsMuonEnsembleX2->Draw("hist"); + hsNoMuonEnsembleX2->Draw("hist same"); + for(unsigned int i = 0; i < sMuonEnsemblePartX.NUniverses(); ++i){ + // using different colors per systematic + Color_t color = kGreen+2; + Color_t color2 =kBlack ; + if (i==0){ color = kGreen+2; color2 =kBlack;} + if (i== 1 || i==2) {color = kViolet +1; color2 =kAzure+2;} + if (i==3 || i==4) {color = kPink; color2=kTeal-7;} + + sMuonEnsemblePartX.Universe(i).ToTH1(pot, color,kDashed)->Draw("hist same"); + sOtherEnsemblePartX.Universe(i).ToTH1(pot, color2,kDashed)->Draw("hist same"); + + } + +/* + // repeat for other variable + new TCanvas; + TH1 * hsAllEnsembleX = sAllEnsembleX.Nominal().ToTH1(pot, kBlue); + TH1 * hsNoMuEnsembleX = sNoMuEnsembleX.Nominal().ToTH1(pot, kGreen+2); + hsAllEnsembleX->Draw("hist"); + hsNoMuEnsembleX->Draw("hist same"); + // a vector to store ratios to nominal + std::vector hratiosxAll, hratiosxNoMu; + std::cout<< "cross has "<Draw("hist same"); + sNoMuEnsembleX.Universe(i).ToTH1(pot, color2, kDashed)->Draw("hist same"); + hratiosxAll.push_back(sAllEnsembleX.Universe(i).ToTH1(pot, color,kDashed)); + hratiosxAll.back()->Divide(hsAllEnsembleX); + hratiosxNoMu.push_back(sNoMuEnsembleX.Universe(i).ToTH1(pot, color2,kDashed)); + hratiosxNoMu.back()->Divide(hsNoMuEnsembleX); + } + hsAllEnsembleX->Draw("hist same"); + //gPad->SaveAs("multiverse_x_all.pdf"); + gPad->SaveAs("multiverse_x_all2.pdf"); + + hratiosxAll[0]->SetMinimum(.6); + hratiosxAll[0]->SetMaximum(1.4); + new TCanvas; + for (unsigned int i = 0; i < sAllEnsembleX.NUniverses(); ++i){ + hratiosxAll[i]->Draw("hist same"); + hratiosxNoMu[i]->Draw("hist same"); + } +// gPad->SaveAs("multiverse_x_ratios_all.pdf"); + gPad->SaveAs("multiverse_x_ratios_all2.pdf"); +*/ +} diff --git a/CAFAna/tute/demo1b.C b/CAFAna/tute/demo1b.C new file mode 100644 index 00000000..3f927c92 --- /dev/null +++ b/CAFAna/tute/demo1b.C @@ -0,0 +1,317 @@ +// Make a simple spectrum plot +// cafe demo0.C + +#include "duneanaobj/StandardRecord/Proxy/SRProxy.h" + +#include "CAFAna/Core/SpectrumLoader.h" +#include "CAFAna/Core/Spectrum.h" +#include "CAFAna/Core/Binning.h" +#include "CAFAna/Core/Var.h" +#include "CAFAna/Core/Cut.h" +#include "CAFAna/Core/HistAxis.h" + +//#include "CAFAna/Cuts/TruthCuts.h" + +#include "TCanvas.h" +#include "TH1.h" +#include "TH2.h" +#include "TPad.h" +#include "TVector3.h" + +using namespace ana; + +const auto beam_dir = TVector3(0.0, -0.05836, 1.0); + + + + +// Mesonless analysis cuts + // From https://indico.fnal.gov/event/61771/contributions/277573/attachments/172154/ + //Require 1 muon (either +/-), 0 pions, and N protons as primary particles (no cuts on photons or electrons tagged as primaries) + //No requirement on the muon entering/exiting MINERvA + //No fiducial volume cuts, No containment cuts +const Cut kMesonlessSelection([](const caf::SRInteractionProxy* sr) + { + int num_muons = 0; + int num_prtns = 0; + int num_pions = 0; + int num_phtns = 0; + int num_elecs = 0; + // loop over particles and count each type + for (const auto & part : sr->part.dlp ){ + if(part.primary == false) + continue; + if( abs(part.pdg) == 13) + num_muons++; + if(part.pdg == 211) + num_pions++; + if(part.pdg == 2212) + num_prtns++; + if(part.pdg == 22) + num_phtns++; + if(part.pdg == 11) + num_elecs++; + } + return ( num_muons==1 && num_pions<1 && num_prtns>0 ); + }); + +const RecoPartCut kContainedPart([](const caf::SRRecoParticleProxy* part){return part->contained;}); + +TVector3 RecoPartDir(const caf::SRRecoParticleProxy* part){ + + TVector3 ret = TVector3(part->end.x, part->end.y, part->end.z) - + TVector3(part->start.x,part->start.y,part->start.z); + return ret; +} + +const RecoPartCut kPartLenCut([](const caf::SRRecoParticleProxy* part) + { + auto len=-5.; + // prevent showers to be accounted + if (part->E_method != caf::PartEMethod::kCalorimetry) len = RecoPartDir(part).Mag(); + return len>2; + }); + +const RecoPartVar kPartLen([](const caf::SRRecoParticleProxy* part) + { + auto len=-5.; + // prevent trying to calculate shw lenght, as they have infinity end-point + if (part->E_method != caf::PartEMethod::kCalorimetry) len = RecoPartDir(part).Mag(); + return len; + }); + +// A generic selection on the pdg of the particle + const RecoPartCut kPartCut(int PDG){ + const RecoPartCut kIsPDG([PDG](const caf::SRRecoParticleProxy* part) + { + return abs(part->pdg) == PDG ; + }); + return kIsPDG; + } +// vars + +const RecoPartVar kPartAngle([](const caf::SRRecoParticleProxy* part) + { + //auto dir = TVector3(part->end.x, part->end.y, part->end.z) - + // TVector3(part->start.x,part->start.y,part->start.z); + auto angle = RecoPartDir(part).Angle(beam_dir) * 180.0 / TMath::Pi(); + //auto angle = TVector3(part->p.x,part->p.y,part->p.z).Angle(beam_dir) * 180.0 / TMath::Pi(); + return angle; + }); + // momentum +const RecoPartVar kPartMomentum([](const caf::SRRecoParticleProxy* part) + { + float p = std::sqrt( (part->p.x * part->p.x) + (part->p.y * part->p.y) + (part->p.z * part->p.z)); + return p; + }); + + +// Using E_method to count tracks/showers, because there's currently no implementation to combine +// entreis from SRNDLarIntProxy and SRInteractionProxy +const Var kNumberOfTracks([](const caf::SRInteractionProxy* ixn) + { + double num_tracks=0; + + for (int j=0; jpart.ndlp; j++){ + if ( ixn->part.dlp[j].E_method == caf::PartEMethod::kRange || + ixn->part.dlp[j].E_method == caf::PartEMethod::kMCS ) + num_tracks++; + + } + return num_tracks; + }); +// +const Var kNumberOfShowers([](const caf::SRInteractionProxy* ixn) + { + double num_shw=0; + for (int j=0; jpart.ndlp; j++){ + if ( ixn->part.dlp[j].E_method == caf::PartEMethod::kCalorimetry) + num_shw++; + + } + return num_shw; + }); + +const Var kNumberOfTrkShw([](const caf::SRInteractionProxy* ixn) + { + return ixn->part.ndlp; + }); + + + +void demo1b() +{ + // Environment variables and wildcards work. As do SAM datasets. + const std::string fname = "/exp/dune/data/users/noeroy/prod/MiniRun5_1E19_RHC/MiniRun5_1E19_RHC.caf.beta1/CAF/0000000/*.root"; + //"/pnfs/dune/persistent/users/mkramer/productions/MiniRun4.5_1E19_RHC/CAF_beta3/CAF/0000000/MiniRun4.5_1E19_RHC.caf.0000*"; + //"/dune/data/users/skumara/Datafiles_2x2/CAF_rootfiles/Picorun4.2/flat/PicoRun4.2_1E17_RHC.flow.0000*"; + /// "/dune/data/users/skumara/Datafiles_2x2/CAF_rootfiles/minirun4/notruth/outputCAF_notruth_*"; + // "/dune/data/users/skumara/Datafiles_2x2/CAF_rootfiles/Picorun4.2/PicoRun4.2_1E17_RHC.flow*"; +// "/dune/data/users/skumara/Datafiles_2x2/CAF_rootfiles/Picorun4.1/PicoRun4.1_1E17_RHC.flow*"; + + + // Source of events + SpectrumLoader loader(fname); + + // We will also use two different Vars. For such simple ones we can use this + // Variables at the level of Particles + const RecoPartVar kRecoParticleEnergy = SIMPLEPARTVAR(E); + const RecoPartVar kRecoParticlePDG = SIMPLEPARTVAR(pdg); + + // Define axes for the spectra we'll make + const RecoPartHistAxis axEnergy("Muon energy (GeV)", Binning::Simple(50, 0, 1), kRecoParticleEnergy); + const RecoPartHistAxis axPDG("PDG of reco particle", Binning::Simple(14, 0, 14), kRecoParticlePDG); + + +// Select particles that have a pdg of muon + const RecoPartCut kIsMuon([](const caf::SRRecoParticleProxy* sr) + { + return abs(sr->pdg) == 13 ; + }); + +// A simple selection cut at the level of vertices: i.e. containment +const Cut kContainment([](const caf::SRInteractionProxy* ixn) + { + double x = ixn->vtx.x; + double y = ixn->vtx.y; + double z = ixn->vtx.z; + bool cont = abs(x)<50 && + abs(x)>10 && + abs(y)<50 && + abs(z)>10 && + abs(z)<50 ; + return cont; + }); + + +const Cut kShwCut([](const caf::SRInteractionProxy* ixn) + { + //Vertex must have more than one shower and 0 tracks. + return !(kNumberOfShowers(ixn)==1 && kNumberOfTracks(ixn)==0 ) ; + }); + + + + //2D histaxis with interaction level variables + const HistAxis vtxPosition( "x(cm)", Binning::Simple(60,-60,60), SIMPLEVAR(vtx.x), + "z(cm)", Binning::Simple(60,-60,60), SIMPLEVAR(vtx.z)); + +// Multiplicity of all particles reconstructed from selected vertices + // tracks + // showers + const HistAxis trackMult("Number of particles", Binning::Simple(20,0,20), kNumberOfTracks); + const HistAxis shwMult("Number of particles", Binning::Simple(20,0,20), kNumberOfShowers); + const HistAxis trkshwMult("Number of particles", Binning::Simple(20,0,20), kNumberOfTrkShw); + + // - Track length of all reconstructed tracks binned in 1 cm bins. + const RecoPartHistAxis trkLen("Track length (cm)", Binning::Simple(100,0,100),kPartLen); + + +// ~~~~**** where the magic happens *****~~~~ + // we use kNoCut at interactions level, meaning no selection on vertices + Spectrum sEnergyMuon(loader.Interactions(RecoType::kDLP).RecoParticles(RecoType::kDLP)[kIsMuon], axEnergy); + Spectrum sEnergyMuonContX(loader.Interactions(RecoType::kDLP)[kContainment].RecoParticles(RecoType::kDLP)[kIsMuon], axEnergy); + Spectrum sEnergyElectron(loader.Interactions(RecoType::kDLP).RecoParticles(RecoType::kDLP)[kPartCut(11)], axEnergy); + + Spectrum sVtxPositionAll(loader.Interactions(RecoType::kDLP), vtxPosition); + Spectrum sVtxPositionCont(loader.Interactions(RecoType::kDLP)[kContainment], vtxPosition); +// +//// This wont work with a cut because the information of number of tracks +//// is in a different branch than the vtx position information + Spectrum sTrackMultContained( loader.Interactions(RecoType::kDLP)[kContainment && kShwCut], trackMult); + Spectrum sShowerMultContained(loader.Interactions(RecoType::kDLP)[kContainment && kShwCut], shwMult); + Spectrum sAllMultContained( loader.Interactions(RecoType::kDLP)[kContainment && kShwCut], trkshwMult); + + Spectrum sTrackLen(loader.Interactions(RecoType::kDLP)[kContainment && kShwCut].RecoParticles(RecoType::kDLP)[kNoPartCut], trkLen); + +////// Mesonless analysis plots +// /// Mesonless analysis axes +// const RecoPartHistAxis axPartMomentum("Momentum (GeV)", Binning::Simple(50, 0.0, 1.0), kPartMomentum); +// const RecoPartHistAxis axPartAngle("angle(deg)",Binning::Simple(60, 0.0, 180),kPartAngle); +// //Candidate = primary protons in selected interactions +// // All +// Spectrum CandidateProtonMomentum(loader.Interactions(RecoType::kDLP)[kMesonlessSelection].RecoParticles(RecoType::kDLP)[kPartCut(2212)],axPartMomentum ); +// Spectrum AllProtonMomentum(loader.Interactions(RecoType::kDLP)[kNoCut].RecoParticles(RecoType::kDLP)[kPartCut(2212)],axPartMomentum ); +// +// Spectrum CandidateProtonMomentumCont(loader.Interactions(RecoType::kDLP)[kMesonlessSelection].RecoParticles(RecoType::kDLP)[kPartCut(2212)&&kContainedPart&&kPartLenCut],axPartMomentum ); +// Spectrum AllProtonMomentumCont( loader.Interactions(RecoType::kDLP)[kNoCut].RecoParticles(RecoType::kDLP)[kPartCut(2212)&&kContainedPart&&kPartLenCut],axPartMomentum ); +// +// +// Spectrum CandidateProtonAngle(loader.Interactions(RecoType::kDLP)[kMesonlessSelection].RecoParticles(RecoType::kDLP)[kPartCut(2212)],axPartAngle ); +// Spectrum AllProtonAngle(loader.Interactions(RecoType::kDLP)[kNoCut].RecoParticles(RecoType::kDLP)[kPartCut(2212)],axPartAngle ); +// +// Spectrum CandidateProtonAngleCont(loader.Interactions(RecoType::kDLP)[kMesonlessSelection].RecoParticles(RecoType::kDLP)[kPartCut(2212)&&kContainedPart&&kPartLenCut],axPartAngle ); +// Spectrum AllProtonAngleCont( loader.Interactions(RecoType::kDLP)[kNoCut].RecoParticles(RecoType::kDLP)[kPartCut(2212)&&kContainedPart&&kPartLenCut],axPartAngle ); +// + +// ~~~~**** -.-.-.-.-.-.-.-.-.-.-.- *****~~~~ + // Fill in the spectrum + loader.Go(); + + // We are forcing the pot value because cafs dont have this information yet + const double pot = 1e17; + + sEnergyMuon.OverridePOT(pot); + sEnergyMuonContX.OverridePOT(pot); + sEnergyElectron.OverridePOT(pot); + + sVtxPositionAll.OverridePOT(pot); + sVtxPositionCont.OverridePOT(pot); + + sTrackMultContained.OverridePOT(pot); + sShowerMultContained.OverridePOT(pot); + sAllMultContained.OverridePOT(pot); + + sTrackLen.OverridePOT(pot); +// CandidateProtonMomentum.OverridePOT(pot); +// CandidateProtonMomentumCont.OverridePOT(pot); +// AllProtonMomentum.OverridePOT(pot); +// AllProtonMomentumCont.OverridePOT(pot); +// +// CandidateProtonAngle.OverridePOT(pot); +// CandidateProtonAngleCont.OverridePOT(pot); +// AllProtonAngle.OverridePOT(pot); +// AllProtonAngleCont.OverridePOT(pot); + //ta da! + sEnergyMuon.ToTH1(pot)->Draw("hist"); + sEnergyMuonContX.ToTH1(pot,kMagenta+2)->Draw("hist same"); + sEnergyElectron.ToTH1(pot,kGreen+1)->Draw("hist same"); + + new TCanvas; + sVtxPositionAll.ToTH2(pot)->Draw("colz"); + gPad->SaveAs("demo1b_AllVtxPosition.pdf"); + new TCanvas; + sVtxPositionCont.ToTH2(pot)->Draw("colz"); + gPad->SaveAs("demo1b_ContainedVtxPosition.pdf"); + + new TCanvas; + sTrackMultContained.ToTH1(pot,kBlue,kDashed)->Draw("hist same"); + sAllMultContained.ToTH1(pot,kRed,kDotted)->Draw("hist same"); +// sShowerMultContained.ToTH1(pot,kRed,kDotted)->Draw("hist same"); + gPad->SaveAs("demo1b_ContainedMultiplicity.pdf"); + + new TCanvas; + sTrackLen.ToTH1(pot,kRed,kDotted)->Draw("hist same"); + gPad->SaveAs("demo1b_ContainedTrackLen.pdf"); +// +// new TCanvas; +// CandidateProtonMomentum.ToTH1(pot)->Draw("hist"); +// CandidateProtonMomentumCont.ToTH1(pot,kRed)->Draw("hist same"); +// gPad->SaveAs("demo1b_mesonless_CandidateProtonMomentum.pdf"); +// +// new TCanvas; +// AllProtonMomentum.ToTH1(pot)->Draw("hist"); +// AllProtonMomentumCont.ToTH1(pot,kRed)->Draw("hist same"); +// gPad->SaveAs("demo1b_All_CandidateProtonMomentum.pdf"); +// +// new TCanvas; +// CandidateProtonAngle.ToTH1(pot)->Draw("hist"); +// CandidateProtonAngleCont.ToTH1(pot,kRed)->Draw("hist same"); +// gPad->SaveAs("demo1b_mesonless_CandidateProtonAngle.pdf"); +// +// new TCanvas; +// AllProtonAngle.ToTH1(pot)->Draw("hist"); +// AllProtonAngleCont.ToTH1(pot,kRed)->Draw("hist same"); +// gPad->SaveAs("demo1b_All_CandidateProtonAngle.pdf"); + +} diff --git a/CAFAna/tute/demo2eb.C b/CAFAna/tute/demo2eb.C new file mode 100644 index 00000000..1defa243 --- /dev/null +++ b/CAFAna/tute/demo2eb.C @@ -0,0 +1,219 @@ + +#include "duneanaobj/StandardRecord/Proxy/SRProxy.h" + +#include "CAFAna/Core/SpectrumLoader.h" +#include "CAFAna/Core/Spectrum.h" +#include "CAFAna/Core/Binning.h" +#include "CAFAna/Core/EnsembleSpectrum.h" +#include "CAFAna/Core/EnsembleRatio.h" +#include "CAFAna/Core/LoadFromFile.h" +#include "CAFAna/Core/Multiverse.h" +#include "CAFAna/Core/Var.h" +#include "CAFAna/Core/Cut.h" +#include "CAFAna/Core/HistAxis.h" +#include "CAFAna/Core/ISyst.h" +#include "demo0eb.C" + +#include "TFile.h" +#include "TCanvas.h" +#include "TH1.h" +#include "TH2.h" +#include "TPad.h" +#include "TColor.h" +#include + +using namespace ana; + + + + class DummySyst: public ISyst + { + public: + DummySyst(const std::string& shortName, const std::string& longName) + :ISyst(shortName, longName) {} + virtual void Shift(double, caf::SRInteractionProxy*, double&) const {} + }; + + + // declare a particular systematic and names + // varied the ionization potential (W_ion) parameter in larnd-sim to +/-3 sigma + // (to 25.1 and 22.7 eV respectively) from its nominal value (23.6 eV). + extern const DummySyst kWIonSyst("WIon", "Ionization Potential"); + extern const DummySyst kDummyNominalSyst("Nominal","Nominal"); + + std::vector GetDummyShifts(const ISyst* s) + { + // do for each different file syst, some may be one-sided, etc... + // not sure if should label it as +/- 1 or 3.. anyways it is easily changed + if (s == &kWIonSyst ) return {-1,0,1}; + else return {0}; + }; + +struct ShiftedSpec +{ + Spectrum spec; + SystShifts shift; +}; + + +// Script to make a basic ensemble spectrum +// Based on file systematics +// So fill up a nominal +// Fill Plus and minus 1 sigma versions +// This is a cross systematic type I guess +// Instantiate a dummy systematic to construct Multiverse +// Get a wrapper that merges various spectra into a simgle ensemble spectrum thing... + +void demo2eb() +{ + + + + // test multiverse + std::vector systs; //,systs2; + systs.push_back(& ); + + + // scans from -n to n sigma shifts, we'll do only the 1 sigma + const Multiverse& cross = Multiverse::Hypercross(systs,1); + + std::cout << cross.LatexName() << std::endl << cross.ShortName() << std::endl; + + // we can save our multiverses to file + TFile fout("test_multiverse.root", "RECREATE"); + cross.SaveTo(&fout, "cross"); + fout.Close(); + + // and then retrieve multiverses from file + TFile fin("test_multiverse.root"); + const FitMultiverse& cross2 = *Multiverse::LoadFrom(&fin, "cross"); + + + // you can print the hypercross universe to see what is going on + for (int i = 0; i< cross.NUniv(); i++){ + for (const auto & [ key, value ] : cross.GetUniverse(i)) { + std::cout << key->ShortName() << ": " << value << std::endl; + } + } + fin.Close(); + //----------------------------------------------------------------------// + // now make ensemble spectra + + const Binning binsEnergy = Binning::Simple(10, 0, 1); + + const HistAxis axMuEnergy("Muon energy (GeV)", binsEnergy, kEnergyInteractionMu); + const HistAxis axEnergy("Interaction energy (GeV)", binsEnergy, kEnergyInteractionAll); + const HistAxis axNoMuEnergy("non-muon energy (GeV)", binsEnergy,kEnergyInteractionButMu); + + const RecoPartHistAxis axRecoPartEnergy("Reco Particle Energy", binsEnergy, kRecoParticleEnergy); + + + //const std::string fname_nom = "/exp/dune/data/users/mcasales/test_cafs/MiniRun5_1E19_RHC.caf.0001013.CAF.root"; + // also beta2a + const std::string fname_nom = "/exp/dune/data/users/noeroy/mywork/MiniRun5_Fixed_truth/MiniRun5_1E19_RHC.caf/CAF.flat/0000000/*.flat.root"; +//"/exp/dune/data/users/noeroy/prod/MiniRun5_1E19_RHC/MiniRun5_1E19_RHC.caf.beta1/CAF/0000000/MiniRun5_1E19_RHC.caf.0000*"; + const std::string fname_up = "/pnfs/dune/persistent/users/cuddandr/2x2_production/MiniRun5_Systematics_W_ION_22.7/MiniRun5_Systematics_W_ION_22.7.caf/CAF/0000000/MiniRun5_Systematics_W_ION_22.7.caf.*"; + const std::string fname_down = "/pnfs/dune/persistent/users/cuddandr/2x2_production/MiniRun5_Systematics_W_ION_25.1/MiniRun5_Systematics_W_ION_25.1.caf/CAF/0000000/MiniRun5_Systematics_W_ION_25.1.caf.*"; + + // Source of events + SpectrumLoader loader_nom(fname_nom); + SpectrumLoader loader_up(fname_up); + SpectrumLoader loader_down(fname_down); + + // Fill various spectra with these... + Spectrum sEnergyMatchedTrueMu_nom(loader_nom.Interactions(RecoType::kDLP)[kHas1RecoMuon], axMuEnergy); + Spectrum sEnergyMatchedTrueMu_up(loader_up.Interactions(RecoType::kDLP)[kHas1RecoMuon], axMuEnergy); + Spectrum sEnergyMatchedTrueMu_down(loader_down.Interactions(RecoType::kDLP)[kHas1RecoMuon], axMuEnergy); + +// Spectrum sEnergyMatchedTrueMu_nom(loader_nom.Interactions(RecoType::kDLP).RecoParticles(RecoType::kDLP)[kIsMuon && kMatchedToTrueMuon], axEnergy); +// Spectrum sEnergyMatchedTrueMu_up(loader_up.Interactions(RecoType::kDLP).RecoParticles(RecoType::kDLP)[kIsMuon && kMatchedToTrueMuon], axEnergy); +// Spectrum sEnergyMatchedTrueMu_down(loader_down.Interactions(RecoType::kDLP).RecoParticles(RecoType::kDLP)[kIsMuon && kMatchedToTrueMuon], axEnergy); + + loader_nom.Go(); + loader_up.Go(); + loader_down.Go(); + + // Save the three spectra to file + TFile fout2("multiverse_ensemble_spec.root", "RECREATE"); + sEnergyMatchedTrueMu_nom.SaveTo(&fout2, "sEnergyMatchedTrueMu_nom"); + sEnergyMatchedTrueMu_up.SaveTo(&fout2, "sEnergyMatchedTrueMu_up"); + sEnergyMatchedTrueMu_down.SaveTo(&fout2, "sEnergyMatchedTrueMu_down"); + cross.SaveTo(&fout2, "cross"); + fout2.Close(); + + TFile * fIn = new TFile("multiverse_ensemble_spec.root"); + std::vector specs= {}; + // make sure to place nominal first... + specs.push_back(*Spectrum::LoadFrom(fIn, "sEnergyMatchedTrueMu_nom").release() ); + // then -1 shift + specs.push_back(*Spectrum::LoadFrom(fIn, "sEnergyMatchedTrueMu_down").release()); + // then +1 shift + specs.push_back(*Spectrum::LoadFrom(fIn, "sEnergyMatchedTrueMu_up").release() ); + + + // get from file + const FitMultiverse& cross22 = *Multiverse::LoadFrom(fIn, "cross"); + + EnsembleSpectrum sEnergyMatchedWIon = EnsembleSpectrum::MergeSpectra(specs, &cross22);//, axMuEnergy ); + + + TFile fout3("multiverse_ensemble_spec_2.root", "RECREATE"); + sEnergyMatchedWIon.SaveTo(&fout3, "sEnergyMatchedWIon"); + fout3.Close(); + + // Read spectra from file + TFile fin2("multiverse_ensemble_spec_2.root"); + + EnsembleSpectrum sEnergyMatchedWIon2 =*EnsembleSpectrum::LoadFrom(&fin2, "sEnergyMatchedWIon"); + + // ------- More canvases for the hypercross univ + double pot = sEnergyMatchedTrueMu_nom.POT(); + new TCanvas; + TH1 * hsMuonEnsembleX = sEnergyMatchedWIon2.Nominal().ToTH1(pot, kBlue); + hsMuonEnsembleX->SetMaximum(1.3*hsMuonEnsembleX->GetMaximum()); + hsMuonEnsembleX->Draw("hist"); + // a vector to store ratios to nominal + std::vector hratiosx; + std::cout<< "cross has "<Draw("hist same"); + hratiosx.push_back(sEnergyMatchedWIon2.Universe(i).ToTH1(pot, color,kDashed)); + hratiosx.back()->Divide(hsMuonEnsembleX); + + } + hsMuonEnsembleX->Draw("hist same"); + gPad->SaveAs("spec_ensemble_test.pdf"); + + hratiosx[0]->SetMinimum(.6); + hratiosx[0]->SetMaximum(1.4); + new TCanvas; + for (unsigned int i = 0; i < sEnergyMatchedWIon2.NUniverses(); ++i) + hratiosx[i]->Draw("hist same"); + gPad->SaveAs("spec_ensemble_test_ratios.pdf"); + + + new TCanvas; + // Grab covariance matrix + Eigen::MatrixXd m= sEnergyMatchedWIon2.CovarianceMatrix(pot); + std::cout << "The matrix m is of size " << m.rows() << "x" << m.cols() << std::endl; + // convert to th2 for drawing + TH2F* hCov = EigenMatrixToTH2(m); + new TCanvas; + hCov->Draw("colz"); + gPad->SaveAs("cov_mx_ion.pdf"); + + /// Drawing the spectra directly + new TCanvas; + TH1 * hsMuonEnsembleX2 = sEnergyMatchedTrueMu_nom.ToTH1(pot, kBlack); + hsMuonEnsembleX2->SetMaximum(1.3*hsMuonEnsembleX2->GetMaximum()); + hsMuonEnsembleX2->Draw("hist"); + sEnergyMatchedTrueMu_up.ToTH1(pot, kBlue)->Draw("hist same");; + sEnergyMatchedTrueMu_down.ToTH1(pot, kPink)->Draw("hist same");; + +} diff --git a/CAFAna/tute/demoPions.C b/CAFAna/tute/demoPions.C new file mode 100644 index 00000000..0a3814e9 --- /dev/null +++ b/CAFAna/tute/demoPions.C @@ -0,0 +1,165 @@ +#include + +#include "duneanaobj/StandardRecord/Proxy/SRProxy.h" +#include "duneanaobj/StandardRecord/Navigate.h" + +#include "CAFAna/Core/SpectrumLoader.h" +#include "CAFAna/Core/Spectrum.h" +#include "CAFAna/Core/Binning.h" +#include "CAFAna/Core/Var.h" +#include "CAFAna/Core/Cut.h" +#include "CAFAna/Core/HistAxis.h" + +#include "TCanvas.h" +#include "TH1.h" +#include "TLegend.h" + +using namespace ana; + + +const RecoPartVar kMatchedTruePartE([](const caf::SRRecoParticleProxy * part) -> float +{ + if (part->truth.empty()) + return -999.; + + // Ancestor() returns the closest ancestor in the SR hierarchy with the template type. + // Once we have the top-level object, we then can connect its + const caf::SRProxy * top = part->Ancestor(); + return caf::FindParticle(top->mc, part->truth[0])->p.E; +}); + +const RecoPartVar kMatchedTruePartPDG([](const caf::SRRecoParticleProxy * part) -> int +{ + if (part->truth.empty()) + return -999; + + // Ancestor() returns the closest ancestor in the SR hierarchy with the template type. + // Once we have the top-level object, we then can connect its + const caf::SRProxy * top = part->Ancestor(); + int pdg = caf::FindParticle(top->mc, part->truth[0])->pdg; + // recast in a different way for easier visualization + //(1) muon + if ( abs(pdg)==13) return 1.; + //(2) electron + if ( abs(pdg)==11) return 2.; + //(3) proton + if ( pdg==2212) return 3.; + // (4) neutron + if ( pdg==2112) return 4.; + // (5) pi + + if ( pdg==211) return 5.; + // (6) pi - + if ( pdg==-211) return 6.; + // (7) pi0 + if ( pdg==111) return 7.; + // (8) photon + if (pdg==22) return 8.; + // (9) Any K0S, K0L K0 or K+/- + if (abs(pdg)==321 || pdg== 311|| pdg== 310|| pdg== 130) return 9.; + else return 10.; +}); +std::vector PDGlabels = {"#mu", "e","p","n","#pi^{+}","#pi^{-}","#pi^{0}","#gamma","K","other"}; + +// reco particles whose best-match particle is a true pion +const RecoPartCut kMatchedToTruePion([](const caf::SRRecoParticleProxy * part) -> float +{ + if (part->truth.empty()) + return false; + + const caf::SRProxy * top = part->Ancestor(); + return std::abs(caf::FindParticle(top->mc, part->truth[0])->pdg) == 211; +}); + +// Select reco particles that have a pdg of muon +const RecoPartCut kIsPion([](const caf::SRRecoParticleProxy* sr) + { + return abs(sr->pdg) == 211 ; + }); + + +// some truth variables +const TruthPartVar kPrimEnergy([](const caf::SRTrueParticleProxy * part) -> float +{ + float ret = -999.; + ret = part->p.E; + return ret; + +}); + +const TruthCut kIsTrueNuMu ([](const caf::SRTrueInteractionProxy* nu){ + int pdg = abs(nu->pdg); + return pdg==14; + }); + +const TruthPartCut kIsPionPrim([](const caf::SRTrueParticleProxy * part){ + int pdg = abs(part->pdg); + return pdg==211; +}); + + +void demoPions() +{ + + const std::string fname = "/exp/dune/data/users/noeroy/mywork/MiniRun5_Fixed_truth/MiniRun5_1E19_RHC.caf/CAF.flat/0000000/*.flat.root"; + + // Source of events + SpectrumLoader loader(fname); + + // Define axes for the spectra we'll make + const RecoPartHistAxis axEnergy("Best-matched true particle energy (GeV)", Binning::Simple(50, 0, 5), kMatchedTruePartE); + const TruthPartHistAxis axTrueEnergy("true pion primary energy (GeV)", Binning::Simple(50,0,5), kPrimEnergy); + const RecoPartHistAxis myHistTruthPartAxisPDG("true particles pdg", Binning::Simple(10, 1, 11), kMatchedTruePartPDG); + + // Reconstructed energy of best matched pions + Spectrum sEnergyMatched(loader.Interactions(RecoType::kDLP).RecoParticles(RecoType::kDLP)[kIsPion], axEnergy); + Spectrum sEnergyMatchedTrueMu(loader.Interactions(RecoType::kDLP).RecoParticles(RecoType::kDLP)[kIsPion && kMatchedToTruePion], axEnergy); + // We want to see what else is there (pdg of the rest identified pions) + Spectrum sNonMatchedPionPDG(loader.Interactions(RecoType::kDLP).RecoParticles(RecoType::kDLP)[kIsPion && !kMatchedToTruePion], myHistTruthPartAxisPDG); + + // True energy of pions... + Spectrum sEnergyTruthPions(loader.NuTruths()[kIsTrueNuMu].TruthParticles(TruePType::kPrim)[kIsPionPrim], axTrueEnergy); + + // ~~~~**** -.-.-.-.-.-.-.-.-.-.-.- *****~~~~ + // Fill in the spectrum + loader.Go(); + + // We are forcing the pot value because cafs dont have this information yet + const double pot = 1e17; + + //sEnergyMatched.OverridePOT(pot); + //sEnergyMatchedTrueMu.OverridePOT(pot); + + TCanvas c; + TLegend leg(0.6, 0.6, 0.9, 0.9); + leg.SetFillStyle(0); + leg.SetBorderSize(0); + + auto h1 = sEnergyMatched.ToTH1(pot); + h1->Draw("hist"); + leg.AddEntry(h1, "All reco pions"); + + auto h2 = sEnergyMatchedTrueMu.ToTH1(pot, kRed); + auto h3 = sEnergyTruthPions.ToTH1(pot, kBlue); + h2->Draw("hist same"); + // h3->Draw("hist same"); + leg.AddEntry(h2, "+ matched to true pions"); + //leg.AddEntry(h3, "all true pions energy"); + leg.Draw(); + c.SaveAs("recoPion_matchedTrueE.png"); + + + + new TCanvas; + h3->Draw("hist") ; + gPad->SaveAs("truePion_TrueE.png"); + + + auto h4 = sNonMatchedPionPDG.ToTH1(pot); + for (unsigned int i = 0; iGetXaxis()->SetBinLabel(i+1,PDGlabels[i].c_str()); + h4->GetXaxis()->SetTitle("non-matched reco pions true pdg"); + new TCanvas; + h4->Draw("hist"); + gPad->SaveAs("nonTruePions_PDG.png"); + +} diff --git a/CAFAna/tute/demo_systs.C b/CAFAna/tute/demo_systs.C new file mode 100644 index 00000000..db8a55f3 --- /dev/null +++ b/CAFAna/tute/demo_systs.C @@ -0,0 +1,235 @@ + +#include "duneanaobj/StandardRecord/Proxy/SRProxy.h" +#include "duneanaobj/StandardRecord/Navigate.h" +#include "duneanaobj/StandardRecord/SREnums.h" +#include "CAFAna/Core/SpectrumLoader.h" +#include "CAFAna/Core/Spectrum.h" +#include "CAFAna/Core/Binning.h" +#include "CAFAna/Core/EnsembleSpectrum.h" +#include "CAFAna/Core/EnsembleRatio.h" +#include "CAFAna/Core/LoadFromFile.h" +#include "CAFAna/Core/Multiverse.h" +#include "CAFAna/Core/Var.h" +#include "CAFAna/Core/Cut.h" +#include "CAFAna/Core/HistAxis.h" +#include "CAFAna/Core/ISyst.h" +#include "CAFAna/Core/Utilities.h" +#include "demo0eb.C" + +#include "TFile.h" +#include "TCanvas.h" +#include "TH1.h" +#include "TH2.h" +#include "TPad.h" +#include "TColor.h" +#include + +using namespace ana; + + + +void demo_systs() +{ + + + std::vector systs; + systs.push_back(&kWIonSyst); + std::vector systs2; + systs2.push_back(&kEnergyScaleTrueMu); + systs2.push_back(&kMECScaleSyst); + + // scans from -n to n sigma shifts, we'll do only the 1 sigma + const Multiverse& cross = Multiverse::Hypercross(systs,1); + const Multiverse& cross_rwgt = Multiverse::Hypercross(systs2,1); + + // we can save our multiverses to file + TFile fout("test_multiverse.root", "RECREATE"); + cross.SaveTo(&fout, "cross"); + cross_rwgt.SaveTo(&fout, "cross_rwgt"); + fout.Close(); + + // and then retrieve multiverses from file + TFile fin("test_multiverse.root"); + const FitMultiverse& cross2 = *Multiverse::LoadFrom(&fin, "cross"); + const FitMultiverse& cross_rwgt2 = *Multiverse::LoadFrom(&fin, "cross_rwgt"); + + + // you can print the hypercross universe to see what is going on + std::cout << cross.LatexName() << ", "<< cross.ShortName() << std::endl; + for (int i = 0; i< cross.NUniv(); i++){ + for (const auto & [ key, value ] : cross.GetUniverse(i)) { + std::cout << key->ShortName() << ": " << value << std::endl; + } + } + std::cout << cross_rwgt.LatexName() << ", "<< cross_rwgt.ShortName() << std::endl; + for (int i = 0; i< cross_rwgt.NUniv(); i++){ + for (const auto & [ key, value ] : cross_rwgt.GetUniverse(i)) { + std::cout << key->ShortName() << ": " << value << std::endl; + } + } + + fin.Close(); + //----------------------------------------------------------------------// + // now make ensemble spectra + + const Binning binsEnergy = Binning::Simple(10, 0, 1); + + const HistAxis axMuEnergy("Muon energy (GeV)", binsEnergy, kEnergyInteractionMu); + + //const std::string fname_nom = "/exp/dune/data/users/mcasales/test_cafs/MiniRun5_1E19_RHC.caf.0001013.CAF.root"; + // also beta2a + + // const std::string fname_nom = "/exp/dune/data/users/noeroy/mywork/MiniRun5_Fixed_truth/MiniRun5_1E19_RHC.caf/CAF.flat/0000000/*.flat.root"; + const std::string fname_nom = "/exp/dune/data/users/noeroy/prod/MiniRun5_1E19_RHC/MiniRun5_1E19_RHC.caf.beta1/CAF.flat/0000000/MiniRun5_1E19_RHC.caf.*"; + const std::string fname_up = "/pnfs/dune/persistent/users/cuddandr/2x2_production/MiniRun5_Systematics_W_ION_22.7/MiniRun5_Systematics_W_ION_22.7.caf/CAF.flat/0000000/MiniRun5_Systematics_W_ION_22.7.caf.*"; + const std::string fname_down = "/pnfs/dune/persistent/users/cuddandr/2x2_production/MiniRun5_Systematics_W_ION_25.1/MiniRun5_Systematics_W_ION_25.1.caf/CAF.flat/0000000/MiniRun5_Systematics_W_ION_25.1.caf.*"; + + // Source of events + SpectrumLoader loader_nom(fname_nom); + SpectrumLoader loader_up(fname_up); + SpectrumLoader loader_down(fname_down); + + // Fill various spectra with these... + Spectrum sEnergyMatchedTrueMu_nom(loader_nom.Interactions(RecoType::kDLP)[kHas1RecoMuon], axMuEnergy); + Spectrum sEnergyMatchedTrueMu_up(loader_up.Interactions(RecoType::kDLP)[kHas1RecoMuon], axMuEnergy); + Spectrum sEnergyMatchedTrueMu_down(loader_down.Interactions(RecoType::kDLP)[kHas1RecoMuon], axMuEnergy); + + // other ensemble with two reweight systematics + EnsembleSpectrum sMuonEnegyEnsemble(loader_nom.Interactions(RecoType::kDLP).Ensemble(cross_rwgt)[kHas1RecoMuon], axMuEnergy ); + + loader_nom.Go(); + loader_up.Go(); + loader_down.Go(); + + // Save the three spectra to file + TFile fout2("multiverse_ensemble_spec.root", "RECREATE"); + sEnergyMatchedTrueMu_nom.SaveTo(&fout2, "sEnergyMatchedTrueMu_nom"); + sEnergyMatchedTrueMu_up.SaveTo(&fout2, "sEnergyMatchedTrueMu_up"); + sEnergyMatchedTrueMu_down.SaveTo(&fout2, "sEnergyMatchedTrueMu_down"); + sMuonEnegyEnsemble.SaveTo( &fout2, "sMuonEnegyEnsemble"); + + cross.SaveTo(&fout2, "cross"); + cross_rwgt.SaveTo(&fout2, "cross_rwgt"); + fout2.Close(); + + TFile * fIn = new TFile("multiverse_ensemble_spec.root"); + std::vector specs= {}; + // make sure to place nominal first,then -1 shift, then +1 shift + specs.push_back(*Spectrum::LoadFrom(fIn, "sEnergyMatchedTrueMu_nom").release() ); + specs.push_back(*Spectrum::LoadFrom(fIn, "sEnergyMatchedTrueMu_down").release()); + specs.push_back(*Spectrum::LoadFrom(fIn, "sEnergyMatchedTrueMu_up").release() ); + + // get from file + const FitMultiverse& cross22 = *Multiverse::LoadFrom(fIn, "cross"); + + EnsembleSpectrum sEnergyMatchedWIon = EnsembleSpectrum::MergeSpectra(specs, &cross22);//, axMuEnergy ); + +//---------------------------------------------------------------------- + // These lines dont crash but I dont know if they are working properly + const FitMultiverse& crossCombined = Multiverse::Hypercross({&kWIonSyst, &kEnergyScaleTrueMu, &kMECScaleSyst},1); + std::cout<< "sMuonEnegyEnsemble has "<< sMuonEnegyEnsemble.NUniverses()<< "sEnergyMatchedWIon has "<< sEnergyMatchedWIon.NUniverses()<< + " and crossCombined has "<< crossCombined.NUniv() <SetMaximum(1.3*hsMuonEnsembleX->GetMaximum()); + hsMuonEnsembleX->Draw("hist"); + + // you can draw the individual spectra for each universe + // in this case our spectra from different files + std::cout<< "\ncross has "<Draw("hist same"); + //sEnergyMatchedIonandEnergyScale2.Universe(i).ToTH1(pot, color+1,kDotted)->Draw("hist same"); + } + gPad->SaveAs("spec_ensemble_test.pdf"); + + + // or draw as TGraph + new TCanvas; + // Error band summing in quadrature + TGraphAsymmErrors* eBand =sEnergyMatchedWIon2.ErrorBand(pot); + DrawErrorBand(hsMuonEnsembleX, eBand); + gPad->SaveAs("spec_ensemble_test_ErrorBand.pdf"); + + // Draw covariance matrix + new TCanvas; + Eigen::MatrixXd m= sEnergyMatchedWIon2.CovarianceMatrix(pot); + std::cout << "The matrix m is of size " << m.rows() << "x" << m.cols() << std::endl; + // convert to th2 for drawing + TH2F* hCov = EigenMatrixToTH2(m); + new TCanvas; + hCov->Draw("colz"); + gPad->SaveAs("cov_mx_ion.pdf"); + + + /// Drawing the spectra directly + new TCanvas; + TH1 * hsMuonEnsembleX2 = sEnergyMatchedTrueMu_nom.ToTH1(pot, kBlue); + hsMuonEnsembleX2->SetMaximum(1.3*hsMuonEnsembleX2->GetMaximum()); + hsMuonEnsembleX2->Draw("hist"); + sEnergyMatchedTrueMu_up.ToTH1(pot, kPink)->Draw("hist same");; + sEnergyMatchedTrueMu_down.ToTH1(pot, kViolet+1)->Draw("hist same");; + gPad->SaveAs("specs_non-ensemble_test.png"); + + // check differences + new TCanvas; + TH1* hdiffNom = sEnergyMatchedTrueMu_nom.ToTH1(pot, kBlue); + hdiffNom->Divide( sEnergyMatchedWIon2.Universe(0).ToTH1(pot)); + TH1* hdiffUp = sEnergyMatchedTrueMu_up.ToTH1(pot, kPink); + hdiffUp->Divide( sEnergyMatchedWIon2.Universe(2).ToTH1(pot)); + TH1* hdiffDown =sEnergyMatchedTrueMu_down.ToTH1(pot, kViolet+1); + hdiffDown->Divide( sEnergyMatchedWIon2.Universe(1).ToTH1(pot)); + hdiffNom->SetMaximum(1.5); hdiffNom->SetMinimum(.5); + hdiffNom->Draw("hist"); + hdiffUp->Draw("hist same"); + hdiffDown->Draw("hist same"); + gPad->SaveAs("specs_ensembe_diff.png"); + + new TCanvas; + EnsembleSpectrum sMuonEnegyEnsemble2 =*EnsembleSpectrum::LoadFrom(&fin2, "sMuonEnegyEnsemble"); + for(unsigned int i = 0; i < sMuonEnegyEnsemble2.NUniverses(); ++i){ + // using different colors per shift + Color_t color = kBlue; + if (i==0) color = kBlue; + if (i== 1 ) color = kViolet +1; + if (i==2 ) color = kPink; + sMuonEnegyEnsemble2.Universe(i).ToTH1(pot, color,kDashed)->Draw("hist same"); + } + gPad->SaveAs("rwgt_ensemble_test.png"); + + new TCanvas; + // Grab covariance matrix + Eigen::MatrixXd m2= sMuonEnegyEnsemble2.CovarianceMatrix(pot); + std::cout << "The matrix m is of size " << m2.rows() << "x" << m2.cols() << std::endl; + // convert to th2 for drawing + TH2F* hCov2 = EigenMatrixToTH2(m2); + + new TCanvas; + hCov2->Draw("colz"); + gPad->SaveAs("cov_mx_rwgt.pdf"); + + +}