diff --git a/CMakeLists.txt b/CMakeLists.txt index a02f2402..40fd7caf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,7 +36,7 @@ cet_set_compiler_flags(DIAGS CAUTIOUS WERROR NO_UNDEFINED ALLOW_DEPRECATIONS - EXTRA_FLAGS -pedantic -Wno-unused-local-typedefs -Wno-undefined-var-template -I $ENV{CLANG_FQ_DIR}/include/c++/v1 + EXTRA_FLAGS -pedantic -Wno-unused-local-typedefs -Wno-undefined-var-template -I $ENV{CLANG_FQ_DIR}/include/c++/v1 -DTBB_INTERFACE_NEW ) cet_report_compiler_flags() @@ -49,6 +49,8 @@ find_ups_root(v6_00_00) find_ups_product(ifdhc) find_ups_product( srproxy ) find_ups_product( osclib ) +find_ups_product( cafanacore ) +find_ups_product( stan_math ) find_ups_product( pygccxml ) #ifdhc diff --git a/sbnana/CAFAna/Analysis/CMakeLists.txt b/sbnana/CAFAna/Analysis/CMakeLists.txt index 97940df5..c583c51d 100644 --- a/sbnana/CAFAna/Analysis/CMakeLists.txt +++ b/sbnana/CAFAna/Analysis/CMakeLists.txt @@ -1,6 +1,3 @@ -# Allow "StandardRecord/" to find the right directory -include_directories(..) - cet_make(LIBRARY_NAME CAFAnaAnalysis LIBRARIES CAFAnaCore CAFAnaExperiment ${ROOT_MINUIT2} diff --git a/sbnana/CAFAna/Analysis/Calcs.cxx b/sbnana/CAFAna/Analysis/Calcs.cxx index 33e6de55..b5fc626e 100644 --- a/sbnana/CAFAna/Analysis/Calcs.cxx +++ b/sbnana/CAFAna/Analysis/Calcs.cxx @@ -25,7 +25,7 @@ namespace ana calc->SetTh23(M_PI/4); // NH from PDG2014 + 2015 update - //http://pdg.lbl.gov/2015/tables/rpp2015-sum-leptons.pdf + //http://pdg.lbl.gov/2015/tables/rpp2015-sum-leptons.pdf calc->SetDmsq32(2.44e-3); // NB: this is normal hierarchy // Reactor average from PDG2014 + 2015 update @@ -46,11 +46,11 @@ namespace ana //---------------------------------------------------------------------- void ResetOscCalcToDefaultIH(osc::IOscCalcAdjustable* calc) { - //Share most defaults + //Share most defaults ResetOscCalcToDefault(calc); - // IH from PDG2014 + 2015 update + // IH from PDG2014 + 2015 update // http://pdg.lbl.gov/2015/tables/rpp2015-sum-leptons.pdf - calc->SetDmsq32(-2.49e-3); + calc->SetDmsq32(-2.49e-3); } diff --git a/sbnana/CAFAna/Analysis/CalcsNuFit_cdr.cxx b/sbnana/CAFAna/Analysis/CalcsNuFit_cdr.cxx index b38dece3..35e44845 100644 --- a/sbnana/CAFAna/Analysis/CalcsNuFit_cdr.cxx +++ b/sbnana/CAFAna/Analysis/CalcsNuFit_cdr.cxx @@ -49,7 +49,7 @@ namespace ana // Uniform throws within +/-3 sigma if(hie > 0){ - ret->SetDmsq32(gRandom->Uniform(kNuFitDmsq32CVNH-3*kNuFitDmsq32ErrNH, + ret->SetDmsq32(gRandom->Uniform(kNuFitDmsq32CVNH-3*kNuFitDmsq32ErrNH, kNuFitDmsq32CVNH+3*kNuFitDmsq32ErrNH)); ret->SetTh23(gRandom->Uniform(kNuFitTh23CVNH-3*kNuFitTh23ErrNH, kNuFitTh23CVNH+3*kNuFitTh23ErrNH)); @@ -64,7 +64,7 @@ namespace ana kNuFitTh13CVIH+3*kNuFitTh13ErrIH)); } ret->SetdCP(gRandom->Uniform(-1*TMath::Pi(), TMath::Pi())); - + return ret; } @@ -145,9 +145,9 @@ namespace ana fTh23Err = (hietrue > 0) ? 0.058*fTh23 : 0.048*fTh23; fRhoErr = 0.02*fRho; - + } - + double Penalizer_GlbLikeCDR::ChiSq(osc::IOscCalcAdjustable* calc, const SystShifts& /*syst*/) const { @@ -156,7 +156,7 @@ namespace ana double ret = util::sqr((calc->GetDmsq21() - fDmsq21)/fDmsq21Err) + - util::sqr((calc->GetTh12() - fTh12)/fTh12Err) + + util::sqr((calc->GetTh12() - fTh12)/fTh12Err) + util::sqr((calc->GetRho() - fRho)/fRhoErr); // if fWeakOnly is set, only apply a constraint to the parameter we can only weakly constrain in DUNE diff --git a/sbnana/CAFAna/Analysis/CutOptimizer.cxx b/sbnana/CAFAna/Analysis/CutOptimizer.cxx index 428947fe..ebd2ae2e 100644 --- a/sbnana/CAFAna/Analysis/CutOptimizer.cxx +++ b/sbnana/CAFAna/Analysis/CutOptimizer.cxx @@ -1,5 +1,7 @@ #include "sbnana/CAFAna/Analysis/CutOptimizer.h" +#include "sbnana/CAFAna/Core/SpectrumLoader.h" + #include "TH1.h" #include @@ -7,7 +9,7 @@ namespace ana { // -------------------------------------------------------------------------- - void MakeNMinusOneSpectra(SpectrumLoader& loader, + void MakeNMinusOneSpectra(ISliceSource& src, const Cut& sigcut, const Cut& presel, const std::vector& axes, @@ -28,8 +30,8 @@ namespace ana nminusone = nminusone && axes[j].GetVars()[0] > cut_pos[j]; } // end for j - sigs.emplace_back(loader, axes[i], nminusone && sigcut); - bkgs.emplace_back(loader, axes[i], nminusone && !sigcut); + sigs.emplace_back(src[nminusone][ sigcut], axes[i]); + bkgs.emplace_back(src[nminusone][!sigcut], axes[i]); } // end for i } @@ -64,7 +66,7 @@ namespace ana { SpectrumLoader loader(wildcard); std::vector sigs, bkgs; - MakeNMinusOneSpectra(loader, sigcut, presel, axes, cut_pos, sigs, bkgs); + MakeNMinusOneSpectra(loader.Slices(), sigcut, presel, axes, cut_pos, sigs, bkgs); loader.Go(); double best_fom = 0; diff --git a/sbnana/CAFAna/Analysis/CutOptimizer.h b/sbnana/CAFAna/Analysis/CutOptimizer.h index a7f3dd95..d294ba6f 100644 --- a/sbnana/CAFAna/Analysis/CutOptimizer.h +++ b/sbnana/CAFAna/Analysis/CutOptimizer.h @@ -2,8 +2,9 @@ #include "sbnana/CAFAna/Core/HistAxis.h" #include "sbnana/CAFAna/Core/Cut.h" -#include "sbnana/CAFAna/Core/Spectrum.h" -#include "sbnana/CAFAna/Core/SpectrumLoader.h" +#include "cafanacore/Spectrum.h" + +#include "sbnana/CAFAna/Core/IRecordSource.h" #include @@ -14,14 +15,14 @@ namespace ana /// This function does *not* call Go() on the loader, allowing you to combine /// it with other spectra-filling if desired. /// - /// \param loader SpectrumLoader to associate spectra with + /// \param src Source to associate spectra with /// \param sigcut Definition of signal (inverse defines background) /// \param presel Cuts that will always be applied /// \param axes Variables that will be cut on /// \param cut_pos Cut position for each variable /// \param[out] sigs Resulting signal spectra /// \param[out] bkgs Resulting background spectra - void MakeNMinusOneSpectra(SpectrumLoader& loader, + void MakeNMinusOneSpectra(ISliceSource& src, const Cut& sigcut, const Cut& presel, const std::vector& axes, diff --git a/sbnana/CAFAna/Analysis/ExpInfo.h b/sbnana/CAFAna/Analysis/ExpInfo.h index d9cfe5f1..5dc98f75 100644 --- a/sbnana/CAFAna/Analysis/ExpInfo.h +++ b/sbnana/CAFAna/Analysis/ExpInfo.h @@ -7,7 +7,7 @@ namespace ana const double kPOTuBoone = 1.3e21; const double kBaselineSBND = 0.11; const double kBaselineMicroBoone = 0.47; - const double kBaselineIcarus = 0.6; + const double kBaselineIcarus = 0.6; const int kSBND = 0; const int kMicroBoone = 1; const int kICARUS = 2; diff --git a/sbnana/CAFAna/Analysis/Fit.cxx b/sbnana/CAFAna/Analysis/Fit.cxx index 9165927a..396086a4 100644 --- a/sbnana/CAFAna/Analysis/Fit.cxx +++ b/sbnana/CAFAna/Analysis/Fit.cxx @@ -1,6 +1,6 @@ #include "sbnana/CAFAna/Analysis/Fit.h" -#include "sbnana/CAFAna/Core/Progress.h" +#include "cafanacore/Progress.h" #include "sbnana/CAFAna/Core/IFitVar.h" #include "sbnana/CAFAna/Core/Utilities.h" #include "sbnana/CAFAna/Experiment/IExperiment.h" @@ -166,7 +166,7 @@ namespace ana mnMin->GetMinosError(i, errLow, errHigh); std::cout << i << "/" << mnMin->NDim() << " " << fParamNames[i] << ": " << errLow << ", +" << errHigh << " (" << mnMin->Errors()[i] << ")" << std::endl; fTempMinosErrors.push_back(std::make_pair(errLow,errHigh)); - } + } } return mnMin; @@ -191,8 +191,8 @@ namespace ana // Need to deal with parameters that are not fit values! SystShifts shift = pt.shift; - // Need to copy over syst values into the seed for this fit - // that were in the input syst shifts, but are not being fit for, + // Need to copy over syst values into the seed for this fit + // that were in the input syst shifts, but are not being fit for, // and therefore not part of the seedPts list for(auto s: bestSysts.ActiveSysts()) { auto fit_systs = shift.ActiveSysts(); diff --git a/sbnana/CAFAna/Analysis/Fit.h b/sbnana/CAFAna/Analysis/Fit.h index acbc126e..4bdcaea3 100644 --- a/sbnana/CAFAna/Analysis/Fit.h +++ b/sbnana/CAFAna/Analysis/Fit.h @@ -1,11 +1,14 @@ #pragma once -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "cafanacore/Spectrum.h" #include "sbnana/CAFAna/Prediction/IPrediction.h" #include "sbnana/CAFAna/Core/SystShifts.h" +#include "sbnana/CAFAna/Core/Utilities.h" #include "Math/Minimizer.h" +#include "TMatrixDSym.h" + #include class TGraph; diff --git a/sbnana/CAFAna/Analysis/FitAxis.h b/sbnana/CAFAna/Analysis/FitAxis.h index acee74c7..5cf268d6 100644 --- a/sbnana/CAFAna/Analysis/FitAxis.h +++ b/sbnana/CAFAna/Analysis/FitAxis.h @@ -13,7 +13,7 @@ namespace ana FitAxis(const IFitVar* var, int nbins, double min, double max, bool islog = false); - + const IFitVar* var; int nbins; double min; diff --git a/sbnana/CAFAna/Analysis/GradientDescent.cxx b/sbnana/CAFAna/Analysis/GradientDescent.cxx index 7a00a49f..bcd69b9f 100644 --- a/sbnana/CAFAna/Analysis/GradientDescent.cxx +++ b/sbnana/CAFAna/Analysis/GradientDescent.cxx @@ -119,7 +119,7 @@ namespace ana const unsigned int N = pt.size(); ROOT::Minuit2::MnAlgebraicVector vec(N); for(unsigned int i = 0; i < N; ++i) vec(i) = pt[i]; - ROOT::Minuit2::MinimumParameters params(vec, chi); + ROOT::Minuit2::MinimumParameters params(vec, chi); ROOT::Minuit2::MinimumState state(params, 0, ncalls); ROOT::Minuit2::MnUserTransformation trans(pt, std::vector(N)); ROOT::Minuit2::MinimumSeed seed(state, trans); diff --git a/sbnana/CAFAna/Analysis/MedianSurface.cxx b/sbnana/CAFAna/Analysis/MedianSurface.cxx index 39e5a066..53a7df35 100644 --- a/sbnana/CAFAna/Analysis/MedianSurface.cxx +++ b/sbnana/CAFAna/Analysis/MedianSurface.cxx @@ -120,22 +120,32 @@ namespace ana } //---------------------------------------------------------------------- - void MedianSurface::SaveTo(TDirectory* dir) const + void MedianSurface::SaveTo(TDirectory* dir, const std::string& name) const { TDirectory* tmp = gDirectory; + + dir = dir->mkdir(name.c_str()); // switch to subdir dir->cd(); + TObjString("MedianSurface").Write("type"); for(unsigned int i = 0; i < fThrows.size(); ++i){ - fThrows[i].SaveTo(dir->mkdir(TString::Format("surf%d", i))); + fThrows[i].SaveTo(dir, TString::Format("surf%d", i).Data()); } + dir->Write(); + delete dir; + tmp->cd(); } //---------------------------------------------------------------------- - std::unique_ptr MedianSurface::LoadFrom(TDirectory* dir) + std::unique_ptr MedianSurface::LoadFrom(TDirectory* dir, + const std::string& name) { + dir = dir->GetDirectory(name.c_str()); // switch to subdir + assert(dir); + DontAddDirectory guard; TObjString* tag = (TObjString*)dir->Get("type"); @@ -144,9 +154,11 @@ namespace ana std::vector surfs; for(unsigned int i = 0; ; ++i){ - TDirectory* surfdir = dir->GetDirectory(TString::Format("surf%d", i)); - if(!surfdir) break; // we got all of them - surfs.push_back(*ana::LoadFrom(surfdir)); + const std::string subname = TString::Format("surf%d", i).Data(); + TDirectory* subdir = dir->GetDirectory(subname.c_str()); + if(!subdir) break; // we got all of them + delete subdir; + surfs.push_back(*ana::LoadFrom(dir, subname)); } return std::make_unique(surfs); diff --git a/sbnana/CAFAna/Analysis/MedianSurface.h b/sbnana/CAFAna/Analysis/MedianSurface.h index 39fab3e2..0cdd1832 100644 --- a/sbnana/CAFAna/Analysis/MedianSurface.h +++ b/sbnana/CAFAna/Analysis/MedianSurface.h @@ -14,8 +14,9 @@ namespace ana void DrawEnsemble(TH2* fc, Color_t color = kGray); void DrawBand(TH2* fc); - void SaveTo(TDirectory * dir) const; - static std::unique_ptr LoadFrom(TDirectory * dir); + void SaveTo(TDirectory* dir, const std::string& name) const; + static std::unique_ptr LoadFrom(TDirectory* dir, + const std::string& name); protected: std::vector fThrows; diff --git a/sbnana/CAFAna/Analysis/Plots.cxx b/sbnana/CAFAna/Analysis/Plots.cxx index 3aa3414c..dbcc8ef4 100644 --- a/sbnana/CAFAna/Analysis/Plots.cxx +++ b/sbnana/CAFAna/Analysis/Plots.cxx @@ -2,8 +2,8 @@ #include "sbnana/CAFAna/Analysis/Style.h" #include "sbnana/CAFAna/Prediction/IPrediction.h" -#include "sbnana/CAFAna/Core/Ratio.h" -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "cafanacore/Ratio.h" +#include "cafanacore/Spectrum.h" #include "sbnana/CAFAna/Core/SystShifts.h" #include "sbnana/CAFAna/Core/MathUtil.h" @@ -143,6 +143,11 @@ namespace ana return ret; } + TH1* ToTHX(const Spectrum& s, double pot, bool force1d) + { + if(force1d) return s.ToTHX(pot); else return s.ToTH1(pot); + } + TH1* GetMCSystTotal(const IPrediction* mc, osc::IOscCalc* calc, const SystShifts& shift, @@ -150,11 +155,11 @@ namespace ana double pot, bool force1D) { - TH1* hTotal = mc->PredictSyst(calc, shift).ToTHX(pot, force1D); + TH1* hTotal = ToTHX(mc->PredictSyst(calc, shift), pot, force1D); hTotal->SetNameTitle((hist_name+"_total").c_str(), (hist_name+"_total").c_str()); return hTotal; } - + TH1* GetMCTotal(const IPrediction* mc, osc::IOscCalc* calc, std::string hist_name, @@ -181,103 +186,103 @@ namespace ana bool force1D) { std::vector ret; - - TH1* hTotal = mc->PredictSyst(calc, shift).ToTHX(pot, force1D); + + TH1* hTotal = ToTHX(mc->PredictSyst(calc, shift), pot, force1D); hTotal->SetNameTitle((hist_name+"_total").c_str(), (hist_name+"_total").c_str()); ret .push_back(hTotal); - - TH1* hNC = mc->PredictComponentSyst(calc,shift, - Flavors::kAll, - Current::kNC, - Sign::kBoth).ToTHX(pot, force1D); + + TH1* hNC = ToTHX(mc->PredictComponentSyst(calc,shift, + Flavors::kAll, + Current::kNC, + Sign::kBoth), pot, force1D); hNC->SetNameTitle((hist_name+"_NC").c_str(), (hist_name+"_NC").c_str()); ret .push_back(hNC); - - TH1* hAllNumu = mc->PredictComponentSyst(calc,shift, - Flavors::kAllNuMu, - Current::kCC, - Sign::kBoth).ToTHX(pot, force1D); + + TH1* hAllNumu = ToTHX(mc->PredictComponentSyst(calc,shift, + Flavors::kAllNuMu, + Current::kCC, + Sign::kBoth), pot, force1D); hAllNumu->SetNameTitle((hist_name+"_AllNumu").c_str(), (hist_name+"_AllNumu").c_str()); ret .push_back(hAllNumu); - TH1* hNumu = mc->PredictComponentSyst(calc,shift, - Flavors::kAllNuMu, - Current::kCC, - Sign::kNu).ToTHX(pot, force1D); + TH1* hNumu = ToTHX(mc->PredictComponentSyst(calc,shift, + Flavors::kAllNuMu, + Current::kCC, + Sign::kNu), pot, force1D); hNumu->SetNameTitle((hist_name+"_Numu").c_str(), (hist_name+"_Numu").c_str()); ret .push_back(hNumu); - - TH1* hNumubar = mc->PredictComponentSyst(calc,shift, - Flavors::kAllNuMu, - Current::kCC, - Sign::kAntiNu).ToTHX(pot, force1D); + + TH1* hNumubar = ToTHX(mc->PredictComponentSyst(calc,shift, + Flavors::kAllNuMu, + Current::kCC, + Sign::kAntiNu), pot, force1D); hNumubar->SetNameTitle((hist_name+"_Numubar").c_str(), (hist_name+"_Numubar").c_str()); ret .push_back(hNumubar); - TH1* hAllNutau = mc->PredictComponentSyst(calc,shift, - Flavors::kAllNuTau, - Current::kCC, - Sign::kBoth).ToTHX(pot, force1D); + TH1* hAllNutau = ToTHX(mc->PredictComponentSyst(calc,shift, + Flavors::kAllNuTau, + Current::kCC, + Sign::kBoth), pot, force1D); hAllNutau->SetNameTitle((hist_name+"_AllNutau").c_str(), (hist_name+"_AllNutau").c_str()); - ret .push_back(hAllNutau); + ret .push_back(hAllNutau); // Want AllSignalNue, SignalNue, SignalNuebar - TH1* hAllNue = mc->PredictComponentSyst(calc,shift, - Flavors::kAllNuE, - Current::kCC, - Sign::kBoth).ToTHX(pot, force1D); + TH1* hAllNue = ToTHX(mc->PredictComponentSyst(calc,shift, + Flavors::kAllNuE, + Current::kCC, + Sign::kBoth), pot, force1D); hAllNue->SetNameTitle((hist_name+"_AllNue").c_str(), (hist_name+"_AllNue").c_str()); - ret .push_back(hAllNue); - - TH1* hAllBeamNue = mc->PredictComponentSyst(calc,shift, - Flavors::kNuEToNuE, - Current::kCC, - Sign::kBoth).ToTHX(pot, force1D); + ret .push_back(hAllNue); + + TH1* hAllBeamNue = ToTHX(mc->PredictComponentSyst(calc,shift, + Flavors::kNuEToNuE, + Current::kCC, + Sign::kBoth), pot, force1D); hAllBeamNue->SetNameTitle((hist_name+"_AllBeamNue").c_str(), (hist_name+"_AllBeamNue").c_str()); ret .push_back(hAllBeamNue); - TH1* hBeamNue = mc->PredictComponentSyst(calc,shift, - Flavors::kNuEToNuE, - Current::kCC, - Sign::kNu).ToTHX(pot, force1D); + TH1* hBeamNue = ToTHX(mc->PredictComponentSyst(calc,shift, + Flavors::kNuEToNuE, + Current::kCC, + Sign::kNu), pot, force1D); hBeamNue->SetNameTitle((hist_name+"_BeamNue").c_str(), (hist_name+"_BeamNue").c_str()); ret .push_back(hBeamNue); - TH1* hBeamNuebar = mc->PredictComponentSyst(calc,shift, - Flavors::kNuEToNuE, - Current::kCC, - Sign::kAntiNu).ToTHX(pot, force1D); + TH1* hBeamNuebar = ToTHX(mc->PredictComponentSyst(calc,shift, + Flavors::kNuEToNuE, + Current::kCC, + Sign::kAntiNu), pot, force1D); hBeamNuebar->SetNameTitle((hist_name+"_BeamNuebar").c_str(), (hist_name+"_BeamNuebar").c_str()); ret .push_back(hBeamNuebar); - - TH1* hAllSignalNue = mc->PredictComponentSyst(calc,shift, - Flavors::kNuMuToNuE, - Current::kCC, - Sign::kBoth).ToTHX(pot, force1D); + + TH1* hAllSignalNue = ToTHX(mc->PredictComponentSyst(calc,shift, + Flavors::kNuMuToNuE, + Current::kCC, + Sign::kBoth), pot, force1D); hAllSignalNue->SetNameTitle((hist_name+"_AllSignalNue").c_str(), (hist_name+"_AllSignalNue").c_str()); ret .push_back(hAllSignalNue); - - TH1* hSignalNue = mc->PredictComponentSyst(calc,shift, - Flavors::kNuMuToNuE, - Current::kCC, - Sign::kNu).ToTHX(pot, force1D); + + TH1* hSignalNue = ToTHX(mc->PredictComponentSyst(calc,shift, + Flavors::kNuMuToNuE, + Current::kCC, + Sign::kNu), pot, force1D); hSignalNue->SetNameTitle((hist_name+"_SignalNue").c_str(), (hist_name+"_SignalNue").c_str()); ret .push_back(hSignalNue); - - TH1* hSignalNuebar = mc->PredictComponentSyst(calc,shift, - Flavors::kNuMuToNuE, - Current::kCC, - Sign::kAntiNu).ToTHX(pot, force1D); + + TH1* hSignalNuebar = ToTHX(mc->PredictComponentSyst(calc,shift, + Flavors::kNuMuToNuE, + Current::kCC, + Sign::kAntiNu), pot, force1D); hSignalNuebar->SetNameTitle((hist_name+"_SignalNuebar").c_str(), (hist_name+"_SignalNuebar").c_str()); ret .push_back(hSignalNuebar); - + return ret; } //---------------------------------------------------------------------- std::vector GetMCTotalForSystShifts(const IPrediction* mc, osc::IOscCalc* calc, - const ISyst* syst, + const ISyst* syst, std::string hist_base_name, double pot, bool force1D) @@ -286,15 +291,15 @@ namespace ana std::string syst_name = syst->ShortName(); for (int i = -3; i < 4; ++i){ SystShifts s(syst, double(i)); - TH1* hTotal = mc->PredictSyst(calc, s).ToTHX(pot, force1D); - hTotal->SetNameTitle((hist_base_name+"_total_"+syst_name+"_"+std::to_string(i)).c_str(), + TH1* hTotal = ToTHX(mc->PredictSyst(calc, s), pot, force1D); + hTotal->SetNameTitle((hist_base_name+"_total_"+syst_name+"_"+std::to_string(i)).c_str(), (hist_base_name+"_total_"+syst_name+"_"+std::to_string(i)).c_str()); ret .push_back(hTotal); } return ret; } - + //---------------------------------------------------------------------- void DataMCRatio(const Spectrum& data, const IPrediction* mc, @@ -680,7 +685,7 @@ namespace ana TGraphAsymmErrors* gr = new TGraphAsymmErrors(h); TFeldmanCousins fc(0.6827);//1 sigma - + for(int i = 0; i < h->GetNbinsX(); ++i){ double x, y; gr->GetPoint(i, x, y); diff --git a/sbnana/CAFAna/Analysis/Plots.h b/sbnana/CAFAna/Analysis/Plots.h index 89dfa669..7b409e0d 100644 --- a/sbnana/CAFAna/Analysis/Plots.h +++ b/sbnana/CAFAna/Analysis/Plots.h @@ -63,7 +63,7 @@ namespace ana std::string hist_name, double pot, bool force1D = false); - + std::vector GetMCSystComponents(const IPrediction* mc, osc::IOscCalc* calc, const SystShifts& shift, @@ -115,12 +115,12 @@ namespace ana /// \param pot POT to evaluate prediction at /// \param col Color of the prediction, default kRed /// \param errCol Color of the shading, default col-7 (kRed-7 is light red) - /// \param headroom Fraction of maximum bin for headroom, default 30% + /// \param headroom Fraction of maximum bin for headroom, default 30% void PlotWithSystErrorBand(IPrediction* pred, const std::vector& systs, osc::IOscCalc* calc, double pot, - int col = -1, int errCol = -1, + int col = -1, int errCol = -1, float headroom = 1.3, bool newaxis = true); @@ -128,14 +128,14 @@ namespace ana /// /// When multiple systematics are used, the errors are the quadrature sum /// - /// \param nominal Nominal spectrum - /// \param upShifts Vector of spectra which have + shifts + /// \param nominal Nominal spectrum + /// \param upShifts Vector of spectra which have + shifts /// \param downShifts Vector of spectra which have - shifts, same order as + - /// \param pot POT to scale spectra to + /// \param pot POT to scale spectra to /// \param col Color of the prediction, default kRed /// \param errCol Color of the shading, default col-7(kRed-7 is light red) /// \param headroom Fraction of maximum bin for headroom, default 30% - void PlotWithSystErrorBand(const Spectrum& nominal, + void PlotWithSystErrorBand(const Spectrum& nominal, const std::vector& upShifts, const std::vector& downShifts, double pot, @@ -164,7 +164,7 @@ namespace ana /// Calculate statistical errors appropriate for small Poisson numbers TGraphAsymmErrors* GraphWithPoissonErrors(const TH1* h, bool noErrorsXaxis = false, bool drawEmptyBins = true); - /// Gives a TGraph with the area between two histograms. Do Draw("f") to draw + /// Gives a TGraph with the area between two histograms. Do Draw("f") to draw /// this area. By default it has a lighter version of the colour of hmin TGraph* ShadeBetweenHistograms(TH1* hmin, TH1* hmax); diff --git a/sbnana/CAFAna/Analysis/Surface.cxx b/sbnana/CAFAna/Analysis/Surface.cxx index f6e79028..f2cb9081 100644 --- a/sbnana/CAFAna/Analysis/Surface.cxx +++ b/sbnana/CAFAna/Analysis/Surface.cxx @@ -4,9 +4,10 @@ #include "sbnana/CAFAna/Analysis/Fit.h" #include "sbnana/CAFAna/Core/LoadFromFile.h" #include "sbnana/CAFAna/Core/IFitVar.h" -#include "sbnana/CAFAna/Core/Progress.h" -#include "sbnana/CAFAna/Core/ThreadPool.h" +#include "cafanacore/Progress.h" +#include "cafanacore/ThreadPool.h" #include "sbnana/CAFAna/Core/Utilities.h" +#include "cafanacore/UtilsExt.h" #include "OscLib/IOscCalc.h" @@ -222,16 +223,17 @@ namespace ana << "This should never happen." << std::endl; } - if(fParallel){ - pool->AddMemberTask(this, &Surface::FillSurfacePoint, - expt, calc, - xax, xv, yax, yv, - profVars, profSysts, seedPts, systSeedPts); - } - else{ + ThreadPool::func_t task = [=](){ FillSurfacePoint(expt, calc, xax, xv, yax, yv, profVars, profSysts, seedPts, systSeedPts); + }; + + if(fParallel){ + pool->AddTask(task); + } + else{ + task(); // Just do it straight away ++neval; prog->SetProgress(neval*grid_stride/double(Nx*Ny)); } @@ -556,10 +558,13 @@ namespace ana TH2* Gaussian5Sigma1D1Sided(const Surface& s){return Flat(23.66, s);} //---------------------------------------------------------------------- - void Surface::SaveTo(TDirectory* dir) const + void Surface::SaveTo(TDirectory* dir, const std::string& name) const { TDirectory* tmp = gDirectory; + + dir = dir->mkdir(name.c_str()); // switch to subdir dir->cd(); + TObjString("Surface").Write("type"); TVectorD v(3); @@ -577,7 +582,7 @@ namespace ana int idx = 0; for(auto it: fProfHists){ profDir->cd(); - it->Write( TString::Format("hist%d", idx++)); + it->Write(TString::Format("hist%d", idx++)); } if(!fBinMask.empty()){ @@ -590,12 +595,19 @@ namespace ana TObjString(fLogX ? "yes" : "no").Write("logx"); TObjString(fLogY ? "yes" : "no").Write("logy"); + dir->Write(); + delete dir; + tmp->cd(); } //---------------------------------------------------------------------- - std::unique_ptr< Surface > Surface::LoadFrom(TDirectory* dir) + std::unique_ptr Surface::LoadFrom(TDirectory* dir, + const std::string& name) { + dir = dir->GetDirectory(name.c_str()); // switch to subdir + assert(dir); + DontAddDirectory guard; TObjString* tag = (TObjString*)dir->Get("type"); @@ -641,7 +653,7 @@ namespace ana { std::vector> surfs; for(TFile* f: files) { - surfs.push_back(Surface::LoadFrom(f->GetDirectory(label.c_str()))); + surfs.push_back(Surface::LoadFrom(f, label)); } int Nx = surfs[0]->fHist->GetNbinsX(); diff --git a/sbnana/CAFAna/Analysis/Surface.h b/sbnana/CAFAna/Analysis/Surface.h index 27ab01d3..1e8adac9 100644 --- a/sbnana/CAFAna/Analysis/Surface.h +++ b/sbnana/CAFAna/Analysis/Surface.h @@ -79,7 +79,7 @@ namespace ana /// Draw the best fit point void DrawBestFit(Color_t color, Int_t marker=kFullCircle) const; double MinChi() const {return fMinChi;} - double GetMinX() const {return fMinX;} + double GetMinX() const {return fMinX;} double GetMinY() const {return fMinY;} /// \param fc Surface to compare against for this significance level @@ -100,8 +100,8 @@ namespace ana /// For expert use, custom painting of contours std::vector GetGraphs(TH2* fc, double minchi = -1); - void SaveTo(TDirectory* dir) const; - static std::unique_ptr LoadFrom(TDirectory* dir); + void SaveTo(TDirectory* dir, const std::string& name) const; + static std::unique_ptr LoadFrom(TDirectory* dir, const std::string& name); static std::unique_ptr LoadFromMulti(const std::vector& files, const std::string& label); static std::unique_ptr LoadFromMulti(const std::string& wildcard, const std::string& label); diff --git a/sbnana/CAFAna/CMakeLists.txt b/sbnana/CAFAna/CMakeLists.txt index 1639a1f8..d59e53da 100644 --- a/sbnana/CAFAna/CMakeLists.txt +++ b/sbnana/CAFAna/CMakeLists.txt @@ -1,7 +1,9 @@ -include_directories($ENV{SRPROXY_INC}) +include_directories(${SRPROXY_INC}) include_directories($ENV{EIGEN_INC}) +include_directories(${CAFANACORE_INC}) + # CAFAna expects assert() to still function even in the prof build add_definitions(-UNDEBUG) @@ -23,8 +25,6 @@ add_subdirectory(bin) # These are in SBNAna for now #cet_script(cafe) -# same place as cafe script so we can find it -#cet_script(load_cafana_libs.C) cet_script(cafana.py) cet_script(rootlogon.C) diff --git a/sbnana/CAFAna/Core/Binning.cxx b/sbnana/CAFAna/Core/Binning.cxx index c0f1c507..937495f7 100644 --- a/sbnana/CAFAna/Core/Binning.cxx +++ b/sbnana/CAFAna/Core/Binning.cxx @@ -1,153 +1,7 @@ #include "sbnana/CAFAna/Core/Binning.h" -#include "TDirectory.h" -#include "TH1.h" -#include "TObjString.h" -#include "TVectorD.h" - namespace ana { - int Binning::fgNextID = 0; - - //---------------------------------------------------------------------- - Binning::Binning() - : fID(-1) - { - } - - //---------------------------------------------------------------------- - Binning Binning::SimpleHelper(int n, double lo, double hi, - const std::vector& labels) - { - assert(labels.empty() || int(labels.size()) == n); - - Binning bins; - bins.fNBins = n; - bins.fMin = lo; - bins.fMax = hi; - bins.fEdges.resize(n+1); - for (int i = 0; i <= n; i++) - bins.fEdges[i] = lo + i*(hi-lo)/n; - bins.fLabels = labels; - bins.fIsSimple = true; - - return bins; - } - - //---------------------------------------------------------------------- - Binning Binning::Simple(int n, double lo, double hi, - const std::vector& labels) - { - Binning bins = SimpleHelper(n, lo, hi, labels); - - auto it = IDMap().find(bins); - if(it == IDMap().end()){ - bins.fID = fgNextID++; - IDMap().emplace(bins, bins.fID); - } - else{ - bins.fID = it->second; - } - - return bins; - } - - //---------------------------------------------------------------------- - Binning Binning::LogUniform(int n, double lo, double hi) - { - std::vector edges(n+1); - const double logSpacing = exp( (log(hi) - log(lo)) / n ); - for (int i = 0; i <= n; ++i) { - if (i == 0) edges[i] = lo; - else edges[i] = logSpacing*edges[i-1]; - } - return Custom(edges); - } - - //---------------------------------------------------------------------- - Binning Binning::CustomHelper(const std::vector& edges) - { - assert(edges.size() > 1); - - Binning bins; - bins.fEdges = edges; - bins.fNBins = edges.size()-1; - bins.fMin = edges.front(); - bins.fMax = edges.back(); - bins.fIsSimple = false; - - return bins; - } - - //---------------------------------------------------------------------- - Binning Binning::Custom(const std::vector& edges) - { - Binning bins = CustomHelper(edges); - - auto it = IDMap().find(bins); - if(it == IDMap().end()){ - bins.fID = fgNextID++; - IDMap().emplace(bins, bins.fID); - } - else{ - bins.fID = it->second; - } - - return bins; - } - - //---------------------------------------------------------------------- - int Binning::FindBin(float x) const - { - // Treat anything outside [fMin, fMax) at Underflow / Overflow - if (x < fMin) return 0; // Underflow - if (x >= fMax) return fEdges.size(); // Overflow - - // Follow ROOT convention, first bin of histogram is bin 1 - - if (this->IsSimple()){ - double binwidth = (fMax - fMin) / fNBins; - int bin = (x - fMin) / binwidth + 1; - return bin; - } - - int bin = - std::lower_bound(fEdges.begin(), fEdges.end(), x) - fEdges.begin(); - if (x == fEdges[bin]) bin++; - assert(bin >= 0 && bin < (int)fEdges.size()); - return bin; - } - - //---------------------------------------------------------------------- - Binning Binning::FromTAxis(const TAxis* ax) - { - Binning bins; - - // Evenly spaced binning - if(!ax->GetXbins()->GetArray()){ - bins = SimpleHelper(ax->GetNbins(), ax->GetXmin(), ax->GetXmax()); - } - else{ - std::vector edges(ax->GetNbins()+1); - ax->GetLowEdge(&edges.front()); - edges[ax->GetNbins()] = ax->GetBinUpEdge(ax->GetNbins()); - - bins = Binning::Custom(edges); - } - - auto it = IDMap().find(bins); - if(it != IDMap().end()){ - bins.fID = it->second; - } - else{ - bins.fID = fgNextID++; - IDMap().emplace(bins, bins.fID); - } - - return bins; - } - - // Can we give trueE bin a special ID? //---------------------------------------------------------------------- Binning TrueEnergyBins() { @@ -192,105 +46,4 @@ namespace ana return Binning::Simple(kNumTrueLOverTrueEBins, klow, khigh); } - - //---------------------------------------------------------------------- - void Binning::SaveTo(TDirectory* dir) const - { - TDirectory* tmp = gDirectory; - dir->cd(); - - TObjString("Binning").Write("type"); - - TVectorD nminmax(3); - - nminmax[0] = fNBins; - nminmax[1] = fMin; - nminmax[2] = fMax; - - nminmax.Write("nminmax"); - - TVectorD issimple(1); - issimple[0] = fIsSimple; - issimple.Write("issimple"); - - TVectorD edges(fEdges.size()); - for(unsigned int i = 0; i < fEdges.size(); ++i) - edges[i] = fEdges[i]; - - edges.Write("edges"); - - for(unsigned int i = 0; i < fLabels.size(); ++i) - TObjString(fLabels[i].c_str()).Write(TString::Format("label%d", i).Data()); - - tmp->cd(); - } - - //---------------------------------------------------------------------- - std::unique_ptr Binning::LoadFrom(TDirectory* dir) - { - TObjString* tag = (TObjString*)dir->Get("type"); - assert(tag); - assert(tag->GetString() == "Binning"); - - TVectorD* vMinMax = (TVectorD*)dir->Get("nminmax"); - assert(vMinMax); - - Binning ret; - - const TVectorD* issimple = (TVectorD*)dir->Get("issimple"); - if((*issimple)[0]){ - ret = Binning::Simple((*vMinMax)[0], - (*vMinMax)[1], - (*vMinMax)[2]); - } - else{ - const TVectorD* vEdges = (TVectorD*)dir->Get("edges"); - std::vector edges(vEdges->GetNrows()); - for(int i = 0; i < vEdges->GetNrows(); ++i) edges[i] = (*vEdges)[i]; - - ret = Binning::Custom(edges); - } - - for(unsigned int i = 0; ; ++i){ - TObjString* s = (TObjString*)dir->Get(TString::Format("label%d", i).Data()); - if(!s) break; - ret.fLabels.push_back(s->GetString().Data()); - } - - return std::make_unique(ret); - } - - //---------------------------------------------------------------------- - bool Binning::operator==(const Binning& rhs) const - { - // NB don't look at ID here or in < because we use these in the maps below - // that are used to find the IDs in the first place - if(fIsSimple != rhs.fIsSimple) return false; - if(fIsSimple){ - return fNBins == rhs.fNBins && fMin == rhs.fMin && fMax == rhs.fMax; - } - else{ - return fEdges == rhs.fEdges; - } - } - - //---------------------------------------------------------------------- - bool Binning::operator<(const Binning& rhs) const - { - if(fIsSimple != rhs.fIsSimple) return fIsSimple < rhs.fIsSimple; - if(fIsSimple){ - return std::make_tuple(fNBins, fMin, fMax) < std::make_tuple(rhs.fNBins, rhs.fMin, rhs.fMax); - } - else{ - return fEdges < rhs.fEdges; - } - } - - //---------------------------------------------------------------------- - std::map& Binning::IDMap() - { - static std::map ret; - return ret; - } - } diff --git a/sbnana/CAFAna/Core/Binning.h b/sbnana/CAFAna/Core/Binning.h index 2d6abfaa..45e00531 100644 --- a/sbnana/CAFAna/Core/Binning.h +++ b/sbnana/CAFAna/Core/Binning.h @@ -1,70 +1,9 @@ #pragma once -#include -#include -#include -#include -#include -#include - -class TAxis; -class TDirectory; +#include "cafanacore/Binning.h" namespace ana { - /// \brief Represent the binning of a Spectrum's x-axis - /// - /// May be "Simple" (equally spaced) or "Custom" (arbitrary binning) - class Binning - { - public: - static Binning Simple(int n, double lo, double hi, - const std::vector& labels = {}); - static Binning LogUniform(int n, double lo, double hi); - static Binning Custom(const std::vector& edges); - static Binning FromTAxis(const TAxis* ax); - - int NBins() const {return fNBins;} - double Min() const {return fMin;} - double Max() const {return fMax;} - int FindBin(float x) const; - bool IsSimple() const {return fIsSimple;} - const std::vector& Edges() const - { - return fEdges; - } - - const std::vector& Labels() const {return fLabels;} - - void SaveTo(TDirectory* dir) const; - static std::unique_ptr LoadFrom(TDirectory* dir); - - int ID() const {return fID;} - static int MaxID() {return fgNextID-1;} - - bool operator==(const Binning& rhs) const; - bool operator<(const Binning& rhs) const; - protected: - Binning(); - - static Binning SimpleHelper(int n, double lo, double hi, - const std::vector& labels = {}); - - static Binning CustomHelper(const std::vector& edges); - - std::vector fEdges; - std::vector fLabels; - int fNBins; - double fMin, fMax; - bool fIsSimple; - - int fID; - /// The next ID that hasn't yet been assigned - static int fgNextID; - - static std::map& IDMap(); - }; - /// Default true-energy bin edges Binning TrueEnergyBins(); /// Default true-energy bin edges diff --git a/sbnana/CAFAna/Core/CMakeLists.txt b/sbnana/CAFAna/Core/CMakeLists.txt index eb89794f..338588b3 100644 --- a/sbnana/CAFAna/Core/CMakeLists.txt +++ b/sbnana/CAFAna/Core/CMakeLists.txt @@ -1,8 +1,5 @@ include_directories( $ENV{IFDHC_FQ_DIR}/inc ) -# Allow "StandardRecord/" to find the right directory -include_directories(..) - include_directories($ENV{OSCLIB_INC}) cet_make(LIBRARY_NAME CAFAnaCore @@ -12,6 +9,8 @@ cet_make(LIBRARY_NAME CAFAnaCore # ${OSCLIB} -L$ENV{OSCLIB_LIB} OscLib + -L$ENV{CAFANACORE_LIB} + CAFAnaCoreExt pthread ${ROOT_BASIC_LIB_LIST} ifdh::ifdh diff --git a/sbnana/CAFAna/Core/Cut.cxx b/sbnana/CAFAna/Core/Cut.cxx deleted file mode 100644 index 45912cde..00000000 --- a/sbnana/CAFAna/Core/Cut.cxx +++ /dev/null @@ -1,236 +0,0 @@ -#include "sbnana/CAFAna/Core/Cut.h" - -#include -#include - -namespace ana -{ - //---------------------------------------------------------------------- - template _Cut:: - _Cut(const std::function& func, - const std::function& liveFunc, - const std::function& potFunc) - : fFunc(func), fLiveFunc(liveFunc), fPOTFunc(potFunc), - fID(fgNextID++) - { - } - - //---------------------------------------------------------------------- - template int _Cut::MaxID() - { - return fgNextID-1; - } - - //---------------------------------------------------------------------- - std::function - CombineExposures(const std::function& a, - const std::function& b) - { - if(!a && !b) return 0; - if(!a) return b; - if(!b) return a; - - return [a, b](const caf::SRSpill* spill){ - const double va = a(spill); - const double vb = b(spill); - - if(va >= 0 && vb >= 0){ - std::cout << "Inconsistent pot/livetime values of " - << va << " and " << vb - << " from two cuts being combined." << std::endl; - abort(); - } - - return std::max(va, vb); - }; - } - - //---------------------------------------------------------------------- - template _Cut operator&&(const _Cut& a, const _Cut& b) - { - // The same pairs of cuts are frequently and-ed together. Make sure those - // duplicates get the same IDs by remembering what we've done in the past. - static std::map, int> ids; - const std::pair key(a.ID(), b.ID()); - - if(ids.count(key)){ - return _Cut([a, b](const T* sr){return a(sr) && b(sr);}, - CombineExposures(a.fLiveFunc, b.fLiveFunc), - CombineExposures(a.fPOTFunc, b.fPOTFunc), - ids[key]); - } - else{ - const _Cut ret([a, b](const T* sr){return a(sr) && b(sr);}, - CombineExposures(a.fLiveFunc, b.fLiveFunc), - CombineExposures(a.fPOTFunc, b.fPOTFunc)); - ids[key] = ret.ID(); - return ret; - } - } - - // Make sure all versions get generated - template Cut operator&&(const Cut& a, const Cut& b); - template SpillCut operator&&(const SpillCut& a, const SpillCut& b); - - //---------------------------------------------------------------------- - template _Cut operator||(const _Cut& a, const _Cut& b) - { - static std::map, int> ids; - const std::pair key(a.ID(), b.ID()); - if(ids.count(key)){ - return _Cut([a, b](const T* sr){return a(sr) || b(sr);}, - CombineExposures(a.fLiveFunc, b.fLiveFunc), - CombineExposures(a.fPOTFunc, b.fPOTFunc), - ids[key]); - } - else{ - const _Cut ret([a, b](const T* sr){return a(sr) || b(sr);}, - CombineExposures(a.fLiveFunc, b.fLiveFunc), - CombineExposures(a.fPOTFunc, b.fPOTFunc)); - ids[key] = ret.ID(); - return ret; - } - } - - // Make sure all versions get generated - template Cut operator||(const Cut& a, const Cut& b); - template SpillCut operator||(const SpillCut& a, const SpillCut& b); - - //---------------------------------------------------------------------- - template _Cut operator!(const _Cut& a) - { - static std::map ids; - if(ids.count(a.ID())){ - return _Cut([a](const T* sr){return !a(sr);}, - 0, 0, ids[a.ID()]); - } - else{ - const _Cut ret([a](const T* sr){return !a(sr);}); - ids[a.ID()] = ret.ID(); - return ret; - } - } - - // Make sure all versions get generated - template Cut operator!(const Cut& a); - template SpillCut operator!(const SpillCut& a); - - - //---------------------------------------------------------------------- - template _Cut - operator>(const _Var& v, double c) - { - return _Cut([v, c](const T* sr){return v(sr) > c;}); - } - - //---------------------------------------------------------------------- - template _Cut - operator>=(const _Var& v, double c) - { - return _Cut([v, c](const T* sr){return v(sr) >= c;}); - } - - //---------------------------------------------------------------------- - template _Cut - operator<(const _Var& v, double c) - { - return _Cut([v, c](const T* sr){return v(sr) < c;}); - } - - //---------------------------------------------------------------------- - template _Cut - operator<=(const _Var& v, double c) - { - return _Cut([v, c](const T* sr){return v(sr) <= c;}); - } - - //---------------------------------------------------------------------- - template _Cut - operator==(const _Var& v, double c) - { - return _Cut([v, c](const T* sr){return v(sr) == c;}); - } - - //---------------------------------------------------------------------- - template _Cut - operator!=(const _Var& v, double c) - { - return !(v == c); - } - - //---------------------------------------------------------------------- - template _Cut - operator>(const _Var& a, const _Var& b) - { - return _Cut([a, b](const T* sr){return a(sr) > b(sr);}); - } - - //---------------------------------------------------------------------- - template _Cut - operator>=(const _Var& a, const _Var& b) - { - return _Cut([a, b](const T* sr){return a(sr) >= b(sr);}); - } - - //---------------------------------------------------------------------- - template _Cut - operator==(const _Var& a, const _Var& b) - { - return _Cut([a, b](const T* sr){return a(sr) == b(sr);}); - } - - // Build the rest up through simple logic - - template _Cut operator>(double c, const _Var& v){return v < c;} - template _Cut operator<(double c, const _Var& v){return v > c;} - template _Cut operator>=(double c, const _Var& v){return v <= c;} - template _Cut operator<=(double c, const _Var& v){return v >= c;} - template _Cut operator!=(double c, const _Var& v){return v != c;} - - template _Cut operator<(const _Var& a, const _Var& b){return !(b >= a);} - template _Cut operator<=(const _Var& a, const _Var& b){return !(b > a);} - template _Cut operator!=(const _Var& a, const _Var& b){return !(b == a);} - - // Make sure all three versions get generated - template class _Cut; - template class _Cut; - - template int _Cut::fgNextID = 0; - - // explicitly instantiate the templates for the types we know we have - template Cut operator>(const Var&, double); - template Cut operator<(const Var&, double); - template Cut operator>=(const Var&, double); - template Cut operator<=(const Var&, double); - template Cut operator==(const Var&, double); - template Cut operator!=(const Var&, double); - - template Cut operator>(const Var&, const Var&); - template Cut operator<(const Var&, const Var&); - template Cut operator>=(const Var&, const Var&); - template Cut operator<=(const Var&, const Var&); - template Cut operator==(const Var&, const Var&); - template Cut operator!=(const Var&, const Var&); - - template Cut operator>(double, const Var&); - template Cut operator<(double, const Var&); - template Cut operator>=(double, const Var&); - template Cut operator<=(double, const Var&); - - template SpillCut operator>(const SpillVar&, double); - template SpillCut operator<(const SpillVar&, double); - template SpillCut operator>=(const SpillVar&, double); - template SpillCut operator<=(const SpillVar&, double); - template SpillCut operator==(const SpillVar&, double); - - template SpillCut operator>(const SpillVar&, const SpillVar&); - template SpillCut operator<(const SpillVar&, const SpillVar&); - template SpillCut operator>=(const SpillVar&, const SpillVar&); - template SpillCut operator<=(const SpillVar&, const SpillVar&); - template SpillCut operator==(const SpillVar&, const SpillVar&); - - template SpillCut operator>(double, const SpillVar&); - template SpillCut operator<(double, const SpillVar&); - template SpillCut operator>=(double, const SpillVar&); - template SpillCut operator<=(double, const SpillVar&); -} diff --git a/sbnana/CAFAna/Core/Cut.h b/sbnana/CAFAna/Core/Cut.h index 44bb8289..fc66d705 100644 --- a/sbnana/CAFAna/Core/Cut.h +++ b/sbnana/CAFAna/Core/Cut.h @@ -1,88 +1,11 @@ #pragma once -// This file defines the basic Cut object. For specific cuts, and examples of -// how to implement your own, see Cuts.h +#include "cafanacore/Cut.h" -#include -#include -#include - -#include "sbnana/CAFAna/Core/Var.h" - -namespace caf{class StandardRecord; class SRSpill; class SRSpillTruthBranch; class SRSlice;} +#include "sbnanaobj/StandardRecord/Proxy/FwdDeclare.h" namespace ana { - template class _Cut; - - template _Cut operator&&(const _Cut& a, - const _Cut& b); - template _Cut operator||(const _Cut& a, - const _Cut& b); - template _Cut operator!(const _Cut& a); - - typedef double (ExposureFunc_t)(const caf::SRSpill* spill); - - /// Template for Cut and SpillCut - template class _Cut - { - public: - /// The type of the function part of a cut - typedef bool (CutFunc_t)(const T* sr); - - /// std::function can wrap a real function, function object, or lambda - _Cut(const std::function& func, - const std::function& liveFunc = 0, - const std::function& potFunc = 0); - - /// Allows a cut to be called with bool result = myCut(sr) syntax - bool operator()(const T* sr) const - { - return fFunc(sr); - } - - /// Provide a Livetime function if your cut is a timing cut etc - double Livetime(const caf::SRSpill* spill) const - { - return fLiveFunc ? fLiveFunc(spill) : -1; - } - - /// Could be useful for cuts on specific batches? - double POT(const caf::SRSpill* spill) const - { - return fPOTFunc ? fPOTFunc(spill) : -1; - } - - /// Cuts with the same definition will have the same ID - int ID() const {return fID;} - - static int MaxID(); - - protected: - friend std::function CombineExposures(const std::function& a, const std::function& b); - - // Give these guys access to the constructor that sets fID. - friend _Cut operator&&<>(const _Cut& a, - const _Cut& b); - friend _Cut operator||<>(const _Cut& a, - const _Cut& b); - friend _Cut operator!<>(const _Cut& a); - _Cut(const std::function& fun, - const std::function& liveFunc, - const std::function& potFunc, - int id) - : fFunc(fun), fLiveFunc(liveFunc), fPOTFunc(potFunc), fID(id) - { - } - - std::function fFunc; - std::function fLiveFunc, fPOTFunc; - - int fID; - /// The next ID that hasn't yet been assigned - static int fgNextID; - }; - /// \brief Representation of a cut (selection) to be applied to a \ref /// caf::StandardRecord object /// @@ -98,33 +21,20 @@ namespace ana /// spill-by-spill data quality cuts typedef _Cut SpillCut; - /// \brief Cut designed to be used over the nuTree, ie all neutrinos, not - /// just those that got slices. - typedef _Cut SpillTruthCut; + /// The simplest possible cut: pass everything, used as a default + const Cut kNoCut(NoCut{}); - template _Cut operator>(const _Var& v, double c); - template _Cut operator<(const _Var& v, double c); - template _Cut operator>=(const _Var& v, double c); - template _Cut operator<=(const _Var& v, double c); - template _Cut operator==(const _Var& v, double c); - template _Cut operator!=(const _Var& v, double c); + /// The simplest possible cut: pass everything, used as a default + const SpillCut kNoSpillCut(NoCut{}); - template _Cut operator>(const _Var& a, const _Var& b); - template _Cut operator<(const _Var& a, const _Var& b); - template _Cut operator>=(const _Var& a, const _Var& b); - template _Cut operator<=(const _Var& a, const _Var& b); - template _Cut operator==(const _Var& a, const _Var& b); - template _Cut operator!=(const _Var& a, const _Var& b); - template _Cut operator>(double c, const _Var& v); - template _Cut operator<(double c, const _Var& v); - template _Cut operator>=(double c, const _Var& v); - template _Cut operator<=(double c, const _Var& v); - template _Cut operator!=(double c, const _Var& v); + typedef _Cut NuTruthCut; + typedef _Cut TrackCut; + typedef _Cut ShowerCut; + typedef _Cut StubCut; - /// The simplest possible cut: pass everything, used as a default - const Cut kNoCut([](const caf::SRSliceProxy*){return true;}); - - /// The simplest possible cut: pass everything, used as a default - const SpillCut kNoSpillCut([](const caf::SRSpillProxy*){return true;}); + const NuTruthCut kNoNuTruthCut(NoCut{}); + const TrackCut kNoTrackCut(NoCut{}); + const ShowerCut kNoShowerCut(NoCut{}); + const StubCut kNoStubCut(NoCut{}); } // namespace diff --git a/sbnana/CAFAna/Core/DebugHelpers.cxx b/sbnana/CAFAna/Core/DebugHelpers.cxx deleted file mode 100644 index 9e4eb172..00000000 --- a/sbnana/CAFAna/Core/DebugHelpers.cxx +++ /dev/null @@ -1,90 +0,0 @@ -// This file sets things up (when libCAFAnaCore is loaded) so that we invoke -// gdb to get a stack trace after any unusual program termination. You can -// suppress this behaviour by setting the CAFE_NO_BACKTRACE environment -// variable. - -#include -#include -#include - -#include - -#include - -namespace ana -{ - void gdb_backtrace() - { - // Have to end with a 'kill' command, otherwise GDB winds up sending us - // SIGSTOP and never resuming us afterwards. - char s[1024]; - sprintf(s, "gdb --batch -ex 'set confirm off' -ex sharedlibrary -ex bt -ex kill root.exe %d", getpid()); - system(s); - } - - bool gIsException = false; - - void handle_terminate() - { - std::cout << "\n\nUncaught exception\n" << std::endl; - gIsException = true; - // Next thing that happens is abort(), which goes to handle_signal() - } - - void handle_signal(int sig, siginfo_t*, void*) - { - if(sig == SIGABRT && !gIsException) - std::cout << "\n\nAborted\n" << std::endl; - if(sig == SIGSEGV) - std::cout << "\n\nSegmentation fault\n" << std::endl; - if(sig == SIGFPE) - std::cout << "\n\nFloating point exception\n" << std::endl; - if(sig == SIGBUS) - std::cout << "\n\nBus error\n" << std::endl; - - gdb_backtrace(); - - // gdb_backtrace() never returns. But if it did, this would be the right - // way to exit with the correct code. - _exit(sig+128); - } - - class InstallHandlers - { - public: - InstallHandlers() - { - // We're already being debugged somehow. Don't complicate things - if(getenv("CAFE_NO_BACKTRACE")) return; - - // Check that this is really a CAFAna job. Somehow this library gets - // loaded into art jobs too?? - char s[1024]; - sprintf(s, "/proc/%d/cmdline", getpid()); - std::ifstream f(s); - if(f){ - std::string ss; - f >> ss; - if(ss.find("root.exe") == std::string::npos) return; - } - - // Handle uncaught exceptions - std::set_terminate(handle_terminate); - - // Handle abort(), segfaults, bus errors, and FPEs - struct sigaction sa; - memset(&sa, 0, sizeof(sa)); - sigemptyset(&sa.sa_mask); - - sa.sa_sigaction = handle_signal; - sa.sa_flags = SA_SIGINFO; - - sigaction(SIGABRT, &sa, NULL); - sigaction(SIGSEGV, &sa, NULL); - sigaction(SIGBUS, &sa, NULL); - sigaction(SIGFPE, &sa, NULL); - } - }; - - static InstallHandlers gHandlerInstaller; -} diff --git a/sbnana/CAFAna/Core/EnsembleOscillatableSpectrum.cxx b/sbnana/CAFAna/Core/EnsembleOscillatableSpectrum.cxx new file mode 100644 index 00000000..865643e6 --- /dev/null +++ b/sbnana/CAFAna/Core/EnsembleOscillatableSpectrum.cxx @@ -0,0 +1,259 @@ +#include "sbnana/CAFAna/Core/EnsembleOscillatableSpectrum.h" + +#include "sbnana/CAFAna/Core/Binning.h" +#include "sbnana/CAFAna/Core/FitMultiverse.h" +#include "sbnana/CAFAna/Core/OscCurve.h" +#include "cafanacore/Ratio.h" +#include "sbnana/CAFAna/Core/Utilities.h" + +#include "sbnana/CAFAna/Analysis/ExpInfo.h" + +#include "sbnanaobj/StandardRecord/Proxy/SRProxy.h" + +#include "OscLib/IOscCalc.h" + +#include "TDirectory.h" +#include "TH2.h" +#include "TMD5.h" +#include "TObjString.h" + +#include +#include + +namespace ana +{ + // Duplicate here because we can't include Vars.h + namespace{ + const Var kTrueE([](const caf::SRSliceProxy* slc) -> double {return slc->truth.E;}); + + const Var kBaseline([](const caf::SRSliceProxy* slc) -> double {return slc->truth.baseline * 1e-3;}); // m -> km + + const Var kTrueLOverE = kBaseline / kTrueE; + + const Cut kHasNu([](const caf::SRSliceProxy* sr) + { + return sr->truth.index >= 0; + }); + } // end anonymous namespace + + //---------------------------------------------------------------------- + EnsembleOscillatableSpectrum:: + EnsembleOscillatableSpectrum(ISliceEnsembleSource& src, + const HistAxis& axis) + : EnsembleReweightableSpectrum(src[kHasNu], axis, HistAxis("True L / E (km / GeV)", kTrueLOverEBins, kTrueLOverE)) + { + } + + //---------------------------------------------------------------------- + EnsembleOscillatableSpectrum:: + EnsembleOscillatableSpectrum(const FitMultiverse* multiverse, + const Eigen::MatrixXd&& mat, + const HistAxis& recoAxis, + double pot, double livetime) + : EnsembleReweightableSpectrum(multiverse, + std::move(mat), + recoAxis, + HistAxis("True L / E (km / GeV)", + kTrueLOverEBins, + kTrueLOverE), + pot, livetime) + { + } + + //---------------------------------------------------------------------- + EnsembleOscillatableSpectrum::~EnsembleOscillatableSpectrum() + { + } + + //---------------------------------------------------------------------- + EnsembleOscillatableSpectrum::EnsembleOscillatableSpectrum(const EnsembleOscillatableSpectrum& rhs) + : EnsembleReweightableSpectrum(rhs) + { + if(rhs.fCache->hash){ + fCache->spect = rhs.fCache->spect; + fCache->hash = std::make_unique(*rhs.fCache->hash); + } + } + + //---------------------------------------------------------------------- + EnsembleOscillatableSpectrum::EnsembleOscillatableSpectrum(EnsembleOscillatableSpectrum&& rhs) + : EnsembleReweightableSpectrum(rhs) + { + if(rhs.fCache->hash){ + fCache->spect = std::move(rhs.fCache->spect); + fCache->hash = std::move(rhs.fCache->hash); + } + } + + //---------------------------------------------------------------------- + EnsembleOscillatableSpectrum& EnsembleOscillatableSpectrum::operator=(const EnsembleOscillatableSpectrum& rhs) + { + if(this == &rhs) return *this; + + EnsembleReweightableSpectrum::operator=(rhs); + + if(rhs.fCache->hash){ + fCache->spect = rhs.fCache->spect; + fCache->hash = std::make_unique(*rhs.fCache->hash); + } + else{ + fCache->hash.reset(); + } + + return *this; + } + + //---------------------------------------------------------------------- + EnsembleOscillatableSpectrum& EnsembleOscillatableSpectrum::operator=(EnsembleOscillatableSpectrum&& rhs) + { + if(this == &rhs) return *this; + + EnsembleReweightableSpectrum::operator=(rhs); + + if(rhs.fCache->hash){ + fCache->spect = std::move(rhs.fCache->spect); + fCache->hash = std::move(rhs.fCache->hash); + } + else{ + fCache->hash.reset(); + } + + return *this; + } + + //---------------------------------------------------------------------- + template EnsembleSpectrum EnsembleOscillatableSpectrum:: + _Oscillated(osc::_IOscCalc* calc, int from, int to) const + { + // POT = 0 implies empty spectrum and oscillated result will also always be + // empty + if(fCache->hash && fPOT == 0) return *fCache->spect; + + TMD5* hash = calc->GetParamsHash(); + if(hash && fCache->hash && *hash == *fCache->hash){ + delete hash; + return *fCache->spect; + } + + const OscCurve curve(calc, from, to); + const EnsembleSpectrum ret = WeightedBy(curve); + if(hash){ + fCache->spect = ret; + fCache->hash.reset(hash); + } + + return ret; + } + + //---------------------------------------------------------------------- + EnsembleSpectrum EnsembleOscillatableSpectrum::Oscillated(osc::IOscCalc* calc, + int from, int to) const + { + return _Oscillated(calc, from, to); + } + + //---------------------------------------------------------------------- + EnsembleOscillatableSpectrum& EnsembleOscillatableSpectrum::operator+=(const EnsembleOscillatableSpectrum& rhs) + { + EnsembleReweightableSpectrum::operator+=(rhs); + + // invalidate + fCache->hash.reset(nullptr); + + return *this; + } + + //---------------------------------------------------------------------- + EnsembleOscillatableSpectrum EnsembleOscillatableSpectrum::operator+(const EnsembleOscillatableSpectrum& rhs) const + { + EnsembleOscillatableSpectrum ret = *this; + ret += rhs; + return ret; + } + + //---------------------------------------------------------------------- + EnsembleOscillatableSpectrum& EnsembleOscillatableSpectrum::operator-=(const EnsembleOscillatableSpectrum& rhs) + { + EnsembleReweightableSpectrum::operator-=(rhs); + + // invalidate + fCache->hash.reset(nullptr); + + return *this; + } + + //---------------------------------------------------------------------- + EnsembleOscillatableSpectrum EnsembleOscillatableSpectrum::operator-(const EnsembleOscillatableSpectrum& rhs) const + { + EnsembleOscillatableSpectrum ret = *this; + ret -= rhs; + return ret; + } + + //---------------------------------------------------------------------- + void EnsembleOscillatableSpectrum::SaveTo(TDirectory* dir, const std::string& name) const + { + _SaveTo(dir, name, "EnsembleOscillatableSpectrum"); + } + + //---------------------------------------------------------------------- + std::unique_ptr EnsembleOscillatableSpectrum::LoadFrom(TDirectory* dir, const std::string& name) + { + dir = dir->GetDirectory(name.c_str()); // switch to subdir + assert(dir); + + DontAddDirectory guard; + + TObjString* tag = (TObjString*)dir->Get("type"); + assert(tag); + assert(tag->GetString() == "EnsembleOscillatableSpectrum"); + 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; + 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, subname)); + TObjString* label = (TObjString*)dir->Get(TString::Format("label%d", i)); + labels.push_back(label ? label->GetString().Data() : ""); + delete label; + } + + delete dir; + + const HistAxis recoAxis(labels, bins); + + 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 EnsembleOscillatableSpectrum( + multiverse, + Eigen::Map(spect->GetArray(), + kTrueLOverEBins.NBins()+2, + (recoAxis.GetBins1D().NBins() + 2) * multiverse->NUniv()), + recoAxis, + hPot->Integral(0, -1), + hLivetime->Integral(0, -1))); + + delete spect; + + delete hPot; + delete hLivetime; + + return ret; + } +} diff --git a/sbnana/CAFAna/Core/EnsembleOscillatableSpectrum.h b/sbnana/CAFAna/Core/EnsembleOscillatableSpectrum.h new file mode 100644 index 00000000..5d38ad25 --- /dev/null +++ b/sbnana/CAFAna/Core/EnsembleOscillatableSpectrum.h @@ -0,0 +1,75 @@ +#pragma once + +#include "sbnana/CAFAna/Core/EnsembleReweightableSpectrum.h" + +#include "cafanacore/FwdDeclare.h" +#include "cafanacore/ThreadLocal.h" + +#include "sbnana/CAFAna/Core/Binning.h" +#include "sbnana/CAFAna/Core/HistAxis.h" +#include "sbnana/CAFAna/Core/SpectrumLoaderBase.h" +#include "sbnana/CAFAna/Core/StanTypedefs.h" +#include "sbnana/CAFAna/Core/IRecordSource.h" + +#include "TMD5.h" + +#include + +namespace osc +{ + template class _IOscCalc; + typedef _IOscCalc IOscCalc; +} + +namespace ana +{ + class Binning; + + struct OscCache + { + std::unique_ptr hash; + std::optional spect; + }; + + /// %Spectrum with true energy information, allowing it to be oscillated + class EnsembleOscillatableSpectrum: public EnsembleReweightableSpectrum + { + public: + EnsembleOscillatableSpectrum(ana::ISliceEnsembleSource& src, + const HistAxis& axis); + + ~EnsembleOscillatableSpectrum(); + + /// Copy constructor + EnsembleOscillatableSpectrum(const EnsembleOscillatableSpectrum& rhs); + EnsembleOscillatableSpectrum(EnsembleOscillatableSpectrum&& rhs); + /// Assignment operator + EnsembleOscillatableSpectrum& operator=(const EnsembleOscillatableSpectrum& rhs); + EnsembleOscillatableSpectrum& operator=(EnsembleOscillatableSpectrum&& rhs); + + // These under a different name + EnsembleSpectrum Unoscillated() const {return UnWeighted();} + EnsembleSpectrum TrueEnergy() const {return WeightingVariable();} + + EnsembleSpectrum Oscillated(osc::IOscCalc* calc, int from, int to) const; + + EnsembleOscillatableSpectrum& operator+=(const EnsembleOscillatableSpectrum& rhs); + EnsembleOscillatableSpectrum operator+(const EnsembleOscillatableSpectrum& rhs) const; + + EnsembleOscillatableSpectrum& operator-=(const EnsembleOscillatableSpectrum& rhs); + EnsembleOscillatableSpectrum operator-(const EnsembleOscillatableSpectrum& rhs) const; + + void SaveTo(TDirectory* dir, const std::string& name) const; + static std::unique_ptr LoadFrom(TDirectory* dir, const std::string& name); + + protected: + EnsembleOscillatableSpectrum(const FitMultiverse* multiverse, + const Eigen::MatrixXd&& mat, + const HistAxis& recoAxis, + double pot, double livetime); + + template EnsembleSpectrum _Oscillated(osc::_IOscCalc* calc, int from, int to) const; + + mutable ThreadLocal fCache; + }; +} diff --git a/sbnana/CAFAna/Core/EnsembleRatio.cxx b/sbnana/CAFAna/Core/EnsembleRatio.cxx index cc79f4be..0c2d84b2 100644 --- a/sbnana/CAFAna/Core/EnsembleRatio.cxx +++ b/sbnana/CAFAna/Core/EnsembleRatio.cxx @@ -2,45 +2,131 @@ #include "sbnana/CAFAna/Core/EnsembleSpectrum.h" +#include "sbnana/CAFAna/Core/FitMultiverse.h" +#include "sbnana/CAFAna/Core/Utilities.h" + +#include "cafanacore/UtilsExt.h" + +#include "TEfficiency.h" #include "TGraphAsymmErrors.h" -#include "TH1.h" namespace ana { //---------------------------------------------------------------------- EnsembleRatio::EnsembleRatio(const EnsembleSpectrum& num, - const EnsembleSpectrum& denom) - : fNom(num.Nominal(), denom.Nominal()) + const EnsembleSpectrum& denom, + bool purOrEffErrs) + : fMultiverse(&num.GetMultiverse()), + fHist(num.fHist), + fAxis(num.GetLabels(), num.GetBinnings()) { - assert(num.NUniverses() == denom.NUniverses()); - fUnivs.reserve(num.NUniverses()); - for(unsigned int i = 0; i < num.NUniverses(); ++i) - fUnivs.emplace_back(num.Universe(i), denom.Universe(i)); + 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 { - std::unique_ptr hnom(fNom.ToTH1()); + // TODO lots of code duplication with EnsembleSpectrum - std::vector> hunivs; - hunivs.reserve(fUnivs.size()); - for(const Ratio& u: fUnivs) hunivs.emplace_back(u.ToTH1()); + const Eigen::ArrayXd arr = fHist.GetEigen(); TGraphAsymmErrors* g = new TGraphAsymmErrors; - for(int binIdx = 0; binIdx < hnom->GetNbinsX()+2; ++binIdx){ - const double xnom = hnom->GetXaxis()->GetBinCenter(binIdx); - const double ynom = hnom->GetBinContent(binIdx); - g->SetPoint(binIdx, xnom, ynom); + const int nbins = fAxis.GetBins1D().NBins()+2; + const std::vector& edges = fAxis.GetBins1D().Edges(); - const double dx = hnom->GetXaxis()->GetBinWidth(binIdx); + 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(hunivs.size()); - for(const std::unique_ptr& hu: hunivs){ - ys.push_back(hu->GetBinContent(binIdx)); - } + 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); @@ -48,7 +134,7 @@ namespace ana // It's theoretically possible for the central value to be outside the // error bands - clamp to zero in that case - g->SetPointError(binIdx, dx/2, dx/2, + g->SetPointError(binIdx-1, dx/2, dx/2, std::max(ynom-y0, 0.), std::max(y1-ynom, 0.)); } // end for binIdx @@ -56,18 +142,64 @@ namespace ana 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); + } + + //---------------------------------------------------------------------- + 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) { - assert(rhs.NUniverses() == fUnivs.size()); - fNom *= rhs.fNom; - for(unsigned int i = 0; i < fUnivs.size(); ++i) - fUnivs[i] *= rhs.fUnivs[i]; + CheckMultiverses(rhs.GetMultiverse(), __func__); + + fHist.Multiply(rhs.fHist); + return *this; } //---------------------------------------------------------------------- - EnsembleRatio EnsembleRatio::operator*(const EnsembleRatio& rhs) const + EnsembleRatio EnsembleRatio::operator*(const EnsembleRatio& rhs) const { EnsembleRatio ret = *this; ret *= rhs; @@ -77,10 +209,10 @@ namespace ana //---------------------------------------------------------------------- EnsembleRatio& EnsembleRatio::operator/=(const EnsembleRatio& rhs) { - assert(rhs.NUniverses() == fUnivs.size()); - fNom /= rhs.fNom; - for(unsigned int i = 0; i < fUnivs.size(); ++i) - fUnivs[i] /= rhs.fUnivs[i]; + CheckMultiverses(rhs.GetMultiverse(), __func__); + + fHist.Divide(rhs.fHist); + return *this; } diff --git a/sbnana/CAFAna/Core/EnsembleRatio.h b/sbnana/CAFAna/Core/EnsembleRatio.h index 5b808086..961e8846 100644 --- a/sbnana/CAFAna/Core/EnsembleRatio.h +++ b/sbnana/CAFAna/Core/EnsembleRatio.h @@ -1,6 +1,6 @@ #pragma once -#include "sbnana/CAFAna/Core/Ratio.h" +#include "cafanacore/Ratio.h" #include "TGraphAsymmErrors.h" @@ -9,22 +9,31 @@ namespace ana { class EnsembleSpectrum; + class FitMultiverse; class EnsembleRatio { public: - EnsembleRatio(const EnsembleSpectrum& nom, const EnsembleSpectrum& denom); + friend class EnsembleSpectrum; - Ratio Nominal() const {return fNom;} - unsigned int NUniverses() const {return fUnivs.size();} - Ratio Universe(unsigned int i) const - { - assert(i < fUnivs.size()); - return fUnivs[i]; - } + 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; @@ -32,8 +41,15 @@ namespace ana EnsembleRatio operator/(const EnsembleRatio& rhs) const; protected: - Ratio fNom; - std::vector fUnivs; + 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, diff --git a/sbnana/CAFAna/Core/EnsembleReweightableSpectrum.cxx b/sbnana/CAFAna/Core/EnsembleReweightableSpectrum.cxx new file mode 100644 index 00000000..28d74779 --- /dev/null +++ b/sbnana/CAFAna/Core/EnsembleReweightableSpectrum.cxx @@ -0,0 +1,411 @@ +#include "sbnana/CAFAna/Core/EnsembleReweightableSpectrum.h" + +#include "sbnana/CAFAna/Core/EnsembleRatio.h" +#include "sbnana/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() + { + } + + //---------------------------------------------------------------------- + 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(); + } +} diff --git a/sbnana/CAFAna/Core/EnsembleReweightableSpectrum.h b/sbnana/CAFAna/Core/EnsembleReweightableSpectrum.h new file mode 100644 index 00000000..579b04d8 --- /dev/null +++ b/sbnana/CAFAna/Core/EnsembleReweightableSpectrum.h @@ -0,0 +1,122 @@ +#pragma once + +#include "sbnana/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(); + + 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; + }; +} diff --git a/sbnana/CAFAna/Core/EnsembleSpectrum.cxx b/sbnana/CAFAna/Core/EnsembleSpectrum.cxx index 689938b9..8e52cf53 100644 --- a/sbnana/CAFAna/Core/EnsembleSpectrum.cxx +++ b/sbnana/CAFAna/Core/EnsembleSpectrum.cxx @@ -2,6 +2,9 @@ #include "sbnana/CAFAna/Core/EnsembleRatio.h" +#include "sbnana/CAFAna/Core/FitMultiverse.h" +#include "sbnana/CAFAna/Core/Utilities.h" + #include "TDirectory.h" #include "TGraphAsymmErrors.h" #include "TH1.h" @@ -11,32 +14,75 @@ namespace ana { //---------------------------------------------------------------------- - EnsembleSpectrum::EnsembleSpectrum(SpectrumLoaderBase& loader, - const HistAxis& axis, - const SpillCut& spillcut, - const Cut& cut, - const std::vector& univ_shifts, - const Var& cv_wei) - : fNom(loader, axis, spillcut, cut, kNoShift, cv_wei) - { - fUnivs.reserve(univ_shifts.size()); - for(const SystShifts& ss: univ_shifts){ - fUnivs.emplace_back(loader, axis, spillcut, cut, ss, cv_wei); - } + 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::ReplicatedData(const Spectrum& spec, const FitMultiverse* multiverse) + { + Eigen::ArrayXd data = spec.GetEigen().replicate(multiverse->NUniv(), 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); } //---------------------------------------------------------------------- - EnsembleSpectrum::EnsembleSpectrum(SpectrumLoaderBase& loader, - const HistAxis& axis, - const SpillCut& spillcut, - const Cut& cut, - const std::vector& univ_weis, - const Var& cv_wei) - : fNom(loader, axis, spillcut, cut, kNoShift, cv_wei) + void EnsembleSpectrum::FillEnsemble(double x, const std::vector& ws) { - fUnivs.reserve(univ_weis.size()); - for(const Var& w: univ_weis){ - fUnivs.emplace_back(loader, axis, spillcut, cut, kNoShift, cv_wei * w); + 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); } } @@ -45,26 +91,27 @@ namespace ana EExposureType expotype, EBinType bintype) const { - std::unique_ptr hnom(fNom.ToTH1(exposure, expotype, bintype)); + // TODO lots of code duplication with EnsembleRatio - std::vector> hunivs; - hunivs.reserve(fUnivs.size()); - for(const Spectrum& u: fUnivs) hunivs.emplace_back(u.ToTH1(exposure, expotype, bintype)); + const Eigen::ArrayXd arr = fHist.GetEigen() * exposure / (expotype == kPOT ? fPOT : fLivetime); TGraphAsymmErrors* g = new TGraphAsymmErrors; - for(int binIdx = 0; binIdx < hnom->GetNbinsX()+2; ++binIdx){ - const double xnom = hnom->GetXaxis()->GetBinCenter(binIdx); - const double ynom = hnom->GetBinContent(binIdx); - g->SetPoint(binIdx, xnom, ynom); + 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 dx = hnom->GetXaxis()->GetBinWidth(binIdx); + 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(hunivs.size()); - for(const std::unique_ptr& hu: hunivs){ - ys.push_back(hu->GetBinContent(binIdx)); - } + 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); @@ -72,7 +119,7 @@ namespace ana // It's theoretically possible for the central value to be outside the // error bands - clamp to zero in that case - g->SetPointError(binIdx, dx/2, dx/2, + g->SetPointError(binIdx-1, dx/2, dx/2, std::max(ynom-y0, 0.), std::max(y1-ynom, 0.)); } // end for binIdx @@ -80,20 +127,122 @@ namespace ana 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) { - fNom.Scale(c); - for(Spectrum& s: fUnivs) s.Scale(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.fL\ +ivetime + << 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) { - fNom += rhs.fNom; - assert(fUnivs.size() == rhs.fUnivs.size()); - for(unsigned int i = 0; i < fUnivs.size(); ++i) fUnivs[i] += rhs.fUnivs[i]; - return *this; + return PlusEqualsHelper(rhs, +1, __func__); } //---------------------------------------------------------------------- @@ -107,10 +256,7 @@ namespace ana //---------------------------------------------------------------------- EnsembleSpectrum& EnsembleSpectrum::operator-=(const EnsembleSpectrum& rhs) { - fNom -= rhs.fNom; - assert(fUnivs.size() == rhs.fUnivs.size()); - for(unsigned int i = 0; i < fUnivs.size(); ++i) fUnivs[i] -= rhs.fUnivs[i]; - return *this; + return PlusEqualsHelper(rhs, -1, __func__); } //---------------------------------------------------------------------- @@ -124,9 +270,9 @@ namespace ana //---------------------------------------------------------------------- EnsembleSpectrum& EnsembleSpectrum::operator*=(const EnsembleRatio& rhs) { - fNom *= rhs.Nominal(); - assert(rhs.NUniverses() == fUnivs.size()); - for(unsigned int i = 0; i < fUnivs.size(); ++i) fUnivs[i] *= rhs.Universe(i); + CheckMultiverses(rhs.GetMultiverse(), __func__); + fHist.Multiply(rhs.fHist); + return *this; } @@ -141,9 +287,9 @@ namespace ana //---------------------------------------------------------------------- EnsembleSpectrum& EnsembleSpectrum::operator/=(const EnsembleRatio& rhs) { - fNom /= rhs.Nominal(); - assert(rhs.NUniverses() == fUnivs.size()); - for(unsigned int i = 0; i < fUnivs.size(); ++i) fUnivs[i] /= rhs.Universe(i); + CheckMultiverses(rhs.GetMultiverse(), __func__); + fHist.Divide(rhs.fHist); + return *this; } @@ -156,40 +302,96 @@ namespace ana } //---------------------------------------------------------------------- - void EnsembleSpectrum::SaveTo(TDirectory* dir) const + 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"); - fNom.SaveTo(dir->mkdir("nom")); - for(unsigned int i = 0; i < fUnivs.size(); ++i){ - fUnivs[i].SaveTo(dir->mkdir(("univ"+std::to_string(i)).c_str())); + 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(); } //---------------------------------------------------------------------- - std::unique_ptr EnsembleSpectrum::LoadFrom(TDirectory* dir) + 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; - TObjString* tag = (TObjString*)dir->Get("type"); + std::unique_ptr tag((TObjString*)dir->Get("type")); assert(tag); assert(tag->GetString() == "EnsembleSpectrum"); - delete tag; - - std::unique_ptr ret(new EnsembleSpectrum(*Spectrum::LoadFrom(dir->GetDirectory("nom")))); - for(unsigned int i = 0; ; ++i){ - TDirectory* d = dir->GetDirectory(("univ"+std::to_string(i)).c_str()); - if(!d) break; - ret->fUnivs.push_back(*Spectrum::LoadFrom(d)); + 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 ret; + 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(); } //---------------------------------------------------------------------- @@ -213,6 +415,7 @@ namespace ana 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)); } diff --git a/sbnana/CAFAna/Core/EnsembleSpectrum.h b/sbnana/CAFAna/Core/EnsembleSpectrum.h index 65fbb897..9743f890 100644 --- a/sbnana/CAFAna/Core/EnsembleSpectrum.h +++ b/sbnana/CAFAna/Core/EnsembleSpectrum.h @@ -1,6 +1,11 @@ #pragma once -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "cafanacore/Spectrum.h" + +#include "sbnana/CAFAna/Core/Cut.h" +#include "sbnana/CAFAna/Core/HistAxis.h" +#include "sbnana/CAFAna/Core/IRecordSource.h" +#include "sbnana/CAFAna/Core/Weight.h" #include @@ -9,44 +14,61 @@ class TGraphAsymmErrors; namespace ana { class EnsembleRatio; + class FitMultiverse; - // TODO Multiverse class encapsulating a vector of shifts/weights and an ID - // number? - - class EnsembleSpectrum + class EnsembleSpectrum : public IValueEnsembleSink { public: - EnsembleSpectrum(SpectrumLoaderBase& loader, - const HistAxis& axis, - const SpillCut& spillcut, - const Cut& cut, - const std::vector& univ_shifts, - const Var& cv_wei = kUnweighted); - - EnsembleSpectrum(SpectrumLoaderBase& loader, - const HistAxis& axis, - const SpillCut& spillcut, - const Cut& cut, - const std::vector& univ_weis, - const Var& cv_wei = kUnweighted); - - Spectrum Nominal() const {return fNom;} - unsigned int NUniverses() const {return fUnivs.size();} - Spectrum Universe(unsigned int i) const + 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) { - assert(i < fUnivs.size()); - return fUnivs[i]; } - double POT() const {return fNom.POT();} + /// \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 Livetime() const {return fNom.Livetime();} + 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; + + virtual void FillLivetime(double livetime) override; + void Scale(double c); EnsembleSpectrum& operator+=(const EnsembleSpectrum& rhs); @@ -61,18 +83,37 @@ namespace ana EnsembleSpectrum& operator/=(const EnsembleRatio& rhs); EnsembleSpectrum operator/(const EnsembleRatio& rhs) const; - void SaveTo(TDirectory* dir) const; - static std::unique_ptr LoadFrom(TDirectory* dir); + 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 fNom.NDimensions();} - std::vector GetLabels() const {return fNom.GetLabels();} - std::vector GetBinnings() const {return fNom.GetBinnings();} + unsigned int NDimensions() const{return fAxis.NDimensions();} + std::vector GetLabels() const {return fAxis.GetLabels();} + std::vector GetBinnings() const {return fAxis.GetBinnings();} protected: - EnsembleSpectrum(const Spectrum& nom) : fNom(nom) {} + 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; - Spectrum fNom; - std::vector fUnivs; + Hist fHist; + double fPOT; + double fLivetime; + LabelsAndBins fAxis; }; // Commutative diff --git a/sbnana/CAFAna/Core/FileListSource.cxx b/sbnana/CAFAna/Core/FileListSource.cxx deleted file mode 100644 index c0a89c4a..00000000 --- a/sbnana/CAFAna/Core/FileListSource.cxx +++ /dev/null @@ -1,110 +0,0 @@ -#include "sbnana/CAFAna/Core/FileListSource.h" - -#include "sbnana/CAFAna/Core/Utilities.h" - -#include "TFile.h" - -#include -#include - -namespace ana -{ - bool FileListSource::fgGotTickets = false; - - //---------------------------------------------------------------------- - FileListSource::FileListSource(const std::vector& files, - int stride, int offset) - : fFileNames(files.begin(), files.end()), - fIt(fFileNames.begin()), - fStride(stride), - fFile(0) - { - if(fFileNames.empty()){ - fN = 0; - return; - } - - if(offset < 0){ - if(getenv("CAFANA_OFFSET")) - offset = atoi(getenv("CAFANA_OFFSET")); - - offset = std::max(offset, 0); - } - - if(fStride < 0){ - if(getenv("CAFANA_STRIDE")) - fStride = atoi(getenv("CAFANA_STRIDE")); - - fStride = std::max(fStride, 1); - } - - if(fStride > int(files.size())){ - std::cerr << "Warning: stride " << fStride - << " is greater than the number of files: " << files.size() - << ". This is strange and inefficient." << std::endl; - // Needs to be nonzero otherwise some callers go off into SAM-query - // land. Having a slightly misleading progress bar is a small price to - // pay in this weird case. - fN = 1; - return; - } - - // How many files will we process from the list with this offset and - // stride? - fN = (int(files.size())-offset-1)/fStride+1; - - for(const std::string& loc: files){ - if(loc.rfind("/pnfs/", 0) == 0){ // ie begins with - if(!fgGotTickets){ - // No kerberos ticket means no point trying to voms-proxy-init. It - // likely also means we're in a grid job, where that would be - // counterproductive anyway. - if(system("klist -5 -s || klist -s") != 0) fgGotTickets = true; - } - - if(!fgGotTickets){ - // This comes from NovaGridUtils, v02.10 onwards. - // system("setup_fnal_security -b"); - - fgGotTickets = true; - break; - } - } - } - - for(int i = 0; i < offset; ++i){ - ++fIt; - if(fIt == fFileNames.end()) break; - } - } - - //---------------------------------------------------------------------- - FileListSource::~FileListSource() - { - delete fFile; - } - - //---------------------------------------------------------------------- - TFile* FileListSource::GetNextFile() - { - // Tidy up the last file we gave, which the caller no longer needs - delete fFile; - fFile = 0; - - if(fIt == fFileNames.end()) return 0; // Ran out of files - - // If the file is on pnfs rewrite it to an xrootd address - std::string loc = *fIt; - // loc = pnfs2xrootd(loc); // no-op for non /pnfs locations - - fFile = TFile::Open(loc.c_str()); // This pattern allows xrootd - assert(fFile); - - for(int i = 0; i < fStride; ++i){ - if(fIt == fFileNames.end()) break; - ++fIt; // Move on to the next file, for the subsequent call - } - - return fFile; - } -} diff --git a/sbnana/CAFAna/Core/FileListSource.h b/sbnana/CAFAna/Core/FileListSource.h deleted file mode 100644 index b8d670db..00000000 --- a/sbnana/CAFAna/Core/FileListSource.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include "sbnana/CAFAna/Core/IFileSource.h" - -#include -#include - -namespace ana -{ - /// Simple file source based on an explicit list provided by the user - class FileListSource: public IFileSource - { - public: - /// default offset and stride mean obey cmd-line options - FileListSource(const std::vector& files, - int stride = -1, int offset = -1); - virtual ~FileListSource(); - - virtual TFile* GetNextFile() override; - int NFiles() const override {return fN;} - protected: - std::vector fFileNames; ///< The list of files - std::vector::iterator fIt; ///< Iterator into \ref fFileNames - int fStride; - int fN; ///< Number of files that will actually be returned - TFile* fFile; ///< The most-recently-returned file - static bool fgGotTickets; ///< Have we renewed our tickets? - }; -} diff --git a/sbnana/CAFAna/Core/FileReducer.cxx b/sbnana/CAFAna/Core/FileReducer.cxx index 2fbd321f..2831b437 100644 --- a/sbnana/CAFAna/Core/FileReducer.cxx +++ b/sbnana/CAFAna/Core/FileReducer.cxx @@ -1,6 +1,7 @@ #include "sbnana/CAFAna/Core/FileReducer.h" -#include "sbnana/CAFAna/Core/Progress.h" +#include "cafanacore/Progress.h" + #include "sbnana/CAFAna/Core/Utilities.h" #include "sbnanaobj/StandardRecord/Proxy/SRProxy.h" @@ -95,7 +96,7 @@ namespace ana void FileReducer::Go() { // FloatingExceptionOnNaN fpnan; - + // Don't want overflow to happen. Set to 1 petabyte: effectively infinite. TTree::SetMaxTreeSize(1e15); @@ -108,7 +109,7 @@ namespace ana const int Nfiles = NFiles(); Progress* prog = 0; - + TFile fout(fOutfile.c_str(), "RECREATE"); TTree* trOut = new TTree("recTree", "recTree"); { diff --git a/sbnana/CAFAna/Core/FitMultiverse.h b/sbnana/CAFAna/Core/FitMultiverse.h new file mode 100644 index 00000000..2bc18f38 --- /dev/null +++ b/sbnana/CAFAna/Core/FitMultiverse.h @@ -0,0 +1,81 @@ +#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];} + + 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 + 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; + }; + +} diff --git a/sbnana/CAFAna/Core/GenieWeightList.cxx b/sbnana/CAFAna/Core/GenieWeightList.cxx deleted file mode 100644 index 7060cbdc..00000000 --- a/sbnana/CAFAna/Core/GenieWeightList.cxx +++ /dev/null @@ -1,153 +0,0 @@ -#include "sbnana/CAFAna/Core/GenieWeightList.h" - -#include -#include - -namespace ana -{ - //---------------------------------------------------------------------- - std::vector GetGenieWeightNames() - { - // I wonder if we can share this somehow with the code that generates these? - return {"MaCCQE","VecFFCCQEshape", - "MaNCEL","EtaNCEL","MaCCRES","MvCCRES", - "MaNCRES","MvNCRES","RDecBR1gamma","RDecBR1eta", - "Theta_Delta2Npi","AhtBY","BhtBY","CV1uBY", - "CV2uBY","FormZone","MFP_pi","FrCEx_pi", - "FrElas_pi","FrInel_pi","FrAbs_pi","FrPiProd_pi", - "MFP_N","FrCEx_N","FrElas_N","FrInel_N", - "FrAbs_N","FrPiProd_N","CCQEPauliSupViaKF","Mnv2p2hGaussEnhancement", - "MKSPP_ReWeight","E2p2h_A_nu","E2p2h_B_nu","E2p2h_A_nubar", - "E2p2h_B_nubar","NR_nu_n_CC_2Pi","NR_nu_n_CC_3Pi","NR_nu_p_CC_2Pi", - "NR_nu_p_CC_3Pi","NR_nu_np_CC_1Pi","NR_nu_n_NC_1Pi","NR_nu_n_NC_2Pi", - "NR_nu_n_NC_3Pi","NR_nu_p_NC_1Pi","NR_nu_p_NC_2Pi","NR_nu_p_NC_3Pi", - "NR_nubar_n_CC_1Pi","NR_nubar_n_CC_2Pi","NR_nubar_n_CC_3Pi","NR_nubar_p_CC_1Pi", - "NR_nubar_p_CC_2Pi","NR_nubar_p_CC_3Pi","NR_nubar_n_NC_1Pi","NR_nubar_n_NC_2Pi", - "NR_nubar_n_NC_3Pi","NR_nubar_p_NC_1Pi","NR_nubar_p_NC_2Pi","NR_nubar_p_NC_3Pi", - "BeRPA_A","BeRPA_B","BeRPA_D","BeRPA_E", - "C12ToAr40_2p2hScaling_nu","C12ToAr40_2p2hScaling_nubar", - "nuenuebar_xsec_ratio","nuenumu_xsec_ratio","SPPLowQ2Suppression" - }; - } - - std::pair GetGenieDialLimits(const std::string& name){ - - static std::map> genieMap = { - // Regular dials - {"MaCCQE",{-3,3}}, - {"MaNCEL",{-3,3}}, - {"EtaNCEL",{-3,3}}, - {"MaCCRES",{-3,3}}, - {"MvCCRES",{-3,3}}, - {"MaNCRES",{-3,3}}, - {"MvNCRES",{-3,3}}, - {"RDecBR1gamma",{-3,3}}, - {"RDecBR1eta",{-3,3}}, - {"AhtBY",{-3,3}}, - {"BhtBY",{-3,3}}, - {"CV1uBY",{-3,3}}, - {"CV2uBY",{-3,3}}, - {"BeRPA_A",{-3,3}}, - {"BeRPA_B",{-3,3}}, - {"BeRPA_D",{-3,3}}, - {"BeRPA_E",{-3,3}}, - - // NRpi dials - {"NR_nu_n_CC_2Pi",{-2,3}}, - {"NR_nu_n_CC_3Pi",{-2,3}}, - {"NR_nu_p_CC_2Pi",{-2,3}}, - {"NR_nu_p_CC_3Pi",{-2,3}}, - {"NR_nu_np_CC_1Pi",{-2,3}}, - {"NR_nu_n_NC_1Pi",{-2,3}}, - {"NR_nu_n_NC_2Pi",{-2,3}}, - {"NR_nu_n_NC_3Pi",{-2,3}}, - {"NR_nu_p_NC_1Pi",{-2,3}}, - {"NR_nu_p_NC_2Pi",{-2,3}}, - {"NR_nu_p_NC_3Pi",{-2,3}}, - {"NR_nubar_n_CC_1Pi",{-2,3}}, - {"NR_nubar_n_CC_2Pi",{-2,3}}, - {"NR_nubar_n_CC_3Pi",{-2,3}}, - {"NR_nubar_p_CC_1Pi",{-2,3}}, - {"NR_nubar_p_CC_2Pi",{-2,3}}, - {"NR_nubar_p_CC_3Pi",{-2,3}}, - {"NR_nubar_n_NC_1Pi",{-2,3}}, - {"NR_nubar_n_NC_2Pi",{-2,3}}, - {"NR_nubar_n_NC_3Pi",{-2,3}}, - {"NR_nubar_p_NC_1Pi",{-2,3}}, - {"NR_nubar_p_NC_2Pi",{-2,3}}, - {"NR_nubar_p_NC_3Pi",{-2,3}}, - - // FSI - {"FormZone",{-2,2}}, - {"MFP_pi",{-2,2}}, - {"FrCEx_pi",{-2,2}}, - {"FrElas_pi",{-2,2}}, - {"FrInel_pi",{-2,2}}, - {"FrAbs_pi",{-2,2}}, - {"FrPiProd_pi",{-2,2}}, - {"MFP_N",{-2,2}}, - {"FrCEx_N",{-2,2}}, - {"FrElas_N",{-2,2}}, - {"FrInel_N",{-2,2}}, - {"FrAbs_N",{-2,2}}, - {"FrPiProd_N",{-2,2}}, - - // On/Off dials - {"VecFFCCQEshape",{-1,1}}, - {"Theta_Delta2Npi",{-1,1}}, - {"CCQEPauliSupViaKF",{-1,1}}, - {"Mnv2p2hGaussEnhancement",{-1,1}}, - {"MKSPP_ReWeight",{-1,1}}, - {"E2p2h_A_nu",{-1,1}}, - {"E2p2h_B_nu",{-1,1}}, - {"E2p2h_A_nubar",{-1,1}}, - {"E2p2h_B_nubar",{-1,1}}, - {"C12ToAr40_2p2hScaling_nu",{-1,1}}, - {"C12ToAr40_2p2hScaling_nubar",{-1,1}}, - {"nuenuebar_xsec_ratio",{-1,1}}, - {"nuenumu_xsec_ratio",{-1,1}}, - {"SPPLowQ2Suppression",{-1,1}} - }; - - if (genieMap.find(name) == genieMap.end()){ - std::cout << "Warning, no known systematic called " << name << " returning nominal" << std::endl; - return {-3,3}; - } - return genieMap[name]; - } - - - //---------------------------------------------------------------------- - int GetGenieIndex(const std::string& name, bool quiet) - { - const std::vector names = GetGenieWeightNames(); - - auto it = std::find(names.begin(), names.end(), name); - - if(it == names.end()){ - if(!quiet){ - std::cerr << "Warning: couldn't find " << name - << " in list of genie systs" << std::endl; - } - return -1; - } - - return it-names.begin(); - } - - std::string GetGenieWeightName(int index){ - const std::vector names = GetGenieWeightNames(); - return names[index]; - } - - double GetGenieMin(int index){ - static const std::vector names = GetGenieWeightNames(); - return GetGenieDialLimits(names[index]).first; - } - - double GetGenieMax(int index){ - static const std::vector names = GetGenieWeightNames(); - return GetGenieDialLimits(names[index]).second; - } - -} diff --git a/sbnana/CAFAna/Core/GenieWeightList.h b/sbnana/CAFAna/Core/GenieWeightList.h deleted file mode 100644 index 091d9cab..00000000 --- a/sbnana/CAFAna/Core/GenieWeightList.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include -#include -#include - -namespace ana -{ - std::vector GetGenieWeightNames(); - - // -1 if not found, and an error printout unless quiet=true - int GetGenieIndex(const std::string& name, bool quiet = false); - - std::string GetGenieWeightName(int index); - - double GetGenieMin(int index); - - double GetGenieMax(int index); - - std::pair GetGenieDialLimits(const std::string& name); - -} diff --git a/sbnana/CAFAna/Core/HistAxis.cxx b/sbnana/CAFAna/Core/HistAxis.cxx deleted file mode 100644 index f9229ba0..00000000 --- a/sbnana/CAFAna/Core/HistAxis.cxx +++ /dev/null @@ -1,88 +0,0 @@ -#include "sbnana/CAFAna/Core/HistAxis.h" - -#include - -namespace ana -{ - //---------------------------------------------------------------------- - template _HistAxis:: - _HistAxis(const std::string& label, - const Binning& bins, - const T& var) - : fLabels(1, label), - fBins(1, bins), - fVars(1, var) - { - } - - //---------------------------------------------------------------------- - template _HistAxis:: - _HistAxis(const std::vector& labels, - const std::vector& bins, - const std::vector& vars) - : fLabels(labels), fBins(bins), fVars(vars) - { - assert(fLabels.size() == fBins.size()); - assert(fBins.size() == fVars.size()); - } - - //---------------------------------------------------------------------- - template _HistAxis:: - _HistAxis(const std::string& labelX, - const Binning& binsX, - const T& varX, - const std::string& labelY, - const Binning& binsY, - const T& varY) - : fLabels({labelX, labelY}), - fBins({binsX, binsY}), - fVars({varX, varY}) - { - } - - //---------------------------------------------------------------------- - template _HistAxis:: - _HistAxis(const std::string& label, - int nx, double x0, double x1, - const T& var) - : _HistAxis(label, Binning::Simple(nx, x0, x1), var) - { - } - - //---------------------------------------------------------------------- - template _HistAxis:: - _HistAxis(const std::string& labelX, - int nx, double x0, double x1, - const T& varX, - const std::string& labelY, - int ny, double y0, double y1, - const T& varY) - : _HistAxis(labelX, Binning::Simple(nx, x0, x1), varX, - labelY, Binning::Simple(ny, y0, y1), varY) - { - } - - //---------------------------------------------------------------------- - template T _HistAxis::GetMultiDVar() const - { - switch(fVars.size()){ - case 1: - return fVars[0]; - case 2: - return Var2D(fVars[0], fBins[0], - fVars[1], fBins[1]); - case 3: - return Var3D(fVars[0], fBins[0], - fVars[1], fBins[1], - fVars[2], fBins[2]); - default: - std::cout << "Error: HistAxis::GetMultiDVar() doesn't support " - << fVars.size() << "-dimensional axes" << std::endl; - abort(); - } - } - - // explicitly instantiate the template for the types we know we have - template class _HistAxis; - template class _HistAxis; -} diff --git a/sbnana/CAFAna/Core/HistAxis.h b/sbnana/CAFAna/Core/HistAxis.h index 813ddbaf..d7469c30 100644 --- a/sbnana/CAFAna/Core/HistAxis.h +++ b/sbnana/CAFAna/Core/HistAxis.h @@ -1,64 +1,16 @@ #pragma once -#include "sbnana/CAFAna/Core/Binning.h" -#include "sbnana/CAFAna/Core/Var.h" +#include "cafanacore/HistAxis.h" -#include +#include "sbnana/CAFAna/Core/Var.h" // TODO do we want our own FwdDeclare.h? namespace ana { - /// \brief Collect information describing the x-axis of an analysis histogram - /// - /// That is, what it should be labelled, what the binning should be, and what - /// variable will be being filled into it. - template class _HistAxis - { - public: - _HistAxis(const std::string& label, - const Binning& bins, - const T& var); - - _HistAxis(const std::vector& labels, - const std::vector& bins, - const std::vector& vars); - - _HistAxis(const std::string& labelX, - const Binning& binsX, - const T& varX, - const std::string& labelY, - const Binning& binsY, - const T& varY); - - /// Shortcut for simple binnings - _HistAxis(const std::string& label, - int nx, double x0, double x1, - const T& var); - - /// Shortcut for simple binnings - _HistAxis(const std::string& labelX, - int nx, double x0, double x1, - const T& varX, - const std::string& labelY, - int ny, double y0, double y1, - const T& varY); - - - unsigned int NDimensions() const{return fLabels.size();} - - std::vector GetLabels() const {return fLabels;} - std::vector GetBinnings() const {return fBins;} - std::vector GetVars() const {return fVars;} - - /// A variable "flattening" all the dimensions into one 1D value. Use - /// sparingly. - T GetMultiDVar() const; - - protected: - std::vector fLabels; - std::vector fBins; - std::vector fVars; - }; - typedef _HistAxis HistAxis; typedef _HistAxis SpillHistAxis; + + typedef _HistAxis NuTruthHistAxis; + typedef _HistAxis TrackHistAxis; + typedef _HistAxis ShowerHistAxis; + typedef _HistAxis StubHistAxis; } diff --git a/sbnana/CAFAna/Core/HistCache.cxx b/sbnana/CAFAna/Core/HistCache.cxx deleted file mode 100644 index 1b6830d0..00000000 --- a/sbnana/CAFAna/Core/HistCache.cxx +++ /dev/null @@ -1,166 +0,0 @@ -#include "sbnana/CAFAna/Core/HistCache.h" - -#include "sbnana/CAFAna/Core/Utilities.h" - -#include "TH2.h" - -#include - -namespace ana -{ - std::multimap> HistCache::fgMap; - std::multimap, std::unique_ptr> HistCache::fgMap2D; - - int HistCache::fgOut = 0; - int HistCache::fgIn = 0; - - long HistCache::fgEstMemUsage = 0; - long HistCache::fgMemHandedOut = 0; - - //--------------------------------------------------------------------- - TH1D* HistCache::New(const std::string& title, const Binning& bins) - { - ++fgOut; - fgMemHandedOut += 16*bins.NBins(); - - // Look in the cache - auto it = fgMap.find(bins.ID()); - if(it != fgMap.end()){ - TH1D* ret = it->second.release(); - fgMap.erase(it); - ret->Reset(); - ret->SetTitle(title.c_str()); - - fgEstMemUsage -= 16*bins.NBins(); - - return ret; - } - - // If not, create a new one directly - return MakeTH1D(UniqueName().c_str(), title.c_str(), bins); - } - - //--------------------------------------------------------------------- - TH1D* HistCache::New(const std::string& title, const TAxis* bins) - { - return New(title, Binning::FromTAxis(bins)); - } - - //--------------------------------------------------------------------- - TH2D* HistCache::NewTH2D(const std::string& title, const Binning& xbins, const Binning& ybins) - { - ++fgOut; - fgMemHandedOut += 16*xbins.NBins()*ybins.NBins(); - - std::pair IDs (xbins.ID(), ybins.ID()); - auto it = fgMap2D.find(IDs); - if(it != fgMap2D.end()){ - TH2D* ret = it->second.release(); - fgMap2D.erase(it); - ret->Reset(); - ret->SetTitle(title.c_str()); - fgEstMemUsage -= 16*xbins.NBins()*ybins.NBins(); - return ret; - } - - return MakeTH2D(UniqueName().c_str(), title.c_str(), xbins, ybins); - } - - //--------------------------------------------------------------------- - TH2D* HistCache::NewTH2D(const std::string& title, const TAxis* xbins, const TAxis* ybins) - { - return NewTH2D(title, Binning::FromTAxis(xbins), Binning::FromTAxis(ybins)); - } - - //--------------------------------------------------------------------- - TH1D* HistCache::Copy(const TH1D* h) - { - TH1D* ret = New(h->GetTitle(), h->GetXaxis()); - *ret = *h; - return ret; - } - - //--------------------------------------------------------------------- - TH2D* HistCache::Copy(const TH2D* h) - { - TH2D* ret = NewTH2D(h->GetTitle(), h->GetXaxis(), h->GetYaxis()); - *ret = *h; - return ret; - } - - //--------------------------------------------------------------------- - void HistCache::Delete(TH1D*& h) - { - if(!h) return; - - ++fgIn; - fgMemHandedOut -= 16*h->GetNbinsX(); - - fgMap.emplace(Binning::FromTAxis(h->GetXaxis()).ID(), - std::unique_ptr(h)); - - fgEstMemUsage += 16*h->GetNbinsX(); - CheckMemoryUse(); - - h = 0; - } - - //--------------------------------------------------------------------- - void HistCache::Delete(TH2D*& h) - { - if(!h) return; - - ++fgIn; - fgMemHandedOut -= 16*h->GetNbinsX()*h->GetNbinsY(); - - fgMap2D.emplace(std::pair(Binning::FromTAxis(h->GetXaxis()).ID(), Binning::FromTAxis(h->GetYaxis()).ID()), - std::unique_ptr(h)); - - fgEstMemUsage += 16*h->GetNbinsX()*h->GetNbinsY(); - CheckMemoryUse(); - - h = 0; - } - - //--------------------------------------------------------------------- - void HistCache::CheckMemoryUse() - { - if(fgEstMemUsage > 500l*1024*1024){ - std::cerr << "Warning! HistCache memory usage exceeds 500MB. " - << "That probably means histograms are being returned " - << "to the cache that weren't originally handed out by it. " - << std::endl; - PrintStats(); - std::cerr << "Now clearing cache. This could take a long time..." - << std::endl; - ClearCache(); - std::cerr << "Done clearing cache" << std::endl; - } - } - - //--------------------------------------------------------------------- - void HistCache::ClearCache() - { - fgMap.clear(); - fgMap2D.clear(); - fgEstMemUsage = 0; - fgOut = 0; - fgIn = 0; - } - - //--------------------------------------------------------------------- - void HistCache::PrintStats() - { - // Count number of unique keys - std::set keys; - for(auto& it: fgMap) keys.insert(it.first); - - std::cout << "Gave out " << fgOut << " histograms, got back " - << fgIn << " of them (" << fgOut-fgIn << " still out, totalling " - << fgMemHandedOut << " bytes), in " - << keys.size() << " different shapes." << std::endl - << "Holding " << fgMap.size()+fgMap2D.size() - << " histograms for an estimated memory usage of " - << fgEstMemUsage << " bytes." << std::endl; - } -} diff --git a/sbnana/CAFAna/Core/HistCache.h b/sbnana/CAFAna/Core/HistCache.h deleted file mode 100644 index e2bf6cb5..00000000 --- a/sbnana/CAFAna/Core/HistCache.h +++ /dev/null @@ -1,51 +0,0 @@ -#pragma once - -#include -#include -#include - -#include "sbnana/CAFAna/Core/Binning.h" - -class TAxis; -class TH1D; -class TH2D; - -namespace ana -{ - /// \brief Helper for \ref Spectrum - /// - /// ROOT's handling of allocations, and especially deletions, can be very - /// slow. It keeps everything in a big map that it then has to lookups - /// in. This class provides a simple cache of histograms, recycling an old - /// histogram of the same binning instead of creating a new one. - /// - /// Allocate new histograms with \ref New, and return them to the cache with - /// \ref Delete. - class HistCache - { - public: - static TH1D* New(const std::string& title, const Binning& bins); - static TH1D* New(const std::string& title, const TAxis* bins); - static TH1D* Copy(const TH1D* h); - - static TH2D* NewTH2D(const std::string& title, const Binning& xbins, const Binning& ybins); - static TH2D* NewTH2D(const std::string& title, const TAxis* xbins, const TAxis* ybins); - static TH2D* Copy(const TH2D* h); - - static void Delete(TH1D*& h); - static void Delete(TH2D*& h); - static void PrintStats(); - static void ClearCache(); - protected: - static void CheckMemoryUse(); - - // Key to the maps is Binning::ID() - static std::multimap> fgMap; - static std::multimap, std::unique_ptr> fgMap2D; - - static int fgOut, fgIn; - - static long fgEstMemUsage; - static long fgMemHandedOut; - }; -} diff --git a/sbnana/CAFAna/Core/IFileSource.h b/sbnana/CAFAna/Core/IFileSource.h deleted file mode 100644 index 48235bc0..00000000 --- a/sbnana/CAFAna/Core/IFileSource.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -class TFile; - -namespace ana -{ - /// \brief Interface class for accessing ROOT files in sequence - /// - /// Used internally by \ref SpectrumLoaderBase etc. - class IFileSource - { - public: - virtual ~IFileSource() {} - /// \brief Returns the next file in sequence, ready for reading - /// - /// A null return means that the end of the sequence has been reached. - /// DO NOT close or delete the file that is returned. - virtual TFile* GetNextFile() = 0; - - /// May return -1 indicating the number of files is not known - virtual int NFiles() const {return -1;} - }; -} diff --git a/sbnana/CAFAna/Core/IFitVar.cxx b/sbnana/CAFAna/Core/IFitVar.cxx index 5b9fd465..8fb1c212 100644 --- a/sbnana/CAFAna/Core/IFitVar.cxx +++ b/sbnana/CAFAna/Core/IFitVar.cxx @@ -6,6 +6,19 @@ namespace ana { + //---------------------------------------------------------------------- + IFitVar::IFitVar(const std::string& shortName, const std::string& latexName) + : INamed(shortName, latexName) + { + } + + //---------------------------------------------------------------------- + IConstrainedFitVar::IConstrainedFitVar(const std::string& shortName, + const std::string& latexName) + : IFitVar(shortName, latexName) + { + } + //---------------------------------------------------------------------- double IConstrainedFitVar::Penalty(double val, osc::IOscCalcAdjustable*) const diff --git a/sbnana/CAFAna/Core/IFitVar.h b/sbnana/CAFAna/Core/IFitVar.h index 6dbddc39..78916723 100644 --- a/sbnana/CAFAna/Core/IFitVar.h +++ b/sbnana/CAFAna/Core/IFitVar.h @@ -1,6 +1,6 @@ #pragma once -#include +#include "cafanacore/INamed.h" namespace osc { @@ -11,13 +11,13 @@ namespace osc namespace ana { /// Interface definition for fittable variables - class IFitVar + class IFitVar: public INamed { public: + IFitVar(const std::string& shortName, const std::string& latexName); + virtual double GetValue(const osc::IOscCalcAdjustable* osc) const = 0; virtual void SetValue(osc::IOscCalcAdjustable* osc, double val) const = 0; - virtual std::string ShortName() const = 0; - virtual std::string LatexName() const = 0; virtual double Penalty(double /*val*/, osc::IOscCalcAdjustable*) const {return 0;} }; @@ -28,6 +28,7 @@ namespace ana class IConstrainedFitVar: public IFitVar { public: + IConstrainedFitVar(const std::string& shortName, const std::string& latexName); virtual double Penalty(double val, osc::IOscCalcAdjustable*) const; virtual double LowLimit() const = 0; virtual double HighLimit() const = 0; diff --git a/sbnana/CAFAna/Core/IRecordSink.h b/sbnana/CAFAna/Core/IRecordSink.h new file mode 100644 index 00000000..7d0cf11f --- /dev/null +++ b/sbnana/CAFAna/Core/IRecordSink.h @@ -0,0 +1,14 @@ +#pragma once + +#include "cafanacore/IRecordSink.h" + +#include "sbnanaobj/StandardRecord/Proxy/FwdDeclare.h" + +namespace ana +{ + using ISpillSink = _IRecordSink; + using ISliceSink = _IRecordSink; + + using ISpillEnsembleSink = _IRecordEnsembleSink; + using ISliceEnsembleSink = _IRecordEnsembleSink; +} diff --git a/sbnana/CAFAna/Core/IRecordSource.cxx b/sbnana/CAFAna/Core/IRecordSource.cxx new file mode 100644 index 00000000..b31ba013 --- /dev/null +++ b/sbnana/CAFAna/Core/IRecordSource.cxx @@ -0,0 +1,208 @@ +#include "sbnana/CAFAna/Core/IRecordSource.h" + +#include "sbnana/CAFAna/Core/Multiverse.h" + +#include "sbnana/CAFAna/Core/SystShifts.h" + +#include "sbnanaobj/StandardRecord/Proxy/SRProxy.h" + +namespace ana +{ + //---------------------------------------------------------------------- + class ShiftedSliceEnsembleSource: + public PassthroughExposure + { + public: + ShiftedSliceEnsembleSource(ISliceSource& src, + const Multiverse& multiverse); + + virtual void HandleRecord(const caf::SRSliceProxy* slc, double weight) override; + + virtual const ana::FitMultiverse* GetMultiverse() const override {return fMultiverse;} + + protected: + const Multiverse* fMultiverse; + std::vector fShifts; + }; + + //---------------------------------------------------------------------- + ShiftedSliceEnsembleSource:: + ShiftedSliceEnsembleSource(ISliceSource& src, const Multiverse& multiverse) + : fMultiverse(&multiverse) + { + src.Register(this); + + // Turn the universes into concrete SystShifts objects up-front + fShifts.reserve(multiverse.NUniv()); + for(unsigned int i = 0; i < multiverse.NUniv(); ++i) fShifts.emplace_back(multiverse.GetUniverse(i)); + } + + //---------------------------------------------------------------------- + void ShiftedSliceEnsembleSource::HandleRecord(const caf::SRSliceProxy* 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(); + } + + // Slice was shifted or we are already in the slow path, so we have to + // handle this individually + if((shifted || anyShifted) && weights[univIdx] != 0) + for(ISliceEnsembleSink* 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(ISliceEnsembleSink* 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(ISliceEnsembleSink* sink: fSinks){ + sink->HandleEnsemble(slc, weights); + } + } + } + + //---------------------------------------------------------------------- + ISliceEnsembleSource& ISliceSource:: + Ensemble(const Multiverse& multiverse) + { + return fEnsembleSources.template Get(&multiverse, *this, multiverse); + } + + //---------------------------------------------------------------------- + //---------------------------------------------------------------------- + + 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); + } + + //---------------------------------------------------------------------- + const caf::Proxy>& + GetSlices(const caf::SRSpillProxy* spill) + { + return spill->slc; + } + + const caf::Proxy>& + GetNuTruths(const caf::SRSpillProxy* spill) + { + return spill->mc.nu; + } + + const caf::Proxy>& + GetTracks(const caf::SRSliceProxy* slc) + { + return slc->reco.trk; + } + + const caf::Proxy>& + GetShowers(const caf::SRSliceProxy* slc) + { + return slc->reco.shw; + } + + const caf::Proxy>& + GetStubs(const caf::SRSliceProxy* slc) + { + return slc->reco.stub; + } + + //---------------------------------------------------------------------- + //---------------------------------------------------------------------- + + // Instantiations + template class VectorAdaptor; + template class VectorAdaptor; + + template class VectorAdaptor; + template class VectorAdaptor; + template class VectorAdaptor; + + template class EnsembleVectorAdaptor; + + template class EnsembleVectorAdaptor; + template class EnsembleVectorAdaptor; + template class EnsembleVectorAdaptor; +} diff --git a/sbnana/CAFAna/Core/IRecordSource.h b/sbnana/CAFAna/Core/IRecordSource.h new file mode 100644 index 00000000..2285845d --- /dev/null +++ b/sbnana/CAFAna/Core/IRecordSource.h @@ -0,0 +1,168 @@ +#pragma once + +#include "cafanacore/IRecordSource.h" + +#include "sbnana/CAFAna/Core/IRecordSink.h" + +#include "sbnanaobj/StandardRecord/Proxy/FwdDeclare.h" + +namespace ana +{ + class ISyst; + template class _Multiverse; + using Multiverse = _Multiverse; + + class SystShifts; + + //---------------------------------------------------------------------- + // Introduce some aliases so we can express ourselves more succinctly + + using ISpillSource = _IRecordSource; + using ISliceSource = _IRecordSource; + using INuTruthSource = _IRecordSource; + + using ISpillEnsembleSource = _IRecordEnsembleSource; + using ISliceEnsembleSource = _IRecordEnsembleSource; + using INuTruthEnsembleSource = _IRecordEnsembleSource; + + //---------------------------------------------------------------------- + + using ITrackSource = _IRecordSource; + using IShowerSource = _IRecordSource; + using IStubSource = _IRecordSource; + + //---------------------------------------------------------------------- + + using ITrackEnsembleSource = _IRecordEnsembleSource; + using IShowerEnsembleSource = _IRecordEnsembleSource; + using IStubEnsembleSource = _IRecordEnsembleSource; + + //---------------------------------------------------------------------- + + /// 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 + + const caf::Proxy>& GetSlices(const caf::SRSpillProxy* spill); + + const caf::Proxy>& GetNuTruths(const caf::SRSpillProxy* spill); + + const caf::Proxy>& GetTracks(const caf::SRSliceProxy* reco); + + const caf::Proxy>& GetShowers(const caf::SRSliceProxy* reco); + + const caf::Proxy>& GetStubs(const caf::SRSliceProxy* reco); + + //---------------------------------------------------------------------- + + template<> class _IRecordSource + : public _IRecordSourceDefaultImpl + { + public: + // Weight-based ensembles are still supported + using _IRecordSourceDefaultImpl::Ensemble; + + // But also support an ensemble based on SystShifts + ISliceEnsembleSource& Ensemble(const Multiverse& multiverse); + + ITrackSource& Tracks() {return fTracks;} + IShowerSource& Showers() {return fShowers;} + IStubSource& Stubs() {return fStubs;} + + protected: + IDDict fEnsembleSources; + + VectorAdaptor fTracks{*this, GetTracks}; + VectorAdaptor fShowers{*this, GetShowers}; + VectorAdaptor fStubs{*this, GetStubs}; + }; + + //---------------------------------------------------------------------- + + // Spill sources also provide a slice source (which loops over the slices) + template<> class _IRecordSource + : public _IRecordSourceDefaultImpl + { + public: + ISliceSource& Slices() {return fSlices;} + INuTruthSource& NuTruths() {return fNuTruths;} + + protected: + VectorAdaptor fSlices{*this, GetSlices}; + VectorAdaptor fNuTruths{*this, GetNuTruths}; + }; + //---------------------------------------------------------------------- + + + /// Helper class for implementing looping over slices, tracks, 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 track / shower / stub sources from the reco branch + // ensemble source. + + template<> class _IRecordEnsembleSource + : public _IRecordEnsembleSourceDefaultImpl + { + public: + ITrackEnsembleSource& Tracks() {return fTracks;} + IShowerEnsembleSource& Showers() {return fShowers;} + IStubEnsembleSource& Stubs() {return fStubs;} + + protected: + EnsembleVectorAdaptor fTracks{*this, GetTracks}; + EnsembleVectorAdaptor fShowers{*this, GetShowers}; + EnsembleVectorAdaptor fStubs{*this, GetStubs}; + }; + + //---------------------------------------------------------------------- + // Spill sources also provide a slice source (which loops over the slices) + template<> class _IRecordEnsembleSource + : public _IRecordEnsembleSourceDefaultImpl + { + public: + ISliceEnsembleSource& Slices() {return fSlices;} + INuTruthEnsembleSource& NuTruths() {return fNuTruths;} + + protected: + EnsembleVectorAdaptor fSlices{*this, GetSlices}; + EnsembleVectorAdaptor fNuTruths{*this, GetNuTruths}; + }; +} diff --git a/sbnana/CAFAna/Core/ISyst.cxx b/sbnana/CAFAna/Core/ISyst.cxx index bd4d24f8..289adb16 100644 --- a/sbnana/CAFAna/Core/ISyst.cxx +++ b/sbnana/CAFAna/Core/ISyst.cxx @@ -1,6 +1,6 @@ #include "sbnana/CAFAna/Core/ISyst.h" -#include "sbnana/CAFAna/Core/SystRegistry.h" +#include "cafanacore/Registry.h" #include "sbnana/CAFAna/Core/MathUtil.h" namespace ana @@ -11,9 +11,9 @@ namespace ana bool applyPenalty, double min, double max) - : fShortName(shortName), fLatexName(latexName), fApplyPenalty(applyPenalty), fMin(min), fMax(max) + : _ISyst(shortName, latexName), fApplyPenalty(applyPenalty), fMin(min), fMax(max) { - SystRegistry::Register(this); + Registry::Register(this); } //---------------------------------------------------------------------- @@ -21,7 +21,7 @@ namespace ana { // 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 SystRegistry. - SystRegistry::UnRegister(this); + Registry::UnRegister(this); } //---------------------------------------------------------------------- diff --git a/sbnana/CAFAna/Core/ISyst.h b/sbnana/CAFAna/Core/ISyst.h index c95941d2..c35970d7 100644 --- a/sbnana/CAFAna/Core/ISyst.h +++ b/sbnana/CAFAna/Core/ISyst.h @@ -1,5 +1,7 @@ #pragma once +#include "cafanacore/ISyst.h" + #include #include "sbnanaobj/StandardRecord/Proxy/FwdDeclare.h" @@ -11,7 +13,7 @@ namespace ana /// /// The Shift() function alters the \ref caf::StandardRecord or the weight /// associated with the event. - class ISyst + class ISyst: public _ISyst { public: ISyst(const std::string& shortName, @@ -19,19 +21,8 @@ namespace ana bool applyPenalty = true, double min = -3, double max = +3); - 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. - - /// The name printed out to the screen - virtual std::string ShortName() const final {return fShortName;} - - /// The name used on plots (ROOT's TLatex syntax) - virtual std::string LatexName() const final {return fLatexName;} - virtual double Penalty(double x) const; /// Should a penalty be applied for this shift? @@ -41,15 +32,6 @@ namespace ana virtual double Min() const{return fMin;} virtual double Max() const{return fMax;} - /// \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::SRSliceProxy* sr, - double& weight) const = 0; - /// PredictionInterp normally interpolates between spectra made at /// +/-1,2,3sigma. For some systematics that's overkill. Override this /// function to specify different behaviour for this systematic. @@ -59,8 +41,6 @@ namespace ana } private: - std::string fShortName; - std::string fLatexName; bool fApplyPenalty; double fMin; double fMax; diff --git a/sbnana/CAFAna/Core/LoadFromFile.cxx b/sbnana/CAFAna/Core/LoadFromFile.cxx index 658e7b74..9343d355 100644 --- a/sbnana/CAFAna/Core/LoadFromFile.cxx +++ b/sbnana/CAFAna/Core/LoadFromFile.cxx @@ -19,8 +19,11 @@ namespace ana { //---------------------------------------------------------------------- template<> std::unique_ptr - LoadFrom(TDirectory* dir) + LoadFrom(TDirectory* dir, const std::string& name) { + dir = dir->GetDirectory(name.c_str()); // switch to subdir + assert(dir); + TObjString* ptag = (TObjString*)dir->Get("type"); assert(ptag); const TString tag = ptag->GetString(); @@ -88,10 +91,11 @@ namespace ana } //---------------------------------------------------------------------- - template<> void SaveTo(const osc::IOscCalc& x, TDirectory* dir) + template<> void SaveTo(const osc::IOscCalc& x, TDirectory* dir, const std::string& name) { TDirectory* tmp = gDirectory; + dir = dir->mkdir(name.c_str()); // switch to subdir dir->cd(); if(dynamic_cast(&x)){ @@ -124,10 +128,10 @@ namespace ana std::cout << "Unknown calculator in SaveTo " << typeid(x).name() << std::endl; abort(); } - + const osc::OscCalcSterile* tmpSterile = dynamic_cast(&x); if(tmpSterile) { - TObjString("OscCalculatorSterile").Write("type"); + TObjString("OscCalculatorSterile").Write("type"); std::vector state = tmpSterile->GetState(); TVectorD params(state.size()); for (unsigned int i = 0; i < state.size(); ++i) params[i] = state[i]; @@ -139,7 +143,7 @@ namespace ana //for the implementation of OscCalcPMNS_NSI const osc::OscCalcPMNS_NSI* tmpNSI = dynamic_cast(&x); if(tmpNSI) { - TObjString("OscCalcPMNS_NSI").Write("type"); + TObjString("OscCalcPMNS_NSI").Write("type"); std::vector state = tmpNSI->GetState(); TVectorD params(state.size()); for (unsigned int i = 0; i < state.size(); ++i) params[i] = state[i]; @@ -156,7 +160,7 @@ namespace ana std::cout << "Unimplemented calculator in SaveTo " << typeid(x).name() << std::endl; abort(); } - + TVectorD params(8); params[0] = y->GetL(); @@ -170,6 +174,9 @@ namespace ana params.Write("params"); + dir->Write(); + delete dir; + tmp->cd(); } } diff --git a/sbnana/CAFAna/Core/LoadFromFile.h b/sbnana/CAFAna/Core/LoadFromFile.h index 47ec8be8..2811b5b4 100644 --- a/sbnana/CAFAna/Core/LoadFromFile.h +++ b/sbnana/CAFAna/Core/LoadFromFile.h @@ -19,9 +19,9 @@ namespace ana { //---------------------------------------------------------------------- // Most classes are happy to load themselves - template std::unique_ptr LoadFrom(TDirectory* dir) + template std::unique_ptr LoadFrom(TDirectory* dir, const std::string& name) { - return T::LoadFrom(dir); + return T::LoadFrom(dir, name); } //---------------------------------------------------------------------- @@ -29,33 +29,26 @@ 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); class IExtrap; - template<> std::unique_ptr LoadFrom(TDirectory* dir); + template<> std::unique_ptr LoadFrom(TDirectory* dir, const std::string& name); class IPrediction; - template<> std::unique_ptr LoadFrom(TDirectory* dir); + template<> std::unique_ptr LoadFrom(TDirectory* dir, const std::string& name); class IExperiment; - template<> std::unique_ptr LoadFrom(TDirectory* dir); - class ModularExtrapComponent; - template<> std::unique_ptr - LoadFrom(TDirectory* dir); - class IBkgdEstimator; - template<> std::unique_ptr LoadFrom(TDirectory* dir); + template<> std::unique_ptr LoadFrom(TDirectory* dir, const std::string& name); // This one is actually implemented in LoadFromFile.cxx to avoid polluting // OscLib with CAFAna conventions. - template<> std::unique_ptr LoadFrom(TDirectory* dir); + template<> std::unique_ptr LoadFrom(TDirectory* dir, const std::string& name); //---------------------------------------------------------------------- // For symmetry - template void SaveTo(const T& x, TDirectory* dir) + template void SaveTo(const T& x, TDirectory* dir, const std::string& name) { - x.SaveTo(dir); + x.SaveTo(dir, name); } // Also in the cxx, to avoid having to put this logic into OscLib - template<> void SaveTo(const osc::IOscCalc& x, TDirectory* dir); + template<> void SaveTo(const osc::IOscCalc& x, TDirectory* dir, const std::string& name); //---------------------------------------------------------------------- template std::unique_ptr LoadFromFile(const std::string& fname, @@ -68,7 +61,7 @@ namespace ana std::cerr << "Didn't find '" << label << "' in " << fname << std::endl; abort(); } - return LoadFrom(dir); + return LoadFrom(&fin, label); } //---------------------------------------------------------------------- @@ -77,6 +70,6 @@ namespace ana const std::string& label) { TFile fout(fname.c_str(), "RECREATE"); - x.SaveTo(fout.mkdir(label.c_str())); + x.SaveTo(&fout, label.c_str()); } } diff --git a/sbnana/CAFAna/Core/Loaders.cxx b/sbnana/CAFAna/Core/Loaders.cxx index 112950ff..fb9bb344 100644 --- a/sbnana/CAFAna/Core/Loaders.cxx +++ b/sbnana/CAFAna/Core/Loaders.cxx @@ -1,6 +1,5 @@ #include "sbnana/CAFAna/Core/Loaders.h" -#include "sbnana/CAFAna/Core/SpectrumLoader.h" #include "sbnana/CAFAna/Core/Utilities.h" #include @@ -9,119 +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, - DataMC datamc, - DataSource src, - SwappingConfig swap) + template void Sources::AddLoader(SrcT* src, + DataMC datamc, + SwappingConfig swap) { assert(datamc == kMC || swap == kNonSwap); - assert(src == kBeam || swap == kNonSwap); - const Key_t key(datamc, src, swap); + const Key_t key(datamc, swap); // Clear out the old one if necessary - DisableLoader(datamc, src, swap); + DisableLoader(datamc, swap); - fLoaderPaths[key] = path; + fSources[key] = src; } //---------------------------------------------------------------------- - void Loaders::SetLoaderFiles(const std::vector& files, - DataMC datamc, - DataSource src, - SwappingConfig swap) + template void Sources::DisableLoader(DataMC datamc, + SwappingConfig swap) { assert(datamc == kMC || swap == kNonSwap); - assert(src == kBeam || swap == kNonSwap); - const Key_t key(datamc, src, swap); - - // Clear out the old one if necessary - DisableLoader(datamc, src, swap); - - fLoaderFiles[key] = files; - } - - //---------------------------------------------------------------------- - void Loaders::AddLoader(SpectrumLoaderBase* file, - DataMC datamc, - DataSource src, - SwappingConfig swap) - { - assert(datamc == kMC || swap == kNonSwap); - assert(src == kBeam || swap == kNonSwap); - - const Key_t key(datamc, src, swap); - - // Clear out the old one if necessary - DisableLoader(datamc, src, swap); - - fLoaders[key] = file; - } - - //---------------------------------------------------------------------- - void Loaders::DisableLoader(DataMC datamc, - DataSource src, - SwappingConfig swap) - { - assert(datamc == kMC || swap == kNonSwap); - assert(src == kBeam || swap == kNonSwap); - - const Key_t key(datamc, src, 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(DataMC datamc, - DataSource src, - SwappingConfig swap) + template SrcT& Sources::GetLoader(DataMC datamc, + SwappingConfig swap) { assert(datamc == kMC || swap == kNonSwap); - assert(src == kBeam || swap == kNonSwap); - const Key_t key(datamc, src, 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, src); - 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, src); - 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; } diff --git a/sbnana/CAFAna/Core/Loaders.h b/sbnana/CAFAna/Core/Loaders.h index 0c88e869..e91ae9c1 100644 --- a/sbnana/CAFAna/Core/Loaders.h +++ b/sbnana/CAFAna/Core/Loaders.h @@ -1,6 +1,6 @@ #pragma once -#include "sbnana/CAFAna/Core/SpectrumLoaderBase.h" +#include "sbnana/CAFAna/Core/SpectrumLoader.h" #include @@ -8,56 +8,75 @@ 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, kIntrinsic}; - /// No loaders initialized. Use \ref SetLoaderPath to configure - Loaders(); - ~Loaders(); - - /// Configure loader via wildcard \a path - void SetLoaderPath(const std::string& path, - DataMC datamc, - DataSource src = kBeam, - SwappingConfig swap = kNonSwap); + Sources(); + ~Sources(); - /// Configure loader via explicit file list - void SetLoaderFiles(const std::vector& files, - DataMC datamc, - DataSource src = kBeam, - SwappingConfig swap = kNonSwap); - - void AddLoader(SpectrumLoaderBase*, - DataMC datamc, - DataSource src = kBeam, - SwappingConfig swap = kNonSwap); + void AddLoader(SrcT*, + DataMC datamc, + SwappingConfig swap = kNonSwap); void DisableLoader(DataMC datamc, - DataSource src = kBeam, SwappingConfig swap = kNonSwap); /// Retrieve a specific loader - SpectrumLoaderBase& GetLoader(DataMC datamc, - DataSource src = kBeam, - 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 SpillSources = Sources; + using SliceSources = Sources; + + class Loaders: public Sources + { + public: + operator SliceSources&() + { + SliceSources* ret = new SliceSources; + 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)).Slices(), + DataMC(dmc), SwappingConfig(swap)); + } + } + return *ret; + } - /// 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 diff --git a/sbnana/CAFAna/Core/MathUtil.h b/sbnana/CAFAna/Core/MathUtil.h index 69e8eb45..0775f9ec 100644 --- a/sbnana/CAFAna/Core/MathUtil.h +++ b/sbnana/CAFAna/Core/MathUtil.h @@ -28,9 +28,9 @@ namespace util{ /// More efficient exponentiation function than pow(x,n) for small n template inline T ipow(T x, unsigned int n) { - T ret = 1; + T ret = 1; if (n == 0) return ret; - for(unsigned int i = 1; i <= n; ++i) ret *= x; + for(unsigned int i = 1; i <= n; ++i) ret *= x; return ret; } diff --git a/sbnana/CAFAna/Core/MultiVar.cxx b/sbnana/CAFAna/Core/MultiVar.cxx deleted file mode 100644 index 80800418..00000000 --- a/sbnana/CAFAna/Core/MultiVar.cxx +++ /dev/null @@ -1,87 +0,0 @@ -#include "sbnana/CAFAna/Core/MultiVar.h" - -#include -#include -#include - -#include - -namespace ana -{ - /// std::function can wrap a real function, function object, or lambda - template _MultiVar::_MultiVar(const std::function& fun) - : fFunc(fun), fID(fgNextID--) - { - } - - //---------------------------------------------------------------------- - /// Helper for \ref MultiVar2D - template class MultiVar2DFunc - { - public: - MultiVar2DFunc(const _MultiVar& a, const Binning binsa, - const _MultiVar& b, const Binning binsb) - : fA(a), fBinsA(binsa), - fB(b), fBinsB(binsb) - { - } - - std::vector operator()(const T* sr) const - { - std::vector returnVec; - - const std::vector vaVec = fA(sr); - const std::vector vbVec = fB(sr); - - if(vaVec.size() != vbVec.size()) - { - std::cout << "MultiVars need to be same size, these two are size " - << vaVec.size() << " " << vbVec.size() << "respectively." << std::endl; - std::abort(); - } - - for(unsigned n = 0; n < vaVec.size(); ++n){ - const double va = vaVec.at(n); - const double vb = vbVec.at(n); - // Since there are no overflow/underflow bins, check the range - if(va < fBinsA.Min() || vb < fBinsB.Min()){ returnVec.push_back(-1); continue;} - if(va > fBinsA.Max() || vb > fBinsB.Max()){ returnVec.push_back(fBinsA.NBins() * fBinsB.NBins()); continue;} - - // FindBin uses root convention, first bin is bin 1, bin 0 is underflow - const int ia = fBinsA.FindBin(va) - 1; - const int ib = fBinsB.FindBin(vb) - 1; - - const int i = ia*fBinsB.NBins()+ib; - - returnVec.push_back(i+.5); - } - return returnVec; - } - protected: - const _MultiVar fA; - const Binning fBinsA; - const _MultiVar fB; - const Binning fBinsB; - }; - - //---------------------------------------------------------------------- - template _MultiVar - MultiVar2D(const _MultiVar& a, const Binning& binsa, - const _MultiVar& b, const Binning& binsb) - { - return _MultiVar(MultiVar2DFunc(a, binsa, b, binsb)); - } - - // explicitly instantiate the template for the types we know we have - template MultiVar MultiVar2D(const MultiVar&, const Binning&, const MultiVar&, const Binning&); - template SpillMultiVar MultiVar2D(const SpillMultiVar&, const Binning&, const SpillMultiVar&, const Binning&); - - // explicitly instantiate the templates for the types we know we have - template class _MultiVar; - template class _MultiVar; - - // Stupid hack to avoid colliding with the IDs of actual Vars. Just count - // down through negative numbers. - template int _MultiVar::fgNextID = -1; - -} diff --git a/sbnana/CAFAna/Core/MultiVar.h b/sbnana/CAFAna/Core/MultiVar.h index c9ebcf2b..dc3f14fc 100644 --- a/sbnana/CAFAna/Core/MultiVar.h +++ b/sbnana/CAFAna/Core/MultiVar.h @@ -1,9 +1,6 @@ #pragma once -#include -#include -#include -#include +#include "cafanacore/MultiVar.h" #include "sbnana/CAFAna/Core/Binning.h" @@ -11,45 +8,6 @@ namespace ana { - /// A Var that returns multiple results for each slice. eg the properties of - /// multiple prongs. All results will be filled into the Spectrum. - template class _MultiVar - { - public: - /// The type of the function part of a var - typedef std::vector (VarFunc_t)(const T* sr); - - /// std::function can wrap a real function, function object, or lambda - _MultiVar(const std::function& fun); - - /// Allows a variable to be called with double value = myVar(sr) syntax - std::vector operator()(const T* sr) const - { - return fFunc(sr); - } - - /// Vars with the same definition will have the same ID - int ID() const {return fID;} - - static int MaxID() {return fgNextID-1;} - protected: - _MultiVar(const std::function& fun, int id) - : fFunc(fun), fID(id) - { - } - - std::function fFunc; - - int fID; - /// The next ID that hasn't yet been assigned - static int fgNextID; - }; - typedef _MultiVar MultiVar; typedef _MultiVar SpillMultiVar; - - template _MultiVar - MultiVar2D(const _MultiVar& a, const Binning& binsa, - const _MultiVar& b, const Binning& binsb); - } // namespace diff --git a/sbnana/CAFAna/Core/Multiverse.cxx b/sbnana/CAFAna/Core/Multiverse.cxx new file mode 100644 index 00000000..20f93a8a --- /dev/null +++ b/sbnana/CAFAna/Core/Multiverse.cxx @@ -0,0 +1,305 @@ +#include "sbnana/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)); + 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(); + } + + //---------------------------------------------------------------------- + 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(); + } +} diff --git a/sbnana/CAFAna/Core/Multiverse.h b/sbnana/CAFAna/Core/Multiverse.h new file mode 100644 index 00000000..7574e73d --- /dev/null +++ b/sbnana/CAFAna/Core/Multiverse.h @@ -0,0 +1,81 @@ +#pragma once + +#include "sbnana/CAFAna/Core/FitMultiverse.h" + +#include "sbnana/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)); + } + + /// 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]); + } + + 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; +} diff --git a/sbnana/CAFAna/Core/OscCalcSterileApprox.cxx b/sbnana/CAFAna/Core/OscCalcSterileApprox.cxx index 5add2546..4cb4d5b8 100644 --- a/sbnana/CAFAna/Core/OscCalcSterileApprox.cxx +++ b/sbnana/CAFAna/Core/OscCalcSterileApprox.cxx @@ -231,4 +231,15 @@ namespace ana abort(); } + + //--------------------------------------------------------------------------- + OscCalcSterileApprox* DowncastToSterileApprox(osc::IOscCalcStan* calc, + bool allowFail) + { + if(allowFail) return 0; + + std::cout << "Stan calculator can not be an OscCalcSterileApprox" << std::endl; + abort(); + } + } diff --git a/sbnana/CAFAna/Core/OscCalcSterileApprox.h b/sbnana/CAFAna/Core/OscCalcSterileApprox.h index 34e3c2c8..3072d30b 100644 --- a/sbnana/CAFAna/Core/OscCalcSterileApprox.h +++ b/sbnana/CAFAna/Core/OscCalcSterileApprox.h @@ -2,6 +2,8 @@ #include "OscLib/IOscCalc.h" +#include "sbnana/CAFAna/Core/StanTypedefs.h" + namespace ana { class OscCalcSterileApprox: public osc::IOscCalc @@ -79,4 +81,7 @@ namespace ana const OscCalcSterileApprox* DowncastToSterileApprox(const osc::IOscCalc* calc, bool allowFail = false); OscCalcSterileApprox* DowncastToSterileApprox(osc::IOscCalc* calc, bool allowFail = false); + + // This is not possible, but need to provide it to satisfy other interface + OscCalcSterileApprox* DowncastToSterileApprox(osc::IOscCalcStan* calc, bool allowFail = false); } diff --git a/sbnana/CAFAna/Core/OscCurve.cxx b/sbnana/CAFAna/Core/OscCurve.cxx index 217b8ca2..b0a55e9a 100644 --- a/sbnana/CAFAna/Core/OscCurve.cxx +++ b/sbnana/CAFAna/Core/OscCurve.cxx @@ -1,12 +1,9 @@ #include "sbnana/CAFAna/Core/OscCurve.h" #include "sbnana/CAFAna/Core/Binning.h" -#include "sbnana/CAFAna/Core/HistCache.h" -#include "sbnana/CAFAna/Core/Utilities.h" #include "OscLib/IOscCalc.h" -#include #include #include @@ -16,113 +13,69 @@ namespace { - inline bool IsNoOscillations(const osc::IOscCalc* c) + template inline bool IsNoOscillations(const osc::_IOscCalc* c) { - return dynamic_cast(c) != 0; + return dynamic_cast*>(c) != 0; } } namespace ana { - //---------------------------------------------------------------------- - OscCurve::OscCurve(osc::IOscCalc* calc, int from, int to, bool LoverE) - : fFrom(from), fTo(to) + /// Helper for constructors + template Eigen::Array + ToEigen(osc::_IOscCalc* calc, int from, int to) { DontAddDirectory guard; + const unsigned int N = kTrueLOverEBins.NBins(); - fHist = LoverE ? HistCache::New("True L / E (km / GeV);Probability", kTrueLOverEBins) : HistCache::New(";True Energy (GeV);Probability", kTrueEnergyBins); + // Have to allow for underflow and overflow + Eigen::Array ret(N+2); + ret[0] = (from == to || to == 0) ? 1 : 0; // underflow + ret[N+1] = 0; // overflow // We have extra knowledge that calculators of this type have special // modes allowing calculation in L/E and an intrinsic energy smearing. OscCalcSterileApprox* approx = DowncastToSterileApprox(calc, true); if(approx){ - for(int i = 0; i < fHist->GetNbinsX()+2; ++i){ - if(LoverE){ - const double LElo = fHist->GetXaxis()->GetBinLowEdge(i); - const double LEhi = fHist->GetXaxis()->GetBinUpEdge(i); - fHist->SetBinContent(i, approx->P_LoverE(from, to, LElo, LEhi)); - } - else{ - const double E = fHist->GetBinCenter(i); - const double Elo = fHist->GetXaxis()->GetBinLowEdge(i); - const double Ehi = fHist->GetXaxis()->GetBinUpEdge(i); - // Use 2% resolution (intended to be << the resolution of any actual - // event) or the bin width, whichever is larger - fHist->SetBinContent(i, approx->P_range(from, to, - std::min(Elo, 0.98*E), - std::max(Ehi, 1.02*E))); - } - fHist->SetBinError(i, 0); + for(unsigned int i = 1; i <= N; ++i){ + const double LElo = kTrueLOverEBins.Edges()[i-1]; + const double LEhi = kTrueLOverEBins.Edges()[i]; + ret[i] = approx->P_LoverE(from, to, LElo, LEhi); } } else{ - if(LoverE && !IsNoOscillations(calc)){ + if(!IsNoOscillations(calc)){ std::cout << "Trying to use a calculator which is not OscCalcSterileApprox with an L/E axis. Will have to code up additional hacks for this to work" << std::endl; abort(); } - - for(int i = 0; i < fHist->GetNbinsX()+2; ++i){ - const double E = fHist->GetBinCenter(i); - fHist->SetBinContent(i, E > 0 ? calc->P(from, to, E) : 0); - fHist->SetBinError(i, 0); - } - } - } - - //---------------------------------------------------------------------- - OscCurve::OscCurve(TH1* h) - { - DontAddDirectory guard; - - const TString className = h->ClassName(); - - if(className == "TH1D"){ - // Shortcut if types match - fHist = HistCache::Copy((TH1D*)h); - } - else{ - fHist = HistCache::New("", h->GetXaxis()); - fHist->Add(h); + for(unsigned int i = 1; i <= N; ++i) ret[i] = calc->P(from, to, 1); // energy irrelevant for NoOsc calc } - fHist->SetTitle(";True Energy (GeV);Probability"); + return ret; } //---------------------------------------------------------------------- - OscCurve::~OscCurve() + OscCurve::OscCurve(osc::IOscCalc* calc, int from, int to) + : Ratio(Hist::Adopt(ToEigen(calc, from, to)), + std::vector(1, kTrueLOverEBins), + std::vector(1, "True L / E (km / GeV)")), + fFrom(from), fTo(to) { - if(fHist && fHist->GetDirectory()){ - static bool once = true; - if(once){ - once = false; - std::cerr << "OscCurve's fHist is associated with a directory. How did that happen?" << std::endl; - } - } - - HistCache::Delete(fHist); } //---------------------------------------------------------------------- - OscCurve::OscCurve(const OscCurve& rhs) + OscCurve::OscCurve(osc::IOscCalcStan* calc, int from, int to) + : Ratio(Hist::AdoptStan(ToEigen(calc, from, to)), + std::vector(1, kTrueLOverEBins), + std::vector(1, "True L / E (km / GeV)")), + fFrom(from), fTo(to) { - DontAddDirectory guard; - - assert(rhs.fHist); - fHist = HistCache::Copy(rhs.fHist); } //---------------------------------------------------------------------- - OscCurve& OscCurve::operator=(const OscCurve& rhs) + OscCurve::~OscCurve() { - if(&rhs == this) return *this; - - DontAddDirectory guard; - - HistCache::Delete(fHist); - assert(rhs.fHist); - fHist = HistCache::Copy(rhs.fHist); - return *this; } //---------------------------------------------------------------------- @@ -131,7 +84,8 @@ namespace ana // Could have a file temporarily open DontAddDirectory guard; - TH1D* ret = HistCache::Copy(fHist); + TH1D* ret = Ratio::ToTH1(); + ret->GetYaxis()->SetTitle("Probability"); if(title){ // Don't do this work unless it's explicitly requested diff --git a/sbnana/CAFAna/Core/OscCurve.h b/sbnana/CAFAna/Core/OscCurve.h index 2af88c37..a9c76411 100644 --- a/sbnana/CAFAna/Core/OscCurve.h +++ b/sbnana/CAFAna/Core/OscCurve.h @@ -1,10 +1,10 @@ #pragma once -#include -#include +#include "cafanacore/FwdDeclare.h" -class TH1; -class TH1D; +#include "cafanacore/Ratio.h" + +#include "sbnana/CAFAna/Core/StanTypedefs.h" namespace osc { @@ -15,19 +15,19 @@ namespace osc namespace ana { /// Transition probability for any one channel as a function of energy - class OscCurve + class OscCurve : public Ratio { public: - OscCurve(osc::IOscCalc* calc, int from, int to, bool LoverE); - OscCurve(TH1* h); + OscCurve(osc::IOscCalc* calc, int from, int to); + OscCurve(osc::IOscCalcStan* calc, int from, int to); virtual ~OscCurve(); - OscCurve(const OscCurve& rhs); - OscCurve& operator=(const OscCurve& rhs); + OscCurve(const OscCurve& rhs) = default; + OscCurve& operator=(const OscCurve& rhs) = default; TH1D* ToTH1(bool title = false) const; + protected: int fFrom, fTo; - TH1D* fHist; }; } diff --git a/sbnana/CAFAna/Core/OscillatableSpectrum.cxx b/sbnana/CAFAna/Core/OscillatableSpectrum.cxx index 64c92753..921edd41 100644 --- a/sbnana/CAFAna/Core/OscillatableSpectrum.cxx +++ b/sbnana/CAFAna/Core/OscillatableSpectrum.cxx @@ -1,9 +1,8 @@ #include "sbnana/CAFAna/Core/OscillatableSpectrum.h" #include "sbnana/CAFAna/Core/Binning.h" -#include "sbnana/CAFAna/Core/HistCache.h" #include "sbnana/CAFAna/Core/OscCurve.h" -#include "sbnana/CAFAna/Core/Ratio.h" +#include "cafanacore/Ratio.h" #include "sbnana/CAFAna/Core/Utilities.h" #include "sbnana/CAFAna/Analysis/ExpInfo.h" @@ -22,196 +21,64 @@ namespace ana { - // Duplicate here because we can't include Vars.h - const Var kTrueE([](const caf::SRSliceProxy* slc) -> double {return slc->truth.E;}); + namespace{ + // Duplicate here because we can't include Vars.h + const Var kTrueE([](const caf::SRSliceProxy* slc) -> double {return slc->truth.E;}); - const Var kBaseline([](const caf::SRSliceProxy* slc) -> double {return slc->truth.baseline * 1e-3;}); // m -> km + const Var kBaseline([](const caf::SRSliceProxy* slc) -> double {return slc->truth.baseline * 1e-3;}); // m -> km - const Var kTrueLOverE = kBaseline / kTrueE; + const Var kTrueLOverE = kBaseline / kTrueE; - //---------------------------------------------------------------------- - OscillatableSpectrum:: - OscillatableSpectrum(const std::string& label, const Binning& bins, - SpectrumLoaderBase& loader, - const Var& var, - const Cut& cut, - const SystShifts& shift, - const Var& wei) - : ReweightableSpectrum(label, bins, kTrueLOverE), - fCachedOsc(0, {}, {}, 0, 0), - fCachedHash(0) - { - fTrueLabel = "True baseline / True energy (km / GeV)"; - - DontAddDirectory guard; - - fHist = HistCache::NewTH2D("", bins, kTrueLOverEBins); - - loader.AddReweightableSpectrum(*this, var, cut, shift, wei); + const Cut kHasNu([](const caf::SRSliceProxy* sr) + { + return sr->truth.index >= 0; + }); } //---------------------------------------------------------------------- - OscillatableSpectrum::OscillatableSpectrum(SpectrumLoaderBase& loader, - const HistAxis& axis, - const Cut& cut, - const SystShifts& shift, - const Var& wei) - : OscillatableSpectrum(loader, axis, kNoSpillCut, cut, shift, wei) + OscillatableSpectrum::OscillatableSpectrum(ISliceSource& src, + const HistAxis& axis) + : ReweightableSpectrum(src[kHasNu], axis, HistAxis("True L / E (km / GeV)", kTrueLOverEBins, kTrueLOverE)) { } //---------------------------------------------------------------------- - OscillatableSpectrum::OscillatableSpectrum(SpectrumLoaderBase& loader, - const HistAxis& axis, - const SpillCut& spillcut, - const SliceCut& slicecut, - const SystShifts& shift, - const Var& wei) - : ReweightableSpectrum(axis.GetLabels(), axis.GetBinnings(), kTrueLOverE), - fCachedOsc(0, {}, {}, 0, 0), - fCachedHash(0) - { - fTrueLabel = "True baseline / True energy (km / GeV)"; - - Binning bins1D = fBins[0]; - if(fBins.size() > 1){ - int n = 1; - for(const Binning& b: fBins) n *= b.NBins(); - bins1D = Binning::Simple(n, 0, n); - } - - std::string label; - for(const std::string& l: fLabels) label += l + " and "; - label.resize(label.size()-5); // drop the last "and" - - DontAddDirectory guard; - - fHist = HistCache::NewTH2D("", bins1D, kTrueLOverEBins); - - Var multiDVar = axis.GetVars()[0]; - if(axis.NDimensions() == 2) - multiDVar = Var2D(axis.GetVars()[0], axis.GetBinnings()[0], - axis.GetVars()[1], axis.GetBinnings()[1]); - if(axis.NDimensions() == 3) - multiDVar = Var3D(axis.GetVars()[0], axis.GetBinnings()[0], - axis.GetVars()[1], axis.GetBinnings()[1], - axis.GetVars()[2], axis.GetBinnings()[2]); - - loader.AddReweightableSpectrum(*this, multiDVar, spillcut, slicecut, shift, wei); - } - - //---------------------------------------------------------------------- - OscillatableSpectrum::OscillatableSpectrum(const std::string& label, - const Binning& bins) - : ReweightableSpectrum(label, bins, kTrueLOverE), - fCachedOsc(0, {}, {}, 0, 0), - fCachedHash(0) - { - fTrueLabel = "True baseline / True energy (km / GeV)"; - - DontAddDirectory guard; - - fPOT = 0; - fLivetime = 0; - - fHist = HistCache::NewTH2D("", bins, kTrueLOverEBins); - } - - //---------------------------------------------------------------------- - OscillatableSpectrum::OscillatableSpectrum(const std::string& label, double pot, double livetime, - const Binning& bins) - : ReweightableSpectrum(label, bins, kTrueLOverE), - fCachedOsc(0, {}, {}, 0, 0), - fCachedHash(0) - { - fTrueLabel = "True baseline / True energy (km / GeV)"; - - DontAddDirectory guard; - - fPOT = pot; - fLivetime = livetime; - - fHist = HistCache::NewTH2D("", bins, kTrueLOverEBins); - } - - //---------------------------------------------------------------------- - OscillatableSpectrum::OscillatableSpectrum(TH2* h, - const std::vector& labels, - const std::vector& bins, + OscillatableSpectrum::OscillatableSpectrum(const Eigen::MatrixXd&& mat, + const HistAxis& recoAxis, double pot, double livetime) - : ReweightableSpectrum(kTrueLOverE, h, labels, bins, pot, livetime), - fCachedOsc(0, {}, {}, 0, 0), - fCachedHash(0) + : ReweightableSpectrum(std::move(mat), recoAxis, + HistAxis("True L / E (km / GeV)", kTrueLOverEBins, kTrueLOverE), + pot, livetime) { - fTrueLabel = "True baseline / True energy (km / GeV)"; - } - - //---------------------------------------------------------------------- - OscillatableSpectrum::OscillatableSpectrum(std::unique_ptr h, - const std::vector& labels, - const std::vector& bins, - double pot, double livetime) - : ReweightableSpectrum(kTrueLOverE, std::move(h), labels, bins, pot, livetime), - fCachedOsc(0, {}, {}, 0, 0), - fCachedHash(0) - { - fTrueLabel = "True baseline / True energy (km / GeV)"; } //---------------------------------------------------------------------- OscillatableSpectrum::~OscillatableSpectrum() { - // Nulls fHist out, so it's safe that ~ReweightableSpectrum tries too - HistCache::Delete(fHist); - - for (SpectrumLoaderBase* loader : fLoaderCount) - { loader->RemoveReweightableSpectrum(this); } - - delete fCachedHash; } //---------------------------------------------------------------------- OscillatableSpectrum::OscillatableSpectrum(const OscillatableSpectrum& rhs) - : ReweightableSpectrum(rhs.fLabels, rhs.fBins, kTrueLOverE), - fCachedOsc(0, {}, {}, 0, 0), - fCachedHash(0) + : ReweightableSpectrum(rhs) { - DontAddDirectory guard; - - fHist = HistCache::Copy(rhs.fHist); - - fPOT = rhs.fPOT; - fLivetime = rhs.fLivetime; - - if(rhs.fCachedHash){ - fCachedOsc = rhs.fCachedOsc; - fCachedHash = new TMD5(*rhs.fCachedHash); + if(rhs.fCache->hash){ + fCache->spect = rhs.fCache->spect; + fCache->hash = std::make_unique(*rhs.fCache->hash); } - assert( rhs.fLoaderCount.empty() ); // Copying with pending loads is unexpected + assert( rhs.fReferences.empty() ); // Copying with pending loads is unexpected } //---------------------------------------------------------------------- OscillatableSpectrum::OscillatableSpectrum(OscillatableSpectrum&& rhs) - : ReweightableSpectrum(rhs.fLabels, rhs.fBins, kTrueLOverE), - fCachedOsc(0, {}, {}, 0, 0), - fCachedHash(0) + : ReweightableSpectrum(rhs) { - DontAddDirectory guard; - - fHist = rhs.fHist; - rhs.fHist = 0; - - fPOT = rhs.fPOT; - fLivetime = rhs.fLivetime; - - if(rhs.fCachedHash){ - fCachedOsc = std::move(rhs.fCachedOsc); - fCachedHash = rhs.fCachedHash; - rhs.fCachedHash = 0; + if(rhs.fCache->hash){ + fCache->spect = std::move(rhs.fCache->spect); + fCache->hash = std::move(rhs.fCache->hash); } - assert( rhs.fLoaderCount.empty() ); // Copying with pending loads is unexpected + assert( rhs.fReferences.empty() ); // Copying with pending loads is unexpected } //---------------------------------------------------------------------- @@ -219,23 +86,18 @@ namespace ana { if(this == &rhs) return *this; - DontAddDirectory guard; + ReweightableSpectrum::operator=(rhs); - HistCache::Delete(fHist); - fHist = HistCache::Copy(rhs.fHist); - fPOT = rhs.fPOT; - fLivetime = rhs.fLivetime; - fLabels = rhs.fLabels; - fBins = rhs.fBins; - - if(rhs.fCachedHash){ - fCachedOsc = rhs.fCachedOsc; - delete fCachedHash; - fCachedHash = new TMD5(*rhs.fCachedHash); + if(rhs.fCache->hash){ + fCache->spect = rhs.fCache->spect; + fCache->hash = std::make_unique(*rhs.fCache->hash); + } + else{ + fCache->hash.reset(); } - assert( rhs.fLoaderCount.empty() ); // Copying with pending loads is unexpected - assert( fLoaderCount.empty() ); // Copying with pending loads is unexpected + assert( rhs.fReferences.empty() ); // Copying with pending loads is unexpected + assert( fReferences.empty() ); // Copying with pending loads is unexpected return *this; } @@ -245,81 +107,67 @@ namespace ana { if(this == &rhs) return *this; - DontAddDirectory guard; + ReweightableSpectrum::operator=(rhs); - HistCache::Delete(fHist); - fHist = rhs.fHist; - rhs.fHist = 0; - fPOT = rhs.fPOT; - fLivetime = rhs.fLivetime; - fLabels = rhs.fLabels; - fBins = rhs.fBins; - - if(rhs.fCachedHash){ - fCachedOsc = rhs.fCachedOsc; - delete fCachedHash; - fCachedHash = rhs.fCachedHash; - rhs.fCachedHash = 0; + if(rhs.fCache->hash){ + fCache->spect = std::move(rhs.fCache->spect); + fCache->hash = std::move(rhs.fCache->hash); + } + else{ + fCache->hash.reset(); } - assert( rhs.fLoaderCount.empty() ); // Copying with pending loads is unexpected - assert( fLoaderCount.empty() ); // Copying with pending loads is unexpected + assert( rhs.fReferences.empty() ); // Copying with pending loads is unexpected + assert( fReferences.empty() ); // Copying with pending loads is unexpected return *this; } //---------------------------------------------------------------------- - Spectrum OscillatableSpectrum::Oscillated(osc::IOscCalc* calc, - int from, int to) const + template Spectrum OscillatableSpectrum:: + _Oscillated(osc::_IOscCalc* calc, int from, int to) const { - // TODO remove this check in a little while, once no one is using old state - // files anymore (comment from Feb 2020). - const bool isLoverE = (fHist->GetYaxis()->GetXmax() == 2); - static bool once = true; - if(once && !isLoverE){ - once = false; - std::cout << "\nWarning: OscillatableSpectrum with legacy non-L/E y-axis detected. Will oscillate correctly for now, but this code will eventually be removed\n" << std::endl; - } - // POT = 0 implies empty spectrum and oscillated result will also always be // empty - if(fCachedHash && fPOT == 0) return fCachedOsc; + if(fCache->hash && fPOT == 0) return fCache->spect; TMD5* hash = calc->GetParamsHash(); - if(hash && fCachedHash && *hash == *fCachedHash){ + if(hash && fCache->hash && *hash == *fCache->hash){ delete hash; - return fCachedOsc; + return fCache->spect; } - const OscCurve curve(calc, from, to, isLoverE); - TH1D* Ps = curve.ToTH1(); - - const Spectrum ret = WeightedBy(Ps); + const OscCurve curve(calc, from, to); + const Spectrum ret = WeightedBy(curve); if(hash){ - fCachedOsc = ret; - delete fCachedHash; - fCachedHash = hash; + fCache->spect = ret; + fCache->hash.reset(hash); } - HistCache::Delete(Ps); + return ret; } //---------------------------------------------------------------------- - OscillatableSpectrum& OscillatableSpectrum::operator+=(const OscillatableSpectrum& rhs) + Spectrum OscillatableSpectrum::Oscillated(osc::IOscCalc* calc, + int from, int to) const { - // If someone actually needs this we can go in and fix the behaviour - assert(fPOT); + return _Oscillated(calc, from, to); + } - if(rhs.fPOT){ - fHist->Add(rhs.fHist, fPOT/rhs.fPOT); - } - else{ - // How can it have events but no POT? - assert(rhs.fHist->Integral() == 0); - } + //---------------------------------------------------------------------- + Spectrum OscillatableSpectrum::Oscillated(osc::IOscCalcStan* calc, + int from, int to) const + { + return _Oscillated(calc, from, to); + } - delete fCachedHash; - fCachedHash = 0; // Invalidate + //---------------------------------------------------------------------- + OscillatableSpectrum& OscillatableSpectrum::operator+=(const OscillatableSpectrum& rhs) + { + ReweightableSpectrum::operator+=(rhs); + + // invalidate + fCache->hash.reset(nullptr); return *this; } @@ -335,16 +183,10 @@ namespace ana //---------------------------------------------------------------------- OscillatableSpectrum& OscillatableSpectrum::operator-=(const OscillatableSpectrum& rhs) { - if(rhs.fPOT){ - fHist->Add(rhs.fHist, -fPOT/rhs.fPOT); - } - else{ - // How can it have events but no POT? - assert(rhs.fHist->Integral() == 0); - } + ReweightableSpectrum::operator-=(rhs); - delete fCachedHash; - fCachedHash = 0; // Invalidate + // invalidate + fCache->hash.reset(nullptr); return *this; } @@ -358,32 +200,17 @@ namespace ana } //---------------------------------------------------------------------- - void OscillatableSpectrum::SaveTo(TDirectory* dir) const + void OscillatableSpectrum::SaveTo(TDirectory* dir, const std::string& name) const { - TDirectory* tmp = gDirectory; - dir->cd(); - - TObjString("OscillatableSpectrum").Write("type"); - - fHist->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 < fBins.size(); ++i){ - TObjString(fLabels[i].c_str()).Write(TString::Format("label%d", i).Data()); - fBins[i].SaveTo(dir->mkdir(TString::Format("bins%d", i))); - } - - tmp->cd(); + _SaveTo(dir, name, "OscillatableSpectrum"); } //---------------------------------------------------------------------- - std::unique_ptr OscillatableSpectrum::LoadFrom(TDirectory* dir) + std::unique_ptr OscillatableSpectrum::LoadFrom(TDirectory* dir, const std::string& name) { + dir = dir->GetDirectory(name.c_str()); // switch to subdir + assert(dir); + DontAddDirectory guard; TObjString* tag = (TObjString*)dir->Get("type"); @@ -402,28 +229,35 @@ namespace ana std::vector bins; for(int i = 0; ; ++i){ - TDirectory* subdir = dir->GetDirectory(TString::Format("bins%d", i)); + const std::string subname = TString::Format("bins%d", i).Data(); + TDirectory* subdir = dir->GetDirectory(subname.c_str()); if(!subdir) break; - bins.push_back(*Binning::LoadFrom(subdir)); + delete subdir; + bins.push_back(*Binning::LoadFrom(dir, subname)); TObjString* label = (TObjString*)dir->Get(TString::Format("label%d", i)); labels.push_back(label ? label->GetString().Data() : ""); - delete subdir; delete label; } - if(bins.empty() && labels.empty()){ - // Must be an old file. Make an attempt at backwards compatibility. - bins.push_back(Binning::FromTAxis(spect->GetXaxis())); - labels.push_back(spect->GetXaxis()->GetTitle()); - } + delete dir; - auto ret = std::make_unique(std::unique_ptr(spect), - labels, bins, - hPot->GetBinContent(1), - hLivetime->GetBinContent(1)); + const HistAxis recoAxis(labels, bins); + + // ROOT histogram storage is row-major, but Eigen is column-major by + // default + typedef Eigen::Matrix MatRowMajor; + + auto ret = std::make_unique(Eigen::Map(spect->GetArray(), kTrueLOverEBins.NBins()+2, recoAxis.GetBins1D().NBins()+2), + recoAxis, + hPot->Integral(0, -1), + hLivetime->Integral(0, -1)); + + + delete spect; delete hPot; delete hLivetime; + return ret; } } diff --git a/sbnana/CAFAna/Core/OscillatableSpectrum.h b/sbnana/CAFAna/Core/OscillatableSpectrum.h index 8c576f5c..dcef564e 100644 --- a/sbnana/CAFAna/Core/OscillatableSpectrum.h +++ b/sbnana/CAFAna/Core/OscillatableSpectrum.h @@ -1,16 +1,23 @@ #pragma once -#include "sbnana/CAFAna/Core/ReweightableSpectrum.h" +#include "cafanacore/ReweightableSpectrum.h" + +#include "cafanacore/FwdDeclare.h" +#include "cafanacore/Spectrum.h" +#include "cafanacore/ThreadLocal.h" #include "sbnana/CAFAna/Core/Binning.h" -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "sbnana/CAFAna/Core/HistAxis.h" #include "sbnana/CAFAna/Core/SpectrumLoaderBase.h" +#include "sbnana/CAFAna/Core/StanTypedefs.h" +#include "sbnana/CAFAna/Core/IRecordSource.h" + +#include "TMD5.h" #include class TH2; class TH2D; -class TMD5; namespace osc { @@ -20,48 +27,32 @@ namespace osc namespace ana { + class Binning; + + struct OscCache + { + std::unique_ptr hash; + Spectrum spect; + + OscCache() + : spect(Spectrum::Uninitialized()) + {} + }; + /// %Spectrum with true energy information, allowing it to be oscillated 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 Var& wei = kUnweighted); - - OscillatableSpectrum(SpectrumLoaderBase& loader, - const HistAxis& axis, - const Cut& cut, - const SystShifts& shift = kNoShift, - const Var& wei = kUnweighted); - - OscillatableSpectrum(SpectrumLoaderBase& loader, - const HistAxis& axis, - const SpillCut& spillcut, - const SliceCut& slicecut, - const SystShifts& shift = kNoShift, - const Var& wei = kUnweighted); - - OscillatableSpectrum(const std::string& label, const Binning& bins); - OscillatableSpectrum(const std::string& label, double pot, double livetime, - const Binning& bins); - OscillatableSpectrum(TH2* h, - const std::vector& labels, - const std::vector& bins, - double pot, double livetime); + OscillatableSpectrum(ana::ISliceSource& src, const HistAxis& axis); - OscillatableSpectrum(std::unique_ptr h, - const std::vector& labels, - const std::vector& bins, + OscillatableSpectrum(const Eigen::MatrixXd&& mat, + const HistAxis& recoAxis, double pot, double livetime); + /// The only valid thing to do with such a spectrum is to assign something + /// else into it. + static OscillatableSpectrum Uninitialized(){return OscillatableSpectrum();} + ~OscillatableSpectrum(); /// Copy constructor @@ -86,6 +77,7 @@ namespace ana Spectrum TrueEnergy() const {return WeightingVariable();} Spectrum Oscillated(osc::IOscCalc* calc, int from, int to) const; + Spectrum Oscillated(osc::IOscCalcStan* calc, int from, int to) const; OscillatableSpectrum& operator+=(const OscillatableSpectrum& rhs); OscillatableSpectrum operator+(const OscillatableSpectrum& rhs) const; @@ -93,30 +85,18 @@ namespace ana OscillatableSpectrum& operator-=(const OscillatableSpectrum& rhs); OscillatableSpectrum operator-(const OscillatableSpectrum& rhs) const; - void SaveTo(TDirectory* dir) const; - static std::unique_ptr LoadFrom(TDirectory* dir); + void SaveTo(TDirectory* dir, const std::string& name) const; + static std::unique_ptr LoadFrom(TDirectory* dir, const std::string& name); protected: - // Derived classes can be trusted take care of their own construction - OscillatableSpectrum(const std::vector& labels, - const std::vector& bins, - const Var& rwVar) - : ReweightableSpectrum(labels, bins, rwVar), - fCachedOsc(0, {}, {}, 0, 0), - fCachedHash(0) - { - } - OscillatableSpectrum(const std::string& label, - const Binning& bins, - const Var& rwVar) - : ReweightableSpectrum(label, bins, rwVar), - fCachedOsc(0, {}, {}, 0, 0), - fCachedHash(0) + /// Constructor for Uninitialized() + OscillatableSpectrum() { } - mutable Spectrum fCachedOsc; - mutable TMD5* fCachedHash; + template Spectrum _Oscillated(osc::_IOscCalc* calc, int from, int to) const; + + mutable ThreadLocal fCache; }; } diff --git a/sbnana/CAFAna/Core/Progress.cxx b/sbnana/CAFAna/Core/Progress.cxx deleted file mode 100644 index eaa097b6..00000000 --- a/sbnana/CAFAna/Core/Progress.cxx +++ /dev/null @@ -1,119 +0,0 @@ -#include "sbnana/CAFAna/Core/Progress.h" - -#include "sys/stat.h" - -#include "TString.h" - -#include - -namespace{ - const int kBarWidth = 60; -} - -namespace ana -{ - bool Progress::fAnyLive = false; - - //---------------------------------------------------------------------- - Progress::Progress(const std::string& title) - : fDone(false), fIFrac(-1), fStart(time(0)), fPrevCall(time(0)), fLive(false) - { - // If no else is drawing, we can - if(!fAnyLive){ - fLive = true; - fAnyLive = false; - } - - if(!fLive) return; - - std::cout << title << "..." << std::endl; - SetProgress(0); // Draw the initial bar - } - - //---------------------------------------------------------------------- - Progress::~Progress() - { - // Finish up in case the user forgot to call Done() - Done(); - - // If we were the ones drawing, we're not anymore - if(fLive) fAnyLive = false; - } - - //---------------------------------------------------------------------- - void Progress::SetProgress(double frac) - { - if(!fLive || fDone) return; - - // Check if we're outputting to a file. If so don't bother showing off - // with the progress bar, it won't work. - struct stat buf; - fstat(fileno(stdout), &buf); - const bool isFile = (buf.st_mode & S_IFREG) || (buf.st_mode & S_IFIFO); - if(isFile) return; - - const int ifrac = (kBarWidth-1)*frac; - - const time_t t_now = time(0); - - // Don't repaint unnecessarily - if(ifrac == fIFrac && t_now - fPrevCall < 2) return; - - fIFrac = ifrac; - fPrevCall = time(0); - - std::string str(kBarWidth, ' '); - for(int i = 0; i < ifrac; ++i) str[i] = '='; - str[ifrac] = '>'; - str[0] = '['; - str[kBarWidth-1] = ']'; - - if(frac > 0){ - const int elapse = t_now - fStart; - if(elapse > 2){ // Don't show for very short steps - if(frac < 1) - str += " "+FormatTime(elapse*(1-frac)/frac); - else - str += " "+FormatTime(elapse); - str += " "; // Enough to cover up any previous version - } - } - - std::cout << "\r" << str << std::flush; - - if(frac == 1){ - fDone = true; - std::cout << std::endl; - } - } - - //---------------------------------------------------------------------- - void Progress::Done() - { - if(!fLive) return; - - if(fDone) return; // Can easily be called multiple times - - SetProgress(1); // Make sure the bar shows 100% - - fDone = true; - } - - //---------------------------------------------------------------------- - std::string Progress::FormatTime(double sec) const - { - // Yes, I'm sure there's a standard way to do this, but this was easy, and - // lets me print exactly what I want. - std::string ret; - if(sec >= 60*60-.5){ - ret += TString::Format("%dh", (int(sec+.5)/(60*60))).Data(); - } - if(sec >= 60-.5){ - ret += TString::Format("%dm", (int(sec+.5)/60)%60).Data(); - } - if(sec < 60*60){ // don't clutter if still measured in hours - ret += TString::Format("%ds", (int(sec+.5)%60)).Data(); - } - return ret; - } -} diff --git a/sbnana/CAFAna/Core/Progress.h b/sbnana/CAFAna/Core/Progress.h deleted file mode 100644 index 04efa8bb..00000000 --- a/sbnana/CAFAna/Core/Progress.h +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include -#include - -namespace ana -{ - /// A simple ascii-art progress bar - class Progress - { - public: - /// Create and draw the progress bar - Progress(const std::string& title); - ~Progress(); - /// Update the progress fraction between zero and one - void SetProgress(double frac); - /// Call this when action is completed - void Done(); - protected: - std::string FormatTime(double sec) const; - - bool fDone; ///< Has \ref Done been called? - int fIFrac; ///< What character are we on? Prevents unnecessary redraws - - time_t fStart; - time_t fPrevCall; - - // Only one bar may be live at a time. Prevents overdrawing - bool fLive; ///< Is this bar live (drawable?) - static bool fAnyLive; ///< Are any bars live? - }; -} diff --git a/sbnana/CAFAna/Core/Ratio.cxx b/sbnana/CAFAna/Core/Ratio.cxx deleted file mode 100644 index 93361346..00000000 --- a/sbnana/CAFAna/Core/Ratio.cxx +++ /dev/null @@ -1,126 +0,0 @@ -#include "sbnana/CAFAna/Core/Ratio.h" - -#include "sbnana/CAFAna/Core/HistCache.h" -#include "sbnana/CAFAna/Core/Utilities.h" - -#include "TH1.h" - -#include - -namespace ana -{ - //---------------------------------------------------------------------- - Ratio::Ratio(const Spectrum& num, const Spectrum& denom, - bool purOrEffErrs) - { - // Scale to same arbitrary POT - fHist = num.ToTH1(1e20); - TH1D* temp = denom.ToTH1(1e20); - if(purOrEffErrs){ - fHist->Divide(fHist, temp, 1, 1, "B"); - } - else{ - fHist->Divide(temp); - } - HistCache::Delete(temp); - - fHist->GetYaxis()->SetTitle("Ratio"); - - // TODO: set error bars smartly - } - - //---------------------------------------------------------------------- - Ratio::Ratio(TH1* h, std::string varName) - { - if(!h){ - fHist = 0; - return; - } - - DontAddDirectory guard; - - const TString className = h->ClassName(); - - if(className == "TH1D"){ - // Shortcut if types match - fHist = HistCache::Copy((TH1D*)h); - } - else{ - fHist = HistCache::New(UniqueName(), h->GetXaxis()); - fHist->GetXaxis()->SetTitle(h->GetXaxis()->GetTitle()); - fHist->Add(h); - } - - if(!varName.empty()) fHist->GetXaxis()->SetTitle(varName.c_str()); - } - - //---------------------------------------------------------------------- - Ratio::~Ratio() - { - HistCache::Delete(fHist); - } - - //---------------------------------------------------------------------- - Ratio::Ratio(const Ratio& rhs) - { - DontAddDirectory guard; - - assert(rhs.fHist); - fHist = HistCache::Copy(rhs.fHist); - } - - //---------------------------------------------------------------------- - Ratio& Ratio::operator=(const Ratio& rhs) - { - if(this == &rhs) return *this; - - DontAddDirectory guard; - - HistCache::Delete(fHist); - assert(rhs.fHist); - fHist = HistCache::Copy(rhs.fHist); - return *this; - } - - //---------------------------------------------------------------------- - Ratio& Ratio::operator*=(const Ratio& rhs) - { - fHist->Multiply(rhs.fHist); - return *this; - } - - //---------------------------------------------------------------------- - Ratio Ratio::operator*(const Ratio& rhs) const - { - Ratio ret = *this; - ret *= rhs; - return ret; - } - - //---------------------------------------------------------------------- - Ratio& Ratio::operator/=(const Ratio& rhs) - { - fHist->Divide(rhs.fHist); - return *this; - } - - //---------------------------------------------------------------------- - Ratio Ratio::operator/(const Ratio& rhs) const - { - Ratio ret = *this; - ret /= rhs; - return ret; - } - - //---------------------------------------------------------------------- - TH1D* Ratio::ToTH1(Color_t col, Style_t style) const - { - // Could have a file temporarily open - DontAddDirectory guard; - - TH1D* ret = HistCache::Copy(fHist); - ret->SetLineColor(col); - ret->SetLineStyle(style); - return ret; - } -} // namespace diff --git a/sbnana/CAFAna/Core/Ratio.h b/sbnana/CAFAna/Core/Ratio.h deleted file mode 100644 index 35c3c11d..00000000 --- a/sbnana/CAFAna/Core/Ratio.h +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include "sbnana/CAFAna/Core/Spectrum.h" - -namespace ana -{ - /// Represent the ratio between two spectra - class Ratio - { - public: - friend class Spectrum; - - /// \param num Numerator of the ratio - /// \param denom Denominator of the ratio - /// \param purOrEffErrs Does this ratio represent a purity or efficiency - /// plot? If so, error bars are calculated differently. - Ratio(const Spectrum& num, const Spectrum& denom, - bool purOrEffErrs = false); - - /// Don't use this constructor unless you REALLY KNOW what you're doing. - Ratio(TH1* h, std::string varName = ""); - virtual ~Ratio(); - - Ratio(const Ratio& rhs); - Ratio& operator=(const Ratio& rhs); - - Ratio& operator*=(const Ratio& rhs); - Ratio operator*(const Ratio& rhs) const; - - Ratio& operator/=(const Ratio& rhs); - Ratio operator/(const Ratio& rhs) const; - - TH1D* ToTH1(Color_t col = kBlack, - Style_t style = kSolid) const; - protected: - TH1D* fHist; - }; - - inline Ratio operator/(const Spectrum& lhs, const Spectrum& rhs){return Ratio(lhs, rhs);} -} // namespace diff --git a/sbnana/CAFAna/Core/Registry.cxx b/sbnana/CAFAna/Core/Registry.cxx new file mode 100644 index 00000000..6451c34f --- /dev/null +++ b/sbnana/CAFAna/Core/Registry.cxx @@ -0,0 +1,13 @@ +#include "cafanacore/Registry.txx" + +#include "sbnana/CAFAna/Core/IFitVar.h" +#include "sbnana/CAFAna/Core/ISyst.h" +#include "sbnana/CAFAna/Core/FitMultiverse.h" + +namespace ana +{ + // Instantiate the registries we need + template class Registry; + template class Registry; + template class Registry; +} diff --git a/sbnana/CAFAna/Core/ReweightableSpectrum.cxx b/sbnana/CAFAna/Core/ReweightableSpectrum.cxx deleted file mode 100644 index f3274bf2..00000000 --- a/sbnana/CAFAna/Core/ReweightableSpectrum.cxx +++ /dev/null @@ -1,522 +0,0 @@ -#include "sbnana/CAFAna/Core/ReweightableSpectrum.h" - -#include "sbnana/CAFAna/Core/Binning.h" -#include "sbnana/CAFAna/Core/HistCache.h" -#include "sbnana/CAFAna/Core/Ratio.h" -#include "sbnana/CAFAna/Core/Var.h" -#include "sbnana/CAFAna/Core/SpectrumLoaderBase.h" -#include "sbnana/CAFAna/Core/Utilities.h" - -#include "TDirectory.h" -#include "TH2.h" -#include "TObjString.h" - -#include -#include -#include - -namespace ana -{ - //---------------------------------------------------------------------- - ReweightableSpectrum::ReweightableSpectrum(SpectrumLoaderBase& loader, - const HistAxis& recoAxis, - const HistAxis& trueAxis, - const Cut& cut, - const SystShifts& shift, - const Var& wei) - : ReweightableSpectrum(loader, recoAxis, trueAxis, kNoSpillCut, cut, shift, wei) - { - } - - //---------------------------------------------------------------------- - ReweightableSpectrum::ReweightableSpectrum(SpectrumLoaderBase& loader, - const HistAxis& recoAxis, - const HistAxis& trueAxis, - const SpillCut& spillcut, - const SliceCut& slicecut, - const SystShifts& shift, - const Var& wei) - : ReweightableSpectrum(recoAxis.GetLabels(), recoAxis.GetBinnings(), - trueAxis.GetVars()[0]) - { - assert(trueAxis.NDimensions() == 1); - - fTrueLabel = trueAxis.GetLabels()[0]; - - DontAddDirectory guard; - - // Can't use HistCache here because y-axis is not necessarily - // TrueEnergyBinning. TODO - that should maybe be generalized. - - const std::string name = UniqueName(); - - Binning xbins = fBins[0]; - if(fBins.size() > 1){ - int n = 1; - for(const Binning& b: fBins) n *= b.NBins(); - xbins = Binning::Simple(n, 0, n); - } - - const Binning ybins = trueAxis.GetBinnings()[0]; - - - // Ugh combinatorics - if(xbins.IsSimple() && ybins.IsSimple()) - fHist = new TH2D(name.c_str(), "", - xbins.NBins(), xbins.Min(), xbins.Max(), - ybins.NBins(), ybins.Min(), ybins.Max()); - - if(xbins.IsSimple() && !ybins.IsSimple()) - fHist = new TH2D(name.c_str(), "", - xbins.NBins(), xbins.Min(), xbins.Max(), - ybins.NBins(), &ybins.Edges()[0]); - - if(!xbins.IsSimple() && ybins.IsSimple()) - fHist = new TH2D(name.c_str(), "", - xbins.NBins(), &xbins.Edges()[0], - ybins.NBins(), ybins.Min(), ybins.Max()); - - if(!xbins.IsSimple() && !ybins.IsSimple()) - fHist = new TH2D(name.c_str(), "", - xbins.NBins(), &xbins.Edges()[0], - ybins.NBins(), &ybins.Edges()[0]); - - loader.AddReweightableSpectrum(*this, recoAxis.GetMultiDVar(), spillcut, slicecut, shift, wei); - } - - //---------------------------------------------------------------------- - ReweightableSpectrum::ReweightableSpectrum(const Var& rwVar, - const std::string& xlabel, const std::string& ylabel, - double pot, - int nbinsx, double xmin, double xmax, - int nbinsy, double ymin, double ymax) - : ReweightableSpectrum(xlabel, - Binning::Simple(nbinsx, xmin, xmax), - rwVar) - { - DontAddDirectory guard; - - fHist = new TH2D(UniqueName().c_str(), "", - nbinsx, xmin, xmax, nbinsy, ymin, ymax); - - fTrueLabel = ylabel; - - // Ensure errors get accumulated properly - fHist->Sumw2(); - } - - //---------------------------------------------------------------------- - ReweightableSpectrum::ReweightableSpectrum(const Var& rwVar, TH2* h, - const std::vector& labels, - const std::vector& bins, - double pot, double livetime) - : ReweightableSpectrum(labels, bins, rwVar) - { - fPOT = pot; - fLivetime = livetime; - - if(!h){ - fHist = 0; - return; - } - - DontAddDirectory guard; - - const TString className = h->ClassName(); - - if(className == "TH2D"){ - // Shortcut if types match - fHist = new TH2D(*((TH2D*)h)); - } - else{ - const TAxis* ax = h->GetXaxis(); - const TAxis* ay = h->GetYaxis(); - // Must have both or neither - assert(bool(ax->GetXbins()->GetArray()) == bool(ay->GetXbins()->GetArray())); - - if(ax->GetXbins()->GetArray()){ - fHist = new TH2D(UniqueName().c_str(), "", - ax->GetNbins(), ax->GetXbins()->GetArray(), - ay->GetNbins(), ay->GetXbins()->GetArray()); - } - else{ - fHist = new TH2D(UniqueName().c_str(), "", - ax->GetNbins(), ax->GetXmin(), ax->GetXmax(), - ay->GetNbins(), ay->GetXmin(), ay->GetXmax()); - } - - fHist->Add(h); - } - - fTrueLabel = h->GetYaxis()->GetTitle(); - } - - //---------------------------------------------------------------------- - ReweightableSpectrum::ReweightableSpectrum(const Var& rwVar, - std::unique_ptr h, - const std::vector& labels, - const std::vector& bins, - double pot, double livetime) - : ReweightableSpectrum(labels, bins, rwVar) - { - fHist = h.release(); - fPOT = pot; - fLivetime = livetime; - - fTrueLabel = fHist->GetYaxis()->GetTitle(); - } - - //---------------------------------------------------------------------- - ReweightableSpectrum::~ReweightableSpectrum() - { - if(fHist && fHist->GetDirectory()){ - static bool once = true; - if(once){ - once = false; - std::cerr << "ReweightableSpectrum's fHist is associated with a directory. How did that happen?" << std::endl; - } - } - - // Can't use HistCache here because that expects all 2D spectra have the - // usual true energy binning on their y-axis. In the case that we're - // actually an OscillatableSpectrum that destructor will indeed take care - // of invoking HistCache. - delete fHist; - } - - //---------------------------------------------------------------------- - ReweightableSpectrum::ReweightableSpectrum(const ReweightableSpectrum& rhs) - : fRWVar(rhs.fRWVar), fLabels(rhs.fLabels), fBins(rhs.fBins) - { - DontAddDirectory guard; - - fHist = new TH2D(*rhs.fHist); - - fPOT = rhs.fPOT; - fLivetime = rhs.fLivetime; - - assert( rhs.fLoaderCount.empty() ); // Copying with pending loads is unexpected - } - - //---------------------------------------------------------------------- - ReweightableSpectrum& ReweightableSpectrum::operator=(const ReweightableSpectrum& rhs) - { - if(this == &rhs) return *this; - - DontAddDirectory guard; - - fRWVar = rhs.fRWVar; - fLabels = rhs.fLabels; - fBins = rhs.fBins; - - delete fHist; - fHist = new TH2D(*rhs.fHist); - fPOT = rhs.fPOT; - fLivetime = rhs.fLivetime; - - assert( fLoaderCount.empty() ); // Copying with pending loads is unexpected - - return *this; - } - - //---------------------------------------------------------------------- - TH2D* ReweightableSpectrum::ToTH2(double pot) const - { - // Could have a file temporarily open - DontAddDirectory guard; - - TH2D* ret = new TH2D(*fHist); - ret->SetName(UniqueName().c_str()); - if(fPOT){ - ret->Scale(pot/fPOT); - } - else{ - // How did it get events with no POT? - assert(ret->Integral() == 0); - } - - - std::string label; - for(const std::string& l: fLabels) label += l + " and "; - label.resize(label.size()-5); // drop the last "and" - ret->GetXaxis()->SetTitle(label.c_str()); - ret->GetYaxis()->SetTitle(fTrueLabel.c_str()); - - return ret; - } - - //---------------------------------------------------------------------- - void ReweightableSpectrum::Fill(double x, double y, double w) - { - fHist->Fill(x, y, w); - } - - /// Helper for \ref Unweighted - void ProjectionX(TH2D* from, TH1D* to) - { - const int Nx = from->GetNbinsX(); - const int Ny = from->GetNbinsY(); - - // Direct access to the bins is faster - double* fromArr = from->GetArray(); - double* toArr = to->GetArray(); - - int fromBin = 0; - for(int y = 0; y < Ny+2; ++y){ - for(int x = 0; x < Nx+2; ++x){ - // Our loops go over the bins in the order they are internally in - // 'from', and we do overflows, so we keep up exactly. If you get - // paranoid, reenable this briefly. - // assert(fromBin == from->GetBin(x, y)); - - const double z = fromArr[fromBin]; - ++fromBin; - - toArr[x] += z; - } - } - } - - //---------------------------------------------------------------------- - Spectrum ReweightableSpectrum::UnWeighted() const - { - DontAddDirectory guard; - - // Create a suitably-sized space for the result - std::unique_ptr h(HistCache::New("", fHist->GetXaxis())); - - ProjectionX(fHist, h.get()); - - return Spectrum(std::move(h), fLabels, fBins, fPOT, fLivetime); - } - - /// Helper for \ref WeightingVariable - void ProjectionY(TH2D* from, TH1D* to) - { - const int Nx = from->GetNbinsX(); - const int Ny = from->GetNbinsY(); - - // Direct access to the bins is faster - double* fromArr = from->GetArray(); - double* toArr = to->GetArray(); - - int fromBin = 0; - for(int y = 0; y < Ny+2; ++y){ - for(int x = 0; x < Nx+2; ++x){ - // Our loops go over the bins in the order they are internally in - // 'from', and we do overflows, so we keep up exactly. If you get - // paranoid, reenable this briefly. - // assert(fromBin == from->GetBin(x, y)); - - const double z = fromArr[fromBin]; - ++fromBin; - - toArr[y] += z; - } - } - } - - //---------------------------------------------------------------------- - Spectrum ReweightableSpectrum::WeightingVariable() const - { - DontAddDirectory guard; - - // Create a suitably-sized space for the result - std::unique_ptr h(HistCache::New("", fHist->GetYaxis())); - - ProjectionY(fHist, h.get()); - - return Spectrum(std::move(h), fLabels, fBins, fPOT, fLivetime); - } - - //---------------------------------------------------------------------- - Spectrum ReweightableSpectrum::WeightedBy(const TH1* ws) const - { - // This function is in the inner loop of oscillation fits, so some - // optimization has been done. - - DontAddDirectory guard; - - assert(ws->GetNbinsX() == fHist->GetNbinsY()); - - TAxis* ax = fHist->GetXaxis(); - TH1D* hRet = HistCache::New("", ax); - - const int X = fHist->GetNbinsX(); - const int Y = fHist->GetNbinsY(); - - // Direct access to the bins is faster - double* retArr = hRet->GetArray(); - double* histArr = fHist->GetArray(); - - int bin = 0; - for(int y = 0; y < Y+2; ++y){ - const double w = ws->GetBinContent(y); - for(int x = 0; x < X+2; ++x){ - // Our loops go over the bins in the order they are internally in - // fHist, and we do overflows, so we keep up exactly. If you get - // paranoid, reenable this briefly. - - // assert(bin == fHist->GetBin(x, y)); - - retArr[x] += histArr[bin]*w; - ++bin; - } - } - - // TODO: can this all be more efficient? - return Spectrum(std::unique_ptr(hRet), fLabels, fBins, fPOT, fLivetime); - } - - - //---------------------------------------------------------------------- - void ReweightableSpectrum::ReweightToTrueSpectrum(const Spectrum& target) - { - // This is a big component of what extrapolations do, so it has been - // optimized for speed - - Ratio corr(target, WeightingVariable()); - std::unique_ptr hcorr(corr.ToTH1()); - - assert(hcorr->GetNbinsX() == fHist->GetNbinsY()); - - const int X = fHist->GetNbinsX(); - const int Y = fHist->GetNbinsY(); - - // Direct access to the bins is faster - double* histArr = fHist->GetArray(); - double* corrArr = hcorr->GetArray(); - - int bin = 0; - for(int y = 0; y < Y+2; ++y){ - const double w = corrArr[y]; - for(int x = 0; x < X+2; ++x){ - // Our loops go over the bins in the order they are internally in - // fHist, and we do overflows, so we keep up exactly. If you get - // paranoid, reenable this briefly. - - // assert(bin == fHist->GetBin(x, y)); - - histArr[bin] *= w; - ++bin; - } - } - - TH1D* todel = hcorr.release(); - HistCache::Delete(todel); - } - - //---------------------------------------------------------------------- - void ReweightableSpectrum::ReweightToRecoSpectrum(const Spectrum& target) - { - // This is a big component of what extrapolations do, so it has been - // optimized for speed - - Ratio corr(target, UnWeighted()); - std::unique_ptr hcorr(corr.ToTH1()); - - assert(hcorr->GetNbinsX() == fHist->GetNbinsX()); - - const int X = fHist->GetNbinsX(); - const int Y = fHist->GetNbinsY(); - - // Direct access to the bins is faster - double* histArr = fHist->GetArray(); - double* corrArr = hcorr->GetArray(); - - int bin = 0; - for(int y = 0; y < Y+2; ++y){ - for(int x = 0; x < X+2; ++x){ - // Our loops go over the bins in the order they are internally in - // fHist, and we do overflows, so we keep up exactly. If you get - // paranoid, reenable this briefly. - - // assert(bin == fHist->GetBin(x, y)); - - histArr[bin] *= corrArr[x]; - ++bin; - } - } - - TH1D* todel = hcorr.release(); - HistCache::Delete(todel); - } - - //---------------------------------------------------------------------- - void ReweightableSpectrum::Clear() - { - fHist->Reset(); - } - - //---------------------------------------------------------------------- - void ReweightableSpectrum::RemoveLoader(SpectrumLoaderBase* p) - { fLoaderCount.erase(p); } - - //---------------------------------------------------------------------- - void ReweightableSpectrum::AddLoader(SpectrumLoaderBase* p) - { fLoaderCount.insert(p); } - - //---------------------------------------------------------------------- - void ReweightableSpectrum::SaveTo(TDirectory* dir) const - { - TDirectory* tmp = gDirectory; - dir->cd(); - - TObjString("ReweightableSpectrum").Write("type"); - - fHist->GetYaxis()->SetTitle(fTrueLabel.c_str()); - fHist->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 < fBins.size(); ++i){ - TObjString(fLabels[i].c_str()).Write(TString::Format("label%d", i).Data()); - fBins[i].SaveTo(dir->mkdir(TString::Format("bins%d", i))); - } - - tmp->cd(); - } - - //---------------------------------------------------------------------- - std::unique_ptr ReweightableSpectrum::LoadFrom(TDirectory* dir) - { - TObjString* tag = (TObjString*)dir->Get("type"); - assert(tag); - assert(tag->GetString() == "ReweightableSpectrum"); - - 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; - std::vector bins; - - for(int i = 0; ; ++i){ - TDirectory* subdir = dir->GetDirectory(TString::Format("bins%d", i)); - if(!subdir) break; - bins.push_back(*Binning::LoadFrom(subdir)); - TObjString* label = (TObjString*)dir->Get(TString::Format("label%d", i)); - labels.push_back(label ? label->GetString().Data() : ""); - } - - if(bins.empty() && labels.empty()){ - // Must be an old file. Make an attempt at backwards compatibility. - bins.push_back(Binning::FromTAxis(spect->GetXaxis())); - labels.push_back(spect->GetXaxis()->GetTitle()); - } - - return std::make_unique(kUnweighted, - spect, - labels, bins, - hPot->GetBinContent(1), - hLivetime->GetBinContent(1)); - } - -} diff --git a/sbnana/CAFAna/Core/ReweightableSpectrum.h b/sbnana/CAFAna/Core/ReweightableSpectrum.h deleted file mode 100644 index 6e8e8b61..00000000 --- a/sbnana/CAFAna/Core/ReweightableSpectrum.h +++ /dev/null @@ -1,143 +0,0 @@ -#pragma once - -#include "sbnana/CAFAna/Core/Spectrum.h" - -#include - -class TDirectory; -class TH2; -class TH2D; - -namespace ana -{ - /// %Spectrum with the value of a second variable, allowing for reweighting - class ReweightableSpectrum - { - public: - friend class SpectrumLoaderBase; - friend class SpectrumLoader; - friend class NullLoader; - friend class MRCCLoader; - - ReweightableSpectrum(SpectrumLoaderBase& loader, - const HistAxis& recoAxis, - const HistAxis& trueAxis, - const Cut& cut, - const SystShifts& shift = kNoShift, - const Var& wei = kUnweighted); - - ReweightableSpectrum(SpectrumLoaderBase& loader, - const HistAxis& recoAxis, - const HistAxis& trueAxis, - const SpillCut& spillcut, - const SliceCut& slicecut, - const SystShifts& shift = kNoShift, - const Var& wei = kUnweighted); - - ReweightableSpectrum(const Var& rwVar, - const std::string& xlabel, const std::string& ylabel, - double pot, - int nbinsx, double xmin, double xmax, - int nbinsy, double ymin, double ymax); - - ReweightableSpectrum(const Var& rwVar, - TH2* h, - const std::vector& labels, - const std::vector& bins, - double pot, double livetime); - - ReweightableSpectrum(const Var& rwVar, - std::unique_ptr h, - const std::vector& labels, - const std::vector& bins, - double pot, double livetime); - - virtual ~ReweightableSpectrum(); - - ReweightableSpectrum(const ReweightableSpectrum& rhs); - ReweightableSpectrum& operator=(const ReweightableSpectrum& rhs); - - /// \brief The variable that will be used to fill the y-axis - /// - /// By convention, return zero if the information can't be obtained, and - /// this event will be skipped. - const Var& ReweightVar() const {return fRWVar;} - - void Fill(double x, double y, double w = 1); - - TH2D* ToTH2(double pot) const; - - Spectrum UnWeighted() const; - - Spectrum WeightingVariable() const; - - Spectrum WeightedBy(const TH1* weights) const; - - /// Rescale bins so that \ref WeightingVariable will return \a target - void ReweightToTrueSpectrum(const Spectrum& target); - /// Recale bins so that \ref Unweighted will return \a target - void ReweightToRecoSpectrum(const Spectrum& target); - - void Clear(); - - /// Function to save a ReweightableSpectrum to file - /// the fRWVar member is not written to file, so when - /// the spectrum is loaded back from file, ReweightVar - /// should not be accessed, but reweighting still works - void SaveTo(TDirectory* dir) const; - - static std::unique_ptr LoadFrom(TDirectory* dir); - - unsigned int NDimensions() const{return fLabels.size();} - std::vector GetLabels() const {return fLabels;} - std::vector GetBinnings() const {return fBins;} - - protected: - // Derived classes can be trusted take care of their own construction - ReweightableSpectrum(const std::vector& labels, - const std::vector& bins, - const Var& rwVar) - : fRWVar(rwVar), - fHist(0), fPOT(0), fLivetime(0), - fLabels(labels), fBins(bins) - { - } - - ReweightableSpectrum(const std::string& label, - const Binning& bins, - const Var& rwVar) - : fRWVar(rwVar), - fHist(0), fPOT(0), fLivetime(0), - fLabels(1, label), fBins(1, bins) - { - } - - /// Constructor needed by LoadFrom. Since there's no good - /// way to store a Var, ReweightVar will return nonsense - /// for ReweightableSpectrum that are loaded from a file - ReweightableSpectrum(TH2* h, - const std::vector& labels, - const std::vector& bins, - double pot, double livetime) - : ReweightableSpectrum(kUnweighted, h, labels, bins, pot, livetime) - { - } - - void RemoveLoader(SpectrumLoaderBase*); - void AddLoader(SpectrumLoaderBase*); - - Var fRWVar; ///< What goes on the y axis? - - TH2D* fHist; - double fPOT; - double fLivetime; - - std::vector fLabels; - std::vector fBins; - - std::string fTrueLabel; - - /// This count is maintained by SpectrumLoader, as a sanity check - std::set fLoaderCount; - }; -} diff --git a/sbnana/CAFAna/Core/SAMProjectSource.cxx b/sbnana/CAFAna/Core/SAMProjectSource.cxx deleted file mode 100644 index b2857459..00000000 --- a/sbnana/CAFAna/Core/SAMProjectSource.cxx +++ /dev/null @@ -1,105 +0,0 @@ -#include "sbnana/CAFAna/Core/SAMProjectSource.h" - -#include "sbnana/CAFAna/Core/Utilities.h" - -#include "ifdh.h" - -#include - -#ifdef DARWINBUILD -#include -#endif - -#include "TFile.h" - -namespace ana -{ - bool SAMProjectSource::fgGotTickets = false; - - //---------------------------------------------------------------------- - SAMProjectSource::SAMProjectSource(const std::string& proj, int fileLimit) - : fIFDH(new ifdh_ns::ifdh) - , fFile(0) - , fNFiles(fileLimit) - { - if(!fgGotTickets){ - // No kerberos ticket means no point trying to voms-proxy-init. It likely - // also means we're in a grid job, where that would be counterproductive - // anyway. - if(system("klist -5 -s || klist -s") != 0) fgGotTickets = true; - } - - if(!fgGotTickets){ - // This comes from NovaGridUtils, v02.10 onwards. - system("setup_fnal_security -b"); - - fgGotTickets = true; - } - - // If X509_USER_PROXY isn't set, set it manually. Can help unconfuse IFDH - // about what x509 it's supposed to be using. - if(getenv("X509_USER_PROXY") == 0) - setenv("X509_USER_PROXY", TString::Format("/tmp/x509up_u%d", getuid()).Data(), 0); - - fIFDH->set_debug("0"); // shut up - - fProjectURL = fIFDH->findProject(proj, SAMExperiment()); - - fProcessID = fIFDH->establishProcess(fProjectURL, "CAFAna", "v0.9", getenv("HOSTNAME"), getenv("USER"), SAMExperiment(), "", fileLimit); - } - - //---------------------------------------------------------------------- - SAMProjectSource::~SAMProjectSource() - { - if(fFile){ - // Tidy up the final file - const std::string fname = fFile->GetName(); - delete fFile; - unlink(fname.c_str()); - } - - // End the process cleanly - fIFDH->endProcess(fProjectURL, fProcessID); - - // certainly wrong for fileLimit case - // status = fIFDH.endProject(fProjectURL); - - fIFDH->cleanup(); - } - - //---------------------------------------------------------------------- - TFile* SAMProjectSource::GetNextFile() - { - if(fFile){ - // Tidy up the previous file - const std::string fname = fFile->GetName(); - delete fFile; - fFile = 0; - unlink(fname.c_str()); - - // And let SAM know we're done with it - fIFDH->updateFileStatus(fProjectURL, fProcessID, fname, "consumed"); - } - - std::string tmp; - - tmp = fIFDH->getNextFile(fProjectURL, fProcessID); - const std::string uri(tmp); - if(uri.empty()) return 0; // out of files - - tmp = fIFDH->fetchInput(uri); - const std::string fname(tmp); - assert(!fname.empty()); - - // Let SAM know we got it OK - fIFDH->updateFileStatus(fProjectURL, fProcessID, fname, "transferred"); - - // Additional newlines because ifdh currently spams us with certificate - // messages. - if(fNFiles < 0) std::cout << std::endl << "Processing " << basename((char *)fname.c_str()) << std::endl << std::endl; - - fFile = new TFile(fname.c_str()); - return fFile; - } -} // namespace - diff --git a/sbnana/CAFAna/Core/SAMProjectSource.h b/sbnana/CAFAna/Core/SAMProjectSource.h deleted file mode 100644 index 5d8eb611..00000000 --- a/sbnana/CAFAna/Core/SAMProjectSource.h +++ /dev/null @@ -1,37 +0,0 @@ -#include -#include - -#include "sbnana/CAFAna/Core/IFileSource.h" - -/// IFDH interface (data handling) -namespace ifdh_ns { - class ifdh; -} - -namespace ana -{ - /// Fetch files from a pre-existing SAM project - class SAMProjectSource: public IFileSource - { - public: - /// \param proj SAM project name (not URL) - /// \param fileLimit Optional maximum number of files to process - SAMProjectSource(const std::string& proj, int fileLimit = -1); - virtual ~SAMProjectSource(); - - virtual TFile* GetNextFile() override; - - int NFiles() const override {return fNFiles;} - protected: - ifdh_ns::ifdh *fIFDH; - - std::string fProjectURL; - std::string fProcessID; - - TFile* fFile; ///< The most-recently-returned file - - int fNFiles; - - static bool fgGotTickets; - }; -} diff --git a/sbnana/CAFAna/Core/SAMQuerySource.cxx b/sbnana/CAFAna/Core/SAMQuerySource.cxx deleted file mode 100644 index b8d1de77..00000000 --- a/sbnana/CAFAna/Core/SAMQuerySource.cxx +++ /dev/null @@ -1,295 +0,0 @@ -#include "sbnana/CAFAna/Core/SAMQuerySource.h" - -#include "sbnana/CAFAna/Core/Progress.h" -#include "sbnana/CAFAna/Core/Utilities.h" - -#include "ifdh.h" - -#include -#include -#include -#include -#include - -#include "TString.h" - -namespace ana -{ - //---------------------------------------------------------------------- - SAMQuerySource::SAMQuerySource(const std::string& query, - int stride, int offset) - // Stride and offset already taken account of in the query - : FileListSource(LocationsForSAMQuery(query, stride, offset), 1, 0) - { - } - - //---------------------------------------------------------------------- - SAMQuerySource::~SAMQuerySource() - { - } - - //---------------------------------------------------------------------- - std::string SAMQuerySource::EnsureDataset(const std::string& query) const - { - const char* user = getenv("GRID_USER"); - assert(user); - - TString dset = TString::Format("%s_cafana_%s", user, query.c_str()); - // Sanitize various special characters that can appear in queries - dset.ReplaceAll(" ", "_"); - dset.ReplaceAll("(", "_OPEN_"); - dset.ReplaceAll(")", "_CLOSE_"); - dset.ReplaceAll(":", "_COLON_"); - dset.ReplaceAll("'", "_SQUOTE_"); - dset.ReplaceAll("\"", "_DQUOTE_"); - - std::cout << "Creating dataset " << dset << " for query " << query << std::endl; - - // I would be much much happier to do this in proper code, but I'm not sure - // how, there's no samweb C++ API? - system(TString::Format("samweb -e %s list-definitions --defname %s | grep %s || samweb -e %s create-definition %s %s", - SAMExperiment().c_str(), - dset.Data(), - dset.Data(), - SAMExperiment().c_str(), - dset.Data(), - query.c_str()).Data()); - - return dset.Data(); - } - - //---------------------------------------------------------------------- - std::string SAMQuerySource::EnsureSnapshot(const std::string& def) const - { - const char* user = getenv("GRID_USER"); - assert(user); - const char* cluster = getenv("CLUSTER"); - assert(cluster); - const char* process = getenv("PROCESS"); - assert(process); - - // Jobs in the same cluster should share the same snapshot of the dataset - // so as not to hammer SAM with multiple requests for the same file list, - // but so that the dataset snapshot is updated with every new submission. - const std::string snap = TString::Format("%s_cafana_snap_%s_%s", - user, def.c_str(), cluster).Data(); - - // I'd love to do all this with a proper API, but samweb doesn't seem to - // have a C++ one? So we get this stew of system() calls... - - // Use this name as an indication that someone is working on creating the - // snapshot and every one else should stand by. - const std::string snaplock = TString::Format("%s_cafana_snap_lock_%s_%s", - user, def.c_str(), cluster).Data(); - - // Try to create the lock. Success means we have to create the snapshot, - // failure means someone else is working on it. The content of the - // definition (the nova.special) doesn't matter, except it has to be unique - // between the jobs, because trying to create an exact duplicate of an - // existing definition counts as success. - std::cout << "Checking lock " << snaplock << std::endl; - if(system(TString::Format("samweb -e %s create-definition %s file_name %s", - SAMExperiment().c_str(), - snaplock.c_str(), - process).Data()) == 0){ - // No one took the lock, it's up to us. Make the actual snapshot - std::cout << "Snapshotting " << def << " as " << snap << std::endl; - system(TString::Format("samweb -e %s take-snapshot %s | xargs samweb -e %s create-definition %s snapshot_id", - SAMExperiment().c_str(), - def.c_str(), - SAMExperiment().c_str(), - snap.c_str()).Data()); - } - else{ - // Lock already exists, just wait for the real snapshot to be created - double period = 1; - while(system(TString::Format("samweb -e %s list-definitions --defname %s | grep %s", - SAMExperiment().c_str(), - snap.c_str(), - snap.c_str()).Data()) != 0){ - sleep(int(period)); - period *= 1.5; - if(period > 60*30){ - std::cout << "We've been waiting a real long time for " << snap << " to be created. I don't think it's happening." << std::endl; - abort(); - } - } - } - std::cout << "Will use " << snap << std::endl; - - return snap; - } - - //---------------------------------------------------------------------- - std::string SAMQuerySource::IFDHBaseURI() const - { - // This is the same logic as implemented in the default ifdh() constructor, - // but using $SAM_EXPERIMENT in place of $EXPERIMENT - - // Allow user to override to arbitrary value - if(getenv("IFDH_BASE_URI")) return getenv("IFDH_BASE_URI"); - - return ifdh::_default_base_uri + SAMExperiment() + "/api"; - } - - //---------------------------------------------------------------------- - std::vector SAMQuerySource:: - LocationsForSAMQuery(const std::string& str, int stride, int offset) - { - TString query = str; - - // This is an actual query - if(query.Contains(' ') && RunningOnGrid()){ - // On the grid we want to convert that to a dataset we can snapshot below - query = EnsureDataset(query.Data()); - } - - // This is a dataset name - if(!query.Contains(' ')){ - if(getenv("CAFANA_USE_SNAPSHOTS")){ - query = "dataset_def_name_newest_snapshot "+query; - } - else{ - // Take one snapshot between all the jobs and share that - if(RunningOnGrid()) query = EnsureSnapshot(query.Data()); - - query = "defname: "+query; - } - } - - if(stride > 1){ - query += TString::Format(" with stride %d", stride).Data(); - if(offset > 0){ - query += TString::Format(" offset %d", offset).Data(); - } - } - - - std::cout << "Looking up files matching '" << query << "' using SAM...\n"; - - std::vector files; - - ifdh i(IFDHBaseURI()); - i.set_debug("0"); // shut up - try{ - files = i.translateConstraints(query.Data()); - } - catch(ifdh_util_ns::WebAPIException& e){ - // I like my error message below better, since this could well be a - // mistyped filename. - } - - if(files.empty()){ - std::cerr << "\nCan't find any files matching '" << str - << "'. Aborting..." << std::endl; - abort(); - } - - // IFDH likes to give back an empty string as the last response - // https://cdcvs.fnal.gov/redmine/issues/6718 - if(!files.empty() && files.back().empty()){ - files.pop_back(); - } - - return LocateSAMFiles(files); - } - - //---------------------------------------------------------------------- - std::vector SAMQuerySource:: - LocateSAMFiles(const std::vector& fnames) - { - std::vector ret; - - // We're going to fill this map of locations for all the files - std::map> locmap; - - Progress prog(TString::Format("Looking up locations of %ld files using SAM", fnames.size()).Data()); - - ifdh i(IFDHBaseURI()); - i.set_debug("0"); // shut up - - // locateFiles() saves the roundtrip time of talking to the server about - // every file individually, but it seems to bog down for large - // queries. Split the query into chunks. Experimentally this is about the - // sweet spot. - const unsigned int kStep = 50; - for(unsigned int fIdx = 0; fIdx < fnames.size(); fIdx += kStep){ - prog.SetProgress(double(fIdx)/fnames.size()); - - // The files we're looking up right now. Careful not to run off the end - // of the vector. - const std::vector fslice(fnames.begin()+fIdx, fIdx+kStep < fnames.size() ? fnames.begin()+fIdx+kStep : fnames.end()); - - const auto locslice = i.locateFiles(fslice); - - locmap.insert(locslice.begin(), locslice.end()); - } - - prog.Done(); - - - // Now go through the map and pick our favourite location for each file, - // and do some cleanup. - for(auto it: locmap){ - const std::string& f = it.first; - const std::vector& locs = it.second; - - int best = 0; - - std::string resolved; - for(TString loc: locs){ - // Never try to access bluearc locations from the grid - if(!RunningOnGrid() && loc.BeginsWith("novadata:") && best < 3){ - loc.Remove(0, 9); - - // Rewrite FNAL bluearc paths so users with matching directory - // structures offsite can access their local copies. - if(std::getenv("NOVA_ANA" )) loc.ReplaceAll("/nova/ana", std::getenv("NOVA_ANA")); - if(std::getenv("NOVA_APP" )) loc.ReplaceAll("/nova/app", std::getenv("NOVA_APP")); - if(std::getenv("NOVA_DATA")) loc.ReplaceAll("/nova/data", std::getenv("NOVA_DATA")); - if(std::getenv("NOVA_PROD")) loc.ReplaceAll("/nova/prod", std::getenv("NOVA_PROD")); - - // Check if the file exists at that location. If not, maybe pnfs has - // it. - struct stat junk; - if(stat((resolved+'/'+f).c_str(), &junk) == 0){ - best = 3; // Prefer bluearc locations - resolved = loc; - } - } - - if(loc.BeginsWith("dcache:") && best < 2){ - // Otherwise, used xrootd. Prefer "dache:" to "enstore:" because - // "dcache:" probably means /pnfs/nova/persistent/ so no chance of a - // huge wait for tape. - best = 2; - - // FileListSource does the actual conversion to xrootd - loc.ReplaceAll("dcache:/pnfs/", "/pnfs/"); - // Strip the bit in brackets from the end - if(loc.First('(') >= 0) loc.Resize(loc.First('(')); - resolved = loc; - } - - if(loc.BeginsWith("enstore:") && best < 1){ - best = 1; - - loc.ReplaceAll("enstore:/pnfs/", "/pnfs/"); - if(loc.First('(') >= 0) loc.Resize(loc.First('(')); - resolved = loc; - } - - } // end for loc - - if(best == 0 || resolved.empty()){ - std::cerr << "\nCouldn't find a usable location for " << f - << "'. Aborting..." << std::endl; - abort(); - } - - ret.push_back((resolved+'/'+f)); - } // end for fIdx - - return ret; - } -} diff --git a/sbnana/CAFAna/Core/SAMQuerySource.h b/sbnana/CAFAna/Core/SAMQuerySource.h deleted file mode 100644 index 40975fec..00000000 --- a/sbnana/CAFAna/Core/SAMQuerySource.h +++ /dev/null @@ -1,25 +0,0 @@ -#include "sbnana/CAFAna/Core/WildcardSource.h" - -namespace ana -{ - /// \brief File source based on a SAM query or dataset (definition) - /// - /// Locates the files on bluearc or pnfs (bluearc preferred). - class SAMQuerySource: public FileListSource - { - public: - /// \param query May be a SAM dataset name or a SAM query string - SAMQuerySource(const std::string& query, int stride = -1, int offset = -1); - virtual ~SAMQuerySource(); - protected: - std::vector LocationsForSAMQuery(const std::string& str, - int stride, int offset); - /// Take filenames, return locations suitable for TFile::Open() - std::vector LocateSAMFiles(const std::vector& fnames); - - std::string IFDHBaseURI() const; - - std::string EnsureDataset(const std::string& query) const; - std::string EnsureSnapshot(const std::string& def) const; - }; -} diff --git a/sbnana/CAFAna/Core/Spectrum.cxx b/sbnana/CAFAna/Core/Spectrum.cxx deleted file mode 100644 index df899a73..00000000 --- a/sbnana/CAFAna/Core/Spectrum.cxx +++ /dev/null @@ -1,998 +0,0 @@ -#include "sbnana/CAFAna/Core/Spectrum.h" - -#include "sbnana/CAFAna/Core/HistCache.h" -#include "sbnana/CAFAna/Core/Ratio.h" -#include "sbnana/CAFAna/Core/Utilities.h" -#include "sbnana/CAFAna/Core/MathUtil.h" - -#include "TDirectory.h" -#include "TH2.h" -#include "TH3.h" -#include "THnSparse.h" -#include "TObjString.h" -#include "TRandom3.h" - -#include -#include - -namespace ana -{ - //---------------------------------------------------------------------- - // The one constructor to rule them all. (Almost) everyone forwards here - Spectrum::Spectrum(const std::vector& labels, - const std::vector& bins, - ESparse sparse) - : fHist(0), fHistSparse(0), fPOT(0), fLivetime(0), - fLabels(labels), fBins(bins) - { - ConstructHistogram(sparse); - } - - //---------------------------------------------------------------------- - // Or here... - Spectrum::Spectrum(const std::string& label, - const Binning& bins, - ESparse sparse) - : fHist(0), fHistSparse(0), fPOT(0), fLivetime(0), - fLabels(1, label), fBins(1, bins) - { - ConstructHistogram(sparse); - } - - //---------------------------------------------------------------------- - Spectrum::Spectrum(const std::string& label, const Binning& bins, - SpectrumLoaderBase& loader, - const Var& var, - const SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift, - const Var& wei) - : Spectrum(label, bins) - { - loader.AddSpectrum(*this, var, spillcut, cut, shift, wei); - } - - //---------------------------------------------------------------------- - Spectrum::Spectrum(const std::string& label, const Binning& bins, - SpectrumLoaderBase& loader, - const SpillVar& var, - const SpillCut& cut, - const SpillVar& wei) - : Spectrum(label, bins) - { - loader.AddSpectrum(*this, var, cut, wei); - } - - //---------------------------------------------------------------------- - Spectrum::Spectrum(const std::string& label, const Binning& bins, - SpectrumLoaderBase& loader, - const MultiVar& var, - const SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift, - const Var& wei) - : Spectrum(label, bins) - { - loader.AddSpectrum(*this, var, spillcut, cut, shift, wei); - } - - //---------------------------------------------------------------------- - Spectrum::Spectrum(const std::string& label, const Binning& bins, - SpectrumLoaderBase& loader, - const SpillMultiVar& var, - const SpillCut& cut, - const SpillVar& wei) - : Spectrum(label, bins) - { - loader.AddSpectrum(*this, var, cut, wei); - } - - //---------------------------------------------------------------------- - Spectrum::Spectrum(SpectrumLoaderBase& loader, - const HistAxis& axis, - const SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift, - const Var& wei) - : Spectrum(axis.GetLabels(), axis.GetBinnings()) - { - loader.AddSpectrum(*this, axis.GetMultiDVar(), spillcut, cut, shift, wei); - } - - //---------------------------------------------------------------------- - Spectrum::Spectrum(const std::string& label, double pot, double livetime, - const Binning& bins) - : Spectrum(label, bins) - { - fPOT = pot; - fLivetime = livetime; - } - - //---------------------------------------------------------------------- - Spectrum::Spectrum(TH1* h, - const std::vector& labels, - const std::vector& bins, - double pot, double livetime) - : fHist(0), fHistSparse(0), fPOT(pot), fLivetime(livetime), fLabels(labels), fBins(bins) - { - if(!h){ - fHist = 0; - return; - } - - DontAddDirectory guard; - - const TString className = h->ClassName(); - - if(className == "TH1D"){ - // Shortcut if types match - fHist = HistCache::Copy((TH1D*)h); - } - else{ - fHist = HistCache::New("", h->GetXaxis()); - fHist->Add(h); - } - } - - //---------------------------------------------------------------------- - Spectrum::Spectrum(std::unique_ptr h, - const std::vector& labels, - const std::vector& bins, - double pot, double livetime) - : fHist(h.release()), fHistSparse(0), fPOT(pot), fLivetime(livetime), fLabels(labels), fBins(bins) - { - } - - //---------------------------------------------------------------------- - Spectrum::Spectrum(const std::string& label, SpectrumLoaderBase& loader, - const Binning& binsx, const Var& varx, - const Binning& binsy, const Var& vary, - const SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift, - const Var& wei) - : Spectrum(label, "", loader, binsx, varx, binsy, vary, spillcut, cut, shift, wei) - { - // TODO do we want this variant when there's one with a labelY just below? - } - - //---------------------------------------------------------------------- - Spectrum::Spectrum(const std::string& label, SpectrumLoaderBase& loader, - const Binning& binsx, const SpillVar& varx, - const Binning& binsy, const SpillVar& vary, - const SpillCut& spillcut, - const SpillVar& wei) - : Spectrum(label, "", loader, binsx, varx, binsy, vary, spillcut, wei) - { - // TODO do we want this variant when there's one with a labelY just below? - } - - //---------------------------------------------------------------------- - Spectrum::Spectrum(const std::string& label, SpectrumLoaderBase& loader, - const Binning& binsx, const MultiVar& varx, - const Binning& binsy, const MultiVar& vary, - const SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift, - const Var& wei) - : Spectrum(label, "", loader, binsx, varx, binsy, vary, spillcut, cut, shift, wei) - { - // TODO do we want this variant when there's one with a labelY just below? - } - - //---------------------------------------------------------------------- - Spectrum::Spectrum(const std::string& label, SpectrumLoaderBase& loader, - const Binning& binsx, const SpillMultiVar& varx, - const Binning& binsy, const SpillMultiVar& vary, - const SpillCut& spillcut, - const SpillVar& wei) - : Spectrum(label, "", loader, binsx, varx, binsy, vary, spillcut, wei) - { - // TODO do we want this variant when there's one with a labelY just below? - } - - //---------------------------------------------------------------------- - Spectrum::Spectrum(SpectrumLoaderBase& loader, - const HistAxis& xAxis, - const HistAxis& yAxis, - const SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift, - const Var& wei) - : Spectrum(xAxis.GetLabels()[0], loader, - xAxis.GetBinnings()[0], xAxis.GetVars()[0], - yAxis.GetBinnings()[0], yAxis.GetVars()[0], - spillcut, cut, shift, wei) - { - // TODO - do we want to keep this variant around? - assert(xAxis.NDimensions() == 1); - assert(yAxis.NDimensions() == 1); - } - - //---------------------------------------------------------------------- - 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 SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift, - const Var& wei) - : Spectrum({xLabel, yLabel}, {binsx, binsy}) - { - Var multiDVar = Var2D(varx, binsx, vary, binsy); - - loader.AddSpectrum(*this, multiDVar, spillcut, cut, shift, wei); - } - - //---------------------------------------------------------------------- - Spectrum::Spectrum(const std::string& xLabel, - const std::string& yLabel, - SpectrumLoaderBase& loader, - const Binning& binsx, const SpillVar& varx, - const Binning& binsy, const SpillVar& vary, - const SpillCut& spillcut, - const SpillVar& wei) - : Spectrum({xLabel, yLabel}, {binsx, binsy}) - { - SpillVar multiDVar = Var2D(varx, binsx, vary, binsy); - - loader.AddSpectrum(*this, multiDVar, spillcut, wei); - } - - //---------------------------------------------------------------------- - Spectrum::Spectrum(const std::string& xLabel, - const std::string& yLabel, - SpectrumLoaderBase& loader, - const Binning& binsx, const MultiVar& varx, - const Binning& binsy, const MultiVar& vary, - const SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift, - const Var& wei) - : Spectrum({xLabel, yLabel}, {binsx, binsy}) - { - MultiVar multiDVar = MultiVar2D(varx, binsx, vary, binsy); - - loader.AddSpectrum(*this, multiDVar, spillcut, cut, shift, wei); - } - - //---------------------------------------------------------------------- - Spectrum::Spectrum(const std::string& xLabel, - const std::string& yLabel, - SpectrumLoaderBase& loader, - const Binning& binsx, const SpillMultiVar& varx, - const Binning& binsy, const SpillMultiVar& vary, - const SpillCut& spillcut, - const SpillVar& wei) - : Spectrum({xLabel, yLabel}, {binsx, binsy}) - { - SpillMultiVar multiDVar = MultiVar2D(varx, binsx, vary, binsy); - - loader.AddSpectrum(*this, multiDVar, spillcut, wei); - } - - //---------------------------------------------------------------------- - Spectrum::Spectrum(const std::string& label, SpectrumLoaderBase& loader, - const Binning& binsx, const Var& varx, - const Binning& binsy, const Var& vary, - const Binning& binsz, const Var& varz, - const SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift, - const Var& wei, - ESparse sparse) - : Spectrum(label, "", "", loader, binsx, varx, binsy, vary, binsz, varz, spillcut, cut, shift, wei, sparse) - { - // TODO do we want this variant when there's one with a labelY and labelZ - // just below? - } - - //---------------------------------------------------------------------- - 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 SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift, - const Var& wei, - ESparse sparse) - : Spectrum({xLabel, yLabel, zLabel}, {binsx, binsy, binsz}, sparse) - { - Var multiDVar = Var3D(varx, binsx, vary, binsy, varz, binsz); - - loader.AddSpectrum(*this, multiDVar, spillcut, cut, shift, wei); - } - - //---------------------------------------------------------------------- - Spectrum::Spectrum(SpectrumLoaderBase& loader, - const HistAxis& xAxis, - const HistAxis& yAxis, - const HistAxis& zAxis, - const SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift, - const Var& wei, - ESparse sparse) - : Spectrum(xAxis.GetLabels()[0], loader, - xAxis.GetBinnings()[0], xAxis.GetVars()[0], - yAxis.GetBinnings()[0], yAxis.GetVars()[0], - zAxis.GetBinnings()[0], zAxis.GetVars()[0], - spillcut, cut, shift, wei, sparse) - { - // TODO - do we want to keep this variant around? - assert(xAxis.NDimensions() == 1); - assert(yAxis.NDimensions() == 1); - assert(zAxis.NDimensions() == 1); - } - - //---------------------------------------------------------------------- - Spectrum::~Spectrum() - { - if(fHist && fHist->GetDirectory()){ - static bool once = true; - if(once){ - once = false; - std::cerr << "Spectrum's fHist (" << fHist << ") is associated with a directory (" << fHist->GetDirectory() << ". How did that happen?" << std::endl; - } - } - - for (SpectrumLoaderBase* loader : fLoaderCount) - { loader->RemoveSpectrum(this); } - - HistCache::Delete(fHist); - - delete fHistSparse; - } - - //---------------------------------------------------------------------- - Spectrum::Spectrum(const Spectrum& rhs): - fHist(0), - fHistSparse(0), - fPOT(rhs.fPOT), - fLivetime(rhs.fLivetime), - fLabels(rhs.fLabels), - fBins(rhs.fBins) - { - DontAddDirectory guard; - - assert(rhs.fHist || rhs.fHistSparse); - if(rhs.fHist) - fHist = HistCache::Copy(rhs.fHist); - if(rhs.fHistSparse){ - // Doesn't exist? - // fHistSparse = new THnSparseD(*rhs.fHistSparse); - fHistSparse = (THnSparseD*)rhs.fHistSparse->Clone(); - } - - assert( rhs.fLoaderCount.empty() ); // Copying with pending loads is unexpected - } - - //---------------------------------------------------------------------- - Spectrum::Spectrum(Spectrum&& rhs): - fHist(0), - fHistSparse(0), - fPOT(rhs.fPOT), - fLivetime(rhs.fLivetime), - fLabels(rhs.fLabels), - fBins(rhs.fBins) - { - assert(rhs.fHist || rhs.fHistSparse); - - if(rhs.fHist){ - fHist = rhs.fHist; - rhs.fHist = 0; - } - if(rhs.fHistSparse){ - fHistSparse = rhs.fHistSparse; - rhs.fHistSparse = 0; - } - - assert( rhs.fLoaderCount.empty() ); // Copying with pending loads is unexpected - } - - //---------------------------------------------------------------------- - Spectrum& Spectrum::operator=(const Spectrum& rhs) - { - if(this == &rhs) return *this; - - DontAddDirectory guard; - - HistCache::Delete(fHist); - delete fHistSparse; - - assert(rhs.fHist || rhs.fHistSparse); - - if(rhs.fHist){ - fHist = HistCache::Copy(rhs.fHist); - fHistSparse = 0; - } - - if(rhs.fHistSparse){ - fHistSparse = (THnSparseD*)rhs.fHistSparse->Clone(); - fHist = 0; - } - - fPOT = rhs.fPOT; - fLivetime = rhs.fLivetime; - fLabels = rhs.fLabels; - fBins = rhs.fBins; - - assert( fLoaderCount.empty() ); // Copying with pending loads is unexpected - - return *this; - } - - //---------------------------------------------------------------------- - Spectrum& Spectrum::operator=(Spectrum&& rhs) - { - if(this == &rhs) return *this; - - HistCache::Delete(fHist); - delete fHistSparse; - - assert(rhs.fHist || rhs.fHistSparse); - - fHist = rhs.fHist; - fHistSparse = rhs.fHistSparse; - - fPOT = rhs.fPOT; - fLivetime = rhs.fLivetime; - fLabels = rhs.fLabels; - fBins = rhs.fBins; - - rhs.fHist = 0; - rhs.fHistSparse = 0; - - assert( fLoaderCount.empty() ); // Copying with pending loads is unexpected - - return *this; - } - - //---------------------------------------------------------------------- - void Spectrum::ConstructHistogram(ESparse sparse) - { - DontAddDirectory guard; - - assert(!fHist && !fHistSparse); - - Binning bins1D = fBins[0]; - if(fBins.size() > 1){ - int n = 1; - for(const Binning& b: fBins) n *= b.NBins(); - bins1D = Binning::Simple(n, 0, n); - } - - if(sparse){ - assert(bins1D.IsSimple()); - const int nbins = bins1D.NBins(); - const double xmin = bins1D.Min(); - const double xmax = bins1D.Max(); - fHistSparse = new THnSparseD(UniqueName().c_str(), UniqueName().c_str(), - 1, &nbins, &xmin, &xmax); - - // Ensure errors get accumulated properly - fHistSparse->Sumw2(); - } - else{ - fHist = HistCache::New("", bins1D); - - // Ensure errors get accumulated properly - fHist->Sumw2(); - } - } - - //---------------------------------------------------------------------- - TH1D* Spectrum::ToTH1(double exposure, Color_t col, Style_t style, - EExposureType expotype, - EBinType bintype) const - { - // Could have a file temporarily open - DontAddDirectory guard; - - TH1D* ret = 0; - if(fHist){ - ret = HistCache::Copy(fHist); - } - else{ - ret = fHistSparse->Projection(0); - } - - if(expotype == kPOT){ - const double pot = exposure; - if(fPOT){ - ret->Scale(pot/fPOT); - } - else{ - // Allow zero POT if there are also zero events - if(ret->Integral() > 0){ - std::cout << "Error: Spectrum with " << ret->Integral() - << " entries has zero POT, no way to scale to " - << exposure << " POT."; - if(fLivetime > 0){ - std::cout << " Spectrum has " << fLivetime << " seconds livetime. " - << "Did you mean to pass kLivetime to ToTH1()?"; - } - std::cout << std::endl; - // abort(); - // fPOT = 1e18; - ret->Scale(pot/1e18); //hack while we add spill tree - } - } - } - if(expotype == kLivetime){ - const double livetime = exposure; - if(fLivetime){ - ret->Scale(livetime/fLivetime); - } - else{ - // Allow zero exposure if there are also zero events - if(ret->Integral() > 0){ - std::cout << "Error: Spectrum with " << ret->Integral() - << " entries has zero livetime, no way to scale to " - << livetime << " seconds."; - if(fPOT > 0){ - std::cout << " Spectrum has " << fPOT << " POT. " - << "Did you mean to pass kPOT to ToTH1()?"; - } - std::cout << std::endl; - abort(); - } - } - } - - std::string label; - for(const std::string& l: fLabels) label += l + " and "; - label.resize(label.size()-5); // drop the last "and" - ret->GetXaxis()->SetTitle(label.c_str()); - - ret->GetYaxis()->SetTitle("Events"); - - - ret->SetLineColor(col); - ret->SetMarkerColor(col); - ret->SetLineStyle(style); - - if(bintype == kBinDensity) ret->Scale(1, "width"); - - // Allow GetMean() and friends to work even if this histogram never had any - // explicit Fill() calls made. - if(ret->GetEntries() == 0) ret->SetEntries(1); - - return ret; - } - - //---------------------------------------------------------------------- - TH2* Spectrum::ToTH2(double exposure, EExposureType expotype, EBinType bintype) const - { - if(fBins.size() != 2){ - std::cout << "Error: This Spectrum does not appear to be 2D." << std::endl; - abort(); - } - - TH2* ret = ana::ToTH2(*this, exposure, expotype, fBins[0], fBins[1]); - - ret->GetXaxis()->SetTitle(fLabels[0].c_str()); - ret->GetYaxis()->SetTitle(fLabels[1].c_str()); - - if(bintype == kBinDensity) ret->Scale(1, "width"); - - // Allow GetMean() and friends to work even if this histogram never had any - // explicit Fill() calls made. - if(ret->GetEntries() == 0) ret->SetEntries(1); - - return ret; - } - - //---------------------------------------------------------------------- - TH2* Spectrum::ToTH2NormX(double exposure, EExposureType expotype) const - { - TH2* xyhist = ToTH2(exposure, expotype); - if(!xyhist) return nullptr; - - const int nbinsx = fBins[0].NBins(); - const int nbinsy = fBins[1].NBins(); - - // Normalize 2D histogram to X-axis spectrum - for(int i=1; i<=nbinsx; ++i){ - double norm = 0.0; - for(int j=1; j<=nbinsy; ++j){ - norm += xyhist->GetBinContent(i, j); - } - /// If no entries in the column, skip normalization - if(norm < 0.0000001) continue; - - norm = 1.0 / norm; - for(int j=1; j<=nbinsy; ++j){ - xyhist->SetBinContent(i,j, xyhist->GetBinContent(i, j) * norm); - } - } - - // Allow GetMean() and friends to work even if this histogram never had any - // explicit Fill() calls made. - if(xyhist->GetEntries() == 0) xyhist->SetEntries(1); - - return xyhist; - } - - //---------------------------------------------------------------------- - TH3* Spectrum::ToTH3(double exposure, EExposureType expotype, EBinType bintype) const - { - if(fBins.size() != 3){ - std::cout << "Error: This Spectrum does not appear to be 3D." << std::endl; - abort(); - } - - TH3* ret = ana::ToTH3(*this, exposure, expotype, - fBins[0], fBins[1], fBins[2]); - - ret->GetXaxis()->SetTitle(fLabels[0].c_str()); - ret->GetYaxis()->SetTitle(fLabels[1].c_str()); - ret->GetZaxis()->SetTitle(fLabels[2].c_str()); - - if(bintype == kBinDensity) ret->Scale(1, "width"); - - // Allow GetMean() and friends to work even if this histogram never had any - // explicit Fill() calls made. - if(ret->GetEntries() == 0) ret->SetEntries(1); - - return ret; - } - - //---------------------------------------------------------------------- - TH1* Spectrum::ToTHX(double exposure, bool force1D, EExposureType expotype) const - { - if (force1D) return this->ToTH1(exposure, expotype); - switch(fBins.size()){ - case 1: - return this->ToTH1(exposure, expotype); - case 2: - return this->ToTH2(exposure, expotype); - case 3: - return this->ToTH3(exposure, expotype); - default: - std::cout << "Error: unable to hande number of dimensions (" << fBins.size() << ")" << std::endl; - abort(); - } - - return NULL; - } - - - //---------------------------------------------------------------------- - void Spectrum::Scale(double c) - { - fHist->Scale(c); - } - - //---------------------------------------------------------------------- - double Spectrum::Integral(double exposure, double* err, - EExposureType expotype) const - { - const double ratio = (expotype == kPOT) ? exposure/fPOT : exposure/fLivetime; - - if(err){ - *err = 0; - - for(int i = 0; i < fHist->GetNbinsX()+2; ++i){ - *err += util::sqr(fHist->GetBinError(i)); - } - *err = sqrt(*err) * ratio; - } - - // TODO how to integrate fHistSparse? - - return fHist->Integral(0, -1) * ratio; - } - - //---------------------------------------------------------------------- - double Spectrum::Mean() const - { - // Allow GetMean() to work even if this histogram never had any explicit - // Fill() calls made. - if(fHist->GetEntries() == 0) fHist->SetEntries(1); - return fHist->GetMean(); - } - - //---------------------------------------------------------------------- - void Spectrum::Fill(double x, double w) - { - assert( (fHist || fHistSparse) && "Somehow both fHist and fHistSparse are null in Spectrum::Fill" ); - - if(fHist) - fHist->Fill(x, w); - else if (fHistSparse) - fHistSparse->Fill(&x, w); - } - - //---------------------------------------------------------------------- - Spectrum Spectrum::MockData(double pot, bool makethrow, int seed) const - { - Spectrum ret = FakeData(pot); - - if (!makethrow) return ret; - - TRandom3 rnd(seed); // zero seeds randomly - - if(ret.fHist){ - for(int i = 0; i < ret.fHist->GetNbinsX()+2; ++i){ - ret.fHist->SetBinContent(i, rnd.Poisson(ret.fHist->GetBinContent(i))); - } - } - if(ret.fHistSparse){ - for(int i = 0; i < ret.fHistSparse->GetNbins(); ++i) - ret.fHistSparse->SetBinContent(i, rnd.Poisson(ret.fHistSparse->GetBinContent(i))); - } - - // Drop old errors, which are based on the MC statistics, and create new - // ones that are based on the prediction for the data - if(ret.fHist){ - ret.fHist->Sumw2(false); - ret.fHist->Sumw2(); - } - - return ret; - } - - //---------------------------------------------------------------------- - Spectrum Spectrum::FakeData(double pot) const - { - Spectrum ret = *this; - if(fPOT > 0){ - if(ret.fHist) - ret.fHist->Scale(pot/fPOT); - if(ret.fHistSparse) - ret.fHistSparse->Scale(pot/fPOT); - } - if(fLivetime > 0) ret.fLivetime *= pot/fPOT; - ret.fPOT = pot; - - // Drop old errors, which are based on the MC statistics, and create new - // ones that are based on the prediction for the data - if(ret.fHist){ - ret.fHist->Sumw2(false); - ret.fHist->Sumw2(); - } - - return ret; - } - - //---------------------------------------------------------------------- - void Spectrum::Clear() - { - fPOT = fLivetime = 0; - if(fHist) fHist->Reset(); - if(fHistSparse) fHistSparse->Reset(); - } - - //---------------------------------------------------------------------- - void Spectrum::RemoveLoader(SpectrumLoaderBase* p) - { fLoaderCount.erase(p); } - - //---------------------------------------------------------------------- - void Spectrum::AddLoader(SpectrumLoaderBase* p) - { fLoaderCount.insert(p); } - - //---------------------------------------------------------------------- - Spectrum& Spectrum::PlusEqualsHelper(const Spectrum& rhs, int sign) - { - // In this case it would be OK to have no POT/livetime - if(rhs.fHist && rhs.fHist->Integral(0, -1) == 0) return *this; - - // Empty RHS -> do nothing - if(rhs.fPOT == 0 && rhs.fLivetime == 0) return *this; - - // Empty LHS -> copy RHS (possibly with sign flip) - if(fPOT == 0 && fLivetime == 0){ - if(rhs.fHist) fHist->Add(rhs.fHist, sign); - if(rhs.fHistSparse) fHistSparse->Add(rhs.fHistSparse, sign); - fPOT = rhs.fPOT; - fLivetime = rhs.fLivetime; - return *this; - } - - 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 - if(rhs.fHist) fHist->Add(rhs.fHist, sign*fPOT/rhs.fPOT); - if(rhs.fHistSparse) fHistSparse->Add(rhs.fHistSparse, 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)){ - std::cout << "Attempting to combine two spectra with incompatible POT / livetime ratio " << fPOT << " / " << fLivetime << " vs " << rhs.fPOT << " / " << rhs.fLivetime << std::endl; - abort(); - } - } - 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 - if(rhs.fHist) fHist->Add(rhs.fHist, sign*fLivetime/rhs.fLivetime); - if(rhs.fHistSparse) fHistSparse->Add(rhs.fHistSparse, 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 << "Spectrum::operator+=(). How did we get here? " - << fPOT << " " << fLivetime << " " - << rhs.fPOT << " " << rhs.fLivetime << std::endl; - abort(); - } - - //---------------------------------------------------------------------- - Spectrum& Spectrum::operator+=(const Spectrum& rhs) - { - return PlusEqualsHelper(rhs, +1); - } - - //---------------------------------------------------------------------- - Spectrum Spectrum::operator+(const Spectrum& rhs) const - { - Spectrum ret = *this; - ret += rhs; - return ret; - } - - //---------------------------------------------------------------------- - Spectrum& Spectrum::operator-=(const Spectrum& rhs) - { - return PlusEqualsHelper(rhs, -1); - } - - //---------------------------------------------------------------------- - Spectrum Spectrum::operator-(const Spectrum& rhs) const - { - Spectrum ret = *this; - ret -= rhs; - return ret; - } - - //---------------------------------------------------------------------- - Spectrum& Spectrum::operator*=(const Ratio& rhs) - { - fHist->Multiply(rhs.fHist); - return *this; - } - - //---------------------------------------------------------------------- - Spectrum Spectrum::operator*(const Ratio& rhs) const - { - Spectrum ret = *this; - ret *= rhs; - return ret; - } - - //---------------------------------------------------------------------- - Spectrum& Spectrum::operator/=(const Ratio& rhs) - { - fHist->Divide(rhs.fHist); - return *this; - } - - //---------------------------------------------------------------------- - Spectrum Spectrum::operator/(const Ratio& rhs) const - { - Spectrum ret = *this; - ret /= rhs; - return ret; - } - - //---------------------------------------------------------------------- - void Spectrum::SaveTo(TDirectory* dir) const - { - TDirectory* tmp = gDirectory; - dir->cd(); - - TObjString("Spectrum").Write("type"); - - if(fHist) fHist->Write("hist"); - if(fHistSparse) fHistSparse->Write("hist_sparse"); - 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 < fBins.size(); ++i){ - TObjString(fLabels[i].c_str()).Write(TString::Format("label%d", i).Data()); - fBins[i].SaveTo(dir->mkdir(TString::Format("bins%d", i))); - } - - tmp->cd(); - } - - //---------------------------------------------------------------------- - std::unique_ptr Spectrum::LoadFrom(TDirectory* dir) - { - DontAddDirectory guard; - - TObjString* tag = (TObjString*)dir->Get("type"); - assert(tag); - assert(tag->GetString() == "Spectrum"); - delete tag; - - TH1D* spect = (TH1D*)dir->Get("hist"); - THnSparseD* spectSparse = (THnSparseD*)dir->Get("hist_sparse"); - assert(spect || spectSparse); - TH1* hPot = (TH1*)dir->Get("pot"); - assert(hPot); - TH1* hLivetime = (TH1*)dir->Get("livetime"); - assert(hLivetime); - - std::vector labels; - std::vector bins; - for(int i = 0; ; ++i){ - TDirectory* subdir = dir->GetDirectory(TString::Format("bins%d", i)); - if(!subdir) break; - bins.push_back(*Binning::LoadFrom(subdir)); - TObjString* label = (TObjString*)dir->Get(TString::Format("label%d", i)); - labels.push_back(label ? label->GetString().Data() : ""); - delete subdir; - delete label; - } - - if(bins.empty() && labels.empty()){ - // Must be an old file. Make an attempt at backwards compatibility. - if(spect){ - bins.push_back(Binning::FromTAxis(spect->GetXaxis())); - labels.push_back(spect->GetXaxis()->GetTitle()); - } - else{ - bins.push_back(Binning::FromTAxis(spectSparse->GetAxis(0))); - labels.push_back(spectSparse->GetAxis(0)->GetTitle()); - } - } - - std::unique_ptr ret; - if(spect){ - ret = std::make_unique(std::unique_ptr(spect), labels, bins, hPot->GetBinContent(1), hLivetime->GetBinContent(1)); - } - else{ - ret = std::make_unique((TH1*)0, labels, bins, hPot->GetBinContent(1), hLivetime->GetBinContent(1)); - ret->fHistSparse = spectSparse; - } - - delete hPot; - delete hLivetime; - - return ret; - } -} diff --git a/sbnana/CAFAna/Core/Spectrum.h b/sbnana/CAFAna/Core/Spectrum.h deleted file mode 100644 index 5168b080..00000000 --- a/sbnana/CAFAna/Core/Spectrum.h +++ /dev/null @@ -1,355 +0,0 @@ -#pragma once - -#include "sbnana/CAFAna/Core/Binning.h" -#include "sbnana/CAFAna/Core/Var.h" -#include "sbnana/CAFAna/Core/MultiVar.h" -#include "sbnana/CAFAna/Core/Cut.h" -#include "sbnana/CAFAna/Core/HistAxis.h" -#include "sbnana/CAFAna/Core/SpectrumLoaderBase.h" -#include "sbnana/CAFAna/Core/Utilities.h" - -#include "TAttLine.h" -#include "THnSparse.h" - -#include -#include -#include - -class TDirectory; -class TH1; -class TH2; -class TH3; -class TH1D; - -/// Oscillation analysis framework, runs over CAF files outside of ART -namespace ana -{ - class Ratio; - - /// Representation of a spectrum in any variable, with associated POT - class Spectrum - { - public: - friend class SpectrumLoaderBase; - friend class SpectrumLoader; - friend class NullLoader; - - enum ESparse{kDense, kSparse}; - - Spectrum(const std::string& label, const Binning& bins, - SpectrumLoaderBase& loader, - const Var& var, - const SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift = kNoShift, - const Var& wei = kUnweighted); - - Spectrum(const std::string& label, const Binning& bins, - SpectrumLoaderBase& loader, - const Var& var, - const Cut& cut, - const SystShifts& shift = kNoShift, - const Var& wei = kUnweighted) - : Spectrum(label, bins, loader, var, kNoSpillCut, cut, shift, wei) - { - } - - Spectrum(const std::string& label, const Binning& bins, - SpectrumLoaderBase& loader, - const SpillVar& var, - const SpillCut& cut, - const SpillVar& wei = kSpillUnweighted); - - /// The only \ref MultiVar variant available - Spectrum(const std::string& label, const Binning& bins, - SpectrumLoaderBase& loader, - const MultiVar& var, - const SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift = kNoShift, - const Var& wei = kUnweighted); - - // And the only SpillMultiVar - Spectrum(const std::string& label, const Binning& bins, - SpectrumLoaderBase& loader, - const SpillMultiVar& var, - const SpillCut& cut, - const SpillVar& wei = kSpillUnweighted); - - Spectrum(SpectrumLoaderBase& loader, - const HistAxis& axis, - const SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift = kNoShift, - const Var& wei = kUnweighted); - - Spectrum(SpectrumLoaderBase& loader, - const HistAxis& axis, - const Cut& cut, - const SystShifts& shift = kNoShift, - const Var& wei = kUnweighted) - : Spectrum(loader, axis, kNoSpillCut, cut, shift, wei) - { - } - - Spectrum(const std::string& label, const Binning& bins, ESparse sparse = kDense); - Spectrum(const std::string& label, double pot, double livetime, const Binning& bins); - - /// Copies \a h - Spectrum(TH1* h, - const std::vector& labels, - const std::vector& bins, - double pot, double livetime); - - /// Takes possession of \a h - Spectrum(std::unique_ptr h, - const std::vector& labels, - const std::vector& bins, - double pot, double livetime); - - /// 2D Spectrum of two Vars - Spectrum(const std::string& label, SpectrumLoaderBase& loader, - const Binning& binsx, const Var& varx, - const Binning& binsy, const Var& vary, - const SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift = kNoShift, - const Var& wei = kUnweighted); - - /// 2D Spectrum of two SpillVars - Spectrum(const std::string& label, SpectrumLoaderBase& loader, - const Binning& binsx, const SpillVar& varx, - const Binning& binsy, const SpillVar& vary, - const SpillCut& spillcut, - const SpillVar& wei = kSpillUnweighted); - - /// 2D Spectrum of two MultiVars - Spectrum(const std::string& label, SpectrumLoaderBase& loader, - const Binning& binsx, const MultiVar& varx, - const Binning& binsy, const MultiVar& vary, - const SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift = kNoShift, - const Var& wei = kUnweighted); - - /// 2D Spectrum of two SpillMultiVars - Spectrum(const std::string& label, SpectrumLoaderBase& loader, - const Binning& binsx, const SpillMultiVar& varx, - const Binning& binsy, const SpillMultiVar& vary, - const SpillCut& spillcut, - const SpillVar& wei = kSpillUnweighted); - - /// 2D Spectrum taking 2 HistAxis - Spectrum(SpectrumLoaderBase& loader, - const HistAxis& xAxis, - const HistAxis& yAxis, - const SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift = kNoShift, - const Var& wei = kUnweighted); - - Spectrum(const std::string& xLabel, - const std::string& yLabel, - SpectrumLoaderBase& loader, - const Binning& binsx, const Var& varx, - const Binning& binsy, const Var& vary, - const SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift = kNoShift, - const Var& wei = kUnweighted); - - Spectrum(const std::string& xLabel, - const std::string& yLabel, - SpectrumLoaderBase& loader, - const Binning& binsx, const SpillVar& varx, - const Binning& binsy, const SpillVar& vary, - const SpillCut& spillcut, - const SpillVar& wei = kSpillUnweighted); - - Spectrum(const std::string& xLabel, - const std::string& yLabel, - SpectrumLoaderBase& loader, - const Binning& binsx, const MultiVar& varx, - const Binning& binsy, const MultiVar& vary, - const SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift = kNoShift, - const Var& wei = kUnweighted); - - Spectrum(const std::string& xLabel, - const std::string& yLabel, - SpectrumLoaderBase& loader, - const Binning& binsx, const SpillMultiVar& varx, - const Binning& binsy, const SpillMultiVar& vary, - const SpillCut& spillcut, - const SpillVar& wei = kSpillUnweighted); - - /// 3D Spectrum of three Vars - Spectrum(const std::string& label, SpectrumLoaderBase& loader, - const Binning& binsx, const Var& varx, - const Binning& binsy, const Var& vary, - const Binning& binsz, const Var& varz, - const SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift = kNoShift, - const Var& wei = kUnweighted, - ESparse sparse = kDense); - - 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 SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift = kNoShift, - const Var& wei = kUnweighted, - ESparse sparse = kDense); - - /// 3D Spectrum taking 3 HistAxis - Spectrum(SpectrumLoaderBase& loader, - const HistAxis& xAxis, - const HistAxis& yAxis, - const HistAxis& zAxis, - const SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift = kNoShift, - const Var& wei = kUnweighted, - ESparse sparse = kDense); - - - virtual ~Spectrum(); - - Spectrum(const Spectrum& rhs); - Spectrum(Spectrum&& rhs); - Spectrum& operator=(const Spectrum& rhs); - Spectrum& operator=(Spectrum&& rhs); - - void Fill(double x, double w = 1); - - /// \brief Histogram made from this Spectrum, scaled to some exposure - /// - /// \param exposure POT or livetime (seconds) - /// \param col Histogram color (default black) - /// \param style Histogram line style (default solid) - /// \param expotype How to interpret exposure (kPOT (default) or kLivetime) - TH1D* ToTH1(double exposure, - Color_t col = kBlack, - Style_t style = kSolid, - EExposureType expotype = kPOT, - EBinType bintype = kBinContent) const; - - /// \brief Histogram made from this Spectrum, scaled to some exposure - /// - /// \param exposure POT or livetime (seconds) - /// \param expotype How to interpret exposure (kPOT (default) or kLivetime) - TH1D* ToTH1(double exposure, - EExposureType expotype, - EBinType bintype = kBinContent) const - { - return ToTH1(exposure, kBlack, kSolid, expotype, bintype); - } - - /// Spectrum must be 2D to obtain TH2 - TH2* ToTH2 (double exposure, EExposureType expotype = kPOT, - EBinType bintype = kBinContent) const; - /// Spectrum must be 2D to obtain TH2. Normalized to X axis. - TH2* ToTH2NormX(double exposure, EExposureType expotype = kPOT) const; - - /// Spectrum must be 3D to obtain TH3 - TH3* ToTH3 (double exposure, EExposureType expotype = kPOT, - EBinType bintype = kBinContent) const; - - /// Function decides what is the appropriate projection based on fBins, and does that - TH1* ToTHX (double exposure, bool force1D = false, EExposureType expotype = kPOT) const; - - /// \brief Return total number of events scaled to \a pot - /// - /// \param exposure POT/livetime to scale to - /// \param err The statistical error on this total (optional) - /// \param expotype What the first parameter represents - double Integral(double exposure, double* err = 0, - EExposureType expotype = kPOT) const; - - /// \brief Return mean of 1D histogram - double Mean() const; - - /// \brief Mock data is \ref FakeData with Poisson fluctuations applied - /// - /// Use for low-budget MDCs, or just getting a sense of the expected scale - /// of statistical variation - Spectrum MockData(double pot, bool makethrow=true, int seed=0) const; - /// \brief Fake data is a MC spectrum scaled to the POT expected in the data - /// - /// Use for sensitivity plots and testing fit convergence - Spectrum FakeData(double pot) const; - - double POT() const {return fPOT;} - - /// Seconds. For informational purposes only. No calculations use this. - double Livetime() const {return fLivetime;} - - /// DO NOT USE UNLESS YOU ARE 110% CERTAIN THERE ISN'T A BETTER WAY! - void OverridePOT(double newpot) {fPOT = newpot;} - - /// DO NOT USE UNLESS YOU ARE 110% CERTAIN THERE ISN'T A BETTER WAY! - void OverrideLivetime(double newlive) {fLivetime = newlive;} - - void Clear(); - - /// Multiply this spectrum by a constant c - void Scale(double c); - - // Arithmetic operators are as if these are unlike samples, each a - // contribution to one total, not seperate sources of stats for the same - // sample. - Spectrum& operator+=(const Spectrum& rhs); - Spectrum operator+(const Spectrum& rhs) const; - - Spectrum& operator-=(const Spectrum& rhs); - Spectrum operator-(const Spectrum& rhs) const; - - Spectrum& operator*=(const Ratio& rhs); - Spectrum operator*(const Ratio& rhs) const; - - Spectrum& operator/=(const Ratio& rhs); - Spectrum operator/(const Ratio& rhs) const; - - void SaveTo(TDirectory* dir) const; - static std::unique_ptr LoadFrom(TDirectory* dir); - - unsigned int NDimensions() const{return fLabels.size();} - std::vector GetLabels() const {return fLabels;} - std::vector GetBinnings() const {return fBins;} - - protected: - Spectrum(const std::vector& labels, - const std::vector& bins, - ESparse sparse = kDense); - - void ConstructHistogram(ESparse sparse = kDense); - - void RemoveLoader(SpectrumLoaderBase*); - void AddLoader(SpectrumLoaderBase*); - - /// Helper for operator+= and operator-= - Spectrum& PlusEqualsHelper(const Spectrum& rhs, int sign); - - TH1D* fHist; - THnSparseD* fHistSparse; - double fPOT; - double fLivetime; - - /// This count is maintained by SpectrumLoader, as a sanity check - std::set fLoaderCount; - - std::vector fLabels; - std::vector fBins; - }; - - // Commutative - inline Spectrum operator*(const Ratio& lhs, const Spectrum& rhs){return rhs*lhs;} - inline Spectrum operator/(const Ratio& lhs, const Spectrum& rhs){return rhs/lhs;} -} diff --git a/sbnana/CAFAna/Core/SpectrumLoader.cxx b/sbnana/CAFAna/Core/SpectrumLoader.cxx index 1efe1b8c..0495844e 100644 --- a/sbnana/CAFAna/Core/SpectrumLoader.cxx +++ b/sbnana/CAFAna/Core/SpectrumLoader.cxx @@ -1,12 +1,12 @@ #include "sbnana/CAFAna/Core/SpectrumLoader.h" -#include "sbnana/CAFAna/Core/Progress.h" -#include "sbnana/CAFAna/Core/ReweightableSpectrum.h" -#include "sbnana/CAFAna/Core/SAMProjectSource.h" -#include "sbnana/CAFAna/Core/Spectrum.h" -#include "sbnana/CAFAna/Core/Utilities.h" +#include "cafanacore/Progress.h" +#include "cafanacore/ReweightableSpectrum.h" +#include "cafanacore/SAMProjectSource.h" +#include "cafanacore/Spectrum.h" -#include "sbnana/CAFAna/Core/GenieWeightList.h" +#include "sbnana/CAFAna/Core/IRecordSink.h" +#include "sbnana/CAFAna/Core/Utilities.h" #include "sbnanaobj/StandardRecord/Proxy/SRProxy.h" @@ -15,39 +15,34 @@ #include #include "TFile.h" -#include "TH2.h" #include "TTree.h" namespace ana { //---------------------------------------------------------------------- - SpectrumLoader::SpectrumLoader(const std::string& wildcard, DataSource src, int max) - : SpectrumLoaderBase(wildcard, src), max_entries(max) + SpectrumLoader::SpectrumLoader(const std::string& wildcard, int max) + : SpectrumLoaderBase(wildcard), max_entries(max) { } //---------------------------------------------------------------------- - SpectrumLoader::SpectrumLoader(const std::vector& fnames, - DataSource src, int max) - : SpectrumLoaderBase(fnames, src), max_entries(max) + SpectrumLoader::SpectrumLoader(const std::vector& fnames, int max) + : SpectrumLoaderBase(fnames), max_entries(max) { } //---------------------------------------------------------------------- - SpectrumLoader::SpectrumLoader(DataSource src) - : SpectrumLoaderBase(src) + SpectrumLoader::SpectrumLoader() { } //---------------------------------------------------------------------- - SpectrumLoader SpectrumLoader::FromSAMProject(const std::string& proj, - DataSource src, - int fileLimit) + SpectrumLoader* SpectrumLoader::FromSAMProject(const std::string& proj, + int fileLimit) { - SpectrumLoader ret; - ret.fSource = src; - 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; } @@ -56,14 +51,6 @@ namespace ana { } - struct CompareByID - { - bool operator()(const Cut& a, const Cut& b) const - { - return a.ID() < b.ID(); - } - }; - //---------------------------------------------------------------------- void SpectrumLoader::Go() { @@ -73,17 +60,6 @@ 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()); - - const int Nfiles = NFiles(); Progress* prog = 0; @@ -94,7 +70,12 @@ namespace ana while(TFile* f = GetNextFile()){ ++fileIdx; - if(Nfiles >= 0 && !prog) prog = new Progress(TString::Format("Filling %lu spectra from %d files matching '%s'", fHistDefs.TotalSize(), Nfiles, fWildcard.c_str()).Data()); + if(Nfiles >= 0 && !prog){ + unsigned int totsinks = 0; + for(const ISpillSink* 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); @@ -108,8 +89,23 @@ namespace ana StoreExposures(); // also triggers the POT printout - fHistDefs.RemoveLoader(this); - fHistDefs.Clear(); + for(ISpillSink* 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 << "}"; + } + + //---------------------------------------------------------------------- + void SpectrumLoader::PrintGraph() const + { + PrintGraph(std::cout); } //---------------------------------------------------------------------- @@ -136,190 +132,35 @@ namespace ana for(long n = 0; n < Nentries; ++n){ tr->LoadTree(n); - // If there is no husk field there is no concept of husk events - if(!has_husk) sr.hdr.husk = false; - - HandleRecord(&sr); - - if(prog) prog->SetProgress(double(n)/Nentries); - } // end for n - } - - //---------------------------------------------------------------------- - /// Helper for \ref HandleRecord - template class CutVarCache - { - public: - CutVarCache() : fVals(U::MaxID()+1), fValsSet(U::MaxID()+1, false) {} - - inline T Get(const U& var, const V* sr) - { - const unsigned int id = var.ID(); - - if(fValsSet[id]){ - return fVals[id]; - } - else{ - const T val = var(sr); - fVals[id] = val; - fValsSet[id] = true; - return val; - } - } - - protected: - // Seems to be faster to do this than [unordered_]map - std::vector fVals; - std::vector fValsSet; - }; - - //---------------------------------------------------------------------- - void SpectrumLoader::HandleRecord(caf::SRSpillProxy* sr) - { - if(sr->hdr.first_in_subrun){ - fPOT += sr->hdr.pot; - // TODO think about if this should be gated behind first_in_file. At the - // moment I think these will be synonymous. And despite the comment on - // hdr.pot, I think it may be file-based in practice too. - if(sr->hdr.ismc) fNReadouts += sr->hdr.ngenevt; - } - - if(!sr->hdr.ismc){ - const int nbnb = sr->hdr.bnbinfo.size(); - const int nnumi = sr->hdr.numiinfo.size(); - if(nbnb > 0 && nnumi > 0){ - std::cout << "SpectrumLoader: nonzero number of both BNB (" << nbnb - << ") and NuMI (" << nnumi << ") triggers. I'm confused" - << std::endl; - abort(); + if(sr.hdr.first_in_subrun){ + fPOT += sr.hdr.pot; + // TODO think about if this should be gated behind first_in_file. At + // the moment I think these will be synonymous. And despite the comment + // on hdr.pot, I think it may be file-based in practice too. + if(sr.hdr.ismc) fNReadouts += sr.hdr.ngenevt; } - fNReadouts += nbnb + nnumi; - } - - // This record was only kept as a receptacle for exposure information. It - // shouldn't be included in any selected spectra. - if(sr->hdr.husk) return; - - // Do the spill-level spectra first. Keep this very simple because we - // intend to change it. - for(auto& spillcutdef: fSpillHistDefs){ - if(!spillcutdef.first(sr)) continue; - for(auto& spillweidef: spillcutdef.second){ - const double wei = spillweidef.first(sr); - if(wei == 0) continue; - for(auto spillvardef: spillweidef.second){ - if(spillvardef.first.IsMulti()){ - for(double val: spillvardef.first.GetMultiVar()(sr)){ - for(Spectrum* s: spillvardef.second.spects) s->Fill(val, wei); - } - } - else{ - const double val = spillvardef.first.GetVar()(sr); - for(Spectrum* s: spillvardef.second.spects) s->Fill(val, wei); - } + if(!sr.hdr.ismc){ + const int nbnb = sr.hdr.bnbinfo.size(); + const int nnumi = sr.hdr.numiinfo.size(); + if(nbnb > 0 && nnumi > 0){ + std::cout << "SpectrumLoader: nonzero number of both BNB (" << nbnb + << ") and NuMI (" << nnumi << ") triggers. I'm confused" + << std::endl; + abort(); } - } - } - - - for(auto& spillcutdef: fHistDefs){ - const SpillCut& spillcut = spillcutdef.first; - - const bool spillpass = spillcut(sr); // nomSpillCutCache.Get(spillcut, sr); - // Cut failed, skip all the histograms that depended on it - if(!spillpass) continue; - - for(caf::SRSliceProxy& slc: sr->slc){ - - // 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: spillcutdef.second){ - 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. - - caf::SRProxySystController::BeginTransaction(); - - bool shifted = false; - - double systWeight = 1; - // Can special-case nominal to not pay cost of Shift() - if(!shift.IsNominal()){ - shift.Shift(&slc, 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(&slc) : nomCutCache.Get(cut, &slc); - // Cut failed, skip all the histograms that depended on it - if(!pass) continue; - - for(auto& weidef: cutdef.second){ - const Var& weivar = weidef.first; - - double wei = shifted ? weivar(&slc) : nomWeiCache.Get(weivar, &slc); - - wei *= systWeight; - if(wei == 0) continue; - for(auto& vardef: weidef.second){ - if(vardef.first.IsMulti()){ - for(double val: vardef.first.GetMultiVar()(&slc)){ - for(Spectrum* s: vardef.second.spects) - s->Fill(val, wei); - } - continue; - } - - const Var& var = vardef.first.GetVar(); - - const double val = shifted ? var(&slc) : nomVarCache.Get(var, &slc); - - 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) s->Fill(val, wei); - - for(ReweightableSpectrum* rw: vardef.second.rwSpects){ - const double yval = rw->ReweightVar()(&slc); + fNReadouts += nbnb + nnumi; + } - 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; - } + // This record was only kept as a receptacle for exposure information. It + // shouldn't be included in any selected spectra. + if(has_husk && sr.hdr.husk) continue; - rw->fHist->Fill(val, yval, wei); - } // end for rw - } // end for vardef - } // end for weidef - } // end for cutdef + HandleRecord(&sr, 1); - // Return StandardRecord to its unshifted form ready for the next - // histogram. - caf::SRProxySystController::Rollback(); - } // end for shiftdef - } // end for slc - } // end for spillcutdef + if(prog) prog->SetProgress(double(n)/Nentries); + } // end for n } //---------------------------------------------------------------------- @@ -332,36 +173,8 @@ namespace ana std::cout << fPOT << " POT over " << fNReadouts << " readouts" << std::endl; - for(auto& shiftdef: fHistDefs){ - for(auto& spillcutdef: shiftdef.second){ - for(auto& cutdef: spillcutdef.second){ - for(auto& weidef: cutdef.second){ - for(auto& vardef: weidef.second){ - for(Spectrum* s: vardef.second.spects){ - s->fPOT += fPOT; - s->fLivetime += fNReadouts; - } - for(ReweightableSpectrum* rw: vardef.second.rwSpects){ - rw->fPOT += fPOT; - rw->fLivetime += fNReadouts; - } - } - } - } - } - } - - - for(auto& spillcutdef: fSpillHistDefs){ - for(auto& spillweidef: spillcutdef.second){ - for(auto spillvardef: spillweidef.second){ - for(Spectrum* s: spillvardef.second.spects){ - s->fPOT += fPOT; - s->fLivetime += fNReadouts; - } - } - } - } - + FillPOT(fPOT); + FillLivetime(fNReadouts); } + } // namespace diff --git a/sbnana/CAFAna/Core/SpectrumLoader.h b/sbnana/CAFAna/Core/SpectrumLoader.h index e3a8137e..7ce77c4d 100644 --- a/sbnana/CAFAna/Core/SpectrumLoader.h +++ b/sbnana/CAFAna/Core/SpectrumLoader.h @@ -2,6 +2,11 @@ #include "sbnana/CAFAna/Core/SpectrumLoaderBase.h" +#include "sbnana/CAFAna/Core/IRecordSource.h" +#include "sbnana/CAFAna/Core/IRecordSink.h" + +#include "cafanacore/Passthrough.h" + class TFile; namespace ana @@ -16,22 +21,24 @@ 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, DataSource src = kBeam, int max = 0); - SpectrumLoader(const std::vector& fnames, - DataSource src = kBeam, int max = 0); + SpectrumLoader(const std::string& wildcard, int max = 0); + SpectrumLoader(const std::vector& fnames, int max = 0); /// Named constructor for SAM projects - static SpectrumLoader FromSAMProject(const std::string& proj, - DataSource src = kBeam, - int fileLimit = -1); + static SpectrumLoader* FromSAMProject(const std::string& proj, + int fileLimit = -1); virtual ~SpectrumLoader(); virtual void Go() override; + virtual void PrintGraph(std::ostream& os) const override; + // Print to stdout + virtual void PrintGraph() const; + protected: - SpectrumLoader(DataSource src = kBeam); + SpectrumLoader(); // Move operations SpectrumLoader(SpectrumLoader&&) = default; @@ -43,15 +50,21 @@ namespace ana virtual void HandleFile(TFile* f, Progress* prog = 0); - virtual void HandleRecord(caf::SRSpillProxy* sr); - /// Save accumulated exposures into the individual spectra virtual void StoreExposures(); - /// All unique cuts contained in fHistDefs - // std::vector fAllCuts; - // std::vector fLivetimeByCut; ///< Indexing matches fAllCuts - // std::vector fPOTByCut; ///< Indexing matches fAllCuts int max_entries; }; + + + class NullLoader: public SpectrumLoader + { + public: + virtual void Go() override {} + }; + static NullLoader kNullLoader; + + + static NullSource kNullSpillSource; + static NullSource kNullSliceSource; } diff --git a/sbnana/CAFAna/Core/SpectrumLoaderBase.cxx b/sbnana/CAFAna/Core/SpectrumLoaderBase.cxx index ed42fb7f..0ad6b9e4 100644 --- a/sbnana/CAFAna/Core/SpectrumLoaderBase.cxx +++ b/sbnana/CAFAna/Core/SpectrumLoaderBase.cxx @@ -1,12 +1,13 @@ #include "sbnana/CAFAna/Core/SpectrumLoaderBase.h" -#include "sbnana/CAFAna/Core/Progress.h" -#include "sbnana/CAFAna/Core/ReweightableSpectrum.h" -#include "sbnana/CAFAna/Core/SAMQuerySource.h" -#include "sbnana/CAFAna/Core/SAMProjectSource.h" -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "cafanacore/Progress.h" +#include "cafanacore/ReweightableSpectrum.h" +#include "cafanacore/SAMQuerySource.h" +#include "cafanacore/SAMProjectSource.h" +#include "cafanacore/Spectrum.h" +#include "cafanacore/WildcardSource.h" + #include "sbnana/CAFAna/Core/Utilities.h" -#include "sbnana/CAFAna/Core/WildcardSource.h" #include "sbnanaobj/StandardRecord/Proxy/SRProxy.h" @@ -24,119 +25,21 @@ namespace ana { //---------------------------------------------------------------------- - void SpectrumLoaderBase::SpectList::Erase(Spectrum* s) - { - auto it = std::find(spects.begin(), spects.end(), s); - if(it != spects.end()) spects.erase(it); - } - - //---------------------------------------------------------------------- - void SpectrumLoaderBase::SpectList::Erase(ReweightableSpectrum* rs) - { - auto it = std::find(rwSpects.begin(), rwSpects.end(), rs); - if(it != rwSpects.end()) rwSpects.erase(it); - } - - //---------------------------------------------------------------------- - void SpectrumLoaderBase::SpectList::RemoveLoader(SpectrumLoaderBase* l) - { - for(Spectrum* s: spects) s->RemoveLoader(l); - for(ReweightableSpectrum* rs: rwSpects) rs->RemoveLoader(l); - } - - //---------------------------------------------------------------------- - size_t SpectrumLoaderBase::SpectList::TotalSize() const - { - return spects.size() + rwSpects.size(); - } - - //---------------------------------------------------------------------- - void SpectrumLoaderBase::SpectList::GetSpectra(std::vector& ss) - { - ss.insert(ss.end(), spects.begin(), spects.end()); - } - - //---------------------------------------------------------------------- - void SpectrumLoaderBase::SpectList:: - GetReweightableSpectra(std::vector& ss) - { - ss.insert(ss.end(), rwSpects.begin(), rwSpects.end()); - } - - //---------------------------------------------------------------------- - 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 template void SpectrumLoaderBase::IDMap::Erase(const V& v) - { - for(auto& it: fElems) it.second.Erase(v); - } - - //---------------------------------------------------------------------- - template void SpectrumLoaderBase::IDMap:: - RemoveLoader(SpectrumLoaderBase* l) + SpectrumLoaderBase::SpectrumLoaderBase() + : fGone(false), fPOT(0), fPOTFromHist(0), fNReadouts(0) { - 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; - } - - //---------------------------------------------------------------------- - template void SpectrumLoaderBase::IDMap:: - GetSpectra(std::vector& ss) - { - for(auto& it: fElems) it.second.GetSpectra(ss); - } - - //---------------------------------------------------------------------- - template void SpectrumLoaderBase::IDMap:: - GetReweightableSpectra(std::vector& ss) - { - for(auto& it: fElems) it.second.GetReweightableSpectra(ss); - } - - // Start of SpectrumLoaderBase proper - - //---------------------------------------------------------------------- - SpectrumLoaderBase::SpectrumLoaderBase(DataSource src) - : fSource(src), fGone(false), fPOT(0), fPOTFromHist(0), fNReadouts(0) - { - } - - //---------------------------------------------------------------------- - SpectrumLoaderBase::SpectrumLoaderBase(const std::string& wildcard, - DataSource src) - : SpectrumLoaderBase(src) + SpectrumLoaderBase::SpectrumLoaderBase(const std::string& wildcard) + : SpectrumLoaderBase() { fWildcard = wildcard; fFileSource = std::unique_ptr(WildcardOrSAMQuery(wildcard)); } //---------------------------------------------------------------------- - SpectrumLoaderBase::SpectrumLoaderBase(const std::vector& fnames, - DataSource src) - : SpectrumLoaderBase(src) + SpectrumLoaderBase::SpectrumLoaderBase(const std::vector& fnames) : SpectrumLoaderBase() { fWildcard = "file list"; fFileSource = std::unique_ptr(new FileListSource(fnames)); @@ -148,7 +51,6 @@ namespace ana //---------------------------------------------------------------------- SpectrumLoaderBase::~SpectrumLoaderBase() { - fHistDefs.RemoveLoader(this); } //---------------------------------------------------------------------- @@ -196,122 +98,6 @@ namespace ana return new SAMQuerySource(str, stride, offset); } - //---------------------------------------------------------------------- - void SpectrumLoaderBase::AddSpectrum(Spectrum& spect, - const Var& var, - const SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift, - const Var& wei) - { - if(fGone){ - std::cerr << "Error: can't add Spectra after the call to Go()" << std::endl; - abort(); - } - - fHistDefs[spillcut][shift][cut][wei][var].spects.push_back(&spect); - - spect.AddLoader(this); // Remember we have a Go() pending - } - - //---------------------------------------------------------------------- - void SpectrumLoaderBase::AddSpectrum(Spectrum& spect, - const MultiVar& var, - const SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift, - const Var& wei) - { - if(fGone){ - std::cerr << "Error: can't add Spectra after the call to Go()" << std::endl; - abort(); - } - - fHistDefs[spillcut][shift][cut][wei][var].spects.push_back(&spect); - - spect.AddLoader(this); // Remember we have a Go() pending - } - - //---------------------------------------------------------------------- - void SpectrumLoaderBase::AddSpectrum(Spectrum& spect, - const SpillVar& var, - const SpillCut& cut, - const SpillVar& wei) - { - if(fGone){ - std::cerr << "Error: can't add Spectra after the call to Go()" << std::endl; - abort(); - } - - fSpillHistDefs[cut][wei][var].spects.push_back(&spect); - - spect.AddLoader(this); // Remember we have a Go() pending - } - - //---------------------------------------------------------------------- - void SpectrumLoaderBase::AddSpectrum(Spectrum& spect, - const SpillMultiVar& var, - const SpillCut& cut, - const SpillVar& wei) - { - if(fGone){ - std::cerr << "Error: can't add Spectra after the call to Go()" << std::endl; - abort(); - } - - fSpillHistDefs[cut][wei][var].spects.push_back(&spect); - - spect.AddLoader(this); // Remember we have a Go() pending - } - - //---------------------------------------------------------------------- - void SpectrumLoaderBase::RemoveSpectrum(Spectrum* spect) - { - fHistDefs.Erase(spect); - } - - //---------------------------------------------------------------------- - void SpectrumLoaderBase::AddReweightableSpectrum(ReweightableSpectrum& spect, - const Var& var, - const Cut& cut, - const SystShifts& shift, - const Var& wei) - { - if(fGone){ - std::cerr << "Error: can't add Spectra after the call to Go()" << std::endl; - abort(); - } - - fHistDefs[kNoSpillCut][shift][cut][wei][var].rwSpects.push_back(&spect); - - spect.AddLoader(this); // Remember we have a Go() pending - } - - //---------------------------------------------------------------------- - void SpectrumLoaderBase::AddReweightableSpectrum(ReweightableSpectrum& spect, - const Var& var, - const SpillCut& spillcut, - const SliceCut& slicecut, - const SystShifts& shift, - const Var& wei) - { - if(fGone){ - std::cerr << "Error: can't add Spectra after the call to Go()" << std::endl; - abort(); - } - - fHistDefs[spillcut][shift][slicecut][wei][var].rwSpects.push_back(&spect); - - spect.AddLoader(this); // Remember we have a Go() pending - } - - //---------------------------------------------------------------------- - void SpectrumLoaderBase:: - RemoveReweightableSpectrum(ReweightableSpectrum* spect) - { - fHistDefs.Erase(spect); - } - //---------------------------------------------------------------------- int SpectrumLoaderBase::NFiles() const { @@ -330,20 +116,4 @@ namespace ana return f; } - - //---------------------------------------------------------------------- - void NullLoader::Go() - { - } - - //---------------------------------------------------------------------- - NullLoader::~NullLoader() - { - } - - // Apparently the existence of fSpillDefs isn't enough and I need to spell - // this out to make sure the function bodies are generated. - template struct SpectrumLoaderBase::IDMap>>>>; - - template struct SpectrumLoaderBase::IDMap>>; } // namespace diff --git a/sbnana/CAFAna/Core/SpectrumLoaderBase.h b/sbnana/CAFAna/Core/SpectrumLoaderBase.h index 10978c5b..9d44e6b5 100644 --- a/sbnana/CAFAna/Core/SpectrumLoaderBase.h +++ b/sbnana/CAFAna/Core/SpectrumLoaderBase.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -7,86 +8,30 @@ #include #include +#include "cafanacore/IFileSource.h" +#include "sbnana/CAFAna/Core/IRecordSource.h" + #include "sbnana/CAFAna/Core/Cut.h" -#include "sbnana/CAFAna/Core/IFileSource.h" #include "sbnana/CAFAna/Core/MultiVar.h" #include "sbnana/CAFAna/Core/SystShifts.h" #include "sbnana/CAFAna/Core/Var.h" +#include "sbnana/CAFAna/Core/Weight.h" namespace caf{class StandardRecord;} class TFile; -class TH1; -class TTree; namespace ana { class Spectrum; class ReweightableSpectrum; - /// Is this data-file representing beam spills or cosmic spills? - enum DataSource{ - // TODO there are no longer any actions taken as a result of this - // distinction. Remove after SA. - kBeam, - kCosmic - }; - /// Base class for the various types of spectrum loader class SpectrumLoaderBase { public: - - 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 SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift, - const Var& wei = kUnweighted); - - /// For use by the \ref Spectrum constructor - virtual void AddSpectrum(Spectrum& spect, - const MultiVar& var, - const SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift, - const Var& wei = kUnweighted); - - /// For use by the \ref Spectrum constructor - virtual void AddSpectrum(Spectrum& spect, - const SpillVar& var, - const SpillCut& cut, - const SpillVar& wei = kSpillUnweighted); - - /// For use by the \ref Spectrum constructor - virtual void AddSpectrum(Spectrum& spect, - const SpillMultiVar& var, - const SpillCut& cut, - const SpillVar& wei = kSpillUnweighted); - - /// For use by the constructors of \ref ReweightableSpectrum subclasses - virtual void AddReweightableSpectrum(ReweightableSpectrum& spect, - const Var& var, - const Cut& cut, - const SystShifts& shift, - const Var& wei); - - /// For use by the constructors of \ref ReweightableSpectrum subclasses - virtual void AddReweightableSpectrum(ReweightableSpectrum& spect, - const Var& var, - const SpillCut& spillcut, - const SliceCut& slicecut, - const SystShifts& shift, - const Var& wei); - /// Load all the registered spectra virtual void Go() = 0; @@ -95,11 +40,11 @@ namespace ana protected: /// Component of other constructors - SpectrumLoaderBase(DataSource src = kBeam); + SpectrumLoaderBase(); /// Construct from a filename, wildcard, SAM definition, or SAM query - SpectrumLoaderBase(const std::string& wildcard, DataSource src = kBeam); + SpectrumLoaderBase(const std::string& wildcard); /// Construct from an explicit list of files - SpectrumLoaderBase(const std::vector& fnames, DataSource src = kBeam); + SpectrumLoaderBase(const std::vector& fnames); // Move operations SpectrumLoaderBase(SpectrumLoaderBase&&) = default; @@ -112,10 +57,6 @@ namespace ana /// Figure out if \a str is a wildcard or SAM query and return a source IFileSource* WildcardOrSAMQuery(const std::string& str) const; - friend class SpectrumLoaderMockData; - virtual void RemoveSpectrum(Spectrum*); - virtual void RemoveReweightableSpectrum(ReweightableSpectrum*); - /// Forwards to \ref fFileSource int NFiles() const; @@ -124,147 +65,10 @@ namespace ana std::string fWildcard; std::unique_ptr fFileSource; - DataSource fSource; - bool fGone; ///< Has Go() been called? Can't add more histograms after that double fPOT; double fPOTFromHist; ///< Accumulated by calls to \ref GetNextFile int fNReadouts; - - /// \brief Helper class for \ref SpectrumLoaderBase - /// - /// List of Spectrum and OscillatableSpectrum, some utility functions - struct SpectList - { - void Erase(Spectrum* s); - void Erase(ReweightableSpectrum* os); - void RemoveLoader(SpectrumLoaderBase* l); - size_t TotalSize() const; - void GetSpectra(std::vector& ss); - void GetReweightableSpectra(std::vector& ss); - - 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();} - - template void Erase(const V& v); - void RemoveLoader(SpectrumLoaderBase* l); - void Clear(); - size_t TotalSize(); - void GetSpectra(std::vector& ss); - void GetReweightableSpectra(std::vector& ss); - protected: - std::vector> fElems; - }; - - template 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; - }; - - typedef _VarOrMultiVar VarOrMultiVar; - typedef _VarOrMultiVar SpillVarOrMultiVar; - - /// \brief All the spectra that need to be filled - /// - /// [spillcut][shift][cut][wei][var] - IDMap>>>> fHistDefs; - /// [spillcut][spillwei][spillvar] - IDMap>> fSpillHistDefs; - }; - - /// \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 SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift, - const Var& wei = kUnweighted) override {} - void AddSpectrum(Spectrum& spect, - const MultiVar& var, - const SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift, - const Var& wei = kUnweighted) override {} - - void AddSpectrum(Spectrum& spect, - const SpillVar& var, - const SpillCut& cut, - const SpillVar& wei = kSpillUnweighted) override {} - - void AddSpectrum(Spectrum& spect, - const SpillMultiVar& var, - const SpillCut& cut, - const SpillVar& wei = kSpillUnweighted) override {} - - void AddReweightableSpectrum(ReweightableSpectrum& spect, - const Var& var, - const Cut& cut, - const SystShifts& shift, - const Var& wei) override {} - - void AddReweightableSpectrum(ReweightableSpectrum& spect, - const Var& var, - const SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift, - const Var& 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/sbnana/CAFAna/Core/StanTypedefs.h b/sbnana/CAFAna/Core/StanTypedefs.h new file mode 100644 index 00000000..08d8440b --- /dev/null +++ b/sbnana/CAFAna/Core/StanTypedefs.h @@ -0,0 +1,54 @@ +/// StanTypedefs.h: +/// Typedefs of various types templated over stan::math::var, +/// centralized here for convenience. +/// They don't get put in the header files associated with the types themselves +/// because there's an annoying chain of declarations needed for the typedef'ing, +/// and it's much easier to maintain if it's in a single place. +#pragma once + +#include "stan/math/rev/core/var_value_fwd_declare.hpp" + +namespace stan +{ + namespace math + { + typedef var_value var; + } +} + +namespace osc +{ + template class _IOscCalcAdjustable; + typedef _IOscCalcAdjustable IOscCalcAdjustableStan; + + template class _IOscCalc; + typedef _IOscCalc IOscCalcStan; + + template class _OscCalcDMP; + typedef _OscCalcDMP OscCalcDMPStan; + + template class _OscCalcPMNS; + typedef _OscCalcPMNS OscCalcPMNSStan; + + template class _OscCalcPMNSOpt; + typedef _OscCalcPMNSOpt OscCalcPMNSOptStan; + + namespace analytic{template class _OscCalc;} + typedef analytic::_OscCalc OscCalcAnalyticStan; +} + +namespace ana +{ + // note: typedefs over forward-declared types are fragile. + // if either the underlying type changes, its forward declaration + // needs to be updated here. + + // --------------------- + // vars + template class _IFitVar; + typedef _IFitVar IFitVarStan; + + template class _IConstrainedFitVar; + typedef _IConstrainedFitVar IConstrainedFitVarStan; + +} diff --git a/sbnana/CAFAna/Core/SystRegistry.cxx b/sbnana/CAFAna/Core/SystRegistry.cxx deleted file mode 100644 index 17882fee..00000000 --- a/sbnana/CAFAna/Core/SystRegistry.cxx +++ /dev/null @@ -1,95 +0,0 @@ -#include "sbnana/CAFAna/Core/SystRegistry.h" - -#include - -#include - -namespace ana -{ - //---------------------------------------------------------------------- - std::map& SystRegistry::Map() - { - // https://isocpp.org/wiki/faq/ctors#static-init-order - static auto m = new std::map; - return *m; - } - - //---------------------------------------------------------------------- - void SystRegistry::Register(const ISyst* s) - { - const std::string name = s->ShortName(); - - if(Map().count(name)){ - std::cout << "SystRegistry: Warning: systematic '" << name - << "' registered multiple times." << std::endl - << "Check you declared it with 'extern' in the .h and " - << "instantiated it in the .cxx and check for other ISysts " - << "that happen to have the same name." << std::endl; - // Store an entry there, so we can detect further duplicates, but make it - // invalid. - Map()[name] = 0; - return; - } - - Map()[name] = s; - } - - //---------------------------------------------------------------------- - void SystRegistry::UnRegister(const ISyst* s) - { - auto it = Map().find(s->ShortName()); - - if(it == Map().end()){ - std::cout << "SystRegistry: Error: unregistering ISyst '" - << s->ShortName() << "' that was never registered!" - << std::endl; - return; - } - - // If was multiply registered, leave that signal - if(it->second) Map().erase(it); - } - - //---------------------------------------------------------------------- - const ISyst* SystRegistry::ShortNameToSyst(const std::string& s, - bool allowFail) - { - auto it = Map().find(s); - if(it == Map().end()){ - if(allowFail) return 0; - std::cout << "SystRegistry: Error: Syst '" << s << "' not found. " - << "Pass allowFail=true to return NULL in this case." - << std::endl; - abort(); - } - - const ISyst* ret = it->second; - - if(!ret){ - std::cout << "SystRegistry: Error: Syst '" << s - << "' was registered multiple times. Refusing to return a" - << " random instance. Go fix the syst registration." - << std::endl; - abort(); - } - - return ret; - } - - //---------------------------------------------------------------------- - void SystRegistry::Print() - { - std::cout << Map().size() << " ISysts:" << std::endl; - for(auto it: Map()){ - std::cout << it.first << " :\t"; - - if(it.second){ - std::cout << abi::__cxa_demangle(typeid(*it.second).name(), 0, 0, 0) - << " at " << it.second << std::endl; - } - else{ - std::cout << "MULTIPLY REGISTERED!" << std::endl; - } - } - } -} diff --git a/sbnana/CAFAna/Core/SystRegistry.h b/sbnana/CAFAna/Core/SystRegistry.h deleted file mode 100644 index d6f004ee..00000000 --- a/sbnana/CAFAna/Core/SystRegistry.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include "sbnana/CAFAna/Core/ISyst.h" - -#include -#include - -namespace ana -{ - class SystRegistry - { - public: - static void Register(const ISyst* s); - - static void UnRegister(const ISyst* s); - - static const ISyst* ShortNameToSyst(const std::string& s, - bool allowFail = false); - - static void Print(); - protected: - static std::map& Map(); - }; -} diff --git a/sbnana/CAFAna/Core/SystShifts.cxx b/sbnana/CAFAna/Core/SystShifts.cxx index 6a56c68a..fd0fd54a 100644 --- a/sbnana/CAFAna/Core/SystShifts.cxx +++ b/sbnana/CAFAna/Core/SystShifts.cxx @@ -1,7 +1,7 @@ #include "sbnana/CAFAna/Core/SystShifts.h" #include "sbnana/CAFAna/Core/MathUtil.h" -#include "sbnana/CAFAna/Core/SystRegistry.h" +#include "cafanacore/Registry.h" #include @@ -16,6 +16,8 @@ namespace ana // Reserve 0 for unshifted int SystShifts::fgNextID = 1; + const SystShifts kNoShift = SystShifts::Nominal(); + //---------------------------------------------------------------------- SystShifts::SystShifts() : fID(0) { @@ -35,6 +37,13 @@ namespace ana for(auto it: shifts) if(it.second != 0) fSysts.emplace(it.first, it.second); } + //---------------------------------------------------------------------- + SystShifts::SystShifts(const std::unordered_map& shifts) + : fID(fgNextID++) + { + for(auto it: shifts) if(it.second != 0) fSysts.emplace(it.first, it.second); + } + //---------------------------------------------------------------------- SystShifts SystShifts::RandomThrow(const std::vector& systs) { @@ -125,11 +134,13 @@ namespace ana } //---------------------------------------------------------------------- - void SystShifts::SaveTo(TDirectory* dir) const + void SystShifts::SaveTo(TDirectory* dir, const std::string& name) const { TDirectory* tmp = gDirectory; + dir = dir->mkdir(name.c_str()); // switch to subdir dir->cd(); + TObjString("SystShifts").Write("type"); // Don't write any histogram for the nominal case @@ -144,12 +155,18 @@ namespace ana h.Write("vals"); } + dir->Write(); + delete dir; + tmp->cd(); } //---------------------------------------------------------------------- - std::unique_ptr SystShifts::LoadFrom(TDirectory* dir) + std::unique_ptr SystShifts::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() == "SystShifts"); @@ -159,7 +176,7 @@ namespace ana TH1* h = (TH1*)dir->Get("vals"); if(h){ // no histogram means nominal for(int i = 1; i <= h->GetNbinsX(); ++i){ - ret->SetShift(SystRegistry::ShortNameToSyst(h->GetXaxis()->GetBinLabel(i)), + ret->SetShift(Registry::ShortNameToPtr(h->GetXaxis()->GetBinLabel(i)), h->GetBinContent(i)); } } diff --git a/sbnana/CAFAna/Core/SystShifts.h b/sbnana/CAFAna/Core/SystShifts.h index 38077a18..7bdebc61 100644 --- a/sbnana/CAFAna/Core/SystShifts.h +++ b/sbnana/CAFAna/Core/SystShifts.h @@ -19,6 +19,7 @@ namespace ana SystShifts(); SystShifts(const ISyst* syst, double shift); SystShifts(const std::map& shifts); + SystShifts(const std::unordered_map& shifts); static SystShifts Nominal(){return SystShifts();} static SystShifts RandomThrow(const std::vector& systs); @@ -46,8 +47,8 @@ namespace ana std::vector ActiveSysts() const; - void SaveTo(TDirectory* dir) const; - static std::unique_ptr LoadFrom(TDirectory* dir); + void SaveTo(TDirectory* dir, const std::string& name) const; + static std::unique_ptr LoadFrom(TDirectory* dir, const std::string& name); protected: @@ -58,5 +59,5 @@ namespace ana static int fgNextID; }; - const SystShifts kNoShift = SystShifts::Nominal(); + extern const SystShifts kNoShift; } diff --git a/sbnana/CAFAna/Core/ThreadPool.cxx b/sbnana/CAFAna/Core/ThreadPool.cxx deleted file mode 100644 index db0ad569..00000000 --- a/sbnana/CAFAna/Core/ThreadPool.cxx +++ /dev/null @@ -1,110 +0,0 @@ -#include "sbnana/CAFAna/Core/ThreadPool.h" - -#include "sbnana/CAFAna/Core/Progress.h" - -#include -#include - -namespace ana -{ - //---------------------------------------------------------------------- - ThreadPool::ThreadPool(unsigned int maxThreads) - : fMaxThreads(maxThreads), fNumLiveThreads(0), - fTasksCompleted(0), fTotalTasks(0), fProgress(0) - { - if(maxThreads == 0){ - fMaxThreads = sysconf(_SC_NPROCESSORS_ONLN); - } - - pthread_mutex_init(&fTasksLock, 0); - pthread_mutex_init(&fThreadsLock, 0); - pthread_mutex_init(&fProgressLock, 0); - } - - //---------------------------------------------------------------------- - ThreadPool::~ThreadPool() - { - // This is safe, even if it's already been explicitly called - Finish(); - - pthread_mutex_destroy(&fTasksLock); - pthread_mutex_destroy(&fThreadsLock); - pthread_mutex_destroy(&fProgressLock); - - delete fProgress; - } - - //---------------------------------------------------------------------- - void ThreadPool::ShowProgress(const std::string& title) - { - if(!fProgress) fProgress = new Progress(title); - } - - //---------------------------------------------------------------------- - void ThreadPool::Finish() - { - void* junk; - for(pthread_t& th: fThreads) pthread_join(th, &junk); - - assert(fNumLiveThreads == 0); - - fThreads.clear(); // Make it safe to call a second time - - if(fProgress) fProgress->Done(); - } - - //---------------------------------------------------------------------- - void* ThreadPool::WorkerFunc(void* arg) - { - // We smuggle essentially the this pointer in through the argument - ThreadPool* pool = (ThreadPool*)arg; - - while(true){ - pthread_mutex_lock(&pool->fTasksLock); - if(pool->fTasks.empty()){ - // Nothing to do, commit suicide - pthread_mutex_unlock(&pool->fTasksLock); - - pthread_mutex_lock(&pool->fThreadsLock); - --pool->fNumLiveThreads; - pthread_mutex_unlock(&pool->fThreadsLock); - - return 0; - } - // Get a task to do - func_t task = pool->fTasks.front(); - pool->fTasks.pop_front(); - pthread_mutex_unlock(&pool->fTasksLock); - - // Actually do the user's work - task(); - - pthread_mutex_lock(&pool->fProgressLock); - ++pool->fTasksCompleted; - - if(pool->fProgress) - pool->fProgress->SetProgress(pool->fTasksCompleted/double(pool->fTotalTasks)); - pthread_mutex_unlock(&pool->fProgressLock); - } - } - - //---------------------------------------------------------------------- - void ThreadPool::AddTaskHelper(func_t func) - { - pthread_mutex_lock(&fTasksLock); - fTasks.push_back(func); - pthread_mutex_unlock(&fTasksLock); - - pthread_mutex_lock(&fProgressLock); - ++fTotalTasks; - pthread_mutex_unlock(&fProgressLock); - - pthread_mutex_lock(&fThreadsLock); - if(fNumLiveThreads < fMaxThreads){ - fThreads.push_back(pthread_t()); - pthread_create(&fThreads.back(), 0, WorkerFunc, this); - ++fNumLiveThreads; - } - pthread_mutex_unlock(&fThreadsLock); - } -} diff --git a/sbnana/CAFAna/Core/ThreadPool.h b/sbnana/CAFAna/Core/ThreadPool.h deleted file mode 100644 index eebbf79e..00000000 --- a/sbnana/CAFAna/Core/ThreadPool.h +++ /dev/null @@ -1,81 +0,0 @@ -#pragma once - -#include -#include -#include - -#include "pthread.h" - -namespace ana -{ - class Progress; - - /// \brief A very simple thread pool for use by \ref Surface - /// - /// With great power comes great responsibility. Use caution on the grid or - /// on shared interactive machines before you get yelled at or banned. - class ThreadPool - { - public: - /// \param maxThreads Maximum number of threads to use at one time. - /// If unspecified, uses number of cores in machine. - /// Use great caution on the grid or on shared - /// interactive machines. - explicit ThreadPool(unsigned int maxThreads = 0); - virtual ~ThreadPool(); - - void ShowProgress(const std::string& title); - - /// Wait for all threads to complete before returning - void Finish(); - - /// Add task with arguments - template void AddTask(F func, A... args); - - /// Add member function task, with arguments - template void AddMemberTask(T* obj, M meth, A... args); - - - protected: - /// \brief The type of the user's worker functions - /// - /// Use std::bind etc to pass arguments - typedef std::function func_t; - - void AddTaskHelper(func_t func); - - - static void* WorkerFunc(void* arg); - - unsigned int fMaxThreads; - - struct Task{func_t func; void* ctx;}; - - pthread_mutex_t fTasksLock; - std::deque fTasks; - - ///< Actually, this is protecting \ref fNumLiveThreads - pthread_mutex_t fThreadsLock; - std::vector fThreads; ///< All threads we ever created - unsigned int fNumLiveThreads; ///< Number of threads that are running - - /// Protects \ref fTasksCompleted and \ref fTotalTasks too - pthread_mutex_t fProgressLock; - int fTasksCompleted; - int fTotalTasks; ///< How many tasks have we ever seen? - Progress* fProgress; - }; -} - - -/// Add task with arguments -template inline void ana::ThreadPool::AddTask(F func, A... args) -{ - AddTaskHelper(std::bind(func, args...)); -} - -/// Add member function task, with arguments -template inline void ana::ThreadPool::AddMemberTask(T* obj, M meth, A... args) -{ - AddTaskHelper(std::bind(meth, obj, args...)); -} diff --git a/sbnana/CAFAna/Core/Utilities.cxx b/sbnana/CAFAna/Core/Utilities.cxx index bdf569b4..0e14d28a 100644 --- a/sbnana/CAFAna/Core/Utilities.cxx +++ b/sbnana/CAFAna/Core/Utilities.cxx @@ -1,7 +1,8 @@ +#include "cafanacore/Spectrum.h" + #include "sbnana/CAFAna/Core/Utilities.h" -#include "sbnana/CAFAna/Core/Spectrum.h" -#include "sbnana/CAFAna/Core/Ratio.h" +#include "cafanacore/Ratio.h" #include "sbnana/CAFAna/Core/MathUtil.h" #include "TArrayD.h" @@ -28,26 +29,6 @@ namespace ana { double LLPerBinFracSystErr::fgErr = -1; - //---------------------------------------------------------------------- - std::string UniqueName() - { - static int N = 0; - return TString::Format("cafanauniq%d", N++).Data(); - } - - //---------------------------------------------------------------------- - DontAddDirectory::DontAddDirectory() - { - fBackup = TH1::AddDirectoryStatus(); - TH1::AddDirectory(false); - } - - //---------------------------------------------------------------------- - DontAddDirectory::~DontAddDirectory() - { - TH1::AddDirectory(fBackup); - } - //---------------------------------------------------------------------- IFDHSilent::IFDHSilent() { @@ -115,50 +96,90 @@ 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()); - auto covmx = std::make_unique(nBins, nBins); + const Eigen::ArrayXd binMeans = GetBinMeans(binSets); - for( unsigned int hist_idx = 0; hist_idx < binSets.size(); ++hist_idx ) + Eigen::MatrixXd covmx = Eigen::MatrixXd::Zero(nBins, nBins); + + 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(); + } + + //---------------------------------------------------------------------- + Eigen::MatrixXd EigenMatrixXdFromTMatrixD(const TMatrixD* mat) + { + Eigen::MatrixXd ret(mat->GetNrows(), mat->GetNcols()); + // TMatrixD doesn't appear to have a GetArray() + for(int i = 0; i < mat->GetNrows(); ++i){ + for(int j = 0; j < mat->GetNcols(); ++j){ + ret.coeffRef(i, j) = (*mat)(i, j); + } + } + return ret; + } + + //---------------------------------------------------------------------- + TMatrixD TMatrixDFromEigenMatrixXd(const Eigen::MatrixXd& mat) + { + TMatrixD ret(mat.rows(), mat.cols()); + // TMatrixD doesn't appear to have a GetArray() + for(int i = 0; i < mat.rows(); ++i){ + for(int j = 0; j < mat.cols(); ++j){ + ret(i, j) = mat.coeffRef(i, j); + } + } + return ret; + } + //---------------------------------------------------------------------- double LogLikelihood(double e, double o) { @@ -217,6 +238,34 @@ namespace ana return chi; } + //---------------------------------------------------------------------- + double LogLikelihood(const Eigen::ArrayXd& ea, const Eigen::ArrayXd& oa, bool useOverflow) + { + assert(ea.size() == oa.size()); + + double chi = 0; + + const int bufferBins = useOverflow ? 0 : -1; + + for(int i = 0; i < ea.size()+bufferBins; ++i){ + chi += LogLikelihood(ea[i], oa[i]); + } + + return chi; + } + + //---------------------------------------------------------------------- + double Chi2CovMx(const Eigen::ArrayXd& e, const Eigen::ArrayXd& o, const Eigen::MatrixXd& covmxinv) + { + assert(e.size() == covmxinv.rows()+2); + + Eigen::ArrayXd diff = e-o; + // Drop underflow and overflow bins + const Eigen::ArrayXd diffSub(Eigen::Map(diff.data()+1, diff.size()-2)); + // dot collapses things down to a single number + return diffSub.matrix().dot(covmxinv*diffSub.matrix()); + } + //---------------------------------------------------------------------- double Chi2CovMx(const TVectorD* e, const TVectorD* o, const TMatrixD* covmxinv) { @@ -363,201 +412,6 @@ namespace ana return invMx; } - // Helper functions for MakeTHND(). - namespace{ - // Eventually the bin parameters will all be unpacked and we just pass them - // on to the regular constructor. - template T* MakeHist(A... a) - { - DontAddDirectory guard; - return new T(a...); - } - - // This function consumes bins from the start of the argument list and - // pushes their translations onto the list of arguments at the end. - template T* MakeHist(const Binning& firstBin, - A... args) - { - if(firstBin.IsSimple()) - return MakeHist(args..., - firstBin.NBins(), firstBin.Min(), firstBin.Max()); - else - return MakeHist(args..., - firstBin.NBins(), &firstBin.Edges().front()); - } - } - - // Concrete instantiations. MakeHist() requires us to put the bin arguments - // first... - //---------------------------------------------------------------------- - TH1D* MakeTH1D(const char* name, const char* title, const Binning& bins) - { - return MakeHist(bins, name, title); - } - - //---------------------------------------------------------------------- - TH2D* MakeTH2D(const char* name, const char* title, - const Binning& binsx, - const Binning& binsy) - { - return MakeHist(binsx, binsy, name, title); - } - - //---------------------------------------------------------------------- - TH2* ToTH2(const Spectrum& s, double exposure, ana::EExposureType expotype, - const Binning& binsx, const Binning& binsy, ana::EBinType bintype) - { - DontAddDirectory guard; - - std::unique_ptr h1(s.ToTH1(exposure, expotype)); - return ToTH2Helper(std::move(h1), binsx, binsy, bintype); - } - - //---------------------------------------------------------------------- - TH2* ToTH2(const Ratio& r, - const Binning& binsx, const Binning& binsy) - { - DontAddDirectory guard; - - std::unique_ptr h1(r.ToTH1()); - return ToTH2Helper(std::move(h1), binsx, binsy); - } - - //---------------------------------------------------------------------- - TH2* ToTH2Helper(std::unique_ptr h1, - const Binning& binsx, const Binning& binsy, - ana::EBinType bintype) - { - // Make sure it's compatible with having been made with this binning - assert(h1->GetNbinsX() == binsx.NBins()*binsy.NBins()); - - TH2* ret = MakeTH2D(UniqueName().c_str(), "", binsx, binsy); - - for(int i = 0; i < h1->GetNbinsX(); ++i){ - const double val = h1->GetBinContent(i+1); - const double err = h1->GetBinError(i+1); - - const int ix = i / binsy.NBins(); - const int iy = i % binsy.NBins(); - - ret->SetBinContent(ix+1, iy+1, val); - ret->SetBinError (ix+1, iy+1, err); - } - - if(bintype == ana::EBinType::kBinDensity) ret->Scale(1, "width"); - - return ret; - } - - //---------------------------------------------------------------------- - - TH3* ToTH3(const Spectrum& s, double exposure, ana::EExposureType expotype, - const Binning& binsx, const Binning& binsy, const Binning& binsz, - ana::EBinType bintype) - { - DontAddDirectory guard; - - std::unique_ptr h1(s.ToTH1(exposure, expotype)); - - return ToTH3Helper(std::move(h1), binsx, binsy, binsz, bintype); - } - - //---------------------------------------------------------------------- - - TH3* ToTH3(const Ratio& r, - const Binning& binsx, const Binning& binsy, const Binning& binsz) - { - DontAddDirectory guard; - - std::unique_ptr h1(r.ToTH1()); - - return ToTH3Helper(std::move(h1), binsx, binsy, binsz); - } - - //---------------------------------------------------------------------- - TH3* ToTH3Helper(std::unique_ptr h1, - const Binning& binsx, - const Binning& binsy, - const Binning& binsz, - ana::EBinType bintype) - { - - const int nx = binsx.NBins(); - const int ny = binsy.NBins(); - const int nz = binsz.NBins(); - - // Make sure it's compatible with having been made with this binning - assert(h1->GetNbinsX() == nx*ny*nz); - - TH3* ret; - - // If all three axes are simple, we can call a simpler constructor - if(binsx.IsSimple() && binsy.IsSimple() && binsz.IsSimple()){ - ret = new TH3F(UniqueName().c_str(), "", - nx, binsx.Min(), binsx.Max(), - ny, binsy.Min(), binsy.Max(), - nz, binsz.Min(), binsz.Max()); - - if(!binsx.IsSimple() || !binsy.IsSimple() || !binsz.IsSimple()){ - // TH3 doesn't have the constructors for mixed simple and custom - std::cerr << "ToTH3: one or more axes is custom, but not all three. Applying Simple binning to all three axes" << std::endl; - } - } - else{ - ret = new TH3F(UniqueName().c_str(), "", - nx, &binsx.Edges().front(), - ny, &binsy.Edges().front(), - nz, &binsz.Edges().front()); - } - - for(int i = 0; i < h1->GetNbinsX(); ++i){ - const double val = h1->GetBinContent(i+1); - const double err = h1->GetBinError(i+1); - - const int nynz = ny*nz; - const int nmodnynz = i%nynz; - const int ix = i/nynz; - const int iy = nmodnynz/nz; - const int iz = i%nz; - - ret->SetBinContent(ix+1, iy+1, iz+1, val); - ret->SetBinError (ix+1, iy+1, iz+1, err); - } - - if(bintype == ana::EBinType::kBinDensity) ret->Scale(1, "width"); - - return ret; - - } - - //---------------------------------------------------------------------- - std::vector Wildcard(const std::string& wildcardString) - { - // Expand environment variables and wildcards like the shell would - wordexp_t p; - const int status = wordexp(wildcardString.c_str(), &p, WRDE_SHOWERR); - - if(status != 0){ - std::cerr << "Wildcard string '" << wildcardString - << "' returned error " << status << " from wordexp()." - << std::endl; - return {}; - } - - std::vector fileList; - - for(unsigned int i = 0; i < p.we_wordc; ++i){ - // Check the file exists before adding it - struct stat sb; - if(stat(p.we_wordv[i], &sb) == 0) - fileList.push_back(p.we_wordv[i]); - } - - wordfree(&p); - - return fileList; - } - //---------------------------------------------------------------------- std::string FindCAFAnaDir() { @@ -634,7 +488,7 @@ namespace ana std::cout << "Found files with duplicate run/subrun metadata: " << r2tmp << std::endl; abort(); - } + } if(r1.empty()){ base[key] = r2; @@ -693,148 +547,6 @@ namespace ana tmp->cd(); } - //---------------------------------------------------------------------- - bool RunningOnGrid() - { - static bool cache; - static bool cache_set = false; - if(!cache_set){ - cache = (getenv("_CONDOR_SCRATCH_DIR") != 0); - cache_set = true; - } - - return cache; - } - - //---------------------------------------------------------------------- - size_t Stride(bool allow_default) - { - static int cache = -1; - - if(cache < 0){ - char* env = getenv("CAFANA_STRIDE"); - if(env){ - cache = std::atoi(env); - } - else{ - if(allow_default){ - cache = 1; - } - else{ - std::cout << "Stride() called, but CAFANA_STRIDE is not set (--stride not passed?)" << std::endl; - abort(); - } - } - } - - return cache; - } - - //---------------------------------------------------------------------- - size_t Offset(bool allow_default) - { - static int cache = -1; - - if(cache < 0){ - char* env = getenv("CAFANA_OFFSET"); - if(env){ - cache = std::atoi(env); - } - else{ - if(allow_default){ - cache = 0; - } - else{ - std::cout << "Offset() called, but CAFANA_OFFSET is not set (--offset not passed?)" << std::endl; - abort(); - } - } - } - - return cache; - } - - //---------------------------------------------------------------------- - int Limit() - { - static int cache = 0; - - if(cache == 0){ - char* env = getenv("CAFANA_LIMIT"); - if(env){ - cache = std::atoi(env); - } - else{ - cache = -1; - } - } - - return cache; - } - - //---------------------------------------------------------------------- - size_t JobNumber() - { - if(!RunningOnGrid()){ - std::cout << "JobNumber() called, but we are not running on the grid" << std::endl; - abort(); - } - - return Offset(false); - } - - //---------------------------------------------------------------------- - size_t NumJobs() - { - if(!RunningOnGrid()){ - std::cout << "NumJobs() called, but we are not running on the grid" << std::endl; - abort(); - } - - return Stride(false); - } - - - //---------------------------------------------------------------------- - bool AlmostEqual(double a, double b) - { - if(a == 0 && b == 0) return true; - - return fabs(a-b)/std::max(a, b) < .0001; // allow 0.01% error - } - - - //---------------------------------------------------------------------- - std::string pnfs2xrootd(std::string loc, bool unauth) - { - static bool first = true; - static bool onsite = false; - - if (first && unauth) { - first = false; - char chostname[255]; - gethostname(chostname, 255); - std::string hostname = chostname; - - if ( hostname.find("fnal.gov") != std::string::npos ){ - onsite = true; - std::cout << "Using unauthenticated xrootd access (port 1095) while on-site, hostname: " << hostname << std::endl; - } - else { - onsite = false; - std::cout << "Using authenticated xrootd access (port 1094) access while off-site, hostname: " << hostname << std::endl; - } - } - - if(loc.rfind("/pnfs/", 0) == 0){ // ie begins with - if ( onsite && unauth ) - loc = std::string("root://fndcagpvm01.fnal.gov:1095//pnfs/fnal.gov/usr/")+&loc.c_str()[6]; - else - loc = std::string("root://fndcagpvm01.fnal.gov:1094//pnfs/fnal.gov/usr/")+&loc.c_str()[6]; - } - return loc; - } - //---------------------------------------------------------------------- FitToFourier::FitToFourier(TH1* h, double xlo, double xhi, int NOsc) : fHist(h), fxlo(xlo), fxhi(xhi), fNOsc(NOsc) @@ -933,41 +645,55 @@ namespace ana //---------------------------------------------------------------------- // Note that this does not work for 3D! - TH1* GetMaskHist(const Spectrum& s, double xmin, double xmax, double ymin, double ymax) + Eigen::ArrayXd GetMaskArray(const Spectrum& s, double xmin, double xmax, double ymin, double ymax) { - if (s.GetBinnings().size() > 2){ + if (s.NDimensions() > 2){ std::cout << "Error: unable to apply a mask in " << s.GetBinnings().size() << " dimensions" << std::endl; abort(); } - // The exposure isn't important here - TH1* fMaskND = s.ToTHX(s.POT()); - TH1D* fMask1D = s.ToTH1(s.POT()); + if(s.NDimensions() == 1 && ymax > ymin){ + std::cout << "Error: GetMaskArray(): can't specify y range for 1D spectrum" << std::endl; + abort(); + } + + const Binning* xbins = &s.GetBinnings()[0]; + const Binning* ybins = (s.NDimensions() == 2) ? &s.GetBinnings()[1] : 0; + + const int Nx = xbins->NBins(); + const int Ny = ybins ? ybins->NBins() : 1; + + // The 1D flattening of 2D binning is pretty confusing. The bins are packed + // densely, without under/overflow, *except* there is a single underflow at + // 0 and single overflow at Nx*Ny+1. So we do our calculations as if there + // were no under/overflow and then add 1 to the output index to account. + + Eigen::ArrayXd ret(Nx*Ny+2); - int ybins = fMaskND->GetNbinsY(); + // Include underflow and overflow if mask disabled, otherwise exclude + ret[0] = ret[Nx*Ny+1] = ((xmin < xmax || ymin < ymax) ? 0 : 1); - for(int i = 0; i < fMask1D->GetNbinsX()+2; ++i){ + for(int i = 0; i < Nx*Ny; ++i){ - int ix = i / ybins; - int iy = i % ybins; + const int ix = i / Ny; + const int iy = i % Ny; bool isMask = false; if (xmin < xmax){ - if (fMaskND->GetXaxis()->GetBinLowEdge(ix+1) < xmin) isMask=true; - if (fMaskND->GetXaxis()->GetBinUpEdge(ix+1) > xmax) isMask=true; + if (xbins->Edges()[ix ] < xmin) isMask = true; + if (xbins->Edges()[ix+1] > xmax) isMask = true; } if (ymin < ymax){ - if (fMaskND->GetYaxis()->GetBinLowEdge(iy+1) < ymin) isMask=true; - if (fMaskND->GetYaxis()->GetBinUpEdge(iy+1) > ymax) isMask=true; + if (ybins->Edges()[iy ] < ymin) isMask = true; + if (ybins->Edges()[iy+1] > ymax) isMask = true; } - if (isMask) fMask1D->SetBinContent(i+1, 0); - else fMask1D->SetBinContent(i+1, 1); - + ret[i+1] = isMask ? 0 : 1; } - return fMask1D; + + return ret; } //---------------------------------------------------------------------- diff --git a/sbnana/CAFAna/Core/Utilities.h b/sbnana/CAFAna/Core/Utilities.h index 12fee2fc..495dbcde 100644 --- a/sbnana/CAFAna/Core/Utilities.h +++ b/sbnana/CAFAna/Core/Utilities.h @@ -1,5 +1,7 @@ #pragma once +#include "cafanacore/UtilsExt.h" + #include #include #include @@ -13,7 +15,9 @@ // because compiler errors result // when the templates are introduced #include "TMatrixD.h" -#include "TVectorD.h" + +#include "cafanacore/StanVar.h" // TODO this is only to make the eigen include safe. Should port more of this file from NOvA +#include class TArrayD; class TDirectory; @@ -25,43 +29,11 @@ class TH1D; class TH2F; class TH2D; class TH3D; -class TVector3; + +#include "sbnana/CAFAna/Core/MathUtil.h" namespace ana { - class Binning; - class Spectrum; - class Ratio; - - enum EBinType - { - kBinContent, ///< Regular histogram - kBinDensity ///< Divide bin contents by bin widths - }; - - - /// For use as an argument to \ref Spectrum::ToTH1 - enum EExposureType{ - kPOT, - kLivetime - }; - - - /// Return a different string each time, for creating histograms - std::string UniqueName(); - - /// \brief Prevent histograms being added to the current directory - /// - /// Upon going out of scope, restores the previous setting - class DontAddDirectory - { - public: - DontAddDirectory(); - ~DontAddDirectory(); - protected: - bool fBackup; - }; - /// \brief ifdh calls between construction and destruction produce no output /// /// Upon going out of scope, restores the previous setting @@ -94,17 +66,24 @@ namespace ana /** \brief Compute bin-to-bin covariance matrix from a collection of sets of bin contents. - \param binSets Collection of sets of bins from which covariances should be calculated - \param firstBin The first bin that should be considered (inclusive) - \param lastBin The last bin that should be considered (inclusive). -1 means "last in set" + \param binSets Collection of sets of bins from which covariances should be calculated + Note that the covariance is calclated from all binSets that are passed and + thus the nominal should not be included (But should be checked for biases) + + \returns Eigen::MatrixXD containing computed covariance matrix unless binSets.size() < 2, + in which case an 0*0 matric is returned + **/ + Eigen::MatrixXd CalcCovMx(const std::vector& binSets); - \returns unique_ptr to TMatrixD containing computed covariance matrix unless binSets.size() < 2, - in which case the unique_ptr's target is nullptr. + /** \brief Compute bias from a collection of sets of bin contents. - Note TH1D is a child class of TArrayD -- so you can pass a vector - of TH1D* to this method. + \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 **/ - std::unique_ptr CalcCovMx(const std::vector & binSets, int firstBin=0, int lastBin=-1); + Eigen::MatrixXd CalcBiasMx(const Eigen::ArrayXd& nom, const std::vector& binSets); class LLPerBinFracSystErr { @@ -129,6 +108,20 @@ namespace ana **/ double LogLikelihood(const TH1* exp, const TH1* obs, bool useOverflow = false); + /** \brief The log-likelihood formula from the PDG. + + \param exp The expected spectrum + \param obs The corresponding observed spectrum + + \returns The log-likelihood formula from the PDG + \f[ \chi^2=2\sum_i^{\rm bins}\left(e_i-o_i+o_i\ln\left({o_i\over e_i}\right)\right) \f] + + Includes underflow bin and an option for + overflow bin (off by default) and handles + zero observed or expected events correctly. + **/ + double LogLikelihood(const Eigen::ArrayXd& exp, const Eigen::ArrayXd& obs, bool useOverflow = false); + /** \brief The log-likelihood formula for a single bin \param exp Expected count @@ -138,8 +131,46 @@ namespace ana \f[ \chi^2=2\left(e-o+o\ln\left({o\over e}\right)\right) \f] Handles zero observed or expected events correctly. + Templated so that it can handle usage with Stan vars and other numeric types. + (The horible third template parameter ensures this function can only be used + with types that accept conversion from double -- which means you can't pass + it a TH1* or a std::vector&, removing the ambiguity with + those other versions of LogLikelihood). The return type promotes to + stan::math::var if either T or U are. **/ - double LogLikelihood(double exp, double obs); + template && std::is_convertible_v, int> = 0> + decltype(T(0) - U(0)) LogLikelihood(T exp, U obs) + { + // http://www.wolframalpha.com/input/?i=d%2Fds+m*(1%2Bs)+-d+%2B+d*ln(d%2F(m*(1%2Bs)))%2Bs%5E2%2FS%5E2%3D0 + // http://www.wolframalpha.com/input/?i=solve+-d%2F(s%2B1)%2Bm%2B2*s%2FS%5E2%3D0+for+s + const auto S = LLPerBinFracSystErr::GetError(); + if(S > 0){ + const auto S2 = util::sqr(S); + const auto s = .25*(sqrt(8*obs*S2+util::sqr(exp*S2-2))-exp*S2-2); + exp *= 1+s; + } + + if(obs*1000 > exp){ + // This strange form is for numerical stability when exp ~ obs + return 2*obs*((exp-obs)/obs + log1p((obs-exp)/exp)); + } + else{ + // But log1p doesn't like arguments near -1 (observation much smaller + // than expectation), and it's better to use the usual formula in that + // case. + if(obs){ + return 2*(exp-obs + obs*log(obs/exp)); + } + else{ + return 2*exp; + } + } + } + + Eigen::MatrixXd EigenMatrixXdFromTMatrixD(const TMatrixD* mat); + + TMatrixD TMatrixDFromEigenMatrixXd(const Eigen::MatrixXd& mat); /** \brief Chi-squared calculation using a covariance matrix. @@ -152,7 +183,7 @@ namespace ana Note that this implicitly assumes Gaussian statistics for the bin counts! **/ - double Chi2CovMx(const TVectorD* exp, const TVectorD* obs, const TMatrixD* covmxinv); + double Chi2CovMx(const Eigen::ArrayXd& exp, const Eigen::ArrayXd& obs, const Eigen::MatrixXd& covmxinv); /// Chi-squared calculation using covariance matrix (calls the TVectorD version internally). double Chi2CovMx(const TH1* exp, const TH1* obs, const TMatrixD* covmxinv); @@ -178,54 +209,6 @@ namespace ana /// the null rows/columns. std::unique_ptr SymmMxInverse(const TMatrixD& mx); - /// Utility function to avoid need to switch on bins.IsSimple() - TH1D* MakeTH1D(const char* name, const char* title, const Binning& bins); - /// Utility function to avoid 4-way combinatorial explosion on the bin types - TH2D* MakeTH2D(const char* name, const char* title, - const Binning& binsx, - const Binning& binsy); - - /// \brief For use with \ref Var2D - /// - /// Re-expand a histogram flattened by \ref Var2D into a 2D histogram for - /// plotting purposes. The binning scheme must match that used in the - /// original Var. - TH2* ToTH2(const Spectrum& s, double exposure, ana::EExposureType expotype, - const Binning& binsx, const Binning& binsy, - ana::EBinType bintype = ana::EBinType::kBinContent); - - /// Same as ToTH2, but with 3 dimensions - TH3* ToTH3(const Spectrum& s, double exposure, ana::EExposureType expotype, - const Binning& binsx, const Binning& binsy, const Binning& binsz, - ana::EBinType bintype = ana::EBinType::kBinContent); - - /// \brief For use with \ref Var2D - /// - /// Re-expand a flatenned histogram into a 2D histogram for - /// plotting purposes. The binning scheme must match that used in the - /// original Var. - TH2* ToTH2(const Ratio& r, const Binning& binsx, const Binning& binsy); - - /// Same as ToTH2, but with 3 dimensions - TH3* ToTH3(const Ratio& r, const Binning& binsx, - const Binning& binsy, const Binning& binsz); - - /// Helper for ana::ToTH2 - TH2* ToTH2Helper(std::unique_ptr h1, - const Binning& binsx, - const Binning& binsy, - ana::EBinType bintype = ana::EBinType::kBinContent); - - /// Helper for ana::ToTH3 - TH3* ToTH3Helper(std::unique_ptr h1, - const Binning& binsx, - const Binning& binsy, - const Binning& binsz, - ana::EBinType bintype = ana::EBinType::kBinContent); - - /// Find files matching a UNIX glob, plus expand environment variables - std::vector Wildcard(const std::string& wildcardString); - /// This is $SRT_PRIVATE_CONTEXT if a CAFAna directory exists there, /// otherwise $SRT_PUBLIC_CONTEXT std::string FindCAFAnaDir(); @@ -255,24 +238,6 @@ namespace ana void WriteCAFMetadata(TDirectory* dir, const std::map& meta); - /// Is this a grid (condor) job? - bool RunningOnGrid(); - - /// Value passed to --stride, or 1 if not specified - size_t Stride(bool allow_default = true); - /// Value passed to --offset, or 0 if not specified - size_t Offset(bool allow_default = true); - /// Value passed to --limit, or -1 if not specified - int Limit(); - - /// What's the process number for a grid job? - size_t JobNumber(); - size_t NumJobs(); - - bool AlmostEqual(double a, double b); - - std::string pnfs2xrootd(std::string loc, bool unauth = false); - // Calling this function will return a Fourier series, fit to the input // histogram. Assumes x-axis covers one period class FitToFourier @@ -293,10 +258,12 @@ namespace ana void EnsurePositiveDefinite(TH2* mat); - /// Returns a masking histogram based on axis limits - TH1* GetMaskHist(const Spectrum& s, - double xmin=0, double xmax=-1, - double ymin=0, double ymax=-1); + /// \brief Returns a masking histogram based on axis limits + /// + /// This mask *does* include entries for underflow and overflow bins + 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 diff --git a/sbnana/CAFAna/Core/Var.cxx b/sbnana/CAFAna/Core/Var.cxx deleted file mode 100644 index 316ecea5..00000000 --- a/sbnana/CAFAna/Core/Var.cxx +++ /dev/null @@ -1,277 +0,0 @@ -#include "sbnana/CAFAna/Core/Var.h" - -#include -#include -#include -#include - -namespace ana -{ - //---------------------------------------------------------------------- - template _Var:: - _Var(const std::function& fun) - : fFunc(fun), fID(fgNextID++) - { - } - - //---------------------------------------------------------------------- - template int _Var::MaxID() - { - return fgNextID-1; - } - - //---------------------------------------------------------------------- - /// Helper for \ref Var2D - template class Var2DFunc - { - public: - Var2DFunc(const _Var& a, const Binning binsa, - const _Var& b, const Binning binsb) - : fA(a), fBinsA(binsa), - fB(b), fBinsB(binsb) - { - } - - double operator()(const T* sr) const - { - // Calculate current values of the variables in StandardRecord once - const double va = fA(sr); - const double vb = fB(sr); - - // Since there are no overflow/underflow bins, check the range - if(va < fBinsA.Min() || vb < fBinsB.Min()) return -1; - if(va > fBinsA.Max() || vb > fBinsB.Max()) return fBinsA.NBins() * fBinsB.NBins(); - - // FindBin uses root convention, first bin is bin 1, bin 0 is underflow - const int ia = fBinsA.FindBin(va) - 1; - const int ib = fBinsB.FindBin(vb) - 1; - - const int i = ia*fBinsB.NBins()+ib; - - return i+.5; - } - - protected: - const _Var fA; - const Binning fBinsA; - const _Var fB; - const Binning fBinsB; - }; - - /// Helper for \ref Var3D - template class Var3DFunc - { - public: - Var3DFunc(const _Var& a, const Binning binsa, - const _Var& b, const Binning binsb, - const _Var& c, const Binning binsc) - : fA(a), fBinsA(binsa), - fB(b), fBinsB(binsb), - fC(c), fBinsC(binsc) - { - } - - double operator()(const T* sr) const - { - /// Calculate current values of the variables in StandardRecord once - const double va = fA(sr); - const double vb = fB(sr); - const double vc = fC(sr); - - /// Since there are no overflow/underflow bins, check the range - if(va < fBinsA.Min() || vb < fBinsB.Min() || vc < fBinsC.Min()){ - return -1.0; - } - - if(va > fBinsA.Max() || vb > fBinsB.Max() || vc > fBinsC.Max()){ - return fBinsA.NBins() * fBinsB.NBins() * fBinsC.NBins(); - } - - const int ia = fBinsA.FindBin(va) - 1; - const int ib = fBinsB.FindBin(vb) - 1; - const int ic = fBinsC.FindBin(vc) - 1; - const int i = ia*fBinsB.NBins()*fBinsC.NBins() + ib*fBinsC.NBins() + ic; - - return i+.5; - } - - protected: - const _Var fA; - const Binning fBinsA; - const _Var fB; - const Binning fBinsB; - const _Var fC; - const Binning fBinsC; - }; - - //---------------------------------------------------------------------- - template _Var - Var2D(const _Var& a, const Binning& binsa, - const _Var& b, const Binning& binsb) - { - return _Var(Var2DFunc(a, binsa, b, binsb)); - } - - //---------------------------------------------------------------------- - template _Var - Var2D(const _Var& a, int na, double a0, double a1, - const _Var& b, int nb, double b0, double b1) - { - return Var2D(a, Binning::Simple(na, a0, a1), - b, Binning::Simple(nb, b0, b1)); - } - - // explicitly instantiate the template for the types we know we have - template Var Var2D(const Var&, const Binning&, const Var&, const Binning&); - template SpillVar Var2D(const SpillVar&, const Binning&, const SpillVar&, const Binning&); - - template Var Var2D(const Var&, int, double, double, const Var&, int, double, double); - template SpillVar Var2D(const SpillVar&, int, double, double, const SpillVar&, int, double, double); - - //---------------------------------------------------------------------- - template _Var - Var3D(const _Var& a, const Binning& binsa, - const _Var& b, const Binning& binsb, - const _Var& c, const Binning& binsc) - { - return _Var(Var3DFunc(a, binsa, b, binsb, c, binsc)); - } - - //---------------------------------------------------------------------- - template _Var - Var3D(const _Var& a, int na, double a0, double a1, - const _Var& b, int nb, double b0, double b1, - const _Var& c, int nc, double c0, double c1) - { - return Var3D(a, Binning::Simple(na, a0, a1), - b, Binning::Simple(nb, b0, b1), - c, Binning::Simple(nc, c0, c1)); - } - - // explicitly instantiate the template for the types we know we have - template Var Var3D(const Var&, const Binning&, const Var&, const Binning&, const Var&, const Binning&); - template SpillVar Var3D(const SpillVar&, const Binning&, const SpillVar&, const Binning&, const SpillVar&, const Binning&); - - template Var Var3D(const Var&, int, double, double, const Var&, int, double, double, const Var&, int, double, double); - template SpillVar Var3D(const SpillVar&, int, double, double, const SpillVar&, int, double, double, const SpillVar&, int, double, double); - - //---------------------------------------------------------------------- - Var Scaled(const Var& v, double s) - { - return Var([v, s](const caf::SRSliceProxy* sr){return s*v(sr);}); - } - - //---------------------------------------------------------------------- - Var Constant(double c) - { - return Var([c](const caf::SRSliceProxy*){return c;}); - } - - //-------------------------------------------------------------------- - - Var Sqrt(const Var& v) - { - return Var([v](const caf::SRSliceProxy* sr){return sqrt(v(sr));}); - } - - //---------------------------------------------------------------------- - template _Var - operator*(const _Var& a, const _Var& b) - { - static std::map, int> ids; - const std::pair key(a.ID(), b.ID()); - - if(ids.count(key)){ - return _Var([a, b](const T* sr){return a(sr) * b(sr);}, - ids[key]); - } - else{ - const _Var ret([a, b](const T* sr){return a(sr) * b(sr);}); - ids[key] = ret.ID(); - return ret; - } - } - - //---------------------------------------------------------------------- - template _Var - operator/(const _Var& a, const _Var& b) - { - static std::map, int> ids; - const std::pair key(a.ID(), b.ID()); - - if(ids.count(key)){ - return _Var([a, b](const T* sr) - { - const double denom = b(sr); - if(denom != 0) - return a(sr) / denom; - else - return 0.0; - }, - ids[key]); - } - else{ - const _Var ret([a, b](const T* sr) - { - const double denom = b(sr); - if(denom != 0) - return a(sr) / denom; - else - return 0.0; - }); - ids[key] = ret.ID(); - return ret; - } - } - - //---------------------------------------------------------------------- - template _Var - operator+(const _Var& a, const _Var& b) - { - static std::map, int> ids; - const std::pair key(a.ID(), b.ID()); - - if(ids.count(key)){ - return _Var([a, b](const T* sr){return a(sr) + b(sr);}, - ids[key]); - } - else{ - const _Var ret([a, b](const T* sr){return a(sr) + b(sr);}); - ids[key] = ret.ID(); - return ret; - } - } - - //---------------------------------------------------------------------- - template _Var - operator-(const _Var& a, const _Var& b) - { - static std::map, int> ids; - const std::pair key(a.ID(), b.ID()); - - if(ids.count(key)){ - return _Var([a, b](const T* sr){return a(sr) - b(sr);}, - ids[key]); - } - else{ - const _Var ret([a, b](const T* sr){return a(sr) - b(sr);}); - ids[key] = ret.ID(); - return ret; - } - } - - // explicitly instantiate the templates for the types we know we have - template class _Var; - template class _Var; - - template int _Var::fgNextID = 0; - - template Var operator*(const Var&, const Var&); - template Var operator/(const Var&, const Var&); - template Var operator+(const Var&, const Var&); - template Var operator-(const Var&, const Var&); - template SpillVar operator*(const SpillVar&, const SpillVar&); - template SpillVar operator/(const SpillVar&, const SpillVar&); - template SpillVar operator+(const SpillVar&, const SpillVar&); - template SpillVar operator-(const SpillVar&, const SpillVar&); -} diff --git a/sbnana/CAFAna/Core/Var.h b/sbnana/CAFAna/Core/Var.h index 0cd1b4c1..209771db 100644 --- a/sbnana/CAFAna/Core/Var.h +++ b/sbnana/CAFAna/Core/Var.h @@ -1,70 +1,11 @@ #pragma once -// This file defines the basic Var object. For specific variables, and examples -// of how to implement your own, see Vars.h - -#include -#include -#include - -#include "sbnana/CAFAna/Core/Binning.h" +#include "cafanacore/Var.h" #include "sbnanaobj/StandardRecord/Proxy/FwdDeclare.h" -namespace caf{class SRSpill; class SRSpillTruthBranch; class SRSlice;} - namespace ana { - - /// Most useful for combining weights. - // need to declare these functions first - // (this needed because of reasons detailed in https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Making_New_Friends; - // we want a 'one-to-one' relationship.) - template class _Var; - template _Var operator*(const _Var& a, const _Var& b); - template _Var operator/(const _Var& a, const _Var& b); - template _Var operator+(const _Var& a, const _Var& b); - template _Var operator-(const _Var& a, const _Var& b); - - /// Template for Var and SpillVar - template class _Var - { - public: - /// The type of the function part of a var - typedef double (VarFunc_t)(const T* sr); - - /// std::function can wrap a real function, function object, or lambda - _Var(const std::function& fun); - - /// Allows a variable to be called with double value = myVar(sr) syntax - double operator()(const T* sr) const - { - return fFunc(sr); - } - - /// Vars with the same definition will have the same ID - int ID() const {return fID;} - - static int MaxID(); - protected: - // Give this guy access to the constructor that sets ID - friend _Var operator*<>(const _Var& a, const _Var& b); - friend _Var operator/<>(const _Var& a, const _Var& b); - friend _Var operator+<>(const _Var& a, const _Var& b); - friend _Var operator-<>(const _Var& a, const _Var& b); - - _Var(const std::function& fun, int id) - : fFunc(fun), fID(id) - { - } - - std::function fFunc; - - int fID; - /// The next ID that hasn't yet been assigned - static int fgNextID; - }; - /// \brief Representation of a variable to be retrieved from a \ref /// caf::StandardRecord object /// @@ -78,54 +19,19 @@ namespace ana /// \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 + /// NB lack of quotes around my.var.str #define SIMPLEVAR(CAFNAME) Var([](const caf::SRSliceProxy* sr) -> double {return sr->CAFNAME;}) #define SIMPLESPILLVAR(CAFNAME) SpillVar([](const caf::SRSpillProxy* sr) -> double {return sr->CAFNAME;}) - /// The simplest possible Var, always 1. Used as a default weight. - const Var kUnweighted([](const caf::SRSliceProxy*){return 1;}); - - const SpillVar kSpillUnweighted([](const caf::SRSpillProxy*){return 1;}); - - /// \brief Variable formed from two input variables - /// - /// The binning of each variable has to be given to allow conversion into a - /// 1D binned representation. - template _Var - Var2D(const _Var& a, const Binning& binsa, - const _Var& b, const Binning& binsb); - - /// \brief Variable formed from two input variables - /// - /// The binning of each variable has to be given to allow conversion into a - /// 1D binned representation. - template _Var - Var2D(const _Var& a, int na, double a0, double a1, - const _Var& b, int nb, double b0, double b1); - - /// This is just like a Var2D, but useful for 3D Spectra - template _Var - Var3D(const _Var& a, const Binning& binsa, - const _Var& b, const Binning& binsb, - const _Var& c, const Binning& binsc); - - /// This is just like a Var2D, but useful for 3D Spectra - template _Var - Var3D(const _Var& a, int na, double a0, double a1, - const _Var& b, int nb, double b0, double b1, - const _Var& c, int nc, double c0, double c1); - - // TODO - remove once no more legacy callers exist - #define SpillTruthVar2D Var2D - #define SpillTruthVar3D Var3D - - /// Use to rescale another variable. - Var Scaled(const Var& v, double s); - /// Use to weight events up and down by some factor - Var Constant(double c); + typedef _Var NuTruthVar; + typedef _Var TrackVar; + typedef _Var ShowerVar; + typedef _Var StubVar; - /// Use to take sqrt of a var - Var Sqrt(const Var& v); +#define SIMPLENUTRUTHVAR(CAFNAME) NuTruthVar([](const caf::SRTrueInteractionProxy* nu) -> double {return nu->CAFNAME;}) +#define SIMPLETRACKVAR(CAFNAME) TrackVar([](const caf::SRTrackProxy* trk) -> double {return trk->CAFNAME;}) +#define SIMPLESHOWERVAR(CAFNAME) ShowerVar([](const caf::SRShowerProxy* shw) -> double {return shw->CAFNAME;}) +#define SIMPLESTUBVAR(CAFNAME) StubVar([](const caf::SRStubProxy* stub) -> double {return stub->CAFNAME;}) } // namespace diff --git a/sbnana/CAFAna/Core/Weight.h b/sbnana/CAFAna/Core/Weight.h new file mode 100644 index 00000000..fc9cca85 --- /dev/null +++ b/sbnana/CAFAna/Core/Weight.h @@ -0,0 +1,20 @@ +#pragma once + +#include "cafanacore/Weight.h" + +#include "sbnanaobj/StandardRecord/Proxy/FwdDeclare.h" + +namespace ana +{ + typedef _Weight Weight; + + /// \brief Equivalent of \ref Weight acting on \ref caf::SRSpill + typedef _Weight SpillWeight; + typedef _Weight NuTruthWeight; + + /// The simplest possible Weight, always 1. Used as a default weight. + const Weight kUnweighted = Unweighted(); + + const SpillWeight kSpillUnweighted = Unweighted(); + const NuTruthWeight kNuTruthUnweighted = Unweighted(); +} // namespace diff --git a/sbnana/CAFAna/Core/WildcardSource.cxx b/sbnana/CAFAna/Core/WildcardSource.cxx deleted file mode 100644 index 18f6a9d0..00000000 --- a/sbnana/CAFAna/Core/WildcardSource.cxx +++ /dev/null @@ -1,63 +0,0 @@ -#include "sbnana/CAFAna/Core/WildcardSource.h" - -#include "sbnana/CAFAna/Core/Utilities.h" - -#include "ifdh.h" - -#include - -#include -#include -#include -#include -namespace -{ - // No-one else needs to see this - std::vector sorted(const std::vector& v) - { - std::vector ret; - ret = v; - std::sort(ret.begin(), ret.end()); - return ret; - } -} - -namespace ana -{ - //---------------------------------------------------------------------- - WildcardSource::WildcardSource(const std::string& wildcard, - int stride, int offset) - // MRCCLoader needs all its lists in matching order, so sort here - : FileListSource(sorted(WildcardOrLs(wildcard)), stride, offset) - { - } - - //---------------------------------------------------------------------- - WildcardSource::~WildcardSource() - { - } - - //---------------------------------------------------------------------- - std::vector WildcardSource:: - WildcardOrLs(const std::string& wildcard) const - { - std::vector ret = Wildcard(wildcard); - - struct stat ss; - // If we found nothing, but it's because pnfs isn't mounted, try ifdh ls - // instead. - if(ret.empty() && - wildcard.find("/pnfs/") == 0 && - stat("/pnfs/", &ss) != 0){ - - std::cout << "No files matching " << wildcard << " but that's probably because /pnfs is not mounted on the current node." << std::endl; - - // This doesn't work because "ifdh ls" doesn't actually understand - // wildcard syntax properly. - // ifdh i; - // ret = i.ls(wildcard, 0); - } - - return ret; - } -} diff --git a/sbnana/CAFAna/Core/WildcardSource.h b/sbnana/CAFAna/Core/WildcardSource.h deleted file mode 100644 index 038570b1..00000000 --- a/sbnana/CAFAna/Core/WildcardSource.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -#include "sbnana/CAFAna/Core/FileListSource.h" - -namespace ana -{ - /// File source based on a wildcard (glob) - class WildcardSource: public FileListSource - { - public: - /// \param wildcard Wildcard or glob. Anything glob() accepts is OK. May be - /// a single literal filename. - WildcardSource(const std::string& wildcard, - int stride = -1, int offset = -1); - virtual ~WildcardSource(); - - protected: - std::vector WildcardOrLs(const std::string& wildcard) const; - }; -} diff --git a/sbnana/CAFAna/Cuts/CMakeLists.txt b/sbnana/CAFAna/Cuts/CMakeLists.txt index f5b2400f..c99c7d23 100644 --- a/sbnana/CAFAna/Cuts/CMakeLists.txt +++ b/sbnana/CAFAna/Cuts/CMakeLists.txt @@ -1,6 +1,3 @@ -# Allow "StandardRecord/" to find the right directory -include_directories(..) - cet_make(LIBRARY_NAME CAFAnaCuts LIBRARIES CAFAnaCore sbnanaobj_StandardRecordProxy diff --git a/sbnana/CAFAna/Experiment/CMakeLists.txt b/sbnana/CAFAna/Experiment/CMakeLists.txt index 042063ed..e45ee273 100644 --- a/sbnana/CAFAna/Experiment/CMakeLists.txt +++ b/sbnana/CAFAna/Experiment/CMakeLists.txt @@ -1,6 +1,3 @@ -# Allow "StandardRecord/" to find the right directory -include_directories(..) - cet_make(LIBRARY_NAME CAFAnaExperiment LIBRARIES CAFAnaCore CAFAnaVars CAFAnaPrediction OscLib diff --git a/sbnana/CAFAna/Experiment/CountingExperiment.cxx b/sbnana/CAFAna/Experiment/CountingExperiment.cxx index 87f0afb5..bac64911 100644 --- a/sbnana/CAFAna/Experiment/CountingExperiment.cxx +++ b/sbnana/CAFAna/Experiment/CountingExperiment.cxx @@ -9,23 +9,12 @@ #include "TDirectory.h" #include "TObjString.h" -#include "TH1.h" namespace ana { - //---------------------------------------------------------------------- - CountingExperiment::CountingExperiment(const IPrediction* p, - const Spectrum& d, - const Spectrum& cosmic) - : fMC(p), fData(d), - fCosmic(cosmic.ToTH1(d.Livetime(), kLivetime)) - { - } - //---------------------------------------------------------------------- CountingExperiment::~CountingExperiment() { - delete fCosmic; } //---------------------------------------------------------------------- @@ -33,47 +22,47 @@ namespace ana const SystShifts& syst) const { double exp = fMC->PredictSyst(osc, syst).Integral(fData.POT()); - if (fCosmic) exp += fCosmic->Integral(0,-1); double obs = fData.Integral(fData.POT()); return LogLikelihood(exp, obs); } //---------------------------------------------------------------------- - void CountingExperiment::SaveTo(TDirectory* dir) const + void CountingExperiment::SaveTo(TDirectory* dir, const std::string& name) const { TDirectory* tmp = dir; + dir = dir->mkdir(name.c_str()); // switch to subdir dir->cd(); + TObjString("CountingExperiment").Write("type"); - fMC->SaveTo(dir->mkdir("mc")); - fData.SaveTo(dir->mkdir("data")); - - if(fCosmic) fCosmic->Write("cosmic"); + fMC->SaveTo(dir, "mc"); + fData.SaveTo(dir, "data"); + + dir->Write(); + delete dir; tmp->cd(); } //---------------------------------------------------------------------- - std::unique_ptr CountingExperiment::LoadFrom(TDirectory* dir) + std::unique_ptr CountingExperiment::LoadFrom(TDirectory* dir, const std::string& name) { + dir = dir->GetDirectory(name.c_str()); // switch to subdir + assert(dir); + TObjString* ptag = (TObjString*)dir->Get("type"); assert(ptag); assert(ptag->GetString() == "CountingExperiment"); assert(dir->GetDirectory("mc")); - assert(dir->GetDirectory("data")); - - const IPrediction* mc = ana::LoadFrom(dir->GetDirectory("mc")).release(); - const std::unique_ptr data = Spectrum::LoadFrom(dir->GetDirectory("data")); - TH1* cosmic = 0; - if(dir->Get("cosmic")) cosmic = (TH1*)dir->Get("cosmic"); + const IPrediction* mc = ana::LoadFrom(dir, "mc").release(); + const std::unique_ptr data = Spectrum::LoadFrom(dir, "data"); auto ret = std::make_unique(mc, *data); - if(cosmic) ret->fCosmic = cosmic; return ret; } } diff --git a/sbnana/CAFAna/Experiment/CountingExperiment.h b/sbnana/CAFAna/Experiment/CountingExperiment.h index 0dda7a51..5e2dd837 100644 --- a/sbnana/CAFAna/Experiment/CountingExperiment.h +++ b/sbnana/CAFAna/Experiment/CountingExperiment.h @@ -1,8 +1,8 @@ #pragma once #include "sbnana/CAFAna/Experiment/IExperiment.h" -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "cafanacore/Spectrum.h" namespace ana { @@ -12,18 +12,15 @@ namespace ana class CountingExperiment: public IExperiment { public: - CountingExperiment(const IPrediction* p, const Spectrum& d, const Spectrum& cosmic); - /// Version without cosmics may be wanted for MC studies - CountingExperiment(const IPrediction* p, const Spectrum& d) : fMC(p), fData(d), fCosmic(0) {} + CountingExperiment(const IPrediction* p, const Spectrum& d) : fMC(p), fData(d) {} ~CountingExperiment(); virtual double ChiSq(osc::IOscCalcAdjustable* osc, const SystShifts& syst = SystShifts::Nominal()) const override; - virtual void SaveTo(TDirectory* dir) const override; - static std::unique_ptr LoadFrom(TDirectory* dir); + virtual void SaveTo(TDirectory* dir, const std::string& name) const override; + static std::unique_ptr LoadFrom(TDirectory* dir, const std::string& name); protected: const IPrediction* fMC; Spectrum fData; - TH1* fCosmic; }; } diff --git a/sbnana/CAFAna/Experiment/IExperiment.cxx b/sbnana/CAFAna/Experiment/IExperiment.cxx index 29a6cdfc..c3e98322 100644 --- a/sbnana/CAFAna/Experiment/IExperiment.cxx +++ b/sbnana/CAFAna/Experiment/IExperiment.cxx @@ -1,7 +1,5 @@ #include "sbnana/CAFAna/Experiment/IExperiment.h" -#include "sbnana/CAFAna/Core/Utilities.h" - #include "TFile.h" #include "TObjString.h" @@ -15,29 +13,31 @@ #include "sbnana/CAFAna/Experiment/MultiExperiment.h" #include "sbnana/CAFAna/Experiment/ReactorExperiment.h" +#include "sbnana/CAFAna/Core/Utilities.h" + namespace ana { //---------------------------------------------------------------------- // Definition to satisfy declaration in Core/LoadFromFile.h - template<> std::unique_ptr LoadFrom(TDirectory* dir) + template<> std::unique_ptr LoadFrom(TDirectory* dir, const std::string& name) { - TObjString* ptag = (TObjString*)dir->Get("type"); + TObjString* ptag = (TObjString*)dir->GetDirectory(name.c_str())->Get("type"); assert(ptag); const TString tag = ptag->GetString(); - if(tag == "CountingExperiment") return CountingExperiment::LoadFrom(dir); - if(tag == "ReactorExperiment") return ReactorExperiment::LoadFrom(dir); - if(tag == "SingleSampleExperiment") return SingleSampleExperiment::LoadFrom(dir); - if(tag == "SolarConstraints") return SolarConstraints::LoadFrom(dir); - if(tag == "MultiExperiment") return MultiExperiment::LoadFrom(dir); + if(tag == "CountingExperiment") return CountingExperiment::LoadFrom(dir, name); + if(tag == "ReactorExperiment") return ReactorExperiment::LoadFrom(dir, name); + if(tag == "SingleSampleExperiment") return SingleSampleExperiment::LoadFrom(dir, name); + if(tag == "SolarConstraints") return SolarConstraints::LoadFrom(dir, name); + if(tag == "MultiExperiment") return MultiExperiment::LoadFrom(dir, name); std::cerr << "Unknown Experiment type '" << tag << "'" << std::endl; abort(); } //---------------------------------------------------------------------- - void IExperiment::SaveTo(TDirectory* dir) const + void IExperiment::SaveTo(TDirectory* dir, const std::string& name) const { assert(0 && "Not implemented"); } diff --git a/sbnana/CAFAna/Experiment/IExperiment.h b/sbnana/CAFAna/Experiment/IExperiment.h index 16cc12e1..de0869fa 100644 --- a/sbnana/CAFAna/Experiment/IExperiment.h +++ b/sbnana/CAFAna/Experiment/IExperiment.h @@ -3,8 +3,6 @@ #include "sbnana/CAFAna/Core/SystShifts.h" #include "sbnana/CAFAna/Core/LoadFromFile.h" -#include - class TDirectory; namespace osc @@ -25,6 +23,6 @@ namespace ana virtual double ChiSq(osc::IOscCalcAdjustable* osc, const SystShifts& syst = SystShifts::Nominal()) const = 0; - virtual void SaveTo(TDirectory* dir) const; + virtual void SaveTo(TDirectory* dir, const std::string& name) const; }; } diff --git a/sbnana/CAFAna/Experiment/MultiExperiment.cxx b/sbnana/CAFAna/Experiment/MultiExperiment.cxx index ccd121ac..f9453e85 100644 --- a/sbnana/CAFAna/Experiment/MultiExperiment.cxx +++ b/sbnana/CAFAna/Experiment/MultiExperiment.cxx @@ -72,7 +72,7 @@ namespace ana } //---------------------------------------------------------------------- - void MultiExperiment::SaveTo(TDirectory* dir) const + void MultiExperiment::SaveTo(TDirectory* dir, const std::string& name) const { bool hasCorr = false; for(auto it: fSystCorrelations) if(!it.empty()) hasCorr = true; @@ -83,19 +83,27 @@ namespace ana TDirectory* tmp = dir; + dir = dir->mkdir(name.c_str()); // switch to subdir dir->cd(); + TObjString("MultiExperiment").Write("type"); for(unsigned int i = 0; i < fExpts.size(); ++i){ - fExpts[i]->SaveTo(dir->mkdir(TString::Format("expt%d", i))); + fExpts[i]->SaveTo(dir, TString::Format("expt%d", i).Data()); } + dir->Write(); + delete dir; + tmp->cd(); } //---------------------------------------------------------------------- - std::unique_ptr MultiExperiment::LoadFrom(TDirectory* dir) + std::unique_ptr MultiExperiment::LoadFrom(TDirectory* dir, const std::string& name) { + dir = dir->GetDirectory(name.c_str()); // switch to subdir + assert(dir); + TObjString* ptag = (TObjString*)dir->Get("type"); assert(ptag); assert(ptag->GetString() == "MultiExperiment"); @@ -103,10 +111,11 @@ namespace ana std::vector expts; for(int i = 0; ; ++i){ - TDirectory* subdir = dir->GetDirectory(TString::Format("expt%d", i)); + const std::string subname = TString::Format("expt%d", i).Data(); + TDirectory* subdir = dir->GetDirectory(subname.c_str()); if(!subdir) break; - expts.push_back(ana::LoadFrom(subdir).release()); + expts.push_back(ana::LoadFrom(dir, subname).release()); } assert(!expts.empty()); diff --git a/sbnana/CAFAna/Experiment/MultiExperiment.h b/sbnana/CAFAna/Experiment/MultiExperiment.h index cb9e841c..3964d850 100644 --- a/sbnana/CAFAna/Experiment/MultiExperiment.h +++ b/sbnana/CAFAna/Experiment/MultiExperiment.h @@ -35,8 +35,8 @@ namespace ana const std::vector>& corrs); - virtual void SaveTo(TDirectory* dir) const override; - static std::unique_ptr LoadFrom(TDirectory* dir); + virtual void SaveTo(TDirectory* dir, const std::string& name) const override; + static std::unique_ptr LoadFrom(TDirectory* dir, const std::string& name); protected: std::vector fExpts; diff --git a/sbnana/CAFAna/Experiment/MultiExperimentSBN.cxx b/sbnana/CAFAna/Experiment/MultiExperimentSBN.cxx deleted file mode 100644 index 83b553fb..00000000 --- a/sbnana/CAFAna/Experiment/MultiExperimentSBN.cxx +++ /dev/null @@ -1,122 +0,0 @@ -#include "sbnana/CAFAna/Experiment/MultiExperimentSBN.h" - -#include "sbnana/CAFAna/Core/LoadFromFile.h" - -#include "TDirectory.h" -#include "TObjString.h" - -#include - -namespace ana -{ - //---------------------------------------------------------------------- - double MultiExperimentSBN::ChiSq(osc::IOscCalcAdjustable* osc, - const SystShifts& syst) const - { - assert(fExpts.size() == fExptNames.size()); - - double ret = 0; - - for(unsigned int n = 0; n < fExpts.size(); ++n){ - // Set baseline for each of the experiments - osc->SetL(kBLs[fExptNames[n]]); - - // Don't waste time fiddling with the systematics if for sure there's - // nothing to do. - if(fSystCorrelations[n].empty()){ - ret += fExpts[n]->ChiSq(osc, syst); - } - else{ - // Make a local copy we're going to rewrite into the terms this - // sub-experiment will accept. - SystShifts localShifts = syst; - for(auto it: fSystCorrelations[n]){ - // We're mapping prim -> sec - const ISyst* prim = it.first; - const ISyst* sec = it.second; - if(syst.GetShift(prim) != 0){ - // sec can be unset, which means there's no representation needed - // of prim in the sub-experiment. - if(sec) localShifts.SetShift(sec, syst.GetShift(prim)); - // We've either translated or discarded prim, so drop it here. - localShifts.SetShift(prim, 0); - } - } - ret += fExpts[n]->ChiSq(osc, localShifts); - } - } - return ret; - } - - //---------------------------------------------------------------------- - void MultiExperimentSBN:: - SetSystCorrelations(int idx, - const std::vector>& corrs) - { - // Sanity-check the mapping - std::map already; - for(auto it: corrs){ - assert(it.first != it.second); - - // Don't worry if second element is null pointer - if (!it.second) continue; - if(already.find(it.second) == already.end()){ - already[it.second] = it.first; - } - else{ - std::cout << "MultiExperimentSBN::SetSystCorrelations(): Warning!\n" - << "In experiment " << idx << " both " - << already[it.second]->ShortName() << " and " - << it.first->ShortName() - << " are configured to map to " << it.second->ShortName() - << ". That's probably not what you want." << std::endl; - } - } - - // Apply it - fSystCorrelations[idx] = corrs; - } - - //---------------------------------------------------------------------- - void MultiExperimentSBN::SaveTo(TDirectory* dir) const - { - bool hasCorr = false; - for(auto it: fSystCorrelations) if(!it.empty()) hasCorr = true; - - if(hasCorr){ - std::cerr << "Warning in MultiExperimentSBN: systematic correlations are set and will not be serialized by this call to SaveTo(). You will have to re-set them once you load the experiment back in." << std::endl; - } - - TDirectory* tmp = dir; - - dir->cd(); - TObjString("MultiExperimentSBN").Write("type"); - - for(unsigned int i = 0; i < fExpts.size(); ++i){ - fExpts[i]->SaveTo(dir->mkdir(TString::Format("expt%d", i))); - } - - tmp->cd(); - } - - //---------------------------------------------------------------------- - std::unique_ptr MultiExperimentSBN::LoadFrom(TDirectory* dir) - { - TObjString* ptag = (TObjString*)dir->Get("type"); - assert(ptag); - assert(ptag->GetString() == "MultiExperimentSBN"); - - std::vector expts; - - for(int i = 0; ; ++i){ - TDirectory* subdir = dir->GetDirectory(TString::Format("expt%d", i)); - if(!subdir) break; - - expts.push_back(ana::LoadFrom(subdir).release()); - } - - assert(!expts.empty()); - - return std::unique_ptr(new MultiExperimentSBN(expts)); - } -} diff --git a/sbnana/CAFAna/Experiment/MultiExperimentSBN.h b/sbnana/CAFAna/Experiment/MultiExperimentSBN.h deleted file mode 100644 index 56dab599..00000000 --- a/sbnana/CAFAna/Experiment/MultiExperimentSBN.h +++ /dev/null @@ -1,56 +0,0 @@ -#pragma once - -#include "sbnana/CAFAna/Experiment/IExperiment.h" -#include "OscLib/IOscCalc.h" -#include "sbnana/CAFAna/Analysis/ExpInfo.h" - -#include -#include - -namespace ana -{ - /// Combine multiple component experiments - class MultiExperimentSBN: public IExperiment - { - public: - // We may want to rewrite this as a pair, but this works for now - // also, to prevent mistakes it's probably best to define - // kSBND, kUBoone and kIcarus somewhere. But again, works for now - MultiExperimentSBN(std::vector expts = {}, - std::vector exptnames = {}) - : fExpts(expts), fExptNames(exptnames) - { - fSystCorrelations.resize(expts.size()); - } - - void Add(const IExperiment* expt, float l){ - fExpts.push_back(expt); - fExptNames.push_back(l); - } - - virtual double ChiSq(osc::IOscCalcAdjustable* osc, - const SystShifts& syst = SystShifts::Nominal()) const override; - - /// For the subexperiment \a idx, set up a mapping between systematics - /// - /// Each element in the vector is a pair from a "primary" systematic to a - /// "secondary". When this MultiExperiment is called with a primary - /// systematic shifted, the sub-experiment will be called with the - /// secondary systematic set to the same value (and the primary unset). - /// - /// You can pass NULL for a secondary to indicate that the systematic - /// simply has no effect on the experiment in question and should be - /// filtered out. - void SetSystCorrelations(int idx, - const std::vector>& corrs); - - virtual void SaveTo(TDirectory* dir) const override; - static std::unique_ptr LoadFrom(TDirectory* dir); - - protected: - std::vector fExpts; - std::vector fExptNames; - std::vector>> fSystCorrelations; - }; -} diff --git a/sbnana/CAFAna/Experiment/RatioExperiment.cxx b/sbnana/CAFAna/Experiment/RatioExperiment.cxx index efabebfe..943c3f50 100644 --- a/sbnana/CAFAna/Experiment/RatioExperiment.cxx +++ b/sbnana/CAFAna/Experiment/RatioExperiment.cxx @@ -1,8 +1,8 @@ #include "sbnana/CAFAna/Experiment/RatioExperiment.h" #include "sbnana/CAFAna/Core/LoadFromFile.h" -#include "sbnana/CAFAna/Core/Ratio.h" -#include "sbnana/CAFAna/Core/HistCache.h" +#include "cafanacore/Ratio.h" +#include "sbnana/CAFAna/Core/Utilities.h" #include "sbnana/CAFAna/Prediction/IPrediction.h" @@ -23,16 +23,11 @@ namespace ana Spectrum predND = fPredND->PredictSyst(osc, syst); osc->SetL(kBaselineIcarus); Spectrum predFD = fPredFD->PredictSyst(osc, syst); - - predFD *= Ratio(fSpectND, predND); - - TH1D* hpred = predFD.ToTH1(fSpectFD.POT()); - TH1D* hdata = fSpectFD.ToTH1(fSpectFD.POT()); - const double ret = LogLikelihood(hpred, hdata); + predFD *= Ratio(fSpectND, predND); - HistCache::Delete(hpred); - HistCache::Delete(hdata); + const double ret = LogLikelihood(predFD.GetEigen(predFD.POT()), + fSpectFD.GetEigen(fSpectFD.POT())); return ret; } diff --git a/sbnana/CAFAna/Experiment/RatioExperiment.h b/sbnana/CAFAna/Experiment/RatioExperiment.h index 46a93fb3..eb2afc48 100644 --- a/sbnana/CAFAna/Experiment/RatioExperiment.h +++ b/sbnana/CAFAna/Experiment/RatioExperiment.h @@ -1,6 +1,6 @@ #pragma once -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "cafanacore/Spectrum.h" #include "sbnana/CAFAna/Experiment/IExperiment.h" #include "sbnana/CAFAna/Analysis/ExpInfo.h" diff --git a/sbnana/CAFAna/Experiment/ReactorExperiment.cxx b/sbnana/CAFAna/Experiment/ReactorExperiment.cxx index 7566c36b..dd16cd21 100644 --- a/sbnana/CAFAna/Experiment/ReactorExperiment.cxx +++ b/sbnana/CAFAna/Experiment/ReactorExperiment.cxx @@ -20,11 +20,13 @@ namespace ana } //---------------------------------------------------------------------- - void ReactorExperiment::SaveTo(TDirectory* dir) const + void ReactorExperiment::SaveTo(TDirectory* dir, const std::string& name) const { TDirectory* tmp = dir; + dir = dir->mkdir(name.c_str()); // switch to subdir dir->cd(); + TObjString("ReactorExperiment").Write("type"); TH1D params("", "", 2, 0, 2); @@ -32,12 +34,18 @@ namespace ana params.SetBinContent(2, fSigma); params.Write("params"); + dir->Write(); + delete dir; + tmp->cd(); } //---------------------------------------------------------------------- - std::unique_ptr ReactorExperiment::LoadFrom(TDirectory* dir) + std::unique_ptr ReactorExperiment::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() == "ReactorExperiment"); @@ -48,8 +56,7 @@ namespace ana const double bestFit = params->GetBinContent(1); const double sigma = params->GetBinContent(2); - return std::unique_ptr(new ReactorExperiment(bestFit, - sigma)); + return std::make_unique(bestFit, sigma); } //---------------------------------------------------------------------- diff --git a/sbnana/CAFAna/Experiment/ReactorExperiment.h b/sbnana/CAFAna/Experiment/ReactorExperiment.h index 255b1e21..2eda9fd1 100644 --- a/sbnana/CAFAna/Experiment/ReactorExperiment.h +++ b/sbnana/CAFAna/Experiment/ReactorExperiment.h @@ -18,8 +18,8 @@ namespace ana virtual double ChiSq(osc::IOscCalcAdjustable* osc, const SystShifts& shift = SystShifts::Nominal()) const override; - void SaveTo(TDirectory* dir) const override; - static std::unique_ptr LoadFrom(TDirectory* dir); + void SaveTo(TDirectory* dir, const std::string& name) const override; + static std::unique_ptr LoadFrom(TDirectory* dir, const std::string& name); protected: double fBestFit, fSigma; }; @@ -33,6 +33,6 @@ namespace ana /// Updated value for SecondAna based on the latest PDG const ReactorExperiment* WorldReactorConstraint2016(); - /// Reactor constraint from PDG 2017 update + /// Reactor constraint from PDG 2017 update const ReactorExperiment* WorldReactorConstraint2017(); } diff --git a/sbnana/CAFAna/Experiment/SingleSampleExperiment.cxx b/sbnana/CAFAna/Experiment/SingleSampleExperiment.cxx index b2f17611..ed5cba61 100644 --- a/sbnana/CAFAna/Experiment/SingleSampleExperiment.cxx +++ b/sbnana/CAFAna/Experiment/SingleSampleExperiment.cxx @@ -1,14 +1,14 @@ #include "sbnana/CAFAna/Experiment/SingleSampleExperiment.h" -#include "sbnana/CAFAna/Core/HistCache.h" #include "sbnana/CAFAna/Core/LoadFromFile.h" +//#include "cafanacore/StanUtils.h" #include "sbnana/CAFAna/Core/Utilities.h" #include "OscLib/IOscCalc.h" #include "TDirectory.h" #include "TObjString.h" -#include "TH1.h" +#include "TH2.h" namespace ana { @@ -17,7 +17,7 @@ namespace ana const Spectrum& data, const Spectrum& cosmicInTime, const Spectrum& cosmicOutOfTime) - : fMC(pred), fData(data), fCosmicInTime(cosmicInTime), fCosmicOutOfTime(cosmicOutOfTime), fMask(0) + : fMC(pred), fData(data), fCosmicInTime(cosmicInTime), fCosmicOutOfTime(cosmicOutOfTime) { if(cosmicInTime.POT() > 0){ std::cout << "SingleSampleExperiment: in-time cosmics have nonzero POT. " @@ -30,93 +30,98 @@ namespace ana //---------------------------------------------------------------------- SingleSampleExperiment::~SingleSampleExperiment() { - delete fMask; } //---------------------------------------------------------------------- double SingleSampleExperiment::ChiSq(osc::IOscCalcAdjustable* calc, const SystShifts& syst) const { - Spectrum p = fMC->PredictSyst(calc, syst); + Spectrum pred = fMC->PredictSyst(calc, syst); if(fCosmicOutOfTime.POT() > 0){ // if out-of-time cosmics supplied - p += fCosmicOutOfTime; + pred += fCosmicOutOfTime; } - TH1D* hpred = p.ToTH1(fData.POT()); + Eigen::ArrayXd apred = pred.GetEigen(fData.POT()); + Eigen::ArrayXd adata = fData.GetEigen(fData.POT()); // "Livetime" here means number of readout windows. if(fCosmicInTime.Livetime() > 0){ // if in-cosmics supplied // This many are already included in the beam MC - const double beamLivetime = p.Livetime() * fData.POT()/p.POT(); + const double beamLivetime = pred.Livetime() * fData.POT()/pred.POT(); // So we need to take this many from the cosmics-only to match the data const double intimeLivetime = fData.Livetime() - beamLivetime; - TH1D* hcosmic = fCosmicInTime.ToTH1(intimeLivetime, kLivetime); - hpred->Add(hcosmic); - HistCache::Delete(hcosmic); + const Eigen::ArrayXd acosmic = fCosmicInTime.GetEigen(intimeLivetime, kLivetime); + apred += acosmic; } - TH1D* hdata = fData.ToTH1(fData.POT()); + ApplyMask(apred, adata); - // If a valid mask has been set, zero out the offending bins - if (fMask){ - assert(hpred->GetNbinsX() == fMask->GetNbinsX()); - assert(hdata->GetNbinsX() == fMask->GetNbinsX()); + // full namespace qualification to avoid degeneracy with method inherited + // from IExperiment + return ana::LogLikelihood(apred, adata); + } - for(int i = 0; i < fMask->GetNbinsX()+2; ++i){ - if (fMask->GetBinContent(i+1) == 1) continue; - hpred->SetBinContent(i+1, 0); - hdata->SetBinContent(i+1, 0); - } - } - - const double ll = LogLikelihood(hpred, hdata); + //---------------------------------------------------------------------- + void SingleSampleExperiment::ApplyMask(Eigen::ArrayXd& a, + Eigen::ArrayXd& b) const + { + if(fMaskA.size() == 0) return; - HistCache::Delete(hpred); - HistCache::Delete(hdata); + assert(a.size() == fMaskA.size()); + assert(b.size() == fMaskA.size()); - return ll; + // Arrays mean we get bin-by-bin operations + a *= fMaskA; + b *= fMaskA; } //---------------------------------------------------------------------- - void SingleSampleExperiment::SaveTo(TDirectory* dir) const + void SingleSampleExperiment::SaveTo(TDirectory* dir, const std::string& name) const { TDirectory* tmp = dir; + dir = dir->mkdir(name.c_str()); // switch to subdir dir->cd(); + TObjString("SingleSampleExperiment").Write("type"); - fMC->SaveTo(dir->mkdir("mc")); - fData.SaveTo(dir->mkdir("data")); - fCosmicInTime.SaveTo(dir->mkdir("cosmicInTime")); - fCosmicOutOfTime.SaveTo(dir->mkdir("cosmicOutOfTime")); + fMC->SaveTo(dir, "mc"); + fData.SaveTo(dir, "data"); + fCosmicInTime.SaveTo(dir, "cosmicInTime"); + fCosmicOutOfTime.SaveTo(dir, "cosmicOutOfTime"); + + dir->Write(); + delete dir; tmp->cd(); } //---------------------------------------------------------------------- - std::unique_ptr SingleSampleExperiment::LoadFrom(TDirectory* dir) + std::unique_ptr SingleSampleExperiment::LoadFrom(TDirectory* dir, const std::string& name) { + dir = dir->GetDirectory(name.c_str()); // switch to subdir + assert(dir); + TObjString* ptag = (TObjString*)dir->Get("type"); assert(ptag); assert(ptag->GetString() == "SingleSampleExperiment"); assert(dir->GetDirectory("mc")); - assert(dir->GetDirectory("data")); - const IPrediction* mc = ana::LoadFrom(dir->GetDirectory("mc")).release(); - const std::unique_ptr data = Spectrum::LoadFrom(dir->GetDirectory("data")); + const IPrediction* mc = ana::LoadFrom(dir, "mc").release(); + const std::unique_ptr data = Spectrum::LoadFrom(dir, "data"); // Legacy format. This is the in-time cosmics if(dir->GetDirectory("cosmic")){ - const std::unique_ptr cosmicInTime = Spectrum::LoadFrom(dir->GetDirectory("cosmic")); - return std::make_unique(mc, *data, *cosmicInTime, Spectrum(0, {}, {}, 0, 0)); + const std::unique_ptr cosmicInTime = Spectrum::LoadFrom(dir, "cosmic"); + return std::make_unique(mc, *data, *cosmicInTime, Spectrum::Uninitialized()); } - const std::unique_ptr cosmicInTime = Spectrum::LoadFrom(dir->GetDirectory("cosmicInTime")); - const std::unique_ptr cosmicOutOfTime = Spectrum::LoadFrom(dir->GetDirectory("cosmicOutOfTime")); + const std::unique_ptr cosmicInTime = Spectrum::LoadFrom(dir, "cosmicInTime"); + const std::unique_ptr cosmicOutOfTime = Spectrum::LoadFrom(dir, "cosmicOutOfTime"); return std::make_unique(mc, *data, *cosmicInTime, *cosmicOutOfTime); } @@ -124,6 +129,6 @@ namespace ana //---------------------------------------------------------------------- void SingleSampleExperiment::SetMaskHist(double xmin, double xmax, double ymin, double ymax) { - fMask = GetMaskHist(fData, xmin, xmax, ymin, ymax); + fMaskA = GetMaskArray(fData, xmin, xmax, ymin, ymax); } } diff --git a/sbnana/CAFAna/Experiment/SingleSampleExperiment.h b/sbnana/CAFAna/Experiment/SingleSampleExperiment.h index 40b39eca..8140c23b 100644 --- a/sbnana/CAFAna/Experiment/SingleSampleExperiment.h +++ b/sbnana/CAFAna/Experiment/SingleSampleExperiment.h @@ -2,7 +2,8 @@ #include "sbnana/CAFAna/Experiment/IExperiment.h" #include "sbnana/CAFAna/Prediction/IPrediction.h" -#include "sbnana/CAFAna/Core/Spectrum.h" + +#include "cafanacore/FwdDeclare.h" namespace ana { @@ -22,7 +23,7 @@ namespace ana /// In MC studies you might not want to bother with cosmics SingleSampleExperiment(const IPrediction* pred, const Spectrum& data) - : fMC(pred), fData(data), fCosmicInTime(0, {}, {}, 0, 0), fCosmicOutOfTime(0, {}, {}, 0, 0), fMask(0) + : fMC(pred), fData(data), fCosmicInTime(Spectrum::Uninitialized()), fCosmicOutOfTime(Spectrum::Uninitialized()) { } @@ -31,10 +32,10 @@ namespace ana virtual double ChiSq(osc::IOscCalcAdjustable* osc, const SystShifts& syst = SystShifts::Nominal()) const override; - virtual void SaveTo(TDirectory* dir) const override; - static std::unique_ptr LoadFrom(TDirectory* dir); + virtual void SaveTo(TDirectory* dir, const std::string& name) const override; + static std::unique_ptr LoadFrom(TDirectory* dir, const std::string& name); - // Didn't make provisions for copying fCosmic or fMC + // Didn't make provisions for copying fMC SingleSampleExperiment(const SingleSampleExperiment&) = delete; SingleSampleExperiment& operator=(const SingleSampleExperiment&) = delete; @@ -48,13 +49,17 @@ namespace ana s.fMC = nullptr; }; - void SetMaskHist(double xmin=0, double xmax=-1, + void SetMaskHist(double xmin=0, double xmax=-1, double ymin=0, double ymax=-1); protected: + virtual void ApplyMask(Eigen::ArrayXd& a, Eigen::ArrayXd& b) const; + const IPrediction* fMC; Spectrum fData; + Spectrum fCosmicInTime, fCosmicOutOfTime; - TH1* fMask; + + Eigen::ArrayXd fMaskA; }; } diff --git a/sbnana/CAFAna/Experiment/SolarConstraints.cxx b/sbnana/CAFAna/Experiment/SolarConstraints.cxx index 40af58d5..80d0bf0a 100644 --- a/sbnana/CAFAna/Experiment/SolarConstraints.cxx +++ b/sbnana/CAFAna/Experiment/SolarConstraints.cxx @@ -17,7 +17,7 @@ namespace ana // These value are from the 2014 PDG // http://pdg.lbl.gov/2014/tables/rpp2014-sum-leptons.pdf std::cerr << "WARNING: Using 2014 Solar constraints." - << "Are you sure you don't want kSolarConstraintsPDG2017 ?" + << "Are you sure you don't want kSolarConstraintsPDG2017 ?" << std::endl; fCentralDmsq = 7.53e-5; @@ -50,11 +50,13 @@ namespace ana } //---------------------------------------------------------------------- - void SolarConstraints::SaveTo(TDirectory* dir) const + void SolarConstraints::SaveTo(TDirectory* dir, const std::string& name) const { TDirectory* tmp = dir; + dir = dir->mkdir(name.c_str()); // switch to subdir dir->cd(); + TObjString("SolarConstraints").Write("type"); TH1D params("", "", 4, 0, 4); @@ -64,12 +66,18 @@ namespace ana params.SetBinContent(4, fErrorAngle); params.Write("params"); + dir->Write(); + delete dir; + tmp->cd(); } //---------------------------------------------------------------------- - std::unique_ptr SolarConstraints::LoadFrom(TDirectory* dir) + std::unique_ptr SolarConstraints::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() == "SolarConstraints"); diff --git a/sbnana/CAFAna/Experiment/SolarConstraints.h b/sbnana/CAFAna/Experiment/SolarConstraints.h index f2a325b8..d90572bb 100644 --- a/sbnana/CAFAna/Experiment/SolarConstraints.h +++ b/sbnana/CAFAna/Experiment/SolarConstraints.h @@ -19,8 +19,8 @@ namespace ana virtual double ChiSq(osc::IOscCalcAdjustable* osc, const SystShifts& syst = SystShifts::Nominal()) const override; - virtual void SaveTo(TDirectory* dir) const override; - static std::unique_ptr LoadFrom(TDirectory* dir); + virtual void SaveTo(TDirectory* dir, const std::string& name) const override; + static std::unique_ptr LoadFrom(TDirectory* dir, const std::string& name); protected: double fCentralDmsq, fErrorDmsq; double fCentralAngle, fErrorAngle; @@ -28,5 +28,5 @@ namespace ana // http://pdg.lbl.gov/2017/tables/rpp2017-sum-leptons.pdf // ssth12 0.307 +/- 0.013 -> ss2th12 0.851 +/- 0.020 - const SolarConstraints kSolarConstraintsPDG2017(7.53e-5, 0.18e-5, 0.851, 0.020); + const SolarConstraints kSolarConstraintsPDG2017(7.53e-5, 0.18e-5, 0.851, 0.020); } diff --git a/sbnana/CAFAna/Extrap/CMakeLists.txt b/sbnana/CAFAna/Extrap/CMakeLists.txt index b25ecb03..f71f35ce 100644 --- a/sbnana/CAFAna/Extrap/CMakeLists.txt +++ b/sbnana/CAFAna/Extrap/CMakeLists.txt @@ -1,6 +1,3 @@ -# Allow "StandardRecord/" to find the right directory -include_directories(..) - cet_make(LIBRARY_NAME CAFAnaExtrap LIBRARIES CAFAnaCore CAFAnaCuts ) diff --git a/sbnana/CAFAna/Extrap/IExtrap.cxx b/sbnana/CAFAna/Extrap/IExtrap.cxx index a287dee9..5c5e87ee 100644 --- a/sbnana/CAFAna/Extrap/IExtrap.cxx +++ b/sbnana/CAFAna/Extrap/IExtrap.cxx @@ -14,21 +14,21 @@ namespace ana { //---------------------------------------------------------------------- // Definition to satisfy declaration in Core/LoadFromFile.h - template<> std::unique_ptr LoadFrom(TDirectory* dir) + template<> std::unique_ptr LoadFrom(TDirectory* dir, const std::string& name) { - TObjString* ptag = (TObjString*)dir->Get("type"); + TObjString* ptag = (TObjString*)dir->GetDirectory(name.c_str())->Get("type"); assert(ptag); const TString tag = ptag->GetString(); - if(tag == "TrivialExtrap") return TrivialExtrap::LoadFrom(dir); + if(tag == "TrivialExtrap") return TrivialExtrap::LoadFrom(dir, name); std::cerr << "Unknown Extrap type '" << tag << "'" << std::endl; abort(); } //---------------------------------------------------------------------- - void IExtrap::SaveTo(TDirectory* dir) const + void IExtrap::SaveTo(TDirectory* dir, const std::string& name) const { assert(0 && "Not implemented"); } diff --git a/sbnana/CAFAna/Extrap/IExtrap.h b/sbnana/CAFAna/Extrap/IExtrap.h index d255af89..9427a119 100644 --- a/sbnana/CAFAna/Extrap/IExtrap.h +++ b/sbnana/CAFAna/Extrap/IExtrap.h @@ -44,6 +44,6 @@ namespace ana virtual OscillatableSpectrum NCComponentFromNumu() = 0; virtual OscillatableSpectrum NCComponentFromNue() = 0; - virtual void SaveTo(TDirectory* dir) const; + virtual void SaveTo(TDirectory* dir, const std::string& name) const; }; } diff --git a/sbnana/CAFAna/Extrap/TrivialExtrap.cxx b/sbnana/CAFAna/Extrap/TrivialExtrap.cxx index e72c42a3..d05306a6 100644 --- a/sbnana/CAFAna/Extrap/TrivialExtrap.cxx +++ b/sbnana/CAFAna/Extrap/TrivialExtrap.cxx @@ -4,157 +4,122 @@ #include "sbnana/CAFAna/Core/Loaders.h" #include "sbnana/CAFAna/Core/SpectrumLoader.h" +#include "sbnanaobj/StandardRecord/Proxy/SRProxy.h" + #include "TDirectory.h" #include "TObjString.h" namespace ana { - //---------------------------------------------------------------------- - TrivialExtrap::TrivialExtrap(SpectrumLoaderBase& loaderNonswap, - SpectrumLoaderBase& loaderNue, - SpectrumLoaderBase& loaderNuTau, - SpectrumLoaderBase& loaderIntrinsic, - const HistAxis& axis, - const SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift, - const Var& wei) - : - fNueApp (loaderNue, axis, spillcut, cut && kIsNueApp && !kIsAntiNu, shift, wei), - fNueAppAnti (loaderNue, axis, spillcut, cut && kIsNueApp && kIsAntiNu, shift, wei), - - fNumuSurv (loaderNonswap, axis, spillcut, cut && kIsNumuCC && !kIsAntiNu, shift, wei), - fNumuSurvAnti (loaderNonswap, axis, spillcut, cut && kIsNumuCC && kIsAntiNu, shift, wei), - - fNumuApp (loaderNuTau, axis, spillcut, cut && kIsNumuApp && !kIsAntiNu, shift, wei), - fNumuAppAnti (loaderNuTau, axis, spillcut, cut && kIsNumuApp && kIsAntiNu, shift, wei), - - fNueSurv (loaderIntrinsic, axis, spillcut, cut && kIsBeamNue && !kIsAntiNu, shift, wei), - fNueSurvAnti (loaderIntrinsic, axis, spillcut, cut && kIsBeamNue && kIsAntiNu, shift, wei), + // TODO it's not ideal this has to be duplicated for a third time + namespace{ + const Var kTrueE([](const caf::SRSliceProxy* slc) -> double {return slc->truth.E;}); - fTauFromE (loaderNue, axis, spillcut, cut && kIsTauFromE && !kIsAntiNu, shift, wei), - fTauFromEAnti (loaderNue, axis, spillcut, cut && kIsTauFromE && kIsAntiNu, shift, wei), + const Var kBaseline([](const caf::SRSliceProxy* slc) -> double {return slc->truth.baseline * 1e-3;}); // m -> km - fTauFromMu (loaderNuTau, axis, spillcut, cut && kIsTauFromMu && !kIsAntiNu, shift, wei), - fTauFromMuAnti(loaderNuTau, axis, spillcut, cut && kIsTauFromMu && kIsAntiNu, shift, wei), + const Var kTrueLOverE = kBaseline / kTrueE; + } - fNCFromNumu (loaderNonswap, axis, spillcut, cut && kIsNCFromNumu, shift, wei), - fNCFromNue (loaderNonswap, axis, spillcut, cut && kIsNCFromNue, shift, wei) + //---------------------------------------------------------------------- + TrivialExtrap::TrivialExtrap(ISliceSource& nonswapSrc, + ISliceSource& nueSrc, + ISliceSource& tauSrc, + ISliceSource& intrinsicSrc, + const HistAxis& axis) + : + 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 (intrinsicSrc[kIsBeamNue && !kIsAntiNu], axis), + fNueSurvAnti (intrinsicSrc[kIsBeamNue && kIsAntiNu], axis), + fTauFromE (nueSrc [kIsTauFromE && !kIsAntiNu], axis), + fTauFromEAnti (nueSrc [kIsTauFromE && kIsAntiNu], axis), + fTauFromMu (tauSrc [kIsTauFromMu && !kIsAntiNu], axis), + fTauFromMuAnti(tauSrc [kIsTauFromMu && kIsAntiNu], axis), + fNCFromNumu (nonswapSrc[kIsNCFromNumu], axis), + fNCFromNue (nonswapSrc[kIsNCFromNue ], 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 .AddReweightableSpectrum(fNCFromNumu, axis.GetMultiDVar(), spillcut, cut && kIsNCFromNumu, shift, wei); - loaderNuTau.AddReweightableSpectrum(fNCFromNumu, axis.GetMultiDVar(), spillcut, cut && kIsNCFromNumu, shift, wei); + nueSrc[kIsNCFromNumu].GetVars(axis.GetVar1D(), kTrueLOverE).Register(&fNCFromNumu); + tauSrc[kIsNCFromNumu].GetVars(axis.GetVar1D(), kTrueLOverE).Register(&fNCFromNumu); - loaderNue .AddReweightableSpectrum(fNCFromNue, axis.GetMultiDVar(), spillcut, cut && kIsNCFromNue, shift, wei); - loaderNuTau.AddReweightableSpectrum(fNCFromNue, axis.GetMultiDVar(), spillcut, cut && kIsNCFromNue, shift, wei); + nueSrc[kIsNCFromNue].GetVars(axis.GetVar1D(), kTrueLOverE).Register(&fNCFromNue); + tauSrc[kIsNCFromNue].GetVars(axis.GetVar1D(), kTrueLOverE).Register(&fNCFromNue); //Also load in intrinsic nues from nonswap file - loaderNonswap.AddReweightableSpectrum(fNueSurv, axis.GetMultiDVar(), spillcut, cut && kIsBeamNue && !kIsAntiNu, shift, wei); - loaderNonswap.AddReweightableSpectrum(fNueSurvAnti, axis.GetMultiDVar(), spillcut, cut && kIsBeamNue && kIsAntiNu, shift, wei); - + nonswapSrc[kIsBeamNue && !kIsAntiNu].GetVars(axis.GetVar1D(), kTrueLOverE).Register(&fNueSurv); + nonswapSrc[kIsBeamNue && kIsAntiNu].GetVars(axis.GetVar1D(), kTrueLOverE).Register(&fNueSurvAnti); } - //---------------------------------------------------------------------- - TrivialExtrap::TrivialExtrap(SpectrumLoaderBase& loaderNonswap, - SpectrumLoaderBase& loaderNue, - SpectrumLoaderBase& loaderNuTau, - SpectrumLoaderBase& loaderIntrinsic, - std::string label, - const Binning& bins, - const Var& var, - const SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift, - const Var& wei) - : - TrivialExtrap(loaderNonswap, loaderNue, loaderNuTau, loaderIntrinsic, - HistAxis(label, bins, var), - spillcut, cut, shift, wei) - { - } - - //---------------------------------------------------------------------- - TrivialExtrap::TrivialExtrap(Loaders& loaders, - std::string label, - const Binning& bins, - const Var& var, - const SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift, - const Var& wei) - : TrivialExtrap(loaders, HistAxis(label, bins, var), spillcut, cut, shift, wei) + TrivialExtrap::TrivialExtrap(SliceSources& srcs, const HistAxis& axis) + : TrivialExtrap(srcs.GetLoader(kMC, kNonSwap), + srcs.GetLoader(kMC, kNueSwap), + srcs.GetLoader(kMC, kNuTauSwap), + srcs.GetLoader(kMC, kIntrinsic), + axis) { } //---------------------------------------------------------------------- - TrivialExtrap::TrivialExtrap(Loaders& loaders, - const HistAxis& axis, - const SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift, - const Var& wei) - : TrivialExtrap(loaders.GetLoader(Loaders::kMC, ana::kBeam, Loaders::kNonSwap), - loaders.GetLoader(Loaders::kMC, ana::kBeam, Loaders::kNueSwap), - loaders.GetLoader(Loaders::kMC, ana::kBeam, Loaders::kNuTauSwap), - loaders.GetLoader(Loaders::kMC, ana::kBeam, Loaders::kIntrinsic), - axis, spillcut, cut, shift, wei) - { - } - - //---------------------------------------------------------------------- - void TrivialExtrap::SaveTo(TDirectory* dir) const + void TrivialExtrap::SaveTo(TDirectory* dir, const std::string& name) const { TDirectory* tmp = gDirectory; + dir = dir->mkdir(name.c_str()); // switch to subdir dir->cd(); TObjString("TrivialExtrap").Write("type"); - fNueApp.SaveTo(dir->mkdir("nue_app")); - fNueAppAnti.SaveTo(dir->mkdir("nue_app_anti")); - fNCFromNumu.SaveTo(dir->mkdir("nc_from_numu")); - fNCFromNue.SaveTo(dir->mkdir("nc_from_nue")); - fNumuSurv.SaveTo(dir->mkdir("numu_surv")); - fNumuSurvAnti.SaveTo(dir->mkdir("numu_surv_anti")); - fNumuApp.SaveTo(dir->mkdir("numu_app")); - fNumuAppAnti.SaveTo(dir->mkdir("numu_app_anti")); - fNueSurv.SaveTo(dir->mkdir("nue_surv")); - fNueSurvAnti.SaveTo(dir->mkdir("nue_surv_anti")); - fTauFromE.SaveTo(dir->mkdir("nutau_from_nue")); - fTauFromEAnti.SaveTo(dir->mkdir("nutau_from_nue_anti")); - fTauFromMu.SaveTo(dir->mkdir("nutau_from_numu")); - fTauFromMuAnti.SaveTo(dir->mkdir("nutau_from_numu_anti")); + fNueApp.SaveTo(dir, "nue_app"); + fNueAppAnti.SaveTo(dir, "nue_app_anti"); + fNCFromNumu.SaveTo(dir, "nc_from_numu"); + fNCFromNue.SaveTo(dir, "nc_from_nue"); + fNumuSurv.SaveTo(dir, "numu_surv"); + fNumuSurvAnti.SaveTo(dir, "numu_surv_anti"); + fNumuApp.SaveTo(dir, "numu_app"); + fNumuAppAnti.SaveTo(dir, "numu_app_anti"); + fNueSurv.SaveTo(dir, "nue_surv"); + fNueSurvAnti.SaveTo(dir, "nue_surv_anti"); + fTauFromE.SaveTo(dir, "nutau_from_nue"); + fTauFromEAnti.SaveTo(dir, "nutau_from_nue_anti"); + fTauFromMu.SaveTo(dir, "nutau_from_numu"); + fTauFromMuAnti.SaveTo(dir, "nutau_from_numu_anti"); + + dir->Write(); + delete dir; tmp->cd(); } //---------------------------------------------------------------------- - std::unique_ptr TrivialExtrap::LoadFrom(TDirectory* dir) + std::unique_ptr TrivialExtrap::LoadFrom(TDirectory* dir, const std::string& name) { + dir = dir->GetDirectory(name.c_str()); // switch to subdir + assert(dir); + std::unique_ptr ret(new TrivialExtrap); - // This is a lot of repetitive typing. Define some macros -#define LOAD_OSC(FIELD, LABEL) assert(dir->GetDirectory(LABEL)); ret->FIELD = *OscillatableSpectrum::LoadFrom(dir->GetDirectory(LABEL)); -#define LOAD_SPECT(FIELD, LABEL) assert(dir->GetDirectory(LABEL)); ret->FIELD = *Spectrum::LoadFrom(dir->GetDirectory(LABEL)); - - LOAD_OSC(fNueApp, "nue_app"); - LOAD_OSC(fNueAppAnti, "nue_app_anti"); - LOAD_OSC(fNumuSurv, "numu_surv"); - LOAD_OSC(fNumuSurvAnti, "numu_surv_anti"); - LOAD_OSC(fNumuApp, "numu_app"); - LOAD_OSC(fNumuAppAnti, "numu_app_anti"); - LOAD_OSC(fNueSurv, "nue_surv"); - LOAD_OSC(fNueSurvAnti, "nue_surv_anti"); - LOAD_OSC(fTauFromE, "nutau_from_nue"); - LOAD_OSC(fTauFromEAnti, "nutau_from_nue_anti"); - LOAD_OSC(fTauFromMu, "nutau_from_numu"); - LOAD_OSC(fTauFromMuAnti, "nutau_from_numu_anti"); - LOAD_OSC(fNCFromNumu, "nc_from_numu"); - LOAD_OSC(fNCFromNue, "nc_from_nue"); + ret->fNueApp = *OscillatableSpectrum::LoadFrom(dir, "nue_app"); + ret->fNueAppAnti = *OscillatableSpectrum::LoadFrom(dir, "nue_app_anti"); + ret->fNumuSurv = *OscillatableSpectrum::LoadFrom(dir, "numu_surv"); + ret->fNumuSurvAnti = *OscillatableSpectrum::LoadFrom(dir, "numu_surv_anti"); + ret->fNumuApp = *OscillatableSpectrum::LoadFrom(dir, "numu_app"); + ret->fNumuAppAnti = *OscillatableSpectrum::LoadFrom(dir, "numu_app_anti"); + ret->fNueSurv = *OscillatableSpectrum::LoadFrom(dir, "nue_surv"); + ret->fNueSurvAnti = *OscillatableSpectrum::LoadFrom(dir, "nue_surv_anti"); + ret->fTauFromE = *OscillatableSpectrum::LoadFrom(dir, "nutau_from_nue"); + ret->fTauFromEAnti = *OscillatableSpectrum::LoadFrom(dir, "nutau_from_nue_anti"); + ret->fTauFromMu = *OscillatableSpectrum::LoadFrom(dir, "nutau_from_numu"); + ret->fTauFromMuAnti = *OscillatableSpectrum::LoadFrom(dir, "nutau_from_numu_anti"); + ret->fNCFromNumu = *OscillatableSpectrum::LoadFrom(dir, "nc_from_numu"); + ret->fNCFromNue = *OscillatableSpectrum::LoadFrom(dir, "nc_from_nue"); return ret; } diff --git a/sbnana/CAFAna/Extrap/TrivialExtrap.h b/sbnana/CAFAna/Extrap/TrivialExtrap.h index 388faff0..732b4c89 100644 --- a/sbnana/CAFAna/Extrap/TrivialExtrap.h +++ b/sbnana/CAFAna/Extrap/TrivialExtrap.h @@ -2,6 +2,9 @@ #include "sbnana/CAFAna/Extrap/IExtrap.h" +#include "sbnana/CAFAna/Core/IRecordSource.h" +#include "sbnana/CAFAna/Core/Loaders.h" + namespace ana { class Loaders; @@ -10,43 +13,13 @@ namespace ana class TrivialExtrap: public IExtrap { public: - TrivialExtrap(SpectrumLoaderBase& loaderNonswap, - SpectrumLoaderBase& loaderNue, - SpectrumLoaderBase& loaderNuTau, - SpectrumLoaderBase& loaderIntrinsic, - const HistAxis& axis, - const SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift, - const Var& wei); - - TrivialExtrap(SpectrumLoaderBase& loaderNonswap, - SpectrumLoaderBase& loaderNue, - SpectrumLoaderBase& loaderNuTau, - SpectrumLoaderBase& loaderIntrinsic, - std::string label, - const Binning& bins, - const Var& var, - const SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift, - const Var& wei); - - TrivialExtrap(Loaders& loaders, - std::string label, - const Binning& bins, - const Var& var, - const SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift = kNoShift, - const Var& wei = kUnweighted); + TrivialExtrap(ISliceSource& nonswapSrc, + ISliceSource& nueSrc, + ISliceSource& tauSrc, + ISliceSource& intrinsicSrc, + const HistAxis& axis); - TrivialExtrap(Loaders& loaders, - const HistAxis& axis, - const SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift = kNoShift, - const Var& wei = kUnweighted); + TrivialExtrap(SliceSources& srcs, const HistAxis& axis); virtual OscillatableSpectrum NueSurvComponent() {return fNueSurv;} virtual OscillatableSpectrum AntiNueSurvComponent() {return fNueSurvAnti;} @@ -69,19 +42,20 @@ namespace ana virtual OscillatableSpectrum NCComponentFromNumu() {return fNCFromNumu;} virtual OscillatableSpectrum NCComponentFromNue() {return fNCFromNue;} - virtual void SaveTo(TDirectory* dir) const; - static std::unique_ptr LoadFrom(TDirectory* dir); + virtual void SaveTo(TDirectory* dir, const std::string& name) const; + static std::unique_ptr LoadFrom(TDirectory* dir, const std::string& name); protected: TrivialExtrap() - : fNueApp(0, {}, {}, 0, 0), fNueAppAnti(0, {}, {}, 0, 0), - fNumuSurv(0, {}, {}, 0, 0), fNumuSurvAnti(0, {}, {}, 0, 0), - fNumuApp(0, {}, {}, 0, 0), fNumuAppAnti(0, {}, {}, 0, 0), - fNueSurv(0, {}, {}, 0, 0), fNueSurvAnti(0, {}, {}, 0, 0), - fTauFromE(0, {}, {}, 0, 0), fTauFromEAnti(0, {}, {}, 0, 0), - fTauFromMu(0, {}, {}, 0, 0), fTauFromMuAnti(0, {}, {}, 0, 0), - fNCFromNumu(0, {}, {}, 0, 0), fNCFromNue(0, {}, {}, 0, 0) - {} + : fNueApp(OscillatableSpectrum::Uninitialized()), fNueAppAnti(OscillatableSpectrum::Uninitialized()), + fNumuSurv(OscillatableSpectrum::Uninitialized()), fNumuSurvAnti(OscillatableSpectrum::Uninitialized()), + fNumuApp(OscillatableSpectrum::Uninitialized()), fNumuAppAnti(OscillatableSpectrum::Uninitialized()), + fNueSurv(OscillatableSpectrum::Uninitialized()), fNueSurvAnti(OscillatableSpectrum::Uninitialized()), + fTauFromE(OscillatableSpectrum::Uninitialized()), fTauFromEAnti(OscillatableSpectrum::Uninitialized()), + fTauFromMu(OscillatableSpectrum::Uninitialized()), fTauFromMuAnti(OscillatableSpectrum::Uninitialized()), + fNCFromNumu(OscillatableSpectrum::Uninitialized()), fNCFromNue(OscillatableSpectrum::Uninitialized()) + { + } OscillatableSpectrum fNueApp, fNueAppAnti; OscillatableSpectrum fNumuSurv, fNumuSurvAnti; diff --git a/sbnana/CAFAna/Prediction/CMakeLists.txt b/sbnana/CAFAna/Prediction/CMakeLists.txt index ee4facc5..98151f42 100644 --- a/sbnana/CAFAna/Prediction/CMakeLists.txt +++ b/sbnana/CAFAna/Prediction/CMakeLists.txt @@ -1,6 +1,3 @@ -# Allow "StandardRecord/" to find the right directory -include_directories(..) - cet_make(LIBRARY_NAME CAFAnaPrediction LIBRARIES CAFAnaCore CAFAnaSysts CAFAnaExtrap ) diff --git a/sbnana/CAFAna/Prediction/IPrediction.cxx b/sbnana/CAFAna/Prediction/IPrediction.cxx index 013f4be0..4c964543 100644 --- a/sbnana/CAFAna/Prediction/IPrediction.cxx +++ b/sbnana/CAFAna/Prediction/IPrediction.cxx @@ -15,7 +15,6 @@ #include "sbnana/CAFAna/Prediction/PredictionInterp.h" #include "sbnana/CAFAna/Prediction/PredictionLinFit.h" #include "sbnana/CAFAna/Prediction/PredictionNoOsc.h" -#include "sbnana/CAFAna/Prediction/PredictionScaleComp.h" #include "sbnana/CAFAna/Prediction/PredictionIncDirt.h" #include "sbnana/CAFAna/Prediction/PredictionSBNExtrap.h" @@ -23,28 +22,24 @@ namespace ana { //---------------------------------------------------------------------- // Definition to satisfy declaration in Core/LoadFromFile.h - template<> std::unique_ptr LoadFrom(TDirectory* dir) + template<> std::unique_ptr LoadFrom(TDirectory* dir, const std::string& name) { - TObjString* ptag = (TObjString*)dir->Get("type"); + TObjString* ptag = (TObjString*)dir->GetDirectory(name.c_str())->Get("type"); assert(ptag); const TString tag = ptag->GetString(); - if(tag == "PredictionNoExtrap") return PredictionNoExtrap::LoadFrom(dir); + if(tag == "PredictionNoExtrap") return PredictionNoExtrap::LoadFrom(dir, name); - // Backwards compatibility - if(tag == "PredictionInterp" || - tag == "PredictionInterp2") return PredictionInterp::LoadFrom(dir); + if(tag == "PredictionInterp") return PredictionInterp::LoadFrom(dir, name); - // if(tag == "PredictionLinFit") return PredictionLinFit::LoadFrom(dir); + // if(tag == "PredictionLinFit") return PredictionLinFit::LoadFrom(dir, name); - if(tag == "PredictionNoOsc") return PredictionNoOsc::LoadFrom(dir); + if(tag == "PredictionNoOsc") return PredictionNoOsc::LoadFrom(dir, name); - if(tag == "PredictionScaleComp") return PredictionScaleComp::LoadFrom(dir); + if(tag == "PredictionIncDirt") return PredictionIncDirt::LoadFrom(dir, name); - if(tag == "PredictionIncDirt") return PredictionIncDirt::LoadFrom(dir); - - if(tag == "PredictionSBNExtrap") return PredictionSBNExtrap::LoadFrom(dir); + if(tag == "PredictionSBNExtrap") return PredictionSBNExtrap::LoadFrom(dir, name); std::cerr << "Unknown Prediction type '" << tag << "'" << std::endl; abort(); @@ -82,7 +77,7 @@ namespace ana } //---------------------------------------------------------------------- - void IPrediction::SaveTo(TDirectory* dir) const + void IPrediction::SaveTo(TDirectory* dir, const std::string& name) const { assert(0 && "Not implemented"); } diff --git a/sbnana/CAFAna/Prediction/IPrediction.h b/sbnana/CAFAna/Prediction/IPrediction.h index 34d5e38c..89d0be0f 100644 --- a/sbnana/CAFAna/Prediction/IPrediction.h +++ b/sbnana/CAFAna/Prediction/IPrediction.h @@ -1,6 +1,6 @@ #pragma once -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "cafanacore/Spectrum.h" #include "sbnana/CAFAna/Core/OscillatableSpectrum.h" @@ -75,10 +75,10 @@ namespace ana Sign::Sign_t sign) const; virtual OscillatableSpectrum ComponentCC(int from, int to) const - {std::cout << "OscillatableSpectrum::ComponentCC() unimplemented" << std::endl; abort();} + {/*std::cout << "OscillatableSpectrum::ComponentCC() unimplemented" << std::endl;*/ abort();} //virtual Spectrum ComponentNC() const //{std::cout << "OscillatableSpectrum::ComponentNC() unimplemented" << std::endl; abort();} - virtual void SaveTo(TDirectory* dir) const; + virtual void SaveTo(TDirectory* dir, const std::string& name) const; }; } diff --git a/sbnana/CAFAna/Prediction/PredictionExtrap.cxx b/sbnana/CAFAna/Prediction/PredictionExtrap.cxx index ed7f996f..2a201cb1 100644 --- a/sbnana/CAFAna/Prediction/PredictionExtrap.cxx +++ b/sbnana/CAFAna/Prediction/PredictionExtrap.cxx @@ -103,24 +103,31 @@ namespace ana // } //---------------------------------------------------------------------- - void PredictionExtrap::SaveTo(TDirectory* dir) const + void PredictionExtrap::SaveTo(TDirectory* dir, const std::string& name) const { TDirectory* tmp = gDirectory; + dir = dir->mkdir(name.c_str()); // switch to subdir dir->cd(); TObjString("PredictionExtrap").Write("type"); - fExtrap->SaveTo(dir->mkdir("extrap")); + fExtrap->SaveTo(dir, "extrap"); + + dir->Write(); + delete dir; tmp->cd(); } //---------------------------------------------------------------------- - std::unique_ptr PredictionExtrap::LoadFrom(TDirectory* dir) + std::unique_ptr PredictionExtrap::LoadFrom(TDirectory* dir, const std::string& name) { + dir = dir->GetDirectory(name.c_str()); // switch to subdir + assert(dir); + assert(dir->GetDirectory("extrap")); - IExtrap* extrap = ana::LoadFrom(dir->GetDirectory("extrap")).release(); + IExtrap* extrap = ana::LoadFrom(dir, "extrap").release(); return std::unique_ptr(new PredictionExtrap(extrap)); } diff --git a/sbnana/CAFAna/Prediction/PredictionExtrap.h b/sbnana/CAFAna/Prediction/PredictionExtrap.h index b9542d92..3dcb6304 100644 --- a/sbnana/CAFAna/Prediction/PredictionExtrap.h +++ b/sbnana/CAFAna/Prediction/PredictionExtrap.h @@ -24,14 +24,13 @@ namespace ana OscillatableSpectrum ComponentCC(int from, int to) const override; // Spectrum ComponentNC() const override; - virtual void SaveTo(TDirectory* dir) const override; - static std::unique_ptr LoadFrom(TDirectory* dir); + virtual void SaveTo(TDirectory* dir, const std::string& name) const override; + static std::unique_ptr LoadFrom(TDirectory* dir, const std::string& name); PredictionExtrap() = delete; IExtrap* GetExtrap() const {return fExtrap;} protected: - IExtrap* fExtrap; }; } diff --git a/sbnana/CAFAna/Prediction/PredictionIncDirt.cxx b/sbnana/CAFAna/Prediction/PredictionIncDirt.cxx index 51fc7821..d7a84b46 100644 --- a/sbnana/CAFAna/Prediction/PredictionIncDirt.cxx +++ b/sbnana/CAFAna/Prediction/PredictionIncDirt.cxx @@ -8,34 +8,23 @@ namespace ana { // -------------------------------------------------------------------------- - PredictionIncDirt::PredictionIncDirt(SpectrumLoaderBase& loaderNonswap, - SpectrumLoaderBase& loaderNue, - SpectrumLoaderBase& loaderNuTau, - SpectrumLoaderBase& loaderIntrinsic, - SpectrumLoaderBase& loaderDirt, - const HistAxis& axis, - const SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift, - const Var& wei) - : fDet(loaderNonswap, loaderNue, loaderNuTau, loaderIntrinsic, - axis, spillcut, cut, shift, wei), - fDirt(loaderDirt, kNullLoader, kNullLoader, kNullLoader, - axis, spillcut, cut, shift, wei) + PredictionIncDirt::PredictionIncDirt(ISliceSource& srcNonswap, + ISliceSource& srcNue, + ISliceSource& srcNuTau, + ISliceSource& srcIntrinsic, + ISliceSource& srcDirt, + const HistAxis& axis) + : fDet(srcNonswap, srcNue, srcNuTau, srcIntrinsic, axis), + fDirt(srcDirt, kNullSliceSource, kNullSliceSource, kNullSliceSource, axis) { } // -------------------------------------------------------------------------- - PredictionIncDirt::PredictionIncDirt(Loaders& loaders, - SpectrumLoaderBase& loaderDirt, - const HistAxis& axis, - const SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift, - const Var& wei) - : fDet(loaders, axis, spillcut, cut, shift, wei), - fDirt(loaderDirt, kNullLoader, kNullLoader, kNullLoader, - axis, spillcut, cut, shift, wei) + PredictionIncDirt::PredictionIncDirt(SliceSources& srcs, + ISliceSource& srcDirt, + const HistAxis& axis) + : fDet(srcs, axis), + fDirt(srcDirt, kNullSliceSource, kNullSliceSource, kNullSliceSource, axis) { } @@ -46,25 +35,32 @@ namespace ana // -------------------------------------------------------------------------- std::unique_ptr - PredictionIncDirt::LoadFrom(TDirectory* dir) + PredictionIncDirt::LoadFrom(TDirectory* dir, const std::string& name) { + dir = dir->GetDirectory(name.c_str()); // switch to subdir + assert(dir); + assert(dir->GetDirectory("det") && dir->GetDirectory("dirt")); - return std::unique_ptr(new PredictionIncDirt(ana::LoadFrom(dir->GetDirectory("det")), - ana::LoadFrom(dir->GetDirectory("dirt")))); + return std::unique_ptr(new PredictionIncDirt(ana::LoadFrom(dir, "det"), + ana::LoadFrom(dir, "dirt"))); } // -------------------------------------------------------------------------- - void PredictionIncDirt::SaveTo(TDirectory* dir) const + void PredictionIncDirt::SaveTo(TDirectory* dir, const std::string& name) const { TDirectory* tmp = gDirectory; + dir = dir->mkdir(name.c_str()); // switch to subdir dir->cd(); TObjString("PredictionIncDirt").Write("type"); - fDet.SaveTo(dir->mkdir("det")); - fDirt.SaveTo(dir->mkdir("dirt")); + fDet.SaveTo(dir, "det"); + fDirt.SaveTo(dir, "dirt"); + + dir->Write(); + delete dir; tmp->cd(); } diff --git a/sbnana/CAFAna/Prediction/PredictionIncDirt.h b/sbnana/CAFAna/Prediction/PredictionIncDirt.h index fad0d9da..5c6f5d00 100644 --- a/sbnana/CAFAna/Prediction/PredictionIncDirt.h +++ b/sbnana/CAFAna/Prediction/PredictionIncDirt.h @@ -12,29 +12,21 @@ namespace ana class PredictionIncDirt: public IPrediction { public: - PredictionIncDirt(SpectrumLoaderBase& loaderNonswap, - SpectrumLoaderBase& loaderNue, - SpectrumLoaderBase& loaderNuTau, - SpectrumLoaderBase& loaderIntrinsic, - SpectrumLoaderBase& loaderDirt, - const HistAxis& axis, - const SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift = kNoShift, - const Var& wei = kUnweighted); - - PredictionIncDirt(Loaders& loaders, - SpectrumLoaderBase& loaderDirt, - const HistAxis& axis, - const SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift = kNoShift, - const Var& wei = kUnweighted); + PredictionIncDirt(ISliceSource& srcNonswap, + ISliceSource& srcNue, + ISliceSource& srcNuTau, + ISliceSource& srcIntrinsic, + ISliceSource& srcDirt, + const HistAxis& axis); + + PredictionIncDirt(SliceSources& srcs, + ISliceSource& srcDirt, + const HistAxis& axis); virtual ~PredictionIncDirt(); - static std::unique_ptr LoadFrom(TDirectory* dir); - virtual void SaveTo(TDirectory* dir) const override; + static std::unique_ptr LoadFrom(TDirectory* dir, const std::string& name); + virtual void SaveTo(TDirectory* dir, const std::string& name) const override; Spectrum PredictDet(osc::IOscCalc* calc) const { @@ -61,7 +53,7 @@ namespace ana { return fDirt.PredictComponent(calc, flav, curr, sign); } - + virtual Spectrum Predict(osc::IOscCalc* calc) const override { return PredictDet(calc) + PredictDirt(calc); diff --git a/sbnana/CAFAna/Prediction/PredictionInterp.cxx b/sbnana/CAFAna/Prediction/PredictionInterp.cxx index a6c7767c..ff81a636 100644 --- a/sbnana/CAFAna/Prediction/PredictionInterp.cxx +++ b/sbnana/CAFAna/Prediction/PredictionInterp.cxx @@ -1,8 +1,7 @@ #include "sbnana/CAFAna/Prediction/PredictionInterp.h" -#include "sbnana/CAFAna/Core/HistCache.h" #include "sbnana/CAFAna/Core/LoadFromFile.h" -#include "sbnana/CAFAna/Core/Ratio.h" -#include "sbnana/CAFAna/Core/SystRegistry.h" +#include "cafanacore/Ratio.h" +#include "cafanacore/Registry.h" #include "sbnana/CAFAna/Core/Utilities.h" #include "TDirectory.h" @@ -33,7 +32,7 @@ namespace ana const SystShifts& shiftMC, EMode_t mode) : fOscOrigin(osc ? osc->Copy() : 0), - fBinning(0, {}, {}, 0, 0), + fBinning(Spectrum::Uninitialized()), fSplitBySign(mode == kSplitBySign) { for(const ISyst* syst: systs){ @@ -69,26 +68,21 @@ namespace ana //---------------------------------------------------------------------- std::vector> PredictionInterp:: FitRatios(const std::vector& shifts, - const std::vector>& ratios) const + const std::vector& ratios) const { + if(ratios.size() < 2){ + std::cout << "PredictionInterp::FitRatios(): ratios.size() = " << ratios.size() << " - how did that happen?" << std::endl; + + abort(); + } + assert(shifts.size() == ratios.size()); std::vector> ret; - const int binMax = ratios[0]->GetNbinsX(); + const int binMax = ratios[0].size(); - // Linear interpolation - if(ratios.size() == 2){ - for(int binIdx = 0; binIdx < binMax+2; ++binIdx){ - ret.push_back({}); - const double y1 = ratios[0]->GetBinContent(binIdx); - const double y2 = ratios[1]->GetBinContent(binIdx); - ret.back().emplace_back(0, 0, y2-y1, y1); - } - return ret; - } - - for(int binIdx = 0; binIdx < binMax+2; ++binIdx){ + for(int binIdx = 0; binIdx < binMax; ++binIdx){ ret.push_back({}); // This is cubic interpolation. For each adjacent set of four points we @@ -102,10 +96,19 @@ namespace ana // at x=1. The matrices are simply the inverses of writing out the // constraints expressed above. + // Special-case for linear interpolation + if(ratios.size() == 2){ + const double y0 = ratios[0][binIdx]; + const double y1 = ratios[1][binIdx]; + + ret.back().emplace_back(0, 0, y1-y0, y0); + continue; + } + { - const double y1 = ratios[0]->GetBinContent(binIdx); - const double y2 = ratios[1]->GetBinContent(binIdx); - const double y3 = ratios[2]->GetBinContent(binIdx); + const double y1 = ratios[0][binIdx]; + const double y2 = ratios[1][binIdx]; + const double y3 = ratios[2][binIdx]; const double v[3] = {y1, y2, (y3-y1)/2}; const double m[9] = { 1, -1, 1, -2, 2, -1, @@ -116,10 +119,10 @@ namespace ana // We're assuming here that the shifts are separated by exactly 1 sigma. for(unsigned int shiftIdx = 1; shiftIdx < ratios.size()-2; ++shiftIdx){ - const double y0 = ratios[shiftIdx-1]->GetBinContent(binIdx); - const double y1 = ratios[shiftIdx ]->GetBinContent(binIdx); - const double y2 = ratios[shiftIdx+1]->GetBinContent(binIdx); - const double y3 = ratios[shiftIdx+2]->GetBinContent(binIdx); + const double y0 = ratios[shiftIdx-1][binIdx]; + const double y1 = ratios[shiftIdx ][binIdx]; + const double y2 = ratios[shiftIdx+1][binIdx]; + const double y3 = ratios[shiftIdx+2][binIdx]; const double v[4] = {y1, y2, (y2-y0)/2, (y3-y1)/2}; const double m[16] = { 2, -2, 1, 1, @@ -132,9 +135,9 @@ namespace ana { const int N = ratios.size()-3; - const double y0 = ratios[N ]->GetBinContent(binIdx); - const double y1 = ratios[N+1]->GetBinContent(binIdx); - const double y2 = ratios[N+2]->GetBinContent(binIdx); + const double y0 = ratios[N ][binIdx]; + const double y1 = ratios[N+1][binIdx]; + const double y2 = ratios[N+2][binIdx]; const double v[3] = {y1, y2, (y2-y0)/2}; const double m[9] = {-1, 1, -1, 0, 0, 1, @@ -181,24 +184,25 @@ namespace ana // relative to some alternate nominal (eg Birks C where the appropriate // nominal is no-rock) can work. const Spectrum nom = pNom->PredictComponent(fOscOrigin, - flav, curr, sign); + flav, curr, sign); - std::vector> ratios; + std::vector ratios; + ratios.reserve(preds.size()); for(auto& p: preds){ ratios.emplace_back(Ratio(p->PredictComponent(fOscOrigin, flav, curr, sign), - nom).ToTH1()); - - // Check none of the ratio values is utterly crazy - std::unique_ptr& r = ratios.back(); - for(int i = 0; i < r->GetNbinsX()+2; ++i){ - const double y = r->GetBinContent(i); - if(y > 500){ - std::cout << "PredictionInterp: WARNING, ratio in bin " - << i << " is " << y - << " for '" << shortName << "'. Ignoring." << std::endl; - r->SetBinContent(i, 1); - } + nom).GetEigen()); + + // Check none of the ratio values is crazy + Eigen::ArrayXd& r = ratios.back(); + for(int i = 0; i < r.size(); ++i){ + if (r[i] > 2){ + // std::cout << "PredictionInterp: WARNING, ratio in bin " + // << i << " for " << shifts[&p-&preds.front()] + // << " sigma shift of " << systName << " is " << y + // << " which exceeds limit of 2. Capping." << std::endl; + r[i] = 2; + } } } @@ -283,38 +287,42 @@ namespace ana } //---------------------------------------------------------------------- - Spectrum PredictionInterp:: - ShiftSpectrum(const Spectrum& s, - CoeffsType type, - bool nubar, - const SystShifts& shift) const + Spectrum PredictionInterp::ShiftSpectrum(const Spectrum& s, CoeffsType type, + bool nubar, + const SystShifts &shift) const { // Save time by not shifting a spectrum that is all zeros anyway if(s.POT() == 0 && s.Livetime() == 0) return s; - if(nubar) assert(fSplitBySign); - - InitFits(); + Eigen::ArrayXd vec = s.GetEigen(s.POT()); + ShiftBins(vec.size(), vec.data(), type, nubar, shift); + return Spectrum(std::move(vec), HistAxis(s.GetLabels(), s.GetBinnings()), s.POT(), s.Livetime()); + } - // TODO histogram operations could be too slow - TH1D* h = s.ToTH1(s.POT()); + //---------------------------------------------------------------------- + void PredictionInterp::ShiftBins(unsigned int N, + double* arr, + CoeffsType type, + bool nubar, + const SystShifts& shift) const + { + if(nubar) assert(fSplitBySign); - const unsigned int N = h->GetNbinsX()+2; - std::vector corr(N,1.0); + std::vector corr(N, 1); for(auto& it: fPreds){ const ISyst* syst = it.first; const ShiftedPreds& sp = it.second; - auto& fits = nubar ? sp.fitsNubar : sp.fits; - double x = shift.GetShift(syst); if(x == 0) continue; int shiftBin = (x - sp.shifts[0])/sp.Stride(); shiftBin = std::max(0, shiftBin); - shiftBin = std::min(shiftBin, sp.nCoeffs-1); + shiftBin = std::min(shiftBin, sp.nCoeffs - 1); + + auto& fits = nubar ? sp.fitsNubar : sp.fits; x -= sp.shifts[shiftBin]; @@ -330,14 +338,12 @@ namespace ana corr[n] *= f.a*x_cube + f.b*x_sqr + f.c*x + f.d; } // end for n + } // end for syst - double* arr = h->GetArray(); - for(unsigned int n = 0; n < N; ++n){ - arr[n] *= std::max(corr[n], 0.); + for(unsigned int n = 0; n < N; ++n) { + arr[n] *= (corr[n] > 0.) ? corr[n] : 0.; } - - return Spectrum(std::unique_ptr(h), s.GetLabels(), s.GetBinnings(), s.POT(), s.Livetime()); } //---------------------------------------------------------------------- @@ -433,15 +439,17 @@ namespace ana } //---------------------------------------------------------------------- - void PredictionInterp::SaveTo(TDirectory* dir) const + void PredictionInterp::SaveTo(TDirectory* dir, const std::string& name) const { TDirectory* tmp = gDirectory; + dir = dir->mkdir(name.c_str()); // switch to subdir dir->cd(); + TObjString("PredictionInterp").Write("type"); - fPredNom->SaveTo(dir->mkdir("pred_nom")); + fPredNom->SaveTo(dir, "pred_nom"); for(auto it: fPreds){ @@ -452,13 +460,13 @@ namespace ana std::cout << "Can't save a PredictionInterp after MinimizeMemory()" << std::endl; abort(); } - sp.preds[i]->SaveTo(dir->mkdir(TString::Format("pred_%s_%+d", - sp.systName.c_str(), - int(sp.shifts[i])).Data())); + sp.preds[i]->SaveTo(dir, TString::Format("pred_%s_%+d", + sp.systName.c_str(), + int(sp.shifts[i])).Data()); } // end for i } // end for it - ana::SaveTo(*fOscOrigin, dir->mkdir("osc_origin")); + ana::SaveTo(*fOscOrigin, dir, "osc_origin"); if(!fPreds.empty()){ TH1F hSystNames("syst_names", ";Syst names", fPreds.size(), 0, fPreds.size()); @@ -472,16 +480,21 @@ namespace ana TObjString split_sign = fSplitBySign ? "yes" : "no"; split_sign.Write("split_sign"); + dir->Write(); + delete dir; + tmp->cd(); } //---------------------------------------------------------------------- - std::unique_ptr PredictionInterp::LoadFrom(TDirectory* dir) + std::unique_ptr PredictionInterp::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() == "PredictionInterp" || - tag->GetString() == "PredictionInterp2"); // backwards compatibility + assert(tag->GetString() == "PredictionInterp"); std::unique_ptr ret(new PredictionInterp); @@ -496,9 +509,9 @@ namespace ana //---------------------------------------------------------------------- void PredictionInterp::LoadFromBody(TDirectory* dir, PredictionInterp* ret, - std::vector veto) + std::vector veto) { - ret->fPredNom = ana::LoadFrom(dir->GetDirectory("pred_nom")); + ret->fPredNom = ana::LoadFrom(dir, "pred_nom"); TH1* hSystNames = (TH1*)dir->Get("syst_names"); if(hSystNames){ @@ -506,15 +519,17 @@ namespace ana ShiftedPreds sp; sp.systName = hSystNames->GetXaxis()->GetBinLabel(systIdx+1); - const ISyst* syst = SystRegistry::ShortNameToSyst(sp.systName); + const ISyst* syst = Registry::ShortNameToPtr(sp.systName); if(std::find(veto.begin(), veto.end(), syst) != veto.end()) continue; for(int shift = -3; shift <= +3; ++shift){ - TDirectory* preddir = dir->GetDirectory(TString::Format("pred_%s_%+d", sp.systName.c_str(), shift).Data()); + const std::string predname = TString::Format("pred_%s_%+d", sp.systName.c_str(), shift).Data(); + TDirectory* preddir = dir->GetDirectory(predname.c_str()); if(!preddir) continue; // Can happen for genie systs + delete preddir; - IPrediction* pred = ana::LoadFrom(preddir).release(); + IPrediction* pred = ana::LoadFrom(dir, predname).release(); sp.shifts.push_back(shift); sp.preds.push_back(pred); @@ -524,7 +539,7 @@ namespace ana } // end for systIdx } // end if hSystNames - ret->fOscOrigin = ana::LoadFrom(dir->GetDirectory("osc_origin")).release(); + ret->fOscOrigin = ana::LoadFrom(dir, "osc_origin").release(); } //---------------------------------------------------------------------- diff --git a/sbnana/CAFAna/Prediction/PredictionInterp.h b/sbnana/CAFAna/Prediction/PredictionInterp.h index 1bac2d1e..1bc34986 100644 --- a/sbnana/CAFAna/Prediction/PredictionInterp.h +++ b/sbnana/CAFAna/Prediction/PredictionInterp.h @@ -62,8 +62,8 @@ namespace ana Current::Current_t curr, Sign::Sign_t sign) const override; - virtual void SaveTo(TDirectory* dir) const override; - static std::unique_ptr LoadFrom(TDirectory* dir); + virtual void SaveTo(TDirectory* dir, const std::string& name) const override; + static std::unique_ptr LoadFrom(TDirectory* dir, const std::string& name); /// After calling this DebugPlots won't work fully and SaveTo won't work at /// all. @@ -78,10 +78,10 @@ namespace ana // If \a savePattern is not empty, print each pad. If it contains "%s" then // multiple files will be written, one per systematic. void DebugPlots(osc::IOscCalc* calc, - const std::string& savePattern = "", - Flavors::Flavors_t flav = Flavors::kAll, - Current::Current_t curr = Current::kBoth, - Sign::Sign_t sign = Sign::kBoth) const; + const std::string& savePattern = "", + Flavors::Flavors_t flav = Flavors::kAll, + Current::Current_t curr = Current::kBoth, + Sign::Sign_t sign = Sign::kBoth) const; void SetOscSeed(osc::IOscCalc* oscSeed); @@ -104,7 +104,7 @@ namespace ana kNCoeffTypes }; - PredictionInterp() : fBinning(0, {}, {}, 0, 0) {} + PredictionInterp() : fBinning(Spectrum::Uninitialized()) {} static void LoadFromBody(TDirectory* dir, PredictionInterp* ret, std::vector veto = {}); @@ -118,7 +118,7 @@ namespace ana /// Find coefficients describing this set of shifts std::vector> FitRatios(const std::vector& shifts, - const std::vector>& ratios) const; + const std::vector& ratios) const; /// Find coefficients describing the ratios from this component std::vector> @@ -194,6 +194,13 @@ namespace ana void InitFitsHelper(ShiftedPreds& sp, std::vector>>& fits, Sign::Sign_t sign) const; + + /// Helper for \ref ShiftSpectrum + void ShiftBins(unsigned int N, + double* arr, + CoeffsType type, + bool nubar, + const SystShifts& shift) const; }; } diff --git a/sbnana/CAFAna/Prediction/PredictionLinFit.cxx b/sbnana/CAFAna/Prediction/PredictionLinFit.cxx index 6cadc15e..2134e55c 100644 --- a/sbnana/CAFAna/Prediction/PredictionLinFit.cxx +++ b/sbnana/CAFAna/Prediction/PredictionLinFit.cxx @@ -1,11 +1,10 @@ #include "sbnana/CAFAna/Prediction/PredictionLinFit.h" -#include "sbnana/CAFAna/Core/HistCache.h" #include "sbnana/CAFAna/Core/LoadFromFile.h" #include "sbnana/CAFAna/Core/MathUtil.h" -#include "sbnana/CAFAna/Core/Progress.h" -#include "sbnana/CAFAna/Core/Ratio.h" -#include "sbnana/CAFAna/Core/SystRegistry.h" +#include "cafanacore/Progress.h" +#include "cafanacore/Ratio.h" +#include "cafanacore/Registry.h" #include "sbnana/CAFAna/Prediction/PredictionGenerator.h" @@ -114,7 +113,7 @@ namespace ana TH1D* hnom = snom.ToTH1(1); // only need this to count the bins :( const int Nbins = hnom->GetNbinsX(); - HistCache::Delete(hnom); + delete hnom; // The data (ratios) that we're trying to fit std::vector> ds(Nbins+2, std::vector(fUnivs.size())); @@ -127,7 +126,7 @@ namespace ana ds[binIdx][univIdx] = log(hr->GetBinContent(binIdx)); } - HistCache::Delete(hr); + delete hr; } Progress prog("Initializing PredictionLinFit"); @@ -308,8 +307,9 @@ namespace ana if(fCoeffs.empty()) InitFits(); // To get correct binning - TH1D* hret = fNom->PredictUnoscillated().ToTH1(1); - hret->Reset(); + Spectrum unosc = fNom->PredictUnoscillated(); + Eigen::ArrayXd aret = unosc.GetEigen(1); + aret.setZero(); const std::vector coords = GetCoords(shift); const unsigned int N = coords.size(); @@ -318,28 +318,28 @@ namespace ana double factor = 0; for(unsigned int i = 0; i < N; ++i) factor += fCoeffs[binIdx][i] * coords[i]; - hret->SetBinContent(binIdx, exp(factor)); + aret[binIdx] = exp(factor); } - const Ratio ret(hret); - HistCache::Delete(hret); - return ret; + return Ratio(std::move(aret), unosc.GetLabels(), unosc.GetBinnings()); } //---------------------------------------------------------------------- - void PredictionLinFit::SaveTo(TDirectory* dir) const + void PredictionLinFit::SaveTo(TDirectory* dir, const std::string& name) const { TDirectory* tmp = gDirectory; + dir = dir->mkdir(name.c_str()); // switch to subdir dir->cd(); + TObjString("PredictionLinFit").Write("type"); - fNom->SaveTo(dir->mkdir("nom")); + fNom->SaveTo(dir, "nom"); for(unsigned int univIdx = 0; univIdx < fUnivs.size(); ++univIdx){ TDirectory* ud = dir->mkdir(TString::Format("univ_%d", univIdx).Data()); - fUnivs[univIdx].first.SaveTo(ud->mkdir("shift")); - fUnivs[univIdx].second->SaveTo(ud->mkdir("pred")); + fUnivs[univIdx].first.SaveTo(ud, "shift"); + fUnivs[univIdx].second->SaveTo(ud, "pred"); } // end for it if(!fSysts.empty()){ @@ -351,6 +351,9 @@ namespace ana hSystNames.Write("syst_names"); } + dir->Write(); + delete dir; + tmp->cd(); } @@ -510,19 +513,22 @@ namespace ana } //---------------------------------------------------------------------- - std::unique_ptr PredictionLinFit::LoadFrom(TDirectory* dir) + std::unique_ptr PredictionLinFit::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() == "PredictionLinFit"); - std::unique_ptr nom = ana::LoadFrom(dir->GetDirectory("nom")); + std::unique_ptr nom = ana::LoadFrom(dir, "nom"); std::vector systs; TH1* hSystNames = (TH1*)dir->Get("syst_names"); if(hSystNames){ for(int systIdx = 0; systIdx < hSystNames->GetNbinsX(); ++systIdx){ - systs.push_back(SystRegistry::ShortNameToSyst(hSystNames->GetXaxis()->GetBinLabel(systIdx+1))); + systs.push_back(Registry::ShortNameToPtr(hSystNames->GetXaxis()->GetBinLabel(systIdx+1))); } } @@ -532,8 +538,8 @@ namespace ana TDirectory* ud = dir->GetDirectory(TString::Format("univ_%d", univIdx).Data()); if(!ud) break; // out of universes - univs.emplace_back(*ana::LoadFrom(ud->GetDirectory("shift")), - ana::LoadFrom(ud->GetDirectory("pred")).release()); + univs.emplace_back(*ana::LoadFrom(ud, "shift"), + ana::LoadFrom(ud, "pred").release()); } // TODO think about memory management diff --git a/sbnana/CAFAna/Prediction/PredictionLinFit.h b/sbnana/CAFAna/Prediction/PredictionLinFit.h index 5ec2c59c..0d6939d9 100644 --- a/sbnana/CAFAna/Prediction/PredictionLinFit.h +++ b/sbnana/CAFAna/Prediction/PredictionLinFit.h @@ -64,8 +64,8 @@ namespace ana Current::Current_t curr = Current::kBoth, Sign::Sign_t sign = Sign::kBoth) const; - void SaveTo(TDirectory* dir) const override; - static std::unique_ptr LoadFrom(TDirectory* dir); + void SaveTo(TDirectory* dir, const std::string& name) const override; + static std::unique_ptr LoadFrom(TDirectory* dir, const std::string& name); protected: void InitFits() const; diff --git a/sbnana/CAFAna/Prediction/PredictionNoExtrap.cxx b/sbnana/CAFAna/Prediction/PredictionNoExtrap.cxx index 0bf8bda8..02cbf5c9 100644 --- a/sbnana/CAFAna/Prediction/PredictionNoExtrap.cxx +++ b/sbnana/CAFAna/Prediction/PredictionNoExtrap.cxx @@ -13,88 +13,49 @@ namespace ana { //---------------------------------------------------------------------- - PredictionNoExtrap::PredictionNoExtrap(SpectrumLoaderBase& loaderNonswap, - SpectrumLoaderBase& loaderNue, - SpectrumLoaderBase& loaderNuTau, - SpectrumLoaderBase& loaderIntrinsic, - const std::string& label, - const Binning& bins, - const Var& var, - const SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift, - const Var& wei) - : PredictionExtrap(new TrivialExtrap(loaderNonswap, loaderNue, loaderNuTau, loaderIntrinsic, - label, bins, var, spillcut, cut, shift, wei)) + PredictionNoExtrap::PredictionNoExtrap(ISliceSource& srcNonswap, + ISliceSource& srcNue, + ISliceSource& srcNuTau, + ISliceSource& srcIntrinsic, + const HistAxis& axis) + : PredictionExtrap(new TrivialExtrap(srcNonswap, srcNue, srcNuTau, srcIntrinsic, axis)) { } //---------------------------------------------------------------------- - PredictionNoExtrap::PredictionNoExtrap(SpectrumLoaderBase& loaderNonswap, - SpectrumLoaderBase& loaderNue, - SpectrumLoaderBase& loaderNuTau, - SpectrumLoaderBase& loaderIntrinsic, - const HistAxis& axis, - const SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift, - const Var& wei) - : PredictionExtrap(new TrivialExtrap(loaderNonswap, loaderNue, loaderNuTau, loaderIntrinsic, - axis, spillcut, cut, shift, wei)) + PredictionNoExtrap::PredictionNoExtrap(SliceSources& srcs, + const HistAxis& axis) + : PredictionExtrap(new TrivialExtrap(srcs, axis)) { } //---------------------------------------------------------------------- - PredictionNoExtrap::PredictionNoExtrap(PredictionExtrap* pred) : PredictionExtrap(pred->GetExtrap()) - { - } - - //---------------------------------------------------------------------- - PredictionNoExtrap::PredictionNoExtrap(Loaders& loaders, - const std::string& label, - const Binning& bins, - const Var& var, - const SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift, - const Var& wei) - : PredictionNoExtrap(loaders, HistAxis(label, bins, var), spillcut, cut, shift, wei) - { - } - - //---------------------------------------------------------------------- - PredictionNoExtrap::PredictionNoExtrap(Loaders& loaders, - const HistAxis& axis, - const SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift, - const Var& wei) - : PredictionExtrap(new TrivialExtrap(loaders, axis, spillcut, cut, shift, wei)) - { - } - - //---------------------------------------------------------------------- - void PredictionNoExtrap::SaveTo(TDirectory* dir) const + void PredictionNoExtrap::SaveTo(TDirectory* dir, const std::string& name) const { TDirectory* tmp = gDirectory; + dir = dir->mkdir(name.c_str()); // switch to subdir dir->cd(); TObjString("PredictionNoExtrap").Write("type"); - fExtrap->SaveTo(dir->mkdir("extrap")); + fExtrap->SaveTo(dir, "extrap"); + + dir->Write(); + delete dir; tmp->cd(); } //---------------------------------------------------------------------- - std::unique_ptr PredictionNoExtrap::LoadFrom(TDirectory* dir) + std::unique_ptr PredictionNoExtrap::LoadFrom(TDirectory* dir, const std::string& name) { - assert(dir->GetDirectory("extrap")); - IExtrap* extrap = ana::LoadFrom(dir->GetDirectory("extrap")).release(); - PredictionExtrap* pred = new PredictionExtrap(extrap); - return std::unique_ptr(new PredictionNoExtrap(pred)); + dir = dir->GetDirectory(name.c_str()); // switch to subdir + assert(dir); + + TrivialExtrap* extrap = ana::LoadFrom(dir, "extrap").release(); + return std::unique_ptr(new PredictionNoExtrap(extrap)); } diff --git a/sbnana/CAFAna/Prediction/PredictionNoExtrap.h b/sbnana/CAFAna/Prediction/PredictionNoExtrap.h index abc13a88..a05b2f41 100644 --- a/sbnana/CAFAna/Prediction/PredictionNoExtrap.h +++ b/sbnana/CAFAna/Prediction/PredictionNoExtrap.h @@ -4,6 +4,8 @@ #include "sbnana/CAFAna/Prediction/PredictionGenerator.h" +#include "sbnana/CAFAna/Extrap/TrivialExtrap.h" + namespace ana { class Loaders; @@ -12,57 +14,28 @@ namespace ana class PredictionNoExtrap: public PredictionExtrap { public: - PredictionNoExtrap(PredictionExtrap* pred); - - PredictionNoExtrap(SpectrumLoaderBase& loaderNonswap, - SpectrumLoaderBase& loaderNue, - SpectrumLoaderBase& loaderNuTau, - SpectrumLoaderBase& loaderIntrinsic, - const std::string& label, - const Binning& bins, - const Var& var, - const SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift = kNoShift, - const Var& wei = kUnweighted); - - PredictionNoExtrap(SpectrumLoaderBase& loaderNonswap, - SpectrumLoaderBase& loaderNue, - SpectrumLoaderBase& loaderNuTau, - SpectrumLoaderBase& loaderIntrinsic, - const HistAxis& axis, - const SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift = kNoShift, - const Var& wei = kUnweighted); + PredictionNoExtrap(ISliceSource& srcNonswap, + ISliceSource& srcNue, + ISliceSource& srcNuTau, + ISliceSource& srcIntrinsic, + const HistAxis& axis); - PredictionNoExtrap(Loaders& loaders, - const std::string& label, - const Binning& bins, - const Var& var, - const SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift = kNoShift, - const Var& wei = kUnweighted); - - PredictionNoExtrap(Loaders& loaders, - const HistAxis& axis, - const SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift = kNoShift, - const Var& wei = kUnweighted); + PredictionNoExtrap(SliceSources& srcs, const HistAxis& axis); virtual ~PredictionNoExtrap(); - static std::unique_ptr LoadFrom(TDirectory* dir); - virtual void SaveTo(TDirectory* dir) const override; + static std::unique_ptr LoadFrom(TDirectory* dir, const std::string& name); + virtual void SaveTo(TDirectory* dir, const std::string& name) const override; + protected: + PredictionNoExtrap(TrivialExtrap* extrap) : PredictionExtrap(extrap) {} }; + /* TODO think about generators class NoExtrapPredictionGenerator: public IPredictionGenerator { public: - NoExtrapPredictionGenerator(HistAxis axis, SpillCut spillcut, Cut cut, Var wei = kUnweighted) + NoExtrapPredictionGenerator(HistAxis axis, SpillCut spillcut, Cut cut, Weight wei = kUnweighted) : fAxis(axis), fSpillCut(spillcut), fCut(cut), fWei(wei) { } @@ -77,6 +50,7 @@ namespace ana HistAxis fAxis; SpillCut fSpillCut; Cut fCut; - Var fWei; + Weight fWei; }; + */ } diff --git a/sbnana/CAFAna/Prediction/PredictionNoOsc.cxx b/sbnana/CAFAna/Prediction/PredictionNoOsc.cxx index 36e023c4..a525ade2 100644 --- a/sbnana/CAFAna/Prediction/PredictionNoOsc.cxx +++ b/sbnana/CAFAna/Prediction/PredictionNoOsc.cxx @@ -15,31 +15,13 @@ namespace ana { //---------------------------------------------------------------------- - PredictionNoOsc::PredictionNoOsc(SpectrumLoaderBase& loader, - const std::string& label, - const Binning& bins, - const Var& var, - const SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift, - const Var& wei) - : PredictionNoOsc(loader, HistAxis(label, bins, var), spillcut, cut, shift, wei) - { - } - - //---------------------------------------------------------------------- - PredictionNoOsc::PredictionNoOsc(SpectrumLoaderBase& loader, - const HistAxis& axis, - const SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift, - const Var& wei) - : fSpectrum( loader, axis, spillcut, cut, shift, wei), - fSpectrumNC( loader, axis, spillcut, cut && kIsNC, shift, wei), - fSpectrumNumu( loader, axis, spillcut, cut && !kIsNC && kIsNumuCC && !kIsAntiNu, shift, wei), - fSpectrumNumubar(loader, axis, spillcut, cut && !kIsNC && kIsNumuCC && kIsAntiNu, shift, wei), - fSpectrumNue( loader, axis, spillcut, cut && !kIsNC && kIsBeamNue && !kIsAntiNu, shift, wei), - fSpectrumNuebar( loader, axis, spillcut, cut && !kIsNC && kIsBeamNue && kIsAntiNu, shift, wei) + PredictionNoOsc::PredictionNoOsc(ISliceSource& src, const HistAxis& axis) + : fSpectrum (src, axis), + fSpectrumNC (src[ kIsNC], 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) { } @@ -79,34 +61,41 @@ namespace ana } //---------------------------------------------------------------------- - void PredictionNoOsc::SaveTo(TDirectory* dir) const + void PredictionNoOsc::SaveTo(TDirectory* dir, const std::string& name) const { TDirectory* tmp = gDirectory; + dir = dir->mkdir(name.c_str()); // switch to subdir dir->cd(); TObjString("PredictionNoOsc").Write("type"); - fSpectrum.SaveTo(dir->mkdir("spect")); - fSpectrumNC.SaveTo(dir->mkdir("spect_nc")); - fSpectrumNumu.SaveTo(dir->mkdir("spect_numu")); - fSpectrumNumubar.SaveTo(dir->mkdir("spect_numubar")); - fSpectrumNue.SaveTo(dir->mkdir("spect_nue")); - fSpectrumNuebar.SaveTo(dir->mkdir("spect_nuebar")); + fSpectrum.SaveTo(dir, "spect"); + fSpectrumNC.SaveTo(dir, "spect_nc"); + fSpectrumNumu.SaveTo(dir, "spect_numu"); + fSpectrumNumubar.SaveTo(dir, "spect_numubar"); + fSpectrumNue.SaveTo(dir, "spect_nue"); + fSpectrumNuebar.SaveTo(dir, "spect_nuebar"); + + dir->Write(); + delete dir; tmp->cd(); } //---------------------------------------------------------------------- - std::unique_ptr PredictionNoOsc::LoadFrom(TDirectory* dir) - { + std::unique_ptr PredictionNoOsc::LoadFrom(TDirectory* dir, const std::string& name) + { + dir = dir->GetDirectory(name.c_str()); // switch to subdir + assert(dir); + PredictionNoOsc* ret = new PredictionNoOsc( - *ana::LoadFrom(dir->GetDirectory("spect")), - *ana::LoadFrom(dir->GetDirectory("spect_nc")), - *ana::LoadFrom(dir->GetDirectory("spect_numu")), - *ana::LoadFrom(dir->GetDirectory("spect_numubar")), - *ana::LoadFrom(dir->GetDirectory("spect_nue")), - *ana::LoadFrom(dir->GetDirectory("spect_nuebar"))); + *ana::LoadFrom(dir, "spect"), + *ana::LoadFrom(dir, "spect_nc"), + *ana::LoadFrom(dir, "spect_numu"), + *ana::LoadFrom(dir, "spect_numubar"), + *ana::LoadFrom(dir, "spect_nue"), + *ana::LoadFrom(dir, "spect_nuebar")); // Can't use make_unique because constructor is protected return std::unique_ptr(ret); diff --git a/sbnana/CAFAna/Prediction/PredictionNoOsc.h b/sbnana/CAFAna/Prediction/PredictionNoOsc.h index af1eb362..32d6447d 100644 --- a/sbnana/CAFAna/Prediction/PredictionNoOsc.h +++ b/sbnana/CAFAna/Prediction/PredictionNoOsc.h @@ -9,24 +9,10 @@ namespace ana class PredictionNoOsc: public IPrediction { public: - PredictionNoOsc(SpectrumLoaderBase& loader, - const HistAxis& axis, - const SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift = kNoShift, - const Var& wei = kUnweighted); + PredictionNoOsc(ISliceSource& src, const HistAxis& axis); - PredictionNoOsc(SpectrumLoaderBase& loader, - const std::string& label, - const Binning& bins, - const Var& var, - const SpillCut& spillcut, - const Cut& cut, - const SystShifts& shift = kNoShift, - const Var& wei = kUnweighted); - - static std::unique_ptr LoadFrom(TDirectory* dir); - virtual void SaveTo(TDirectory* dir) const override; + static std::unique_ptr LoadFrom(TDirectory* dir, const std::string& name); + virtual void SaveTo(TDirectory* dir, const std::string& name) const override; virtual Spectrum Predict(osc::IOscCalc* /*calc*/) const override { @@ -67,7 +53,7 @@ namespace ana HistAxis axis, SpillCut spillcut, Cut cut, - Var wei = kUnweighted) + Weight wei = kUnweighted) : fLoader(loader), fAxis(axis), fSpillCut(spillcut), fCut(cut), fWei(wei) { } @@ -75,18 +61,22 @@ namespace ana virtual std::unique_ptr Generate(Loaders& loaders, const SystShifts& shiftMC = kNoShift) const override { + abort(); + // TODO TODO TODO + /* return std::unique_ptr(new PredictionNoOsc(fLoader, fAxis, fSpillCut, fCut, shiftMC, fWei)); + */ } protected: SpectrumLoaderBase& fLoader; HistAxis fAxis; SpillCut fSpillCut; Cut fCut; - Var fWei; + Weight fWei; }; } diff --git a/sbnana/CAFAna/Prediction/PredictionSBNExtrap.cxx b/sbnana/CAFAna/Prediction/PredictionSBNExtrap.cxx index 6d3913f3..6ac32b80 100644 --- a/sbnana/CAFAna/Prediction/PredictionSBNExtrap.cxx +++ b/sbnana/CAFAna/Prediction/PredictionSBNExtrap.cxx @@ -1,7 +1,7 @@ #include "sbnana/CAFAna/Prediction/PredictionSBNExtrap.h" #include "sbnana/CAFAna/Core/LoadFromFile.h" -#include "sbnana/CAFAna/Core/Ratio.h" +#include "cafanacore/Ratio.h" #include "sbnana/CAFAna/Analysis/ExpInfo.h" @@ -13,6 +13,7 @@ namespace ana { + /* //---------------------------------------------------------------------- PredictionSBNExtrap::PredictionSBNExtrap(Loaders& loadersND, Loaders& loadersFD, @@ -20,15 +21,16 @@ namespace ana const SpillCut& spillcut, const Cut& cut, const SystShifts& shift_mc, - const Var& wei_mc, + const Weight& wei_mc, const SystShifts& shift_data, - const Var& wei_data) + const Weight& wei_data) : fPredND(loadersND, axis, spillcut, cut, shift_mc, wei_mc), fPredFD(loadersFD, axis, spillcut, cut, shift_mc, wei_mc), // TODO how on earth do fake ND oscillations get in here? fDataND(loadersND.GetLoader(Loaders::kData), axis, spillcut, cut, shift_data, wei_data) { } + */ //---------------------------------------------------------------------- PredictionSBNExtrap::~PredictionSBNExtrap() @@ -88,33 +90,36 @@ namespace ana // } //---------------------------------------------------------------------- - void PredictionSBNExtrap::SaveTo(TDirectory* dir) const + void PredictionSBNExtrap::SaveTo(TDirectory* dir, const std::string& name) const { TDirectory* tmp = gDirectory; + dir = dir->mkdir(name.c_str()); // switch to subdir dir->cd(); TObjString("PredictionSBNExtrap").Write("type"); - fPredND.SaveTo(dir->mkdir("predND")); - fPredFD.SaveTo(dir->mkdir("predFD")); - fDataND.SaveTo(dir->mkdir("dataND")); + fPredND.SaveTo(dir, "predND"); + fPredFD.SaveTo(dir, "predFD"); + fDataND.SaveTo(dir, "dataND"); + + dir->Write(); + delete dir; tmp->cd(); } //---------------------------------------------------------------------- - std::unique_ptr PredictionSBNExtrap::LoadFrom(TDirectory* dir) + std::unique_ptr PredictionSBNExtrap::LoadFrom(TDirectory* dir, const std::string& name) { - assert(dir->GetDirectory("predND")); - assert(dir->GetDirectory("predFD")); - assert(dir->GetDirectory("dataND")); + dir = dir->GetDirectory(name.c_str()); // switch to subdir + assert(dir); // TODO are these leaks? return std::unique_ptr(new PredictionSBNExtrap( - *ana::LoadFrom(dir->GetDirectory("predND")).release(), - *ana::LoadFrom(dir->GetDirectory("predFD")).release(), - *ana::LoadFrom(dir->GetDirectory("dataND")).release())); + *ana::LoadFrom(dir, "predND").release(), + *ana::LoadFrom(dir, "predFD").release(), + *ana::LoadFrom(dir, "dataND").release())); } //---------------------------------------------------------------------- @@ -122,9 +127,9 @@ namespace ana const HistAxis& ax, const SpillCut& spillcut, const Cut& cut, - const Var& wei_mc, + const Weight& wei_mc, const SystShifts& shift_data, - const Var& wei_data) + const Weight& wei_data) : fLoadersND(loaders_nd), fAxis(ax), fSpillCut(spillcut), fCut(cut), fWeightMC(wei_mc), fShiftData(shift_data), fWeightData(wei_data) { @@ -134,7 +139,8 @@ namespace ana std::unique_ptr SBNExtrapGenerator::Generate(Loaders& loaders_fd, const SystShifts& shiftMC) const { + abort(); // TODO TODO TODO // No data shifts or weights - return std::unique_ptr(new PredictionSBNExtrap(fLoadersND, loaders_fd, fAxis, fSpillCut, fCut, shiftMC, fWeightMC, fShiftData, fWeightData)); + // return std::unique_ptr(new PredictionSBNExtrap(fLoadersND, loaders_fd, fAxis, fSpillCut, fCut, shiftMC, fWeightMC, fShiftData, fWeightData)); } } diff --git a/sbnana/CAFAna/Prediction/PredictionSBNExtrap.h b/sbnana/CAFAna/Prediction/PredictionSBNExtrap.h index 343ee2cd..87d56f37 100644 --- a/sbnana/CAFAna/Prediction/PredictionSBNExtrap.h +++ b/sbnana/CAFAna/Prediction/PredictionSBNExtrap.h @@ -12,15 +12,18 @@ namespace ana class PredictionSBNExtrap: public IPrediction { public: + // TODO TODO TODO + /* PredictionSBNExtrap(Loaders& loadersND, Loaders& loadersFD, const HistAxis& axis, const SpillCut& spillcut, const Cut& cut, const SystShifts& shift_mc = kNoShift, - const Var& wei_mc = kUnweighted, + const Weight& wei_mc = kUnweighted, const SystShifts& shift_data = kNoShift, - const Var& wei_data = kUnweighted); + const Weight& wei_data = kUnweighted); + */ virtual ~PredictionSBNExtrap(); virtual Spectrum Predict(osc::IOscCalc* calc) const override; @@ -33,8 +36,8 @@ namespace ana OscillatableSpectrum ComponentCC(int from, int to) const override; // Spectrum ComponentNC() const override; - virtual void SaveTo(TDirectory* dir) const override; - static std::unique_ptr LoadFrom(TDirectory* dir); + virtual void SaveTo(TDirectory* dir, const std::string& name) const override; + static std::unique_ptr LoadFrom(TDirectory* dir, const std::string& name); PredictionSBNExtrap() = delete; @@ -57,9 +60,9 @@ namespace ana const HistAxis& ax, const SpillCut& spillcut, const Cut& cut, - const Var& wei_mc, + const Weight& wei_mc, const SystShifts& shift_data = kNoShift, - const Var& wei_data = kUnweighted); + const Weight& wei_data = kUnweighted); std::unique_ptr Generate(Loaders& loaders_fd, const SystShifts& shiftMC = kNoShift) const override; diff --git a/sbnana/CAFAna/Prediction/PredictionScaleComp.cxx b/sbnana/CAFAna/Prediction/PredictionScaleComp.cxx deleted file mode 100644 index f5e1a566..00000000 --- a/sbnana/CAFAna/Prediction/PredictionScaleComp.cxx +++ /dev/null @@ -1,199 +0,0 @@ -#include "sbnana/CAFAna/Prediction/PredictionScaleComp.h" - -#include "sbnana/CAFAna/Core/Cut.h" -#include "sbnana/CAFAna/Core/HistCache.h" -#include "sbnana/CAFAna/Core/LoadFromFile.h" -#include "sbnana/CAFAna/Prediction/PredictionNoOsc.h" -#include "sbnana/CAFAna/Prediction/PredictionNoExtrap.h" - -#include "TDirectory.h" -#include "TObjString.h" -#include "TH1.h" -#include "TVectorD.h" - -#include - -namespace ana -{ - //---------------------------------------------------------------------- - PredictionScaleComp:: - PredictionScaleComp(SpectrumLoaderBase& loader, - const HistAxis& axis, - SpillCut spillcut, - Cut cut, - const std::vector& systs, - const SystShifts& shift, - const Var& wei) - : fSysts(systs) - { - Cut complementCut = kNoCut; - - assert(!systs.empty() && "Please give at least one systematic."); - for(const SystComponentScale* syst: systs){ - fPreds.push_back(new PredictionNoOsc(loader, axis, - spillcut, cut && syst->GetCut(), shift, wei)); - } - - fTotal = new PredictionNoOsc(loader, axis, spillcut, cut, shift, wei); - } - - //---------------------------------------------------------------------- - PredictionScaleComp:: - PredictionScaleComp(SpectrumLoaderBase& loaderNonswap, - SpectrumLoaderBase& loaderNue, - SpectrumLoaderBase& loaderNuTau, - SpectrumLoaderBase& loaderIntrinsic, - const HistAxis& axis, - SpillCut spillcut, - Cut cut, - const std::vector& systs, - const SystShifts& shift, - const Var& wei) - : fSysts(systs) - { - assert(!systs.empty() && "Please give at least one systematic."); - for(const SystComponentScale* syst: systs){ - fPreds.push_back(new PredictionNoExtrap(loaderNonswap, loaderNue, loaderNuTau, loaderIntrinsic, - axis, spillcut, cut && syst->GetCut(), shift, wei)); - } - - fTotal = new PredictionNoExtrap(loaderNonswap, loaderNue, loaderNuTau, loaderIntrinsic, - axis, spillcut, cut, shift, wei); - } - - //---------------------------------------------------------------------- - PredictionScaleComp:: - PredictionScaleComp(SpectrumLoaderBase& loader, - const HistAxis& axis1, - const HistAxis& axis2, - SpillCut spillcut, - Cut cut, - const std::vector& systs, - const SystShifts& shift, - const Var& wei) - { - assert(0 && "unimplemented"); - - // TODO TODO TODO - /* - assert(truthcuts.size()>0 && "Please give at least one truth selection."); - for(unsigned int i = 0; i < truthcuts.size(); ++i){ - fPreds.push_back(new PredictionNoOsc(loader, axis1, axis2, - cut && truthcuts[i], shift, wei)); - fSysts.push_back(new DummyScaleCompSyst(i)); - fComplementCut = fComplementCut && !truthcuts[i]; - } - - // The idea is that if truthcuts are exhaustive, this Spectrum should wind - // up empty - fComplement = new Spectrum(loader, axis1, axis2, - cut && fComplementCut, shift, wei); - */ - } - - //---------------------------------------------------------------------- - PredictionScaleComp:: - PredictionScaleComp(const IPrediction* total, - const std::vector& preds, - const std::vector& systs) - : fSysts(systs), - fPreds(preds), - fTotal(total) - { - } - - //---------------------------------------------------------------------- - PredictionScaleComp::~PredictionScaleComp() - { - for(const IPrediction* p: fPreds) delete p; - delete fTotal; - } - - //---------------------------------------------------------------------- - Spectrum PredictionScaleComp::PredictComponentSyst(osc::IOscCalc* calc, - const SystShifts& shift, - Flavors::Flavors_t flav, - Current::Current_t curr, - Sign::Sign_t sign) const - { - SystShifts shiftClean = shift; - for(const ISyst* s: fSysts) shiftClean.SetShift(s, 0); - - // Starting with the total and adding in the differences for components - // that need to change is faster if most of the knobs are set to zero. - Spectrum ret = fTotal->PredictSyst(calc, shiftClean); - - for(unsigned int i = 0; i < fPreds.size(); ++i){ - const double x = shift.GetShift(fSysts[i]); - if(x == 0) continue; // Nominal, can skip - - Spectrum si = fPreds[i]->PredictComponentSyst(calc, shiftClean, - flav, curr, sign); - - si.Scale(pow(1+fSysts[i]->OneSigmaScale(), x) - 1); - - ret += si; - } - - return ret; - } - - //---------------------------------------------------------------------- - Spectrum PredictionScaleComp:: - PredictCategory(osc::IOscCalc* osc, - const SystComponentScale* syst) const - { - for(unsigned int i = 0; i < fSysts.size(); ++i){ - if(fSysts[i] == syst) return fPreds[i]->Predict(osc); - } - - std::cout << "PredictionScaleComp::PredictCategory(): Unknown systematic " << syst->ShortName() << std::endl; - abort(); - } - - //---------------------------------------------------------------------- - void PredictionScaleComp::SaveTo(TDirectory* dir) const - { - TDirectory* tmp = gDirectory; - dir->cd(); - - TObjString("PredictionScaleComp").Write("type"); - - fTotal->SaveTo(dir->mkdir("total")); - - for(unsigned int i = 0; i < fPreds.size(); ++i){ - fPreds[i]->SaveTo(dir->mkdir(("pred"+std::to_string(i)).c_str())); - } - - for(unsigned int i = 0; i < fSysts.size(); ++i){ - fSysts[i]->SaveTo(dir->mkdir(("syst"+std::to_string(i)).c_str())); - } - - tmp->cd(); - } - - //---------------------------------------------------------------------- - std::unique_ptr PredictionScaleComp::LoadFrom(TDirectory* dir) - { - IPrediction* total = ana::LoadFrom(dir->GetDirectory("total")).release(); - - std::vector preds; - for(unsigned int i = 0; ; ++i){ - TDirectory* di = dir->GetDirectory(("pred"+std::to_string(i)).c_str()); - if(!di) break; // We got all the predictions - - preds.push_back(ana::LoadFrom(di).release()); - } - - std::vector systs; - for(unsigned int i = 0; ; ++i){ - TDirectory* si = dir->GetDirectory(("syst"+std::to_string(i)).c_str()); - if(!si) break; // We got all the predictions - - systs.push_back(ana::LoadFrom(si).release()); - } - - return std::unique_ptr(new PredictionScaleComp(total, preds, systs)); - } - -} diff --git a/sbnana/CAFAna/Prediction/PredictionScaleComp.h b/sbnana/CAFAna/Prediction/PredictionScaleComp.h deleted file mode 100644 index 357b85ac..00000000 --- a/sbnana/CAFAna/Prediction/PredictionScaleComp.h +++ /dev/null @@ -1,93 +0,0 @@ -#pragma once - -#include "sbnana/CAFAna/Core/ISyst.h" -#include "sbnana/CAFAna/Core/SystShifts.h" -#include "sbnana/CAFAna/Prediction/IPrediction.h" -#include "sbnana/CAFAna/Systs/SystComponentScale.h" - -#include "OscLib/IOscCalc.h" - -namespace ana -{ - /// \brief Prediction broken down into arbitrary components whose scales can - /// be varied independently. - class PredictionScaleComp : public IPrediction - { - public: - /// \param cut Cut applied to all histograms - /// \param truthcuts Prediction will be broken down into N components - /// following these cuts. - PredictionScaleComp(SpectrumLoaderBase& loader, - const HistAxis& axis, - SpillCut spillcut, - Cut cut, - const std::vector& systs, - const SystShifts& shift = kNoShift, - const Var& wei = kUnweighted); - /// Constructor to take two HistAxis's to weight 2D spectra - PredictionScaleComp(SpectrumLoaderBase& loader, - const HistAxis& axis1, - const HistAxis& axis2, - SpillCut spillcut, - Cut cut, - const std::vector& systs, - const SystShifts& shift = kNoShift, - const Var& wei = kUnweighted); - - /// This is for the FD via PredictionNoExtrap - PredictionScaleComp(SpectrumLoaderBase& loaderNonswap, - SpectrumLoaderBase& loaderNue, - SpectrumLoaderBase& loaderNuTau, - SpectrumLoaderBase& loaderIntrinsic, - const HistAxis& axis, - SpillCut spillcut, - Cut cut, - const std::vector& systs, - const SystShifts& shift = kNoShift, - const Var& wei = kUnweighted); - - virtual ~PredictionScaleComp(); - - virtual Spectrum Predict(osc::IOscCalc* osc) const override - { - return fTotal->Predict(osc); - } - - virtual Spectrum PredictSyst(osc::IOscCalc* osc, - const SystShifts& syst) const override - { - return PredictComponentSyst(osc, syst, - Flavors::kAll, Current::kBoth, Sign::kBoth); - } - - virtual Spectrum PredictComponent(osc::IOscCalc* calc, - Flavors::Flavors_t flav, - Current::Current_t curr, - Sign::Sign_t sign) const override - { - return fTotal->PredictComponent(calc, flav, curr, sign); - } - - virtual Spectrum PredictComponentSyst(osc::IOscCalc* calc, - const SystShifts& syst, - Flavors::Flavors_t flav, - Current::Current_t curr, - Sign::Sign_t sign) const override; - - Spectrum PredictCategory(osc::IOscCalc* osc, - const SystComponentScale* syst) const; - - static std::unique_ptr LoadFrom(TDirectory* dir); - virtual void SaveTo(TDirectory* dir) const override; - - protected: - PredictionScaleComp(const IPrediction* total, - const std::vector& preds, - const std::vector& systs); - - std::vector fSysts; - std::vector fPreds; - - const IPrediction* fTotal; - }; -} diff --git a/sbnana/CAFAna/Systs/CMakeLists.txt b/sbnana/CAFAna/Systs/CMakeLists.txt index 1acdddbe..7c8d1e8b 100644 --- a/sbnana/CAFAna/Systs/CMakeLists.txt +++ b/sbnana/CAFAna/Systs/CMakeLists.txt @@ -1,6 +1,3 @@ -# Allow "StandardRecord/" to find the right directory -include_directories(..) - cet_make(LIBRARY_NAME CAFAnaSysts LIBRARIES CAFAnaCore CAFAnaCuts diff --git a/sbnana/CAFAna/Systs/EnergySysts.cxx b/sbnana/CAFAna/Systs/EnergySysts.cxx index 66d01fac..19f12ac9 100644 --- a/sbnana/CAFAna/Systs/EnergySysts.cxx +++ b/sbnana/CAFAna/Systs/EnergySysts.cxx @@ -12,7 +12,7 @@ namespace ana { bool ub = (detector == EnergyScaleSystDetector::kMicroBooNE && det != caf::kSBND && det != caf::kICARUS); bool fd = (detector == EnergyScaleSystDetector::kICARUS && det == caf::kICARUS); bool detector_cut = all || nd || ub || fd; - if(!sr->truth.iscc || abs(sr->truth.pdg) != 14 || isnan(sr->fake_reco.nuE) || !detector_cut) + if(!sr->truth.iscc || abs(sr->truth.pdg) != 14 || isnan(sr->fake_reco.nuE) || !detector_cut) return ; double particle_energy = 0.0; switch(part) { @@ -58,7 +58,7 @@ namespace ana { break; } sr->fake_reco.nuE += particle_energy * scale; - + } const EnergyScaleSyst kEnergyScaleMuon(EnergyScaleSystTerm::kConstant, EnergyScaleSystParticle::kMuon, EnergyScaleSystDetector::kAll, 0.02, "EnergyScaleMuon", "Correlated linear E_{#mu} scale"); diff --git a/sbnana/CAFAna/Systs/EnergySysts.h b/sbnana/CAFAna/Systs/EnergySysts.h index 55620a88..08e8986c 100644 --- a/sbnana/CAFAna/Systs/EnergySysts.h +++ b/sbnana/CAFAna/Systs/EnergySysts.h @@ -33,7 +33,7 @@ namespace ana class EnergyScaleSyst: public ISyst { public: - EnergyScaleSyst(EnergyScaleSystTerm _term, EnergyScaleSystParticle _part, EnergyScaleSystDetector _detector, double _uncertainty, const std::string& name, const std::string& latexName) : + EnergyScaleSyst(EnergyScaleSystTerm _term, EnergyScaleSystParticle _part, EnergyScaleSystDetector _detector, double _uncertainty, const std::string& name, const std::string& latexName) : ISyst(name, latexName), term(_term), part(_part), detector(_detector), uncertainty(_uncertainty) {} void Shift(double sigma, caf::SRSliceProxy *sr, double& weight) const override; diff --git a/sbnana/CAFAna/Systs/SBNWeightSysts.cxx b/sbnana/CAFAna/Systs/SBNWeightSysts.cxx index bb18eb23..268c4848 100644 --- a/sbnana/CAFAna/Systs/SBNWeightSysts.cxx +++ b/sbnana/CAFAna/Systs/SBNWeightSysts.cxx @@ -18,16 +18,14 @@ namespace ana } // -------------------------------------------------------------------------- - double UniverseWeight::operator()(const caf::SRSliceProxy* sr) const + double UniverseWeight::operator()(const caf::SRTrueInteractionProxy* sr) const { - if(sr->truth.index < 0) return 1; - if(fPSetIdx == -1){ const UniverseOracle& uo = UniverseOracle::Instance(); fPSetIdx = uo.ParameterSetIndex(fPSetName); } - const caf::Proxy>& wgts = sr->truth.wgt; + const caf::Proxy>& wgts = sr->wgt; if(wgts.empty()) return 1; const int Nwgts = wgts[fPSetIdx].univ.size(); @@ -43,6 +41,14 @@ namespace ana return wgts[fPSetIdx].univ[unividx]; } + // -------------------------------------------------------------------------- + double UniverseWeight::operator()(const caf::SRSliceProxy* sr) const + { + if(sr->truth.index < 0) return 1; + + return (*this)(&sr->truth); + } + // -------------------------------------------------------------------------- SBNWeightSyst::SBNWeightSyst(const std::string& systName) : ISyst(systName, systName), @@ -184,7 +190,7 @@ namespace ana } // -------------------------------------------------------------------------- - + const std::vector& GetSBNBoosterFluxWeightSysts() { static std::vector ret; @@ -209,5 +215,5 @@ namespace ana } return ret; } - + } diff --git a/sbnana/CAFAna/Systs/SBNWeightSysts.h b/sbnana/CAFAna/Systs/SBNWeightSysts.h index ef4f3c6c..8c230174 100644 --- a/sbnana/CAFAna/Systs/SBNWeightSysts.h +++ b/sbnana/CAFAna/Systs/SBNWeightSysts.h @@ -2,7 +2,7 @@ #include "sbnana/CAFAna/Core/ISyst.h" #include "sbnana/CAFAna/Core/Cut.h" -#include "sbnana/CAFAna/Core/Var.h" +#include "sbnana/CAFAna/Core/Weight.h" #include "sbnanaobj/StandardRecord/Proxy/FwdDeclare.h" @@ -16,6 +16,7 @@ namespace ana public: UniverseWeight(const std::string& psetName, int univIdx); + double operator()(const caf::SRTrueInteractionProxy* sr) const; double operator()(const caf::SRSliceProxy* sr) const; protected: @@ -24,9 +25,13 @@ namespace ana int fUnivIdx; }; - Var GetUniverseWeight(const std::string& psetName, int univIdx) + NuTruthWeight GetNuTruthUniverseWeight(const std::string& psetName, int univIdx) { - return Var(UniverseWeight(psetName, univIdx)); + return NuTruthWeight(UniverseWeight(psetName, univIdx)); + } + Weight GetUniverseWeight(const std::string& psetName, int univIdx) + { + return Weight(UniverseWeight(psetName, univIdx)); } diff --git a/sbnana/CAFAna/Systs/SystComponentScale.cxx b/sbnana/CAFAna/Systs/SystComponentScale.cxx index 20b92a33..8d1d1c4d 100644 --- a/sbnana/CAFAna/Systs/SystComponentScale.cxx +++ b/sbnana/CAFAna/Systs/SystComponentScale.cxx @@ -30,8 +30,11 @@ namespace ana } //---------------------------------------------------------------------- - std::unique_ptr SystComponentScale::LoadFrom(TDirectory* dir) + std::unique_ptr SystComponentScale::LoadFrom(TDirectory* dir, const std::string& name) { + dir = dir->GetDirectory(name.c_str()); // switch to subdir + assert(dir); + TObjString* ptag = (TObjString*)dir->Get("type"); assert(ptag); diff --git a/sbnana/CAFAna/Systs/SystComponentScale.h b/sbnana/CAFAna/Systs/SystComponentScale.h index 4e059425..a337ea87 100644 --- a/sbnana/CAFAna/Systs/SystComponentScale.h +++ b/sbnana/CAFAna/Systs/SystComponentScale.h @@ -3,6 +3,10 @@ #include "sbnana/CAFAna/Core/Cut.h" #include "sbnana/CAFAna/Core/ISyst.h" +#include + +class TDirectory; + namespace ana { /// Uncertainty in the scale of a single component of the spectrum @@ -35,8 +39,8 @@ namespace ana // Some derived classes might have a back-channel allowing them to // implement this. - static std::unique_ptr LoadFrom(TDirectory* dir); - virtual void SaveTo(TDirectory* dir) const {assert(0 && "unimplemented");} + static std::unique_ptr LoadFrom(TDirectory* dir, const std::string& name); + virtual void SaveTo(TDirectory* dir, const std::string& name) const {assert(0 && "unimplemented");} protected: Cut fCut; diff --git a/sbnana/CAFAna/Unfold/UnfoldIterative.h b/sbnana/CAFAna/Unfold/UnfoldIterative.h index fe98b709..4d23efba 100644 --- a/sbnana/CAFAna/Unfold/UnfoldIterative.h +++ b/sbnana/CAFAna/Unfold/UnfoldIterative.h @@ -1,4 +1,4 @@ -#include "sbnana/CAFAna/Core/ReweightableSpectrum.h" +#include "cafanacore/ReweightableSpectrum.h" namespace ana { diff --git a/sbnana/CAFAna/Unfold/UnfoldSVD.cxx b/sbnana/CAFAna/Unfold/UnfoldSVD.cxx index 5fbfe7c9..012c508f 100644 --- a/sbnana/CAFAna/Unfold/UnfoldSVD.cxx +++ b/sbnana/CAFAna/Unfold/UnfoldSVD.cxx @@ -31,7 +31,10 @@ namespace ana // TODO in principle these should be the true labels and bins. Will be // easier with cafanacore - return Spectrum(std::move(h_unf), reco.GetLabels(), reco.GetBinnings(), + Eigen::ArrayXd arr = Eigen::Map(h_unf->GetArray(), + h_unf->GetNbinsX()+2); + return Spectrum(arr, + LabelsAndBins(reco.GetLabels(), recoVsTrue.GetTrueBinnings()), pot, reco.Livetime()); } } diff --git a/sbnana/CAFAna/Unfold/UnfoldSVD.h b/sbnana/CAFAna/Unfold/UnfoldSVD.h index 3f9925d8..582a4992 100644 --- a/sbnana/CAFAna/Unfold/UnfoldSVD.h +++ b/sbnana/CAFAna/Unfold/UnfoldSVD.h @@ -1,4 +1,4 @@ -#include "sbnana/CAFAna/Core/ReweightableSpectrum.h" +#include "cafanacore/ReweightableSpectrum.h" namespace ana { diff --git a/sbnana/CAFAna/Unfold/UnfoldTikhonov.cxx b/sbnana/CAFAna/Unfold/UnfoldTikhonov.cxx index 93facb8e..0296435b 100644 --- a/sbnana/CAFAna/Unfold/UnfoldTikhonov.cxx +++ b/sbnana/CAFAna/Unfold/UnfoldTikhonov.cxx @@ -1,8 +1,5 @@ #include "sbnana/CAFAna/Unfold/UnfoldTikhonov.h" -//#include "sbnana/CAFAna/Core/Utilities.h" -#include "sbnana/CAFAna/Core/HistCache.h" - #include "TH2.h" #include @@ -38,7 +35,7 @@ namespace ana double tot = 0; for(unsigned int i = 0; i < Nreco; ++i){ const double mij = m->GetBinContent(i+1, j+1); - M(i, j) = mij; + M(i, j) = mij; tot += mij; } // Normalize each column of true energy. One true event smears to one @@ -51,7 +48,7 @@ namespace ana TH1D* hy = reco.ToTH1(reco.POT()); Eigen::VectorXd y(Nreco); for(unsigned int i = 0; i < Nreco; ++i) y[i] = hy->GetBinContent(i+1); - HistCache::Delete(hy); + delete hy; // Matrix penalizing true distributions with large second derivative. Would // also need an update here for multi-dimensional distribution. I think you @@ -79,15 +76,10 @@ namespace ana Eigen::ColPivHouseholderQR dec(lhs); const Eigen::VectorXd ret = dec.solve(rhs); - - // To get the correct binning - std::unique_ptr hret(recoVsTrue.WeightingVariable().ToTH1(reco.POT())); - hret->Reset(); - for(unsigned int i = 0; i < Ntrue; ++i) hret->SetBinContent(i+1, ret[i]); - // TODO in principle these should be the true labels and bins. Will be // easier with cafanacore - return Spectrum(std::move(hret), {""}, {recoVsTrue.GetBinnings()[1]}, + return Spectrum(Eigen::ArrayXd(ret.array()), + LabelsAndBins(reco.GetLabels(), recoVsTrue.GetTrueBinnings()), reco.POT(), reco.Livetime()); } } diff --git a/sbnana/CAFAna/Unfold/UnfoldTikhonov.h b/sbnana/CAFAna/Unfold/UnfoldTikhonov.h index 7551eeb7..e1fe413d 100644 --- a/sbnana/CAFAna/Unfold/UnfoldTikhonov.h +++ b/sbnana/CAFAna/Unfold/UnfoldTikhonov.h @@ -1,4 +1,4 @@ -#include "sbnana/CAFAna/Core/ReweightableSpectrum.h" +#include "cafanacore/ReweightableSpectrum.h" namespace ana { diff --git a/sbnana/CAFAna/Vars/CMakeLists.txt b/sbnana/CAFAna/Vars/CMakeLists.txt index 0a462284..060c532b 100644 --- a/sbnana/CAFAna/Vars/CMakeLists.txt +++ b/sbnana/CAFAna/Vars/CMakeLists.txt @@ -1,6 +1,3 @@ -# Allow "StandardRecord/" to find the right directory -include_directories(..) - cet_make(LIBRARY_NAME CAFAnaVars LIBRARIES CAFAnaCore sbnanaobj_StandardRecordProxy diff --git a/sbnana/CAFAna/Vars/FitVars.h b/sbnana/CAFAna/Vars/FitVars.h index 9d57b139..20a4899b 100644 --- a/sbnana/CAFAna/Vars/FitVars.h +++ b/sbnana/CAFAna/Vars/FitVars.h @@ -10,14 +10,13 @@ namespace ana class FitTheta13: public IFitVar { public: + FitTheta13() : IFitVar("th13", "#theta_{13}") {} virtual double GetValue(const osc::IOscCalcAdjustable* osc) const; virtual void SetValue(osc::IOscCalcAdjustable* osc, double val) const; - virtual std::string ShortName() const {return "th13";} - virtual std::string LatexName() const {return "#theta_{13}";} }; /// \f$ \theta_{13} \f$ - const FitTheta13 kFitTheta13 = FitTheta13(); + const FitTheta13 kFitTheta13; //---------------------------------------------------------------------- @@ -25,17 +24,16 @@ namespace ana class FitSinSq2Theta13: public IConstrainedFitVar { public: + FitSinSq2Theta13() : IConstrainedFitVar("ss2th13", "sin^{2}2#theta_{13}") {} virtual double GetValue(const osc::IOscCalcAdjustable* osc) const; virtual void SetValue(osc::IOscCalcAdjustable* osc, double val) const; - virtual std::string ShortName() const {return "ss2th13";} - virtual std::string LatexName() const {return "sin^{2}2#theta_{13}";} virtual double LowLimit() const {return 0;} virtual double HighLimit() const {return 1;} }; /// \f$ \sin^22\theta_{13} \f$ - const FitSinSq2Theta13 kFitSinSq2Theta13 = FitSinSq2Theta13(); + const FitSinSq2Theta13 kFitSinSq2Theta13; //---------------------------------------------------------------------- @@ -43,45 +41,43 @@ namespace ana class FitDeltaInPiUnits: public IFitVar { public: + FitDeltaInPiUnits() : IFitVar("delta(pi)", "#delta / #pi") {} virtual double GetValue(const osc::IOscCalcAdjustable* osc) const; virtual void SetValue(osc::IOscCalcAdjustable* osc, double val) const; - virtual std::string ShortName() const {return "delta(pi)";} - virtual std::string LatexName() const {return "#delta / #pi";} }; /// \f$ \delta_{CP}/\pi \f$ - const FitDeltaInPiUnits kFitDeltaInPiUnits = FitDeltaInPiUnits(); + const FitDeltaInPiUnits kFitDeltaInPiUnits; //---------------------------------------------------------------------- /// \f$ \theta_{13} \f$ class FitTheta23: public IFitVar { public: + FitTheta23() : IFitVar("th23", "#theta_{23}") {} virtual double GetValue(const osc::IOscCalcAdjustable* osc) const; virtual void SetValue(osc::IOscCalcAdjustable* osc, double val) const; - virtual std::string ShortName() const {return "th23";} - virtual std::string LatexName() const {return "#theta_{23}";} }; /// \f$ \theta_{13} \f$ - const FitTheta23 kFitTheta23 = FitTheta23(); + const FitTheta23 kFitTheta23; //---------------------------------------------------------------------- /// \f$ \sin^2\theta_{23} \f$ class FitSinSqTheta23: public IConstrainedFitVar { public: + FitSinSqTheta23() : IConstrainedFitVar("ssth23", "sin^{2}#theta_{23}") {} + virtual double GetValue(const osc::IOscCalcAdjustable* osc) const; virtual void SetValue(osc::IOscCalcAdjustable* osc, double val) const; - virtual std::string ShortName() const {return "ssth23";} - virtual std::string LatexName() const {return "sin^{2}#theta_{23}";} virtual double LowLimit() const {return 0;} virtual double HighLimit() const {return 1;} }; /// \f$ \sin^2\theta_{23} \f$ - const FitSinSqTheta23 kFitSinSqTheta23 = FitSinSqTheta23(); + const FitSinSqTheta23 kFitSinSqTheta23; //---------------------------------------------------------------------- @@ -89,18 +85,17 @@ namespace ana class FitSinSq2Theta23: public IConstrainedFitVar { public: + FitSinSq2Theta23() : IConstrainedFitVar("ss2th23", "sin^{2}2#theta_{23}") {} + virtual double GetValue(const osc::IOscCalcAdjustable* osc) const; virtual void SetValue(osc::IOscCalcAdjustable* osc, double val) const; - virtual std::string ShortName() const {return "ss2th23";} - virtual std::string LatexName() const {return "sin^{2}2#theta_{23}";} - virtual double LowLimit() const {return 0;} virtual double HighLimit() const {return 1;} }; /// \f$ \sin^22\theta_{23} \f$ - const FitSinSq2Theta23 kFitSinSq2Theta23 = FitSinSq2Theta23(); + const FitSinSq2Theta23 kFitSinSq2Theta23; //---------------------------------------------------------------------- @@ -108,10 +103,10 @@ namespace ana class FitDmSq32: public IConstrainedFitVar { public: + FitDmSq32() : IConstrainedFitVar("dmsq32", "#Deltam^{2}_{32}") {} + virtual double GetValue(const osc::IOscCalcAdjustable* osc) const; virtual void SetValue(osc::IOscCalcAdjustable* osc, double val) const; - virtual std::string ShortName() const {return "dmsq32";} - virtual std::string LatexName() const {return "#Deltam^{2}_{32}";} // "1eV^2 splitting should be enough for anyone" // OscCalcPMNS freaks out at large splittings @@ -120,7 +115,7 @@ namespace ana }; /// \f$ \Delta m^2_{32} \f$ - const FitDmSq32 kFitDmSq32 = FitDmSq32(); + const FitDmSq32 kFitDmSq32; //------------------------------------------------------------------------- @@ -128,10 +123,10 @@ namespace ana class FitDmSq32Scaled: public IConstrainedFitVar { public: + FitDmSq32Scaled() : IConstrainedFitVar("dmsq32scaled", "#Deltam^{2}_{32} (10^{-3} eV^{2})") {} + virtual double GetValue(const osc::IOscCalcAdjustable* osc) const; virtual void SetValue(osc::IOscCalcAdjustable* osc, double val) const; - virtual std::string ShortName() const {return "dmsq32scaled";} - virtual std::string LatexName() const {return "#Deltam^{2}_{32} (10^{-3} eV^{2})";} // "1eV^2 splitting should be enough for anyone" // OscCalcPMNS freaks out at large splittings @@ -140,7 +135,7 @@ namespace ana }; /// \f$ \Delta m^2_{32}\times10^3{\rm eV}^2 \f$ - const FitDmSq32Scaled kFitDmSq32Scaled = FitDmSq32Scaled(); + const FitDmSq32Scaled kFitDmSq32Scaled; //---------------------------------------------------------------------- @@ -148,17 +143,17 @@ namespace ana class FitTanSqTheta12: public IConstrainedFitVar { public: + FitTanSqTheta12() : IConstrainedFitVar("tsth12", "tan^{2}#theta_{12}") {} + virtual double GetValue(const osc::IOscCalcAdjustable* osc) const; virtual void SetValue(osc::IOscCalcAdjustable* osc, double val) const; - virtual std::string ShortName() const {return "tsth12";} - virtual std::string LatexName() const {return "tan^{2}#theta_{12}";} virtual double LowLimit() const {return 0;} virtual double HighLimit() const {return std::numeric_limits::max();} }; /// \f$ \tan^2\theta_{12} \f$ - const FitTanSqTheta12 kFitTanSqTheta12 = FitTanSqTheta12(); + const FitTanSqTheta12 kFitTanSqTheta12; //---------------------------------------------------------------------- @@ -166,17 +161,17 @@ namespace ana class FitSinSq2Theta12: public IConstrainedFitVar { public: + FitSinSq2Theta12() : IConstrainedFitVar("ss2th12", "sin^{2}2#theta_{12}") {} + virtual double GetValue(const osc::IOscCalcAdjustable* osc) const; virtual void SetValue(osc::IOscCalcAdjustable* osc, double val) const; - virtual std::string ShortName() const {return "ss2th12";} - virtual std::string LatexName() const {return "sin^{2}2#theta_{12}";} virtual double LowLimit() const {return 0;} virtual double HighLimit() const {return 1;} }; /// \f$ \sin^22\theta_{12} \f$ - const FitSinSq2Theta12 kFitSinSq2Theta12 = FitSinSq2Theta12(); + const FitSinSq2Theta12 kFitSinSq2Theta12; //---------------------------------------------------------------------- @@ -184,10 +179,10 @@ namespace ana class FitDmSq21: public IConstrainedFitVar { public: + FitDmSq21() : IConstrainedFitVar("dmsq21","#Deltam^{2}_{21}") {} + virtual double GetValue(const osc::IOscCalcAdjustable* osc) const; virtual void SetValue(osc::IOscCalcAdjustable* osc, double val) const; - virtual std::string ShortName() const {return "dmsq21";} - virtual std::string LatexName() const {return "#Deltam^{2}_{21}";} // "1eV^2 splitting should be enough for anyone" // OscCalcPMNS freaks out at large splittings @@ -196,16 +191,16 @@ namespace ana }; /// \f$ \Delta m^2_{21} \f$ - const FitDmSq21 kFitDmSq21 = FitDmSq21(); + const FitDmSq21 kFitDmSq21; /// \f$ \rho \f$ class FitRho: public IConstrainedFitVar { public: + FitRho() : IConstrainedFitVar("rho", "#rho") {} + virtual double GetValue(const osc::IOscCalcAdjustable* osc) const; virtual void SetValue(osc::IOscCalcAdjustable* osc, double val) const; - virtual std::string ShortName() const {return "rho";} - virtual std::string LatexName() const {return "#rho";} //Density should be greater than zero (set a ridiculously high high limit) virtual double LowLimit() const {return 0;} @@ -214,7 +209,7 @@ namespace ana }; /// \f$ \rho \f$ - const FitRho kFitRho = FitRho(); + const FitRho kFitRho; //---------------------------------------------------------------------- diff --git a/sbnana/CAFAna/Vars/FitVarsSterile.cxx b/sbnana/CAFAna/Vars/FitVarsSterile.cxx index 9ce41381..7ef99148 100644 --- a/sbnana/CAFAna/Vars/FitVarsSterile.cxx +++ b/sbnana/CAFAna/Vars/FitVarsSterile.cxx @@ -9,8 +9,8 @@ namespace ana { - - //--------------------------------------------------------------------------- + + //--------------------------------------------------------------------------- double FitDmSq32Sterile::GetValue(const osc::IOscCalcAdjustable* osc) const { const osc::IOscCalcSterile* sterile = osc::DowncastToSterile(osc); @@ -18,8 +18,8 @@ namespace ana double dm231 = sterile->GetDm(3); return dm231 - dm221; } - - //--------------------------------------------------------------------------- + + //--------------------------------------------------------------------------- void FitDmSq32Sterile::SetValue(osc::IOscCalcAdjustable* osc, double val) const { osc::IOscCalcSterile* sterile = osc::DowncastToSterile(osc); @@ -28,19 +28,19 @@ namespace ana sterile->SetDm(3, dm231); } - //--------------------------------------------------------------------------- + //--------------------------------------------------------------------------- double FitDmSq41Sterile::GetValue(const osc::IOscCalcAdjustable* osc) const { return osc::DowncastToSterile(osc)->GetDm(4); } - - //--------------------------------------------------------------------------- + + //--------------------------------------------------------------------------- void FitDmSq41Sterile::SetValue(osc::IOscCalcAdjustable* osc, double val) const { osc::DowncastToSterile(osc)->SetDm(4, val); } - //--------------------------------------------------------------------------- + //--------------------------------------------------------------------------- double FitDmSq43Sterile::GetValue(const osc::IOscCalcAdjustable* osc) const { const osc::IOscCalcSterile* sterile = osc::DowncastToSterile(osc); @@ -48,8 +48,8 @@ namespace ana double dm231 = sterile->GetDm(3); return dm241 - dm231; } - - //--------------------------------------------------------------------------- + + //--------------------------------------------------------------------------- void FitDmSq43Sterile::SetValue(osc::IOscCalcAdjustable* osc, double val) const { osc::IOscCalcSterile* sterile = osc::DowncastToSterile(osc); @@ -57,7 +57,7 @@ namespace ana double dm241 = val + dm231; sterile->SetDm(4, dm241); } - + //---------------------------------------------------------------------- double FitDelta13InPiUnitsSterile::GetValue(const osc::IOscCalcAdjustable* osc) const { @@ -106,7 +106,7 @@ namespace ana osc::DowncastToSterile(osc)->SetDelta(2, 4, M_PI*val); } - //--------------------------------------------------------------------------- + //--------------------------------------------------------------------------- double FitTheta13Sterile::GetValue(const osc::IOscCalcAdjustable* osc) const { return osc::DowncastToSterile(osc)->GetAngle(1,3); @@ -130,7 +130,7 @@ namespace ana osc::DowncastToSterile(osc)->SetAngle(1, 3, asin(sqrt(Clamp(val)))); } - //--------------------------------------------------------------------------- + //--------------------------------------------------------------------------- double FitTheta23Sterile::GetValue(const osc::IOscCalcAdjustable* osc) const { return osc::DowncastToSterile(osc)->GetAngle(2,3); @@ -154,7 +154,7 @@ namespace ana osc::DowncastToSterile(osc)->SetAngle(2, 3, asin(sqrt(Clamp(val)))); } - //--------------------------------------------------------------------------- + //--------------------------------------------------------------------------- double FitTheta14Sterile::GetValue(const osc::IOscCalcAdjustable* osc) const { return osc::DowncastToSterile(osc)->GetAngle(1,4); @@ -190,7 +190,7 @@ namespace ana osc::DowncastToSterile(osc)->SetAngle(1,4, asin(sqrt(Clamp(val)))/2); } - //--------------------------------------------------------------------------- + //--------------------------------------------------------------------------- double FitTheta24Sterile::GetValue(const osc::IOscCalcAdjustable* osc) const { return osc::DowncastToSterile(osc)->GetAngle(2,4); @@ -226,7 +226,7 @@ namespace ana osc::DowncastToSterile(osc)->SetAngle(2,4, asin(sqrt(Clamp(val)))/2); } - //--------------------------------------------------------------------------- + //--------------------------------------------------------------------------- double FitTheta34Sterile::GetValue(const osc::IOscCalcAdjustable* osc) const { return osc::DowncastToSterile(osc)->GetAngle(3,4); @@ -262,7 +262,7 @@ namespace ana osc::DowncastToSterile(osc)->SetAngle(3,4, asin(sqrt(Clamp(val)))/2); } - //--------------------------------------------------------------------------- + //--------------------------------------------------------------------------- double FitTheta13InDegreesSterile::GetValue(const osc::IOscCalcAdjustable* osc) const { return TMath::RadToDeg()*osc::DowncastToSterile(osc)->GetAngle(1,3); @@ -274,7 +274,7 @@ namespace ana osc::DowncastToSterile(osc)->SetAngle(1, 3, TMath::DegToRad()*Clamp(val)); } - //--------------------------------------------------------------------------- + //--------------------------------------------------------------------------- double FitTheta23InDegreesSterile::GetValue(const osc::IOscCalcAdjustable* osc) const { return TMath::RadToDeg()*osc::DowncastToSterile(osc)->GetAngle(2,3); @@ -286,7 +286,7 @@ namespace ana osc::DowncastToSterile(osc)->SetAngle(2, 3, TMath::DegToRad()*Clamp(val)); } - //--------------------------------------------------------------------------- + //--------------------------------------------------------------------------- double FitTheta14InDegreesSterile::GetValue(const osc::IOscCalcAdjustable* osc) const { return TMath::RadToDeg()*osc::DowncastToSterile(osc)->GetAngle(1,4); @@ -298,7 +298,7 @@ namespace ana osc::DowncastToSterile(osc)->SetAngle(1, 4, TMath::DegToRad()*Clamp(val)); } - //--------------------------------------------------------------------------- + //--------------------------------------------------------------------------- double FitTheta24InDegreesSterile::GetValue(const osc::IOscCalcAdjustable* osc) const { return TMath::RadToDeg()*osc::DowncastToSterile(osc)->GetAngle(2,4); @@ -310,7 +310,7 @@ namespace ana osc::DowncastToSterile(osc)->SetAngle(2, 4, TMath::DegToRad()*Clamp(val)); } - //--------------------------------------------------------------------------- + //--------------------------------------------------------------------------- double FitTheta34InDegreesSterile::GetValue(const osc::IOscCalcAdjustable* osc) const { return TMath::RadToDeg()*osc::DowncastToSterile(osc)->GetAngle(3,4); diff --git a/sbnana/CAFAna/Vars/FitVarsSterile.h b/sbnana/CAFAna/Vars/FitVarsSterile.h index 78add0e8..c918b4b5 100644 --- a/sbnana/CAFAna/Vars/FitVarsSterile.h +++ b/sbnana/CAFAna/Vars/FitVarsSterile.h @@ -10,60 +10,60 @@ namespace ana /// \f$ \Delta m^2_{32} \f$ class FitDmSq32Sterile: public IFitVar { - public: + public: + FitDmSq32Sterile() : IFitVar("dmsq32", "#Deltam^{2}_{32} (eV^{2})") {} + virtual double GetValue(const osc::IOscCalcAdjustable* osc) const; virtual void SetValue(osc::IOscCalcAdjustable* osc, double val) const; - virtual std::string ShortName() const {return "dmsq32";} - virtual std::string LatexName() const {return "#Deltam^{2}_{32} (eV^{2})";} }; /// \f$ \Delta m^2_{32} \f$ - const FitDmSq32Sterile kFitDmSq32Sterile = FitDmSq32Sterile(); - + const FitDmSq32Sterile kFitDmSq32Sterile; + //---------------------------------------------------------------------- /// \f$ \Delta m^2_{41} \f$ class FitDmSq41Sterile: public IFitVar { - public: + public: + FitDmSq41Sterile() : IFitVar("dmsq41", "#Deltam^{2}_{41} (eV^{2})") {} + virtual double GetValue(const osc::IOscCalcAdjustable* osc) const; virtual void SetValue(osc::IOscCalcAdjustable* osc, double val) const; - virtual std::string ShortName() const {return "dmsq41";} - virtual std::string LatexName() const {return "#Deltam^{2}_{41} (eV^{2})";} }; /// \f$ \Delta m^2_{41} \f$ - const FitDmSq41Sterile kFitDmSq41Sterile = FitDmSq41Sterile(); + const FitDmSq41Sterile kFitDmSq41Sterile; //---------------------------------------------------------------------- /// \f$ \Delta m^2_{43} \f$ class FitDmSq43Sterile: public IFitVar { - public: + public: + FitDmSq43Sterile() : IFitVar("dmsq43", "#Deltam^{2}_{43} (eV^{2})") {} + virtual double GetValue(const osc::IOscCalcAdjustable* osc) const; virtual void SetValue(osc::IOscCalcAdjustable* osc, double val) const; - virtual std::string ShortName() const {return "dmsq43";} - virtual std::string LatexName() const {return "#Deltam^{2}_{43} (eV^{2})";} }; - + /// \f$ \Delta m^2_{43} \f$ - const FitDmSq43Sterile kFitDmSq43Sterile = FitDmSq43Sterile(); - + const FitDmSq43Sterile kFitDmSq43Sterile; + //---------------------------------------------------------------------- /// \f$ \delta_{13}/\pi \f$ class FitDelta13InPiUnitsSterile: public IFitVar { public: + FitDelta13InPiUnitsSterile() : IFitVar("delta13(pi)", "#delta_{13} / #pi") {} + virtual double GetValue(const osc::IOscCalcAdjustable* osc) const; virtual void SetValue(osc::IOscCalcAdjustable* osc, double val) const; - virtual std::string ShortName() const {return "delta13(pi)";} - virtual std::string LatexName() const {return "#delta_{13} / #pi";} }; /// \f$ \delta_{CP}/\pi \f$ - const FitDelta13InPiUnitsSterile kFitDelta13InPiUnitsSterile = FitDelta13InPiUnitsSterile(); + const FitDelta13InPiUnitsSterile kFitDelta13InPiUnitsSterile; //---------------------------------------------------------------------- @@ -71,14 +71,14 @@ namespace ana class FitDelta14InPiUnitsSterile: public IFitVar { public: + FitDelta14InPiUnitsSterile() : IFitVar("delta14(pi)", "#delta_{14} / #pi") {} + virtual double GetValue(const osc::IOscCalcAdjustable* osc) const; virtual void SetValue(osc::IOscCalcAdjustable* osc, double val) const; - virtual std::string ShortName() const {return "delta14(pi)";} - virtual std::string LatexName() const {return "#delta_{14} / #pi";} }; /// \f$ \delta_{14}/\pi \f$ - const FitDelta14InPiUnitsSterile kFitDelta14InPiUnitsSterile = FitDelta14InPiUnitsSterile(); + const FitDelta14InPiUnitsSterile kFitDelta14InPiUnitsSterile; //---------------------------------------------------------------------- @@ -86,14 +86,14 @@ namespace ana class FitDelta24InPiUnitsSterile: public IFitVar { public: + FitDelta24InPiUnitsSterile() : IFitVar("delta24(pi)", "#delta_{24} / #pi") {} + virtual double GetValue(const osc::IOscCalcAdjustable* osc) const; virtual void SetValue(osc::IOscCalcAdjustable* osc, double val) const; - virtual std::string ShortName() const {return "delta24(pi)";} - virtual std::string LatexName() const {return "#delta_{24} / #pi";} }; /// \f$ \delta_{24}/\pi \f$ - const FitDelta24InPiUnitsSterile kFitDelta24InPiUnitsSterile = FitDelta24InPiUnitsSterile(); + const FitDelta24InPiUnitsSterile kFitDelta24InPiUnitsSterile; //---------------------------------------------------------------------- @@ -101,17 +101,17 @@ namespace ana class FitTheta13Sterile: public IConstrainedFitVar { public: + FitTheta13Sterile() : IConstrainedFitVar("th13", "#theta_{13}") {} + virtual double GetValue(const osc::IOscCalcAdjustable* osc) const; virtual void SetValue(osc::IOscCalcAdjustable* osc, double val) const; - virtual std::string ShortName() const {return "th13";} - virtual std::string LatexName() const {return "#theta_{13}";} virtual double LowLimit() const {return 0;} virtual double HighLimit() const {return TMath::Pi()/2;} }; /// \f$ \theta_{13} \f$ - const FitTheta13Sterile kFitTheta13Sterile = FitTheta13Sterile(); + const FitTheta13Sterile kFitTheta13Sterile; //---------------------------------------------------------------------- @@ -119,17 +119,17 @@ namespace ana class FitSinSqTheta13Sterile: public IConstrainedFitVar { public: + FitSinSqTheta13Sterile() : IConstrainedFitVar("ssth13", "sin^{2}#theta_{13}") {} + virtual double GetValue(const osc::IOscCalcAdjustable* osc) const; virtual void SetValue(osc::IOscCalcAdjustable* osc, double val) const; - virtual std::string ShortName() const {return "ssth13";} - virtual std::string LatexName() const {return "sin^{2}#theta_{13}";} virtual double LowLimit() const {return 0;} virtual double HighLimit() const {return 1;} }; /// \f$ \sin^2\theta_{13} \f$ - const FitSinSqTheta13Sterile kFitSinSqTheta13Sterile = FitSinSqTheta13Sterile(); + const FitSinSqTheta13Sterile kFitSinSqTheta13Sterile; //---------------------------------------------------------------------- @@ -137,17 +137,17 @@ namespace ana class FitTheta23Sterile: public IConstrainedFitVar { public: + FitTheta23Sterile() : IConstrainedFitVar("th23", "#theta_{23}") {} + virtual double GetValue(const osc::IOscCalcAdjustable* osc) const; virtual void SetValue(osc::IOscCalcAdjustable* osc, double val) const; - virtual std::string ShortName() const {return "th23";} - virtual std::string LatexName() const {return "#theta_{23}";} virtual double LowLimit() const {return 0;} virtual double HighLimit() const {return TMath::Pi()/2;} }; /// \f$ \theta_{23} \f$ - const FitTheta23Sterile kFitTheta23Sterile = FitTheta23Sterile(); + const FitTheta23Sterile kFitTheta23Sterile; //---------------------------------------------------------------------- @@ -155,17 +155,17 @@ namespace ana class FitSinSqTheta23Sterile: public IConstrainedFitVar { public: + FitSinSqTheta23Sterile() : IConstrainedFitVar("ssth23", "sin^{2}#theta_{23}") {} + virtual double GetValue(const osc::IOscCalcAdjustable* osc) const; virtual void SetValue(osc::IOscCalcAdjustable* osc, double val) const; - virtual std::string ShortName() const {return "ssth23";} - virtual std::string LatexName() const {return "sin^{2}#theta_{23}";} virtual double LowLimit() const {return 0;} virtual double HighLimit() const {return 1;} }; /// \f$ \sin^2\theta_{23} \f$ - const FitSinSqTheta23Sterile kFitSinSqTheta23Sterile = FitSinSqTheta23Sterile(); + const FitSinSqTheta23Sterile kFitSinSqTheta23Sterile; //---------------------------------------------------------------------- @@ -173,17 +173,17 @@ namespace ana class FitTheta14Sterile: public IConstrainedFitVar { public: + FitTheta14Sterile() : IConstrainedFitVar("th14", "#theta_{14}") {} + virtual double GetValue(const osc::IOscCalcAdjustable* osc) const; virtual void SetValue(osc::IOscCalcAdjustable* osc, double val) const; - virtual std::string ShortName() const {return "th14";} - virtual std::string LatexName() const {return "#theta_{14}";} virtual double LowLimit() const {return 0;} virtual double HighLimit() const {return TMath::Pi()/2;} }; /// \f$ \theta_{14} \f$ - const FitTheta14Sterile kFitTheta14Sterile = FitTheta14Sterile(); + const FitTheta14Sterile kFitTheta14Sterile; //---------------------------------------------------------------------- @@ -191,17 +191,17 @@ namespace ana class FitSinSqTheta14Sterile: public IConstrainedFitVar { public: + FitSinSqTheta14Sterile() : IConstrainedFitVar("ssth14", "sin^{2}#theta_{14}") {} + virtual double GetValue(const osc::IOscCalcAdjustable* osc) const; virtual void SetValue(osc::IOscCalcAdjustable* osc, double val) const; - virtual std::string ShortName() const {return "ssth14";} - virtual std::string LatexName() const {return "sin^{2}#theta_{14}";} virtual double LowLimit() const {return 0;} virtual double HighLimit() const {return 1;} }; /// \f$ \sin^2\theta_{14} \f$ - const FitSinSqTheta14Sterile kFitSinSqTheta14Sterile = FitSinSqTheta14Sterile(); + const FitSinSqTheta14Sterile kFitSinSqTheta14Sterile; //---------------------------------------------------------------------- @@ -210,17 +210,17 @@ namespace ana class FitSinSq2Theta14Sterile: public IConstrainedFitVar { public: + FitSinSq2Theta14Sterile() : IConstrainedFitVar("ss2th14", "sin^{2}2#theta_{14}") {} + virtual double GetValue(const osc::IOscCalcAdjustable* osc) const; virtual void SetValue(osc::IOscCalcAdjustable* osc, double val) const; - virtual std::string ShortName() const {return "ss2th14";} - virtual std::string LatexName() const {return "sin^{2}2#theta_{14}";} virtual double LowLimit() const {return 0;} virtual double HighLimit() const {return 1;} }; /// \f$ \sin^22\theta_{14} \f$ - const FitSinSq2Theta14Sterile kFitSinSq2Theta14Sterile = FitSinSq2Theta14Sterile(); + const FitSinSq2Theta14Sterile kFitSinSq2Theta14Sterile; //---------------------------------------------------------------------- @@ -228,17 +228,17 @@ namespace ana class FitTheta24Sterile: public IConstrainedFitVar { public: + FitTheta24Sterile() : IConstrainedFitVar("th24", "#theta_{24}") {} + virtual double GetValue(const osc::IOscCalcAdjustable* osc) const; virtual void SetValue(osc::IOscCalcAdjustable* osc, double val) const; - virtual std::string ShortName() const {return "th24";} - virtual std::string LatexName() const {return "#theta_{24}";} virtual double LowLimit() const {return 0;} virtual double HighLimit() const {return TMath::Pi()/4;} }; /// \f$ \theta_{24} \f$ - const FitTheta24Sterile kFitTheta24Sterile = FitTheta24Sterile(); + const FitTheta24Sterile kFitTheta24Sterile; //---------------------------------------------------------------------- @@ -246,17 +246,17 @@ namespace ana class FitSinSqTheta24Sterile: public IConstrainedFitVar { public: + FitSinSqTheta24Sterile() : IConstrainedFitVar("ssth24", "sin^{2}#theta_{24}") {} + virtual double GetValue(const osc::IOscCalcAdjustable* osc) const; virtual void SetValue(osc::IOscCalcAdjustable* osc, double val) const; - virtual std::string ShortName() const {return "ssth24";} - virtual std::string LatexName() const {return "sin^{2}#theta_{24}";} virtual double LowLimit() const {return 0;} virtual double HighLimit() const {return 1;} }; /// \f$ \sin^2\theta_{24} \f$ - const FitSinSqTheta24Sterile kFitSinSqTheta24Sterile = FitSinSqTheta24Sterile(); + const FitSinSqTheta24Sterile kFitSinSqTheta24Sterile; //---------------------------------------------------------------------- @@ -264,17 +264,17 @@ namespace ana class FitSinSq2Theta24Sterile: public IConstrainedFitVar { public: + FitSinSq2Theta24Sterile() : IConstrainedFitVar("ss2th24", "sin^{2}2#theta_{24}") {} + virtual double GetValue(const osc::IOscCalcAdjustable* osc) const; virtual void SetValue(osc::IOscCalcAdjustable* osc, double val) const; - virtual std::string ShortName() const {return "ss2th24";} - virtual std::string LatexName() const {return "sin^{2}2#theta_{24}";} virtual double LowLimit() const {return 0;} virtual double HighLimit() const {return 1;} }; /// \f$ \sin^22\theta_{24} \f$ - const FitSinSq2Theta24Sterile kFitSinSq2Theta24Sterile = FitSinSq2Theta24Sterile(); + const FitSinSq2Theta24Sterile kFitSinSq2Theta24Sterile; //---------------------------------------------------------------------- @@ -282,17 +282,17 @@ namespace ana class FitTheta34Sterile: public IConstrainedFitVar { public: + FitTheta34Sterile() : IConstrainedFitVar("th34", "#theta_{34}") {} + virtual double GetValue(const osc::IOscCalcAdjustable* osc) const; virtual void SetValue(osc::IOscCalcAdjustable* osc, double val) const; - virtual std::string ShortName() const {return "th34";} - virtual std::string LatexName() const {return "#theta_{34}";} virtual double LowLimit() const {return 0;} virtual double HighLimit() const {return TMath::Pi()/2;} }; /// \f$ \theta_{34} \f$ - const FitTheta34Sterile kFitTheta34Sterile = FitTheta34Sterile(); + const FitTheta34Sterile kFitTheta34Sterile; //---------------------------------------------------------------------- @@ -300,17 +300,17 @@ namespace ana class FitSinSqTheta34Sterile: public IConstrainedFitVar { public: + FitSinSqTheta34Sterile() : IConstrainedFitVar("ssth34", "sin^{2}#theta_{34}") {} + virtual double GetValue(const osc::IOscCalcAdjustable* osc) const; virtual void SetValue(osc::IOscCalcAdjustable* osc, double val) const; - virtual std::string ShortName() const {return "ssth34";} - virtual std::string LatexName() const {return "sin^{2}#theta_{34}";} virtual double LowLimit() const {return 0;} virtual double HighLimit() const {return 1;} }; /// \f$ \sin^2\theta_{34} \f$ - const FitSinSqTheta34Sterile kFitSinSqTheta34Sterile = FitSinSqTheta34Sterile(); + const FitSinSqTheta34Sterile kFitSinSqTheta34Sterile; //---------------------------------------------------------------------- @@ -318,17 +318,17 @@ namespace ana class FitSinSq2Theta34Sterile: public IConstrainedFitVar { public: + FitSinSq2Theta34Sterile() : IConstrainedFitVar("ss2th34", "sin^{2}2#theta_{34}") {} + virtual double GetValue(const osc::IOscCalcAdjustable* osc) const; virtual void SetValue(osc::IOscCalcAdjustable* osc, double val) const; - virtual std::string ShortName() const {return "ss2th34";} - virtual std::string LatexName() const {return "sin^{2}2#theta_{34}";} virtual double LowLimit() const {return 0;} virtual double HighLimit() const {return 1;} }; /// \f$ \sin^22\theta_{34} \f$ - const FitSinSq2Theta34Sterile kFitSinSq2Theta34Sterile = FitSinSq2Theta34Sterile(); + const FitSinSq2Theta34Sterile kFitSinSq2Theta34Sterile; //---------------------------------------------------------------------- @@ -336,17 +336,17 @@ namespace ana class FitTheta13InDegreesSterile: public IConstrainedFitVar { public: + FitTheta13InDegreesSterile() : IConstrainedFitVar("th13(degrees)", "#theta_{13}") {} + virtual double GetValue(const osc::IOscCalcAdjustable* osc) const; virtual void SetValue(osc::IOscCalcAdjustable* osc, double val) const; - virtual std::string ShortName() const {return "th13(degrees)";} - virtual std::string LatexName() const {return "#theta_{13}";} virtual double LowLimit() const {return 0;} virtual double HighLimit() const {return 90;} }; /// \f$ \theta_{13} \f$ - const FitTheta13InDegreesSterile kFitTheta13InDegreesSterile = FitTheta13InDegreesSterile(); + const FitTheta13InDegreesSterile kFitTheta13InDegreesSterile; //---------------------------------------------------------------------- @@ -354,17 +354,17 @@ namespace ana class FitTheta23InDegreesSterile: public IConstrainedFitVar { public: + FitTheta23InDegreesSterile() : IConstrainedFitVar("th23(degrees)", "#theta_{23}") {} + virtual double GetValue(const osc::IOscCalcAdjustable* osc) const; virtual void SetValue(osc::IOscCalcAdjustable* osc, double val) const; - virtual std::string ShortName() const {return "th23(degrees)";} - virtual std::string LatexName() const {return "#theta_{23}";} virtual double LowLimit() const {return 0;} virtual double HighLimit() const {return 90;} }; /// \f$ \theta_{23} \f$ - const FitTheta23InDegreesSterile kFitTheta23InDegreesSterile = FitTheta23InDegreesSterile(); + const FitTheta23InDegreesSterile kFitTheta23InDegreesSterile; //---------------------------------------------------------------------- @@ -372,17 +372,17 @@ namespace ana class FitTheta14InDegreesSterile: public IConstrainedFitVar { public: + FitTheta14InDegreesSterile() : IConstrainedFitVar("th14(degrees)", "#theta_{14}") {} + virtual double GetValue(const osc::IOscCalcAdjustable* osc) const; virtual void SetValue(osc::IOscCalcAdjustable* osc, double val) const; - virtual std::string ShortName() const {return "th14(degrees)";} - virtual std::string LatexName() const {return "#theta_{14}";} virtual double LowLimit() const {return 0;} virtual double HighLimit() const {return 90;} }; /// \f$ \theta_{14} \f$ - const FitTheta14InDegreesSterile kFitTheta14InDegreesSterile = FitTheta14InDegreesSterile(); + const FitTheta14InDegreesSterile kFitTheta14InDegreesSterile; //---------------------------------------------------------------------- @@ -390,17 +390,17 @@ namespace ana class FitTheta24InDegreesSterile: public IConstrainedFitVar { public: + FitTheta24InDegreesSterile() : IConstrainedFitVar("th24(degrees)", "#theta_{24}") {} + virtual double GetValue(const osc::IOscCalcAdjustable* osc) const; virtual void SetValue(osc::IOscCalcAdjustable* osc, double val) const; - virtual std::string ShortName() const {return "th24(degrees)";} - virtual std::string LatexName() const {return "#theta_{24}";} virtual double LowLimit() const {return 0;} virtual double HighLimit() const {return 45;} }; /// \f$ \theta_{24} \f$ - const FitTheta24InDegreesSterile kFitTheta24InDegreesSterile = FitTheta24InDegreesSterile(); + const FitTheta24InDegreesSterile kFitTheta24InDegreesSterile; //---------------------------------------------------------------------- @@ -408,17 +408,17 @@ namespace ana class FitTheta34InDegreesSterile: public IConstrainedFitVar { public: + FitTheta34InDegreesSterile() : IConstrainedFitVar("th34(degrees)", "#theta_{34}") {} + virtual double GetValue(const osc::IOscCalcAdjustable* osc) const; virtual void SetValue(osc::IOscCalcAdjustable* osc, double val) const; - virtual std::string ShortName() const {return "th34(degrees)";} - virtual std::string LatexName() const {return "#theta_{34}";} virtual double LowLimit() const {return 0;} virtual double HighLimit() const {return 90;} }; /// \f$ \theta_{34} \f$ - const FitTheta34InDegreesSterile kFitTheta34InDegreesSterile = FitTheta34InDegreesSterile(); + const FitTheta34InDegreesSterile kFitTheta34InDegreesSterile; //---------------------------------------------------------------------- diff --git a/sbnana/CAFAna/Vars/FitVarsSterileApprox.h b/sbnana/CAFAna/Vars/FitVarsSterileApprox.h index f9587cc1..ddc714f4 100644 --- a/sbnana/CAFAna/Vars/FitVarsSterileApprox.h +++ b/sbnana/CAFAna/Vars/FitVarsSterileApprox.h @@ -10,17 +10,17 @@ namespace ana class FitDmSqSterile: public IConstrainedFitVar { public: + FitDmSqSterile() : IConstrainedFitVar("dmsq", "#Deltam^{2} (eV^{2})") {} + virtual double GetValue(const osc::IOscCalcAdjustable* osc) const; virtual void SetValue(osc::IOscCalcAdjustable* osc, double val) const; - virtual std::string ShortName() const {return "dmsq";} - virtual std::string LatexName() const {return "#Deltam^{2} (eV^{2})";} virtual double LowLimit() const {return 0;} virtual double HighLimit() const {return 1e6;} }; /// \Delta m^2 \f$ - const FitDmSqSterile kFitDmSqSterile = FitDmSqSterile(); + const FitDmSqSterile kFitDmSqSterile; //---------------------------------------------------------------------- @@ -28,17 +28,17 @@ namespace ana class FitSinSq2ThetaMuMu: public IConstrainedFitVar { public: + FitSinSq2ThetaMuMu() : IConstrainedFitVar("ss2thmm", "sin^{2}2#theta_{#mu#mu}") {} + virtual double GetValue(const osc::IOscCalcAdjustable* osc) const; virtual void SetValue(osc::IOscCalcAdjustable* osc, double val) const; - virtual std::string ShortName() const {return "ss2thmm";} - virtual std::string LatexName() const {return "sin^{2}2#theta_{#mu#mu}";} virtual double LowLimit() const {return 0;} virtual double HighLimit() const {return 1;} }; /// \f$ \sin^22\theta_{\mu\mu} \f$ - const FitSinSq2ThetaMuMu kFitSinSq2ThetaMuMu = FitSinSq2ThetaMuMu(); + const FitSinSq2ThetaMuMu kFitSinSq2ThetaMuMu; //---------------------------------------------------------------------- @@ -46,16 +46,16 @@ namespace ana class FitSinSq2ThetaMuE: public IConstrainedFitVar { public: + FitSinSq2ThetaMuE() : IConstrainedFitVar("ss2thme", "sin^{2}2#theta_{#mue}") {} + virtual double GetValue(const osc::IOscCalcAdjustable* osc) const; virtual void SetValue(osc::IOscCalcAdjustable* osc, double val) const; - virtual std::string ShortName() const {return "ss2thme";} - virtual std::string LatexName() const {return "sin^{2}2#theta_{#mue}";} virtual double LowLimit() const {return 0;} virtual double HighLimit() const {return 1;} }; /// \f$ \sin^22\theta_{\mu e} \f$ - const FitSinSq2ThetaMuE kFitSinSq2ThetaMuE = FitSinSq2ThetaMuE(); + const FitSinSq2ThetaMuE kFitSinSq2ThetaMuE; } // namespace diff --git a/sbnana/CAFAna/XSec/Flux.cxx b/sbnana/CAFAna/XSec/Flux.cxx index a187de4b..839d7e03 100644 --- a/sbnana/CAFAna/XSec/Flux.cxx +++ b/sbnana/CAFAna/XSec/Flux.cxx @@ -1,8 +1,15 @@ #include "sbnana/CAFAna/XSec/Flux.h" +#include "sbnana/CAFAna/Core/HistAxis.h" +#include "sbnana/CAFAna/Core/Var.h" +#include "sbnana/CAFAna/Core/Weight.h" + #include "sbnanaobj/StandardRecord/Proxy/SRProxy.h" +#include "TDirectory.h" +#include "TObjString.h" #include "TH1.h" +#include "TVectorD.h" namespace ana { @@ -21,57 +28,167 @@ namespace ana //---------------------------------------------------------------------- bool IsNCQEOnArgon(const caf::SRTrueInteractionProxy* nu, int pdg) { - // This process works for very low neutrino energy where the muon mass - // becomes relevant. + // The issue with the CC interaction is there is a threshold around the + // muon mass. This process works for lower neutrino energies too return nu->pdg == pdg && !nu->iscc && nu->genie_mode == caf::kQE && nu->genie_inttype == caf::kNCQE && - nu->targetPDG == 1000180400 /* Argon 40 */ && + nu->targetPDG == 1000180400 /* Argon 40 */ && !nu->ischarm && nu->hitnuc == 2112; } //---------------------------------------------------------------------- - const Var kInvXSec([](const caf::SRSliceProxy* sr) - { - // GENIE uses GeV internally. We ultimately want a flux - // in m^-2 - const double GeV2perm2 = 2.56819e31; + const NuTruthWeight kInvXSec([](const caf::SRTrueInteractionProxy* nu) + { + // GENIE uses GeV internally. We ultimately want + // a flux in m^-2 + const double GeV2perm2 = 2.56819e31; - return GeV2perm2/sr->truth.xsec; - }); + return GeV2perm2/nu->xsec; + }); //---------------------------------------------------------------------- - // TODO can this operate completely in true interaction mode? Right now we - // are folding in a slicing efficiency - Cut IsCCQEOnArgonCut(int pdg) + NuTruthCut IsNCQEOnArgonCut(int pdg) { - return Cut([pdg](const caf::SRSliceProxy* slc) - { - if(slc->truth.index < 0) return false; - return IsCCQEOnArgon(&slc->truth, pdg); - }); + return NuTruthCut([pdg](const caf::SRTrueInteractionProxy* nu) + { + return IsNCQEOnArgon(nu, pdg); + }); } //---------------------------------------------------------------------- - FluxTimesNuclei::FluxTimesNuclei(SpectrumLoaderBase& loader, + FluxTimesNuclei::FluxTimesNuclei(INuTruthSource& src, const Binning& bins, - const Cut& fidvol, - int pdg) - : Spectrum("", bins, loader, SIMPLEVAR(truth.E), - SIMPLEVAR(truth.index) >= 0 && IsCCQEOnArgonCut(pdg) && fidvol, - kNoShift, kInvXSec), + const NuTruthCut& fidvol, + int pdg, + const NuTruthWeight& wgt) + : Spectrum(src[IsNCQEOnArgonCut(pdg) && fidvol].Weighted(wgt *kInvXSec), + NuTruthHistAxis("True neutrino energy (GeV)", + bins, + SIMPLENUTRUTHVAR(E))), fPdg(pdg) { } //---------------------------------------------------------------------- - TH1D* FluxTimesNuclei::ToTH1(double exposure, + TH1D* FluxTimesNuclei::ToTH1(double pot, Color_t col, Style_t style, EBinType bintype) { - TH1D* ret = Spectrum::ToTH1(exposure, col, style, kPOT, bintype); - ret->GetXaxis()->SetTitle("True neutrino energy (GeV)"); + TH1D* ret = Spectrum::ToTH1(pot, col, style, kPOT, bintype); + + std::string ytitle = "Flux #times nuclei ("; + switch(fPdg){ + case +12: ytitle += "#nu_e"; break; + case -12: ytitle += "#bar{#nu}_e"; break; + case +14: ytitle += "#nu_{#mu}"; break; + case -14: ytitle += "#bar{#nu}_{#mu}"; break; + } + + ytitle += "/ m^{2}"; + if(bintype == kBinDensity) ytitle += " / GeV"; + ytitle += ")"; + ret->GetYaxis()->SetTitle(ytitle.c_str()); + return ret; + } + + //---------------------------------------------------------------------- + void FluxTimesNuclei::SaveTo(TDirectory* dir, const std::string& name) const + { + TDirectory* tmp = gDirectory; + + dir = dir->mkdir(name.c_str()); // switch to subdir + dir->cd(); + + TObjString("FluxTimesNuclei").Write("type"); + + TVectorD pdg(1); + pdg[0] = fPdg; + pdg.Write("pdg"); + + Spectrum::SaveTo(dir, "spectrum"); + + dir->Write(); + delete dir; + + tmp->cd(); + } + + //---------------------------------------------------------------------- + std::unique_ptr FluxTimesNuclei::LoadFrom(TDirectory* dir, const std::string& name) + { + dir = dir->GetDirectory(name.c_str()); // switch to subdir + assert(dir); + + DontAddDirectory guard; + + std::unique_ptr tag((TObjString*)dir->Get("type")); + assert(tag); + assert(tag->GetString() == "FluxTimesNuclei"); + + std::unique_ptr pdg((TVectorD*)dir->Get("pdg")); + assert(pdg && pdg->GetNrows()==1); + + return std::unique_ptr( + new FluxTimesNuclei(std::move(*Spectrum::LoadFrom(dir, "spectrum")), (*pdg)[0])); + } + + //---------------------------------------------------------------------- + FluxTimesNuclei::FluxTimesNuclei(const Spectrum&& spec, const int pdg) + : Spectrum(spec), fPdg(pdg) + { + } + + //---------------------------------------------------------------------- + FluxTimesNuclei::FluxTimesNuclei(const Eigen::ArrayXd&& hist, + const LabelsAndBins& axis, + double pot, + double livetime, + int pdg) + : Spectrum(hist, axis, pot, livetime), fPdg(pdg) + { + } + + //---------------------------------------------------------------------- + FluxTimesNuclei FluxTimesNuclei::MakeTotalFlux(const LabelsAndBins& axis) const + { + const unsigned int nbins = axis.GetBins1D().NBins()+2; + + const Eigen::ArrayXd hist = Eigen::ArrayXd::Constant(nbins, Integral(fPOT)); + + return FluxTimesNuclei(std::move(hist), axis, fPOT, fLivetime, fPdg); + } + + //---------------------------------------------------------------------- + EnsembleFluxTimesNuclei::EnsembleFluxTimesNuclei(INuTruthEnsembleSource& src, + const Binning& bins, + const NuTruthCut& fidvol, + int pdg, + const NuTruthWeight& wgt) + : EnsembleSpectrum(src[IsNCQEOnArgonCut(pdg) && fidvol].Weighted(wgt * kInvXSec), + NuTruthHistAxis("True neutrino energy (GeV)", + bins, + SIMPLENUTRUTHVAR(E))), + fPdg(pdg) + { + } + + //---------------------------------------------------------------------- + EnsembleFluxTimesNuclei EnsembleFluxTimesNuclei::ReplicatedNominal(const FluxTimesNuclei& spec, + const FitMultiverse* multiverse) + { + return EnsembleFluxTimesNuclei(EnsembleSpectrum::ReplicatedData(spec, multiverse), spec.PDG()); + } + + + //---------------------------------------------------------------------- + TH1D* EnsembleFluxTimesNuclei::ToTH1(double pot, + Color_t col, + Style_t style, + EBinType bintype) + { + TH1D* ret = EnsembleSpectrum::Nominal().ToTH1(pot, col, style, kPOT, bintype); std::string ytitle = "Flux #times nuclei ("; switch(fPdg){ @@ -87,4 +204,79 @@ namespace ana ret->GetYaxis()->SetTitle(ytitle.c_str()); return ret; } + + //---------------------------------------------------------------------- + void EnsembleFluxTimesNuclei::SaveTo(TDirectory* dir, const std::string& name) const + { + TDirectory* tmp = gDirectory; + + dir = dir->mkdir(name.c_str()); // switch to subdir + dir->cd(); + + TObjString("EnsembleFluxTimesNuclei").Write("type"); + + TVectorD pdg(1); + pdg[0] = fPdg; + pdg.Write("pdg"); + + EnsembleSpectrum::SaveTo(dir, "ensemblespectrum"); + + dir->Write(); + delete dir; + + tmp->cd(); + } + + //---------------------------------------------------------------------- + std::unique_ptr EnsembleFluxTimesNuclei::LoadFrom(TDirectory* dir, const std::string& name) + { + dir = dir->GetDirectory(name.c_str()); // switch to subdir + assert(dir); + + DontAddDirectory guard; + + std::unique_ptr tag((TObjString*)dir->Get("type")); + assert(tag); + assert(tag->GetString() == "EnsembleFluxTimesNuclei"); + + std::unique_ptr pdg((TVectorD*)dir->Get("pdg")); + assert(pdg && pdg->GetNrows()==1); + + return std::unique_ptr( + new EnsembleFluxTimesNuclei(std::move(*EnsembleSpectrum::LoadFrom(dir, "ensemblespectrum")), (*pdg)[0])); + } + + //---------------------------------------------------------------------- + EnsembleFluxTimesNuclei::EnsembleFluxTimesNuclei(const EnsembleSpectrum&& spec, const int pdg) + : EnsembleSpectrum(spec), fPdg(pdg) + { + } + + //---------------------------------------------------------------------- + EnsembleFluxTimesNuclei::EnsembleFluxTimesNuclei(const FitMultiverse* multiverse, + const Hist&& hist, + double pot, + double livetime, + const LabelsAndBins& axis, + int pdg) + : EnsembleSpectrum(multiverse, std::move(hist), pot, livetime, axis), fPdg(pdg) + { + } + + //---------------------------------------------------------------------- + EnsembleFluxTimesNuclei EnsembleFluxTimesNuclei::MakeTotalFlux(const LabelsAndBins& axis) const + { + const unsigned int nuniv = NUniverses(); + const unsigned int nbins = axis.GetBins1D().NBins()+2; + + Hist hist = Hist::Zero(nbins * nuniv); + + for(unsigned int univIdx = 0; univIdx < nuniv; ++univIdx){ + const double univIntegral(Universe(univIdx).Integral(fPOT)); + for(unsigned int bin = 0; bin < nbins; ++bin) + hist.Fill(nbins * univIdx + bin, univIntegral); + } + + return EnsembleFluxTimesNuclei(fMultiverse, std::move(hist), fPOT, fLivetime, axis, fPdg); + } } diff --git a/sbnana/CAFAna/XSec/Flux.h b/sbnana/CAFAna/XSec/Flux.h index 44549311..32e70e9a 100644 --- a/sbnana/CAFAna/XSec/Flux.h +++ b/sbnana/CAFAna/XSec/Flux.h @@ -1,4 +1,9 @@ -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "cafanacore/Spectrum.h" +#include "sbnana/CAFAna/Core/EnsembleSpectrum.h" + +#include "sbnana/CAFAna/Core/IRecordSource.h" + +#include "sbnana/CAFAna/Core/Cut.h" #include "sbnanaobj/StandardRecord/Proxy/FwdDeclare.h" @@ -12,14 +17,78 @@ namespace ana { public: /// pdg PDG code for neutrino, -14,-12,+12,14 - FluxTimesNuclei(SpectrumLoaderBase& loader, const Binning& bins, - const Cut& fidvol, int pdg); + FluxTimesNuclei(INuTruthSource& src, const Binning& bins, + const NuTruthCut& fidvol, int pdg, const NuTruthWeight& wgt = kNuTruthUnweighted); - TH1D* ToTH1(double exposure, + TH1D* ToTH1(double pot, Color_t col = kBlack, Style_t style = kSolid, EBinType bintype = kBinContent); + + void SaveTo(TDirectory* dir, const std::string& name) const; + + static std::unique_ptr LoadFrom(TDirectory* dir, const std::string& name); + + /// Convert an \ref FluxTimesNuclei into a \ref Spectrum where every bin is the integral of the + /// \ref FluxTimesNuclei, useful for dividing out flux in cross section measurement + FluxTimesNuclei MakeTotalFlux(const LabelsAndBins& axis) const; + + int PDG() const {return fPdg;}; + protected: + /// Helper for LoadFrom() + FluxTimesNuclei(const Spectrum&& spec, const int pdg); + FluxTimesNuclei(const Eigen::ArrayXd&& hist, + const LabelsAndBins& axis, + double pot, + double livetime, + int pdg); + + int fPdg; + + friend class EnsembleFluxTimesNuclei; + }; + + class EnsembleFluxTimesNuclei: public EnsembleSpectrum + { + public: + /// pdg PDG code for neutrino, -14,-12,+12,14 + EnsembleFluxTimesNuclei(INuTruthEnsembleSource& src, const Binning& bins, + const NuTruthCut& fidvol, int pdg, const NuTruthWeight& wgt = kNuTruthUnweighted); + + /// \brief Creates an ensemble flux times nuceli from a nominal input \ref FluxTimesNuclei + // which is replicated nUniverse times from the multiverse which it adopts. + // Note that this is a temporary workaround for now + static EnsembleFluxTimesNuclei ReplicatedNominal(const FluxTimesNuclei& spec, const FitMultiverse* multiverse); + + TH1D* ToTH1(double pot, + Color_t col = kBlack, + Style_t style = kSolid, + EBinType bintype = kBinContent); + + void SaveTo(TDirectory* dir, const std::string& name) const; + + static std::unique_ptr LoadFrom(TDirectory* dir, const std::string& name); + FluxTimesNuclei Nominal() const {return Universe(0);} + FluxTimesNuclei Universe(unsigned int i) const{return FluxTimesNuclei(EnsembleSpectrum::Universe(i), fPdg);}; + + /// Convert an \ref EnsembleFluxTimesNuclei into a \ref EnsembleSpectrum where every bin within + /// a given universe is the integral of the \ref EnsembleFluxTimesNuclei, useful for dividing + /// out flux in cross section measurement + EnsembleFluxTimesNuclei MakeTotalFlux(const LabelsAndBins& axis) const; + + int PDG() const {return fPdg;}; + + protected: + /// Helper for LoadFrom() + EnsembleFluxTimesNuclei(const EnsembleSpectrum&& spec, const int pdg); + EnsembleFluxTimesNuclei(const FitMultiverse* multiverse, + const Hist&& hist, + double pot, + double livetime, + const LabelsAndBins& axis, + int pdg); + int fPdg; }; } diff --git a/sbnana/CAFAna/check_proxy.C b/sbnana/CAFAna/check_proxy.C index 104896b6..dfdad386 100644 --- a/sbnana/CAFAna/check_proxy.C +++ b/sbnana/CAFAna/check_proxy.C @@ -5,7 +5,7 @@ #include "TFile.h" #include "TTree.h" -#include "sbnana/CAFAna/StandardRecord/StandardRecord.h" +#include "sbnanaobj/StandardRecord/StandardRecord.h" #include "sbnanaobj/StandardRecord/Proxy/SRProxy.h" #include @@ -39,7 +39,7 @@ void check_proxy(std::string fname, std::string fname2 = "", int N = -1) recTree->GetEntry(i); - if(type != caf::kFlatMultiTree) tr->LoadTree(i); + tr->LoadTree(i); srProxy.CheckEquals(*sr); } diff --git a/sbnana/CAFAna/diag_flux_systs.C b/sbnana/CAFAna/diag_flux_systs.C index 7ad473a0..c2653a3c 100644 --- a/sbnana/CAFAna/diag_flux_systs.C +++ b/sbnana/CAFAna/diag_flux_systs.C @@ -1,6 +1,6 @@ #include "sbnana/CAFAna/Core/SpectrumLoader.h" -#include "sbnana/CAFAna/Core/Spectrum.h" -#include "sbnana/CAFAna/Core/Ratio.h" +#include "cafanacore/Spectrum.h" +#include "cafanacore/Ratio.h" #include "sbnana/CAFAna/Core/Binning.h" #include "sbnana/CAFAna/Core/Var.h" #include "sbnana/CAFAna/Cuts/TruthCuts.h" @@ -20,6 +20,8 @@ #include "TGraph.h" #include "TH2.h" #include "TLatex.h" +#include "TMatrixD.h" +#include "TVectorD.h" #include @@ -107,19 +109,13 @@ void diag_flux_systs(bool force_rebuild = false) // TODO does anything in here impact the flux shape? // const Var kWeight = SIMPLEVAR(reco.weight); - const Cut kOneTrue([](const caf::SRProxy* sr) - { - return (sr->truth.size() == 1); - }); - - const Var kTrueE = SIMPLEVAR(truth[0].neutrino.energy); - const HistAxis axis("True neutrino energy (GeV)", - Binning::Simple(NEnergyBins, 0, MaxEnergy), kTrueE); + Binning::Simple(NEnergyBins, 0, MaxEnergy), + SIMPLEVAR(truth.E)); // NB beam nues are only about 0.08% of the flux. Anti-numus are as much as 0.8%. Anti-nues basically don't exist - const Cut kIsNumu = kOneTrue && SIMPLEVAR(truth[0].neutrino.initpdg) == 14; - const Cut kIsNue = kOneTrue && SIMPLEVAR(truth[0].neutrino.initpdg) == 12; + const Cut kIsNumu = SIMPLEVAR(truth.initpdg) == 14; + const Cut kIsNue = SIMPLEVAR(truth.initpdg) == 12; if(force_rebuild || TFile(state_name).IsZombie()){ TFile fout(state_name, "RECREATE"); @@ -133,12 +129,12 @@ void diag_flux_systs(bool force_rebuild = false) SpectrumLoader loader(fname); - Spectrum numu_nom(loader, axis, kIsNumu); - Spectrum nue_nom(loader, axis, kIsNue); + Spectrum numu_nom(loader.Slices()[kIsNumu], axis); + Spectrum nue_nom(loader.Slices()[kIsNue], axis); std::vector numus, nues; for(int univIdx = 0; univIdx < NUnivs; ++univIdx){ - const Var wei = GetUniverseWeight({ + const Weight wei = GetUniverseWeight({ "kminus_PrimaryHadronNormalization", "kplus_PrimaryHadronFeynmanScaling", "kzero_PrimaryHadronSanfordWang", @@ -146,19 +142,19 @@ void diag_flux_systs(bool force_rebuild = false) "piminus_PrimaryHadronSWCentralSplineVariation", }, univIdx); - numus.push_back(new Spectrum(loader, axis, kIsNumu, kNoShift, wei)); - nues .push_back(new Spectrum(loader, axis, kIsNue, kNoShift, wei)); + numus.push_back(new Spectrum(loader.Slices()[kIsNumu].Weighted(wei), axis)); + nues .push_back(new Spectrum(loader.Slices()[kIsNue].Weighted(wei), axis)); } // end for univIdx loader.Go(); TDirectory* ddet = fout.mkdir(det.c_str()); TDirectory* dnumu = ddet->mkdir("numu"); - numu_nom.SaveTo(dnumu->mkdir("nom")); - for(int i = 0; i < NUnivs; ++i) numus[i]->SaveTo(dnumu->mkdir(TString::Format("univ_%d", i).Data())); + numu_nom.SaveTo(dnumu, "nom"); + for(int i = 0; i < NUnivs; ++i) numus[i]->SaveTo(dnumu, TString::Format("univ_%d", i).Data()); TDirectory* dnue = ddet->mkdir("nue"); - nue_nom.SaveTo(dnue->mkdir("nom")); - for(int i = 0; i < NUnivs; ++i) nues[i]->SaveTo(dnue->mkdir(TString::Format("univ_%d", i).Data())); + nue_nom.SaveTo(dnue, "nom"); + for(int i = 0; i < NUnivs; ++i) nues[i]->SaveTo(dnue, TString::Format("univ_%d", i).Data()); } // end for det } // end if rebuild @@ -167,13 +163,13 @@ void diag_flux_systs(bool force_rebuild = false) DontAddDirectory guard; - Spectrum snom_numu_nd(*LoadFrom(fin.GetDirectory("nd/numu/nom"))); - Spectrum snom_numu_fd(*LoadFrom(fin.GetDirectory("fd/numu/nom"))); - Spectrum snom_numu_ub(*LoadFrom(fin.GetDirectory("ub/numu/nom"))); + Spectrum snom_numu_nd(*LoadFrom(&fin, "nd/numu/nom")); + Spectrum snom_numu_fd(*LoadFrom(&fin, "fd/numu/nom")); + Spectrum snom_numu_ub(*LoadFrom(&fin, "ub/numu/nom")); - Spectrum snom_nue_nd(*LoadFrom(fin.GetDirectory("nd/nue/nom"))); - Spectrum snom_nue_fd(*LoadFrom(fin.GetDirectory("fd/nue/nom"))); - Spectrum snom_nue_ub(*LoadFrom(fin.GetDirectory("ub/nue/nom"))); + Spectrum snom_nue_nd(*LoadFrom(&fin, "nd/nue/nom")); + Spectrum snom_nue_fd(*LoadFrom(&fin, "fd/nue/nom")); + Spectrum snom_nue_ub(*LoadFrom(&fin, "ub/nue/nom")); TMatrixD mcov(NSpectra*NEnergyBins, NSpectra*NEnergyBins); @@ -182,16 +178,16 @@ void diag_flux_systs(bool force_rebuild = false) NSpectra*NEnergyBins, 0, NSpectra*NEnergyBins); for(int univIdx = 0; univIdx < NUnivs; ++univIdx){ - TH1* hmnd = Ratio(*LoadFrom(fin.GetDirectory(TString::Format("nd/numu/univ_%d", univIdx).Data())), snom_numu_nd).ToTH1(); - TH1* hmub = Ratio(*LoadFrom(fin.GetDirectory(TString::Format("ub/numu/univ_%d", univIdx).Data())), snom_numu_ub).ToTH1(); - TH1* hmfd = Ratio(*LoadFrom(fin.GetDirectory(TString::Format("fd/numu/univ_%d", univIdx).Data())), snom_numu_fd).ToTH1(); + TH1* hmnd = Ratio(*LoadFrom(&fin, TString::Format("nd/numu/univ_%d", univIdx).Data()), snom_numu_nd).ToTH1(); + TH1* hmub = Ratio(*LoadFrom(&fin, TString::Format("ub/numu/univ_%d", univIdx).Data()), snom_numu_ub).ToTH1(); + TH1* hmfd = Ratio(*LoadFrom(&fin, TString::Format("fd/numu/univ_%d", univIdx).Data()), snom_numu_fd).ToTH1(); // We don't use these for anything. They're basically insignificant, and // make the matrix decomposition fail. /* - TH1* hend = Ratio(*LoadFrom(fin.GetDirectory(TString::Format("nd/nue/univ_%d", univIdx).Data())), snom_nue_nd).ToTH1(); - TH1* heub = Ratio(*LoadFrom(fin.GetDirectory(TString::Format("ub/nue/univ_%d", univIdx).Data())), snom_nue_ub).ToTH1(); - TH1* hefd = Ratio(*LoadFrom(fin.GetDirectory(TString::Format("fd/nue/univ_%d", univIdx).Data())), snom_nue_fd).ToTH1(); + TH1* hend = Ratio(*LoadFrom(&fin, TString::Format("nd/nue/univ_%d", univIdx).Data()), snom_nue_nd).ToTH1(); + TH1* heub = Ratio(*LoadFrom(&fin, TString::Format("ub/nue/univ_%d", univIdx).Data()), snom_nue_ub).ToTH1(); + TH1* hefd = Ratio(*LoadFrom(&fin, TString::Format("fd/nue/univ_%d", univIdx).Data()), snom_nue_fd).ToTH1(); */ TH1* htot = new TH1D("", "", NSpectra*NEnergyBins, 0, NSpectra*NEnergyBins); diff --git a/sbnana/CAFAna/rootlogon.C b/sbnana/CAFAna/rootlogon.C index 5b4f85da..5b0fad4e 100755 --- a/sbnana/CAFAna/rootlogon.C +++ b/sbnana/CAFAna/rootlogon.C @@ -174,7 +174,7 @@ void CenterTitles(TH1* histo) { histo->GetXaxis()->CenterTitle(); histo->GetYaxis()->CenterTitle(); - histo->GetZaxis()->CenterTitle(); + histo->GetZaxis()->CenterTitle(); } #endif \ No newline at end of file diff --git a/sbnana/CAFAna/sbn/fitter_comparisons/drawStack.C b/sbnana/CAFAna/sbn/fitter_comparisons/drawStack.C index abef7f08..0030c910 100644 --- a/sbnana/CAFAna/sbn/fitter_comparisons/drawStack.C +++ b/sbnana/CAFAna/sbn/fitter_comparisons/drawStack.C @@ -3,7 +3,7 @@ // Replace SBND with the appropriate experiment TFile* f = new TFile("output/output_SBND.root"); - + TH1D* SBND_All_NC_all = (TH1D*) f->Get("SBND_All_NC_all"); TH1D* SBND_QE_CC_all = (TH1D*) f->Get("SBND_QE_CC_all"); TH1D* SBND_Res_CC_all = (TH1D*) f->Get("SBND_Res_CC_all"); @@ -59,7 +59,7 @@ prelim->Draw(); c1->SaveAs("output/Stack_numu.root"); c1->SaveAs("output/Stack_numu.pdf"); - + TCanvas* c2 = new TCanvas("c2","c2", 700,800); c2->Divide(1,2); diff --git a/sbnana/CAFAna/sbn/fitter_comparisons/drawStack_finalstate.C b/sbnana/CAFAna/sbn/fitter_comparisons/drawStack_finalstate.C index 8ebaa666..3c8ea855 100644 --- a/sbnana/CAFAna/sbn/fitter_comparisons/drawStack_finalstate.C +++ b/sbnana/CAFAna/sbn/fitter_comparisons/drawStack_finalstate.C @@ -2,7 +2,7 @@ // event_numbers.C has to be executed first! // Replace SBND with the appropriate experiment TFile* f = new TFile("output/output_finalstate_SBND.root"); - + TH1D* SBND_All_NC_all = (TH1D*) f->Get("SBND_All_NC_all"); TH1D* SBND_0pi_CC_all = (TH1D*) f->Get("SBND_0pi_CC_all"); TH1D* SBND_1piCh_CC_all = (TH1D*) f->Get("SBND_1piCh_CC_all"); @@ -68,7 +68,7 @@ prelim->Draw(); c1->SaveAs("output/Stack_finalstate_numu.root"); c1->SaveAs("output/Stack_finalstate_numu.pdf"); - + TCanvas* c2 = new TCanvas("c2","c2", 700,800); c2->Divide(1,2); diff --git a/sbnana/CAFAna/sbn/fitter_comparisons/drawStack_nue.C b/sbnana/CAFAna/sbn/fitter_comparisons/drawStack_nue.C index abb88580..01b2ceb9 100644 --- a/sbnana/CAFAna/sbn/fitter_comparisons/drawStack_nue.C +++ b/sbnana/CAFAna/sbn/fitter_comparisons/drawStack_nue.C @@ -3,7 +3,7 @@ // Replace SBND with the appropriate experiment TFile* f = new TFile("output/output_nue_SBND.root"); - + TH1D* SBND_NC = (TH1D*) f->Get("SBND_NC"); TH1D* SBND_numu = (TH1D*) f->Get("SBND_numu"); TH1D* SBND_int = (TH1D*) f->Get("SBND_int"); @@ -53,7 +53,7 @@ prelim->Draw(); c1->SaveAs("output/Stack_nue.root"); c1->SaveAs("output/Stack_nue.pdf"); - + TCanvas* c2 = new TCanvas("c2","c2", 700,800); c2->Divide(1,2); diff --git a/sbnana/CAFAna/sbn/fitter_comparisons/event_numbers.C b/sbnana/CAFAna/sbn/fitter_comparisons/event_numbers.C index 97a0e072..f5557356 100644 --- a/sbnana/CAFAna/sbn/fitter_comparisons/event_numbers.C +++ b/sbnana/CAFAna/sbn/fitter_comparisons/event_numbers.C @@ -2,7 +2,7 @@ // cafe event_numbers.C #include "sbnana/CAFAna/Core/SpectrumLoader.h" -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "cafanacore/Spectrum.h" #include "sbnana/CAFAna/Core/Binning.h" #include "sbnana/CAFAna/Core/Var.h" @@ -24,7 +24,7 @@ using namespace ana; -// Put an "SBND simulation" tag in the corner +// Put an "SBND simulation" tag in the corner void Experiment(std::string expt) { TLatex* prelim = new TLatex(.9, .95, (expt+" Simulation").c_str()); @@ -142,7 +142,7 @@ void event_numbers(const std::string expt = "SBND") for(unsigned int k = 0; k < kNumCurrents; k++){ for(unsigned int j = k; j < kNumSigns; j++){ // loop over signs only for CC for(unsigned int i = k; i < kNumFlavours-k; i++){ // loop over flavours only for CC - h[m][k][j][i] = pred[m]->PredictComponent(noosc, k == 0 ? flav[i].flav : Flavors::kAll, + h[m][k][j][i] = pred[m]->PredictComponent(noosc, k == 0 ? flav[i].flav : Flavors::kAll, curr[k].curr, (k == 0) ? sign[j].sign : Sign::kBoth).ToTH1(pot); float nEvts = h[m][k][j][i]->Integral(); std::cout << ", " << nEvts ; @@ -157,7 +157,7 @@ void event_numbers(const std::string expt = "SBND") TCanvas* c1 = new TCanvas("c1","c1"); for(unsigned int m = 0; m < kNumModes; m++){ - for(unsigned int k = 0; k < kNumCurrents; k++){ + for(unsigned int k = 0; k < kNumCurrents; k++){ for(unsigned int j = k; j < kNumSigns; j++){ // loop over signs only for CC for(unsigned int i = k; i < kNumFlavours-k; i++){ // loop over flavours only for CC @@ -167,8 +167,8 @@ void event_numbers(const std::string expt = "SBND") h[m][k][j][i]->SetLineColor(cuts[m].colour); h[m][k][j][i]->SetMarkerColor(cuts[m].colour); - h[m][k][j][i]->Write((expt+"_"+cuts[m].label+"_"+currLabel+"_"+signLabel+flavLabel).c_str()); - h[m][k][j][i]->SetName((cuts[m].label+"_"+currLabel+"_"+signLabel+flavLabel).c_str()); + h[m][k][j][i]->Write((expt+"_"+cuts[m].label+"_"+currLabel+"_"+signLabel+flavLabel).c_str()); + h[m][k][j][i]->SetName((cuts[m].label+"_"+currLabel+"_"+signLabel+flavLabel).c_str()); h[m][k][j][i]->Draw("hist"); Experiment(expt); c1->SaveAs(("output/"+expt+"_"+cuts[m].label+"_"+currLabel+"_"+signLabel+flavLabel+".pdf").c_str()); diff --git a/sbnana/CAFAna/sbn/fitter_comparisons/event_numbers_finalstate.C b/sbnana/CAFAna/sbn/fitter_comparisons/event_numbers_finalstate.C index c7545286..2ada945b 100644 --- a/sbnana/CAFAna/sbn/fitter_comparisons/event_numbers_finalstate.C +++ b/sbnana/CAFAna/sbn/fitter_comparisons/event_numbers_finalstate.C @@ -2,7 +2,7 @@ // cafe event_numbers.C #include "sbnana/CAFAna/Core/SpectrumLoader.h" -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "cafanacore/Spectrum.h" #include "sbnana/CAFAna/Core/Binning.h" #include "sbnana/CAFAna/Core/Var.h" @@ -24,7 +24,7 @@ using namespace ana; -// Put an "SBND simulation" tag in the corner +// Put an "SBND simulation" tag in the corner void Experiment(std::string expt) { TLatex* prelim = new TLatex(.9, .95, (expt+" Simulation").c_str()); @@ -115,7 +115,7 @@ void event_numbers_finalstate(const std::string expt = "SBND") const Cut kTwoPiCh = (kNumPiZeros == 0 && kNumPiCharged == 2); const Cut kOneEach = (kNumPiZeros == 1 && kNumPiCharged == 1); const Cut kTwoPi0 = (kNumPiZeros == 2 && kNumPiCharged == 0); - const Cut kElsePi = (!kZeroPi && !kOnePiCh && !kOnePi0 + const Cut kElsePi = (!kZeroPi && !kOnePiCh && !kOnePi0 && !kTwoPiCh && !kOneEach && !kTwoPi0); const unsigned int kNumModes = 8; @@ -167,7 +167,7 @@ void event_numbers_finalstate(const std::string expt = "SBND") for(unsigned int k = 0; k < kNumCurrents; k++){ for(unsigned int j = k; j < kNumSigns; j++){ // loop over signs only for CC for(unsigned int i = k; i < kNumFlavours-k; i++){ // loop over flavours only for CC - h[m][k][j][i] = pred[m]->PredictComponent(noosc, k == 0 ? flav[i].flav : Flavors::kAll, + h[m][k][j][i] = pred[m]->PredictComponent(noosc, k == 0 ? flav[i].flav : Flavors::kAll, curr[k].curr, (k == 0) ? sign[j].sign : Sign::kBoth).ToTH1(pot); float nEvts = h[m][k][j][i]->Integral(); std::cout << ", " << nEvts ; @@ -182,7 +182,7 @@ void event_numbers_finalstate(const std::string expt = "SBND") TCanvas* c1 = new TCanvas("c1","c1"); for(unsigned int m = 0; m < kNumModes; m++){ - for(unsigned int k = 0; k < kNumCurrents; k++){ + for(unsigned int k = 0; k < kNumCurrents; k++){ for(unsigned int j = k; j < kNumSigns; j++){ // loop over signs only for CC for(unsigned int i = k; i < kNumFlavours-k; i++){ // loop over flavours only for CC @@ -192,8 +192,8 @@ void event_numbers_finalstate(const std::string expt = "SBND") h[m][k][j][i]->SetLineColor(cuts[m].colour); h[m][k][j][i]->SetMarkerColor(cuts[m].colour); - h[m][k][j][i]->Write((expt+"_"+cuts[m].label+"_"+currLabel+"_"+signLabel+flavLabel).c_str()); - h[m][k][j][i]->SetName((cuts[m].label+"_"+currLabel+"_"+signLabel+flavLabel).c_str()); + h[m][k][j][i]->Write((expt+"_"+cuts[m].label+"_"+currLabel+"_"+signLabel+flavLabel).c_str()); + h[m][k][j][i]->SetName((cuts[m].label+"_"+currLabel+"_"+signLabel+flavLabel).c_str()); h[m][k][j][i]->Draw("hist"); Experiment(expt); c1->SaveAs(("output/"+expt+"_"+cuts[m].label+"_"+currLabel+"_"+signLabel+flavLabel+".pdf").c_str()); diff --git a/sbnana/CAFAna/sbn/fitter_comparisons/event_numbers_nue.C b/sbnana/CAFAna/sbn/fitter_comparisons/event_numbers_nue.C index ab542cbc..dc0788db 100644 --- a/sbnana/CAFAna/sbn/fitter_comparisons/event_numbers_nue.C +++ b/sbnana/CAFAna/sbn/fitter_comparisons/event_numbers_nue.C @@ -3,7 +3,7 @@ #include "sbnana/CAFAna/Core/SpectrumLoader.h" #include "sbnana/CAFAna/Core/Loaders.h" -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "cafanacore/Spectrum.h" #include "sbnana/CAFAna/Core/Binning.h" #include "sbnana/CAFAna/Core/Var.h" @@ -26,7 +26,7 @@ using namespace ana; -// Put an "SBND simulation" tag in the corner +// Put an "SBND simulation" tag in the corner void Experiment(std::string expt) { TLatex* prelim = new TLatex(.9, .95, (expt+" Simulation").c_str()); @@ -126,19 +126,19 @@ void event_numbers_nue(const std::string expt = "SBND") h_numu->SetLineColor(kGreen+2); h_numu->SetMarkerColor(kGreen+2); - h_numu->Write((expt+"_numu").c_str()); + h_numu->Write((expt+"_numu").c_str()); h_NC->SetLineColor(kBlack); h_NC->SetMarkerColor(kBlack); - h_NC->Write((expt+"_NC").c_str()); + h_NC->Write((expt+"_NC").c_str()); h_int->SetLineColor(kRed); h_int->SetMarkerColor(kRed); - h_int->Write((expt+"_int").c_str()); + h_int->Write((expt+"_int").c_str()); h_osc->SetLineColor(kBlue); h_osc->SetMarkerColor(kBlue); - h_osc->Write((expt+"_osc").c_str()); + h_osc->Write((expt+"_osc").c_str()); fOutput->Close(); diff --git a/sbnana/CAFAna/sbn/fitter_comparisons/osc_prob.C b/sbnana/CAFAna/sbn/fitter_comparisons/osc_prob.C index 257afb63..9d9487e1 100644 --- a/sbnana/CAFAna/sbn/fitter_comparisons/osc_prob.C +++ b/sbnana/CAFAna/sbn/fitter_comparisons/osc_prob.C @@ -1,6 +1,6 @@ #include "sbnana/CAFAna/Core/SpectrumLoader.h" #include "sbnana/CAFAna/Core/OscillatableSpectrum.h" -#include "sbnana/CAFAna/Core/Ratio.h" +#include "cafanacore/Ratio.h" #include "sbnana/CAFAna/Core/OscCalcSterileApprox.h" #include "sbnana/CAFAna/Cuts/TruthCuts.h" @@ -13,8 +13,7 @@ using namespace ana; #include "TH2.h" #include "TPad.h" -const Cut kOneNu([](const caf::SRProxy* sr){return sr->truth.size() == 1;}); -const Var kTrueE = SIMPLEVAR(truth[0].neutrino.energy); +const Var kTrueE = SIMPLEVAR(truth.E); const Var kRecoE = SIMPLEVAR(reco.reco_energy); void osc_prob() @@ -22,10 +21,10 @@ void osc_prob() const std::string dir = "/sbnd/data/users/jlarkin/workshop_samples/"; const std::string fnameBeam = dir + "output_SBNOsc_NumuSelection_Modern_SBND.flat.root"; - SpectrumLoader loader(fnameBeam, ana::kBeam); - - OscillatableSpectrum s("True E (GeV)", Binning::Simple(100, .5, 1.5), loader, kTrueE, kOneNu && kIsNumuCC); - OscillatableSpectrum s_reco("Reco E (GeV)", Binning::Simple(100, .5, 1.5), loader, kRecoE, kOneNu && kIsNumuCC); + SpectrumLoader loader(fnameBeam); + + OscillatableSpectrum s(loader.Slices()[kIsNumuCC], HistAxis("True E (GeV)", Binning::Simple(100, .5, 1.5), kTrueE)); + OscillatableSpectrum s_reco(loader.Slices()[kIsNumuCC], HistAxis("Reco E (GeV)", Binning::Simple(100, .5, 1.5), kRecoE)); loader.Go(); diff --git a/sbnana/CAFAna/sbn/sensitivities/allowed.C b/sbnana/CAFAna/sbn/sensitivities/allowed.C index 9571e9b2..57610928 100644 --- a/sbnana/CAFAna/sbn/sensitivities/allowed.C +++ b/sbnana/CAFAna/sbn/sensitivities/allowed.C @@ -1,9 +1,8 @@ +#include "sbnana/CAFAna/Prediction/PredictionInterp.h" #include "sbnana/CAFAna/Core/LoadFromFile.h" #include "sbnana/CAFAna/Core/OscCalcSterileApprox.h" #include "sbnana/CAFAna/Vars/FitVarsSterileApprox.h" -#include "sbnana/CAFAna/Prediction/PredictionInterp.h" #include "sbnana/CAFAna/Experiment/SingleSampleExperiment.h" -#include "sbnana/CAFAna/Experiment/MultiExperimentSBN.h" #include "sbnana/CAFAna/Experiment/CountingExperiment.h" #include "sbnana/CAFAna/Analysis/ExpInfo.h" #include "sbnana/CAFAna/Analysis/Surface.h" @@ -28,19 +27,19 @@ const double uboonePOT = 1.3e21; void allowed() { - TFile fin("surfaces.root"); + TFile fin("surfaces.root"); + + Surface& surf_syst_nd = *ana::LoadFrom(&fin, "allowed/nd_prop_systs").release(); + Surface& surf_syst_fd = *ana::LoadFrom(&fin, "allowed/fd_prop_systs").release(); + Surface& surf_syst_ub = *ana::LoadFrom(&fin, "allowed/ub_prop_systs").release(); + Surface& surf_syst_nd_fd = *ana::LoadFrom(&fin, "allowed/nd_fd_prop_systs").release(); + Surface& surf_syst_all = *ana::LoadFrom(&fin, "allowed/allexpt_prop_systs").release(); - Surface& surf_syst_nd = *ana::LoadFrom(fin.GetDirectory("allowed/nd_prop_systs")).release(); - Surface& surf_syst_fd = *ana::LoadFrom(fin.GetDirectory("allowed/fd_prop_systs")).release(); - Surface& surf_syst_ub = *ana::LoadFrom(fin.GetDirectory("allowed/ub_prop_systs")).release(); - Surface& surf_syst_nd_fd = *ana::LoadFrom(fin.GetDirectory("allowed/nd_fd_prop_systs")).release(); - Surface& surf_syst_all = *ana::LoadFrom(fin.GetDirectory("allowed/allexpt_prop_systs")).release(); - - Surface& surf_nom_nd = *ana::LoadFrom(fin.GetDirectory("allowed/nom_nd")).release(); - Surface& surf_nom_ub = *ana::LoadFrom(fin.GetDirectory("allowed/nom_ub")).release(); - Surface& surf_nom_fd = *ana::LoadFrom(fin.GetDirectory("allowed/nom_fd")).release(); - Surface& surf_nom_nd_fd = *ana::LoadFrom(fin.GetDirectory("allowed/nom_nd_fd")).release(); - Surface& surf_nom = *ana::LoadFrom(fin.GetDirectory("allowed/nom")).release(); + Surface& surf_nom_nd = *ana::LoadFrom(&fin, "allowed/nom_nd").release(); + Surface& surf_nom_ub = *ana::LoadFrom(&fin, "allowed/nom_ub").release(); + Surface& surf_nom_fd = *ana::LoadFrom(&fin, "allowed/nom_fd").release(); + Surface& surf_nom_nd_fd = *ana::LoadFrom(&fin, "allowed/nom_nd_fd").release(); + Surface& surf_nom = *ana::LoadFrom(&fin, "allowed/nom").release(); TH2* crit5sig = Gaussian5Sigma2D(surf_nom); TH2* crit3sig = Gaussian3Sigma2D(surf_nom); @@ -49,7 +48,7 @@ void allowed() TH2* crit99 = Gaussian99Percent2D(surf_nom); surf_nom.SetTitle("3 Sigma Allowed Regions"); - + surf_nom.DrawContour(crit3sig, 7, kBlack); surf_nom_nd_fd.DrawContour(crit3sig, 7, kMagenta); surf_nom_nd.DrawContour(crit3sig,7,kRed); @@ -61,7 +60,7 @@ void allowed() surf_syst_ub.DrawContour(crit3sig, kSolid, kGreen); surf_syst_fd.DrawContour(crit3sig, kSolid, kBlue); surf_syst_nd_fd.DrawContour(crit3sig, kSolid, kMagenta); - + TLegend * lgdis = new TLegend(0.11,0.11,0.3,0.3); lgdis->SetFillColor(0); lgdis->SetBorderSize(0); @@ -83,7 +82,7 @@ void allowed() gPad->Print("allowed_3sig.pdf"); // TFile fout("allowed_graphs.root", "RECREATE"); -// +// // std::vector surfaces {surf_nom, surf_nom_nd, surf_nom_ub, surf_nom_fd, surf_nom_nd_fd, surf_syst_all, surf_syst_nd, surf_syst_ub, surf_syst_fd, surf_syst_nd_fd}; // // std::vector con_lev {crit90, crit95, crit99, crit3sig, crit5sig}; @@ -91,12 +90,12 @@ void allowed() // std::vector s_name {"all_stat", "nd_stat", "ub_stat", "fd_stat", "nd_fd_stat", "all_syst", "nd_syst", "ub_syst", "fd_syst", "nd_fd_syst"}; // // std::vector c_name {"_90pct", "_95pct", "_99pct", "_3sig", "_5sig"}; -// +// // std::cout<<"Before Loop"<(fin.GetDirectory("exclusion/nd_prop_systs")).release(); - //Surface& surf_syst_fd = *ana::LoadFrom(fin.GetDirectory("exclusion/fd_prop_systs")).release(); - //Surface& surf_syst_ub = *ana::LoadFrom(fin.GetDirectory("exclusion/ub_prop_systs")).release(); - Surface& surf_syst_nd_fd = *ana::LoadFrom(fin.GetDirectory("exclusion/nd_fd_prop_systs")).release(); - //Surface& surf_syst_all = *ana::LoadFrom(fin.GetDirectory("exclusion/allexpt_prop_systs")).release(); + //Surface& surf_syst_nd = *ana::LoadFrom(&fin, "exclusion/nd_prop_systs").release(); + //Surface& surf_syst_fd = *ana::LoadFrom(&fin, "exclusion/fd_prop_systs").release(); + //Surface& surf_syst_ub = *ana::LoadFrom(&fin, "exclusion/ub_prop_systs").release(); + Surface& surf_syst_nd_fd = *ana::LoadFrom(&fin, "exclusion/nd_fd_prop_systs").release(); + //Surface& surf_syst_all = *ana::LoadFrom(&fin, "exclusion/allexpt_prop_systs").release(); - //Surface& surf_nom_nd = *ana::LoadFrom(fin.GetDirectory("exclusion/nom_nd")).release(); - //Surface& surf_nom_ub = *ana::LoadFrom(fin.GetDirectory("exclusion/nom_ub")).release(); - //Surface& surf_nom_fd = *ana::LoadFrom(fin.GetDirectory("exclusion/nom_fd")).release(); - Surface& surf_nom_nd_fd = *ana::LoadFrom(fin.GetDirectory("exclusion/nom_nd_fd")).release(); - //Surface& surf_nom = *ana::LoadFrom(fin.GetDirectory("exclusion/nom")).release(); + //Surface& surf_nom_nd = *ana::LoadFrom(&fin, "exclusion/nom_nd").release(); + //Surface& surf_nom_ub = *ana::LoadFrom(&fin, "exclusion/nom_ub").release(); + //Surface& surf_nom_fd = *ana::LoadFrom(&fin, "exclusion/nom_fd").release(); + Surface& surf_nom_nd_fd = *ana::LoadFrom(&fin, "exclusion/nom_nd_fd").release(); + //Surface& surf_nom = *ana::LoadFrom(&fin, "exclusion/nom").release(); TGraph * proposal_90pctCL = (TGraph *) fprop.Get( "lim_dis_3p1_sbnproposal_90pctCL" ); TGraph * proposal_3sigCL = (TGraph *) fprop.Get( "lim_dis_3p1_sbnproposal_3sigCL" ); @@ -74,7 +73,7 @@ void exclusion(const std::string anatype = numuStr) TH2* crit99 = Gaussian99Percent1D1Sided(surf_nom_nd_fd); //surf_nom.SetTitle("90% Exclusion"); - + //surf_nom.DrawContour(crit90, 7, kBlack); surf_nom_nd_fd.DrawContour(crit90, 7, kMagenta); //surf_nom_nd.DrawContour(crit90,7,kRed); @@ -86,7 +85,7 @@ void exclusion(const std::string anatype = numuStr) //surf_syst_ub.DrawContour(crit90, kSolid, kGreen+3); //surf_syst_fd.DrawContour(crit90, kSolid, kBlue); surf_syst_nd_fd.DrawContour(crit90, kSolid, kMagenta); - + //proposal_90pctCL->SetLineColor(kGreen); //proposal_90pctCL->Draw("l"); //minosp_90pctCL->SetLineColor(kCyan); @@ -118,13 +117,13 @@ void exclusion(const std::string anatype = numuStr) gPad->Print(name_out); // TFile fout("exclusion_graphs.root", "RECREATE"); -// +// // std::vector graph_nd_fd_90 = surf_nom_nd_fd.GetGraphs(crit90); // std::vector graph_nd_fd_95 = surf_nom_nd_fd.GetGraphs(crit95); // std::vector graph_nd_fd_99 = surf_nom_nd_fd.GetGraphs(crit99); // std::vector graph_nd_fd_3s = surf_nom_nd_fd.GetGraphs(crit3sig); // std::vector graph_nd_fd_5s = surf_nom_nd_fd.GetGraphs(crit5sig); -// +// // std::vector surfaces {surf_nom, surf_nom_nd, surf_nom_ub, surf_nom_fd, surf_nom_nd_fd, surf_syst_all, surf_syst_nd, surf_syst_ub, surf_syst_fd, surf_syst_nd_fd}; // // std::vector con_lev {crit90, crit95, crit99, crit3sig, crit5sig}; @@ -132,9 +131,9 @@ void exclusion(const std::string anatype = numuStr) // std::vector s_name {"all_stat", "nd_stat", "ub_stat", "fd_stat", "nd_fd_stat", "all_syst", "nd_syst", "ub_syst", "fd_syst", "nd_fd_syst"}; // // std::vector c_name {"_90pct", "_95pct", "_99pct", "_3sig", "_5sig"}; -// +// // std::cout<<"Before Loop"<truth[0].neutrino.iscc << " " << sr->truth[0].neutrino.pdg << " " << sr->reco.weight << std::endl; + std::cout << sr->truth[0].neutrino.iscc << " " << sr->truth[0].neutrino.pdg << " " << sr->reco.weight << std::endl; if (sr->truth[0].neutrino.iscc && sr->truth[0].neutrino.pdg == 12) return 0.8; if (sr->truth[0].neutrino.iscc && sr->truth[0].neutrino.pdg == 14) return 0.0058; if (sr->truth[0].neutrino.isnc) return 0.058; @@ -228,11 +228,11 @@ void make_state(const std::string anatype = numuStr) TFile fout(("cafe_state_smear_"+anatype+".root").c_str(), "RECREATE"); for(unsigned int i = 0; i < systWs.size(); ++i){ - preds_nd[i]->SaveTo(fout.mkdir(TString::Format("pred_nd_%s_%d", anatype.c_str(), i).Data())); - preds_fd[i]->SaveTo(fout.mkdir(TString::Format("pred_fd_%s_%d", anatype.c_str(), i).Data())); + preds_nd[i]->SaveTo(&fout, TString::Format("pred_nd_%s_%d", anatype.c_str(), i).Data()); + preds_fd[i]->SaveTo(&fout, TString::Format("pred_fd_%s_%d", anatype.c_str(), i).Data()); } - pred_nom_nd.SaveTo(fout.mkdir(TString::Format("pred_nd_%s_nom", anatype.c_str()).Data())); - pred_nom_fd.SaveTo(fout.mkdir(TString::Format("pred_fd_%s_nom", anatype.c_str()).Data())); + pred_nom_nd.SaveTo(&fout, TString::Format("pred_nd_%s_nom", anatype.c_str()).Data()); + pred_nom_fd.SaveTo(&fout, TString::Format("pred_fd_%s_nom", anatype.c_str()).Data()); } diff --git a/sbnana/CAFAna/sbn/sensitivities/make_state_extrap.C b/sbnana/CAFAna/sbn/sensitivities/make_state_extrap.C index ec3b48b5..8246dad0 100644 --- a/sbnana/CAFAna/sbn/sensitivities/make_state_extrap.C +++ b/sbnana/CAFAna/sbn/sensitivities/make_state_extrap.C @@ -1,5 +1,5 @@ #include "sbnana/CAFAna/Core/SpectrumLoader.h" -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "cafanacore/Spectrum.h" #include "sbnana/CAFAna/Core/Binning.h" #include "sbnana/CAFAna/Core/Var.h" #include "sbnana/CAFAna/Cuts/TruthCuts.h" @@ -54,6 +54,6 @@ void make_state_extrap() std::cout << "Creating file " << "cafe_state_extrap.root" << std::endl; TFile fout("cafe_state_extrap.root", "RECREATE"); - pred.SaveTo(fout.mkdir("pred")); - predND.SaveTo(fout.mkdir("predND")); + pred.SaveTo(&fout, "pred"); + predND.SaveTo(&fout, "predND"); } diff --git a/sbnana/CAFAna/sbn/sensitivities/make_state_extrap_syst.C b/sbnana/CAFAna/sbn/sensitivities/make_state_extrap_syst.C index 5f643703..a604ab27 100644 --- a/sbnana/CAFAna/sbn/sensitivities/make_state_extrap_syst.C +++ b/sbnana/CAFAna/sbn/sensitivities/make_state_extrap_syst.C @@ -1,5 +1,5 @@ #include "sbnana/CAFAna/Core/SpectrumLoader.h" -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "cafanacore/Spectrum.h" #include "sbnana/CAFAna/Core/Binning.h" #include "sbnana/CAFAna/Core/Var.h" #include "sbnana/CAFAna/Cuts/TruthCuts.h" @@ -74,8 +74,8 @@ void make_state_extrap_syst() std::cout << "Creating file " << "cafe_state_extrap.root" << std::endl; TFile fout("cafe_state_extrap_syst.root", "RECREATE"); - pred.SaveTo(fout.mkdir("pred")); - predInterp.SaveTo(fout.mkdir("pred_syst")); - predND.SaveTo(fout.mkdir("predND")); - predNDInterp.SaveTo(fout.mkdir("predND_syst")); + pred.SaveTo(&fout, "pred"); + predInterp.SaveTo(&fout, "pred_syst"); + predND.SaveTo(&fout, "predND"); + predNDInterp.SaveTo(&fout, "predND_syst"); } diff --git a/sbnana/CAFAna/sbn/sensitivities/make_state_syst.C b/sbnana/CAFAna/sbn/sensitivities/make_state_syst.C index 32f75f34..766534c4 100644 --- a/sbnana/CAFAna/sbn/sensitivities/make_state_syst.C +++ b/sbnana/CAFAna/sbn/sensitivities/make_state_syst.C @@ -1,5 +1,5 @@ #include "sbnana/CAFAna/Core/SpectrumLoader.h" -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "cafanacore/Spectrum.h" #include "sbnana/CAFAna/Core/Binning.h" #include "sbnana/CAFAna/Core/Var.h" #include "sbnana/CAFAna/Cuts/TruthCuts.h" @@ -111,9 +111,9 @@ void make_state_syst(const std::string anatype = numuStr) TFile fout(("cafe_state_syst_"+anatype+".root").c_str(), "RECREATE"); - pred_nd.SaveTo(fout.mkdir("pred_nd")); - pred_fd.SaveTo(fout.mkdir("pred_fd")); - pred_ub.SaveTo(fout.mkdir("pred_ub")); + pred_nd.SaveTo(&fout, "pred_nd"); + pred_fd.SaveTo(&fout, "pred_fd"); + pred_ub.SaveTo(&fout, "pred_ub"); } diff --git a/sbnana/CAFAna/sbn/sensitivities/make_surfaces.C b/sbnana/CAFAna/sbn/sensitivities/make_surfaces.C index 01d4f46d..2257630e 100644 --- a/sbnana/CAFAna/sbn/sensitivities/make_surfaces.C +++ b/sbnana/CAFAna/sbn/sensitivities/make_surfaces.C @@ -1,10 +1,10 @@ +#include "sbnana/CAFAna/Prediction/PredictionInterp.h" #include "sbnana/CAFAna/Core/LoadFromFile.h" #include "sbnana/CAFAna/Core/OscCalcSterileApprox.h" #include "sbnana/CAFAna/Vars/FitVarsSterileApprox.h" -#include "sbnana/CAFAna/Prediction/PredictionInterp.h" #include "sbnana/CAFAna/Experiment/SingleSampleExperiment.h" -#include "sbnana/CAFAna/Experiment/MultiExperimentSBN.h" #include "sbnana/CAFAna/Experiment/CountingExperiment.h" +#include "sbnana/CAFAna/Experiment/MultiExperiment.h" #include "sbnana/CAFAna/Analysis/ExpInfo.h" #include "sbnana/CAFAna/Analysis/Surface.h" #include "sbnana/CAFAna/Systs/SBNWeightSysts.h" @@ -40,7 +40,7 @@ void make_surfaces(const std::string anatype = numuStr) auto systs_flux = GetBoosterFluxWeightSysts(); auto systs_genie = GetSBNGenieWeightSysts(); - + std::vector systs_to_process; std::vector syst_names{"expskin_FluxUnisim","horncurrent_FluxUnisim","kminus_PrimaryHadronNormalization","kplus_PrimaryHadronFeynmanScaling","kzero_PrimaryHadronSanfordWang","nucleoninexsec_FluxUnisim","nucleonqexsec_FluxUnisim","nucleontotxsec_FluxUnisim","piminus_PrimaryHadronSWCentralSplineVariation","pioninexsec_FluxUnisim","pionqexsec_FluxUnisim","piontotxsec_FluxUnisim","piplus_PrimaryHadronSWCentralSplineVariation","genie_ccresAxial_Genie","genie_ncresAxial_Genie","genie_qema_Genie","genie_NC_Genie","genie_NonResRvbarp1pi_Genie","genie_NonResRvbarp2pi_Genie","genie_NonResRvp1pi_Genie","genie_NonResRvp2pi_Genie","genie_NonResRvbarp1piAlt_Genie","genie_NonResRvbarp2piAlt_Genie","genie_NonResRvp1piAlt_Genie","genie_NonResRvp2piAlt_Genie"}; @@ -67,26 +67,23 @@ void make_surfaces(const std::string anatype = numuStr) TFile fin(name_in); TFile fout(name_out,"RECREATE"); - PredictionInterp* p_nd = LoadFrom(fin.GetDirectory("pred_nd")).release(); - PredictionInterp* p_fd = LoadFrom(fin.GetDirectory("pred_fd")).release(); - PredictionInterp* p_ub = LoadFrom(fin.GetDirectory("pred_ub")).release(); + PredictionInterp* p_nd = LoadFrom(&fin, "pred_nd").release(); + PredictionInterp* p_fd = LoadFrom(&fin, "pred_fd").release(); + PredictionInterp* p_ub = LoadFrom(&fin, "pred_ub").release(); OscCalcSterileApproxAdjustable* calc = DefaultSterileApproxCalc(); OscCalcSterileApproxAdjustable* seed = DefaultSterileApproxCalc(); //JL - try different values here, how much does it matter what values we choose, does this - //have any impact on disappearance? + //have any impact on disappearance? if (anatype == nueStr) { seed->calc.SetSinSq2ThetaMuE(1e-2); seed->calc.SetDmsq(1); - seed->SetL(kBaselineSBND); p_nd->SetOscSeed(seed); - seed->SetL(kBaselineIcarus); p_fd->SetOscSeed(seed); - seed->SetL(kBaselineMicroBoone); p_ub->SetOscSeed(seed); } - + //Define fit axes @@ -115,26 +112,19 @@ void make_surfaces(const std::string anatype = numuStr) SingleSampleExperiment expt_fd(p_fd, data_fd); SingleSampleExperiment expt_ub(p_ub, data_ub); - MultiExperimentSBN multiExpt({&expt_nd, &expt_fd, &expt_ub}, {kSBND, kICARUS, kMicroBoone}); - MultiExperimentSBN fd_nd({&expt_nd, &expt_fd}, {kSBND, kICARUS}); + MultiExperiment multiExpt({&expt_nd, &expt_fd, &expt_ub}); + MultiExperiment fd_nd({&expt_nd, &expt_fd}); - //Surface surf_nom(&multiExpt, calc, kAxForTh, kAxDmSq); Surface surf_nd_fd(&fd_nd, calc, kAxForTh, kAxDmSq); - calc->SetL(kBaselineSBND); - //Surface surf_nom_nd(&expt_nd, calc, kAxForTh, kAxDmSq); - calc->SetL(kBaselineIcarus); - //Surface surf_nom_fd(&expt_fd, calc, kAxForTh, kAxDmSq); - calc->SetL(kBaselineMicroBoone); - //Surface surf_nom_ub(&expt_ub, calc, kAxForTh, kAxDmSq); fout.mkdir("exclusion"); - fout.cd("exclusion"); + fout.cd("exclusion"); - //surf_nom.SaveTo(gDirectory->mkdir("nom")); - //surf_nom_nd.SaveTo(gDirectory->mkdir("nom_nd")); - //surf_nom_fd.SaveTo(gDirectory->mkdir("nom_fd")); - //surf_nom_ub.SaveTo(gDirectory->mkdir("nom_ub")); - surf_nd_fd.SaveTo(gDirectory->mkdir("nom_nd_fd")); + //surf_nom.SaveTo(gDirectory, "nom"); + //surf_nom_nd.SaveTo(gDirectory, "nom_nd"); + //surf_nom_fd.SaveTo(gDirectory, "nom_fd"); + //surf_nom_ub.SaveTo(gDirectory, "nom_ub"); + surf_nd_fd.SaveTo(gDirectory, "nom_nd_fd"); std::vector> slists; //slists.emplace_back(1, systs[0]); @@ -152,11 +142,11 @@ void make_surfaces(const std::string anatype = numuStr) std::string suffix = "prop_systs"; - //surf_syst_nd.SaveTo(gDirectory->mkdir(("nd_"+suffix).c_str())); - //surf_syst_fd.SaveTo(gDirectory->mkdir(("fd_"+suffix).c_str())); - //surf_syst_ub.SaveTo(gDirectory->mkdir(("ub_"+suffix).c_str())); - //surf_syst.SaveTo(gDirectory->mkdir(("allexpt_"+suffix).c_str())); - surf_syst_nd_fd.SaveTo(gDirectory->mkdir(("nd_fd_"+suffix).c_str())); + //surf_syst_nd.SaveTo(gDirectory, "nd_"+suffix); + //surf_syst_fd.SaveTo(gDirectory, "fd_"+suffix); + //surf_syst_ub.SaveTo(gDirectory, "ub_"+suffix); + //surf_syst.SaveTo(gDirectory, "allexpt_"+suffix); + surf_syst_nd_fd.SaveTo(gDirectory, "nd_fd_"+suffix); } // end for s @@ -185,45 +175,39 @@ void make_surfaces(const std::string anatype = numuStr) SingleSampleExperiment expt_fd2(p_fd, data_fd2); SingleSampleExperiment expt_ub2(p_ub, data_ub2); - MultiExperimentSBN multiExpt2({&expt_nd2, &expt_fd2, &expt_ub2}, {kSBND, kICARUS, kMicroBoone}); - MultiExperimentSBN fd_nd2({&expt_nd2, &expt_fd2}, {kSBND, kICARUS}); + MultiExperiment multiExpt2({&expt_nd2, &expt_fd2, &expt_ub2}); + MultiExperiment fd_nd2({&expt_nd2, &expt_fd2}); //Surface surf_nom2(&multiExpt2, calc2, kAxForTh, kAxDmSq); //Surface surf_nd_fd2(&fd_nd2, calc2, kAxForTh, kAxDmSq); - calc2->SetL(kBaselineSBND); //Surface surf_nom_nd2(&expt_nd2, calc2, kAxForTh, kAxDmSq); - calc2->SetL(kBaselineIcarus); //Surface surf_nom_fd2(&expt_fd2, calc2, kAxForTh, kAxDmSq); - calc2->SetL(kBaselineMicroBoone); //Surface surf_nom_ub2(&expt_ub2, calc2, kAxForTh, kAxDmSq); - + //fout.cd(".."); //fout.mkdir("allowed"); //fout.cd("allowed"); - //surf_nom2.SaveTo(gDirectory->mkdir("nom")); - //surf_nom_nd2.SaveTo(gDirectory->mkdir("nom_nd")); - //surf_nom_fd2.SaveTo(gDirectory->mkdir("nom_fd")); - //surf_nom_ub2.SaveTo(gDirectory->mkdir("nom_ub")); - //surf_nd_fd2.SaveTo(gDirectory->mkdir("nom_nd_fd")); + //surf_nom2.SaveTo(gDirectory, "nom"); + //surf_nom_nd2.SaveTo(gDirectory, "nom_nd"); + //surf_nom_fd2.SaveTo(gDirectory, "nom_fd"); + //surf_nom_ub2.SaveTo(gDirectory, "nom_ub"); + //surf_nd_fd2.SaveTo(gDirectory, "nom_nd_fd"); for(const std::vector slist: slists){ //Surface surf_syst2(&multiExpt2, calc2, kAxForTh, kAxDmSq, {}, slist); //Surface surf_syst_nd_fd2(&fd_nd2, calc2, kAxForTh, kAxDmSq, {}, slist); - calc2->SetL(kBaselineSBND); //Surface surf_syst_nd2(&expt_nd2, calc2, kAxForTh, kAxDmSq, {}, slist); - calc2->SetL(kBaselineIcarus); //Surface surf_syst_fd2(&expt_fd2, calc2, kAxForTh, kAxDmSq, {}, slist); - calc2->SetL(kBaselineMicroBoone); //Surface surf_syst_ub2(&expt_ub2, calc2, kAxForTh, kAxDmSq, {}, slist); std::string suffix = "prop_systs"; - //surf_syst_nd2.SaveTo(gDirectory->mkdir(("nd_"+suffix).c_str())); - //surf_syst_fd2.SaveTo(gDirectory->mkdir(("fd_"+suffix).c_str())); - //surf_syst_ub2.SaveTo(gDirectory->mkdir(("ub_"+suffix).c_str())); - //surf_syst2.SaveTo(gDirectory->mkdir(("allexpt_"+suffix).c_str())); - //surf_syst_nd_fd2.SaveTo(gDirectory->mkdir(("nd_fd_"+suffix).c_str())); + //surf_syst_nd2.SaveTo(gDirectory, "nd_"+suffix); + //surf_syst_fd2.SaveTo(gDirectory, "fd_"+suffix); + //surf_syst_ub2.SaveTo(gDirectory, "ub_"+suffix); + //surf_syst2.SaveTo(gDirectory, "allexpt_"+suffix); + //surf_syst_nd_fd2.SaveTo(gDirectory, "nd_fd_"+suffix); } // end for s } diff --git a/sbnana/CAFAna/sbn/sensitivities/nus.C b/sbnana/CAFAna/sbn/sensitivities/nus.C index 7a597437..071c4b0a 100644 --- a/sbnana/CAFAna/sbn/sensitivities/nus.C +++ b/sbnana/CAFAna/sbn/sensitivities/nus.C @@ -1,5 +1,5 @@ #include "sbnana/CAFAna/Core/SpectrumLoader.h" -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "cafanacore/Spectrum.h" #include "sbnana/CAFAna/Core/Binning.h" #include "sbnana/CAFAna/Core/Var.h" #include "sbnana/CAFAna/Cuts/TruthCuts.h" @@ -7,7 +7,7 @@ #include "sbnana/CAFAna/Prediction/PredictionInterp.h" #include "sbnana/CAFAna/Analysis/Calcs.h" #include "OscLib/OscCalcSterile.h" -#include "sbnana/CAFAna/StandardRecord/StandardRecord.h" +#include "sbnanaobj/StandardRecord/StandardRecord.h" #include "sbnana/CAFAna/Vars/FitVarsSterile.h" #include "sbnana/CAFAna/Analysis/FitAxis.h" @@ -22,7 +22,6 @@ #include "sbnana/CAFAna/Analysis/MedianSurface.h" #include "sbnana/CAFAna/Experiment/SingleSampleExperiment.h" #include "sbnana/CAFAna/Experiment/MultiExperiment.h" -#include "sbnana/CAFAna/Experiment/MultiExperimentSBN.h" #include "sbnana/CAFAna/Experiment/GaussianConstraint.h" #include "sbnana/CAFAna/Analysis/ExpInfo.h" @@ -50,14 +49,13 @@ void nus(const char* stateFname = basicFname, int nmock = 0, bool useSysts = tru return; } - std::cout << "Loading state from " << stateFname << std::endl; + std::cout << "Loading state from " << stateFname << std::endl; TFile fin(stateFname); - PredictionInterp& pred_nd_numu = *ana::LoadFrom(fin.GetDirectory("pred_nd_numu")).release(); - PredictionInterp& pred_fd_numu = *ana::LoadFrom(fin.GetDirectory("pred_fd_numu")).release(); + PredictionInterp& pred_nd_numu = *ana::LoadFrom(&fin, "pred_nd_numu").release(); + PredictionInterp& pred_fd_numu = *ana::LoadFrom(&fin, "pred_fd_numu").release(); // Calculator OscCalcSterileApproxAdjustable* calc = DefaultSterileApproxCalc(); - calc->SetL(kBaselineSBND); // To make a fit we need to have a "data" spectrum to compare to our MC // Prediction object @@ -79,7 +77,7 @@ void nus(const char* stateFname = basicFname, int nmock = 0, bool useSysts = tru {}, allSysts); - surf.SaveTo(fOutput->mkdir("surf")); + surf.SaveTo(fOutput, "surf"); TCanvas* c1 = new TCanvas("c1"); c1->SetLeftMargin(0.12); @@ -99,15 +97,15 @@ void nus(const char* stateFname = basicFname, int nmock = 0, bool useSysts = tru const Spectrum data2 = pred_fd_numu.Predict(calc).FakeData(icarusPOT); SingleSampleExperiment expt2(&pred_fd_numu, data2); - MultiExperimentSBN multiExpt({&expt, &expt2}, {kSBND,kICARUS}); + MultiExperiment multiExpt({&expt, &expt2}); Surface surf2(&expt2, calc, kAxSinSq2ThetaMuMu, kAxDmSq, {}, allSysts); - - surf2.SaveTo(fOutput->mkdir("surf2")); + + surf2.SaveTo(fOutput, "surf2"); c1->Clear(); // just in case @@ -130,13 +128,11 @@ void nus(const char* stateFname = basicFname, int nmock = 0, bool useSysts = tru const FitAxis kCoarseAxDmSq(&kFitDmSqSterile, 20, 2e-2, 100, true); osc::IOscCalcAdjustable* c = DefaultSterileApproxCalc(); - c->SetL(kBaselineSBND); SingleSampleExperiment e1(&pred_nd_numu, pred_nd_numu.Predict(c).MockData(sbndPOT)); - c->SetL(kBaselineIcarus); // Icarus SingleSampleExperiment e2(&pred_fd_numu, pred_fd_numu.Predict(c).MockData(icarusPOT)); - MultiExperimentSBN me({&e1, &e2}, {kSBND, kICARUS}); + MultiExperiment me({&e1, &e2}); Surface ms(&me, c, kCoarseAxSinSq2ThetaMuMu, @@ -147,14 +143,14 @@ void nus(const char* stateFname = basicFname, int nmock = 0, bool useSysts = tru mockSurfs.push_back(ms); } - surfMulti.SaveTo(fOutput->mkdir("surfMulti")); + surfMulti.SaveTo(fOutput, "surfMulti"); c1->Clear(); // just in case TH2* crit2sigMulti = Gaussian3Sigma1D1Sided(surfMulti); surfMulti.DrawContour(crit2sigMulti, kSolid, kRed); - + c1->SaveAs(useSysts ? "nus_BOTH.pdf" : "nus_BOTH_statsOnly.pdf"); c1->Clear(); @@ -165,7 +161,7 @@ void nus(const char* stateFname = basicFname, int nmock = 0, bool useSysts = tru ms.DrawEnsemble(crit2); ms.DrawContour(crit2, kSolid, kRed); - ms.SaveTo(fOutput->mkdir("median_surf")); + ms.SaveTo(fOutput, "median_surf"); } surfMulti.DrawContour(crit2sigMulti, nmock > 0 ? 7 : kSolid, kRed); diff --git a/sbnana/CAFAna/sbn/sensitivities/nus_extrap.C b/sbnana/CAFAna/sbn/sensitivities/nus_extrap.C index c8c021e6..c2d96620 100644 --- a/sbnana/CAFAna/sbn/sensitivities/nus_extrap.C +++ b/sbnana/CAFAna/sbn/sensitivities/nus_extrap.C @@ -1,5 +1,5 @@ #include "sbnana/CAFAna/Core/SpectrumLoader.h" -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "cafanacore/Spectrum.h" #include "sbnana/CAFAna/Core/Binning.h" #include "sbnana/CAFAna/Core/Var.h" #include "sbnana/CAFAna/Cuts/TruthCuts.h" @@ -14,7 +14,7 @@ #include "sbnana/CAFAna/Analysis/Surface.h" #include "sbnana/CAFAna/Experiment/SingleSampleExperiment.h" -#include "sbnana/CAFAna/Experiment/MultiExperimentSBN.h" +#include "sbnana/CAFAna/Experiment/MultiExperiment.h" #include "sbnana/CAFAna/Experiment/CountingExperiment.h" #include "sbnana/CAFAna/Analysis/ExpInfo.h" @@ -48,10 +48,10 @@ void nus_extrap(const char* stateFname = basicFname) // But only use the first 10 of them for(const ISyst* s: GetBoosterFluxHadronSysts(10)) systs.push_back(s); - std::cout << "Loading state from " << stateFname << std::endl; + std::cout << "Loading state from " << stateFname << std::endl; TFile fin(stateFname); - IPrediction* pred = ana::LoadFrom(fin.GetDirectory("pred_syst")).release(); - IPrediction* predND = ana::LoadFrom(fin.GetDirectory("predND_syst")).release(); + IPrediction* pred = ana::LoadFrom(&fin, "pred_syst").release(); + IPrediction* predND = ana::LoadFrom(&fin, "predND_syst").release(); // Calculator OscCalcSterileApproxAdjustable* calc = DefaultSterileApproxCalc(); @@ -60,15 +60,13 @@ void nus_extrap(const char* stateFname = basicFname) // To make a fit we need to have a "data" spectrum to compare to our MC // Prediction object - calc->SetL(kBaselineIcarus); const Spectrum data = pred->Predict(calc).FakeData(icarusPOT); SingleSampleExperiment expt(pred, data); - calc->SetL(kBaselineSBND); const Spectrum dataND = predND->Predict(calc).FakeData(sbndPOT); CountingExperiment exptCount(predND, dataND); - MultiExperimentSBN multiExpt({&expt, &exptCount}, {kICARUS, kSBND}); + MultiExperiment multiExpt({&expt, &exptCount}); //Define fit axes const FitAxis kAxSinSq2ThetaMuMu(&kFitSinSq2ThetaMuMu, 40, 1e-3, 1, true); @@ -90,7 +88,6 @@ void nus_extrap(const char* stateFname = basicFname) kAxSinSq2ThetaMuMu, kAxDmSq); - calc->SetL(kBaselineSBND); Surface surfCount(&exptCount, calc, kAxSinSq2ThetaMuMuCoarse, kAxDmSqCoarse, diff --git a/sbnana/CAFAna/sbn/sensitivities/plot_multi.C b/sbnana/CAFAna/sbn/sensitivities/plot_multi.C index 70d0ea53..bea90289 100644 --- a/sbnana/CAFAna/sbn/sensitivities/plot_multi.C +++ b/sbnana/CAFAna/sbn/sensitivities/plot_multi.C @@ -1,10 +1,10 @@ #include "sbnana/CAFAna/Core/LoadFromFile.h" -#include "sbnana/CAFAna/Core/Ratio.h" +#include "cafanacore/Ratio.h" #include "sbnana/CAFAna/Core/OscCalcSterileApprox.h" #include "sbnana/CAFAna/Vars/FitVarsSterileApprox.h" #include "sbnana/CAFAna/Prediction/PredictionInterp.h" #include "sbnana/CAFAna/Experiment/SingleSampleExperiment.h" -#include "sbnana/CAFAna/Experiment/MultiExperimentSBN.h" +#include "sbnana/CAFAna/Experiment/MultiExperiment.h" #include "sbnana/CAFAna/Experiment/RatioExperiment.h" #include "sbnana/CAFAna/Experiment/CountingExperiment.h" #include "sbnana/CAFAna/Analysis/ExpInfo.h" @@ -67,12 +67,12 @@ void plot_multi() std::vector preds_nd(Nuniv), preds_fd(Nuniv); for(int i = 0; i < Nuniv; ++i){ - preds_nd[i] = LoadFrom(fin.GetDirectory(TString::Format("pred_nd_numu_%d", i).Data())).release(); - preds_fd[i] = LoadFrom(fin.GetDirectory(TString::Format("pred_fd_numu_%d", i).Data())).release(); + preds_nd[i] = LoadFrom(&fin, TString::Format("pred_nd_numu_%d", i).Data()).release(); + preds_fd[i] = LoadFrom(&fin, TString::Format("pred_fd_numu_%d", i).Data()).release(); } - PredictionInterp* nom_nd = LoadFrom(fin.GetDirectory("pred_nd_numu_nom")).release(); - PredictionInterp* nom_fd = LoadFrom(fin.GetDirectory("pred_fd_numu_nom")).release(); + PredictionInterp* nom_nd = LoadFrom(&fin, "pred_nd_numu_nom").release(); + PredictionInterp* nom_fd = LoadFrom(&fin, "pred_fd_numu_nom").release(); // osc::NoOscillations calc; OscCalcSterileApproxAdjustable* calc = DefaultSterileApproxCalc(); @@ -109,9 +109,7 @@ void plot_multi() const FitAxis kAxDmSq(&kFitDmSqSterile, 15/*40*/, 2e-2, 1e2, true); // We'll call zero nominal - calc->SetL(kBaselineSBND); const Spectrum data_nd = nom_nd->Predict(calc).FakeData(sbndPOT); - calc->SetL(kBaselineIcarus); const Spectrum data_fd = nom_fd->Predict(calc).FakeData(icarusPOT); new TCanvas; @@ -124,8 +122,8 @@ void plot_multi() SingleSampleExperiment expt_nd(nom_nd, data_nd); SingleSampleExperiment expt_fd(nom_fd, data_fd); - MultiExperimentSBN multiExpt({&expt_nd, &expt_fd}, {kSBND, kICARUS}); - // MultiExperimentSBN multiExpt({&expt_fd}, {kICARUS}); + MultiExperiment multiExpt({&expt_nd, &expt_fd}); + // MultiExperiment multiExpt({&expt_fd}); surf_nom = new Surface(&multiExpt, calc, kAxSinSq2ThetaMuMu, @@ -154,7 +152,6 @@ void plot_multi() rsurf_nom = new Surface(&rexp, calc, kAxSinSq2ThetaMuMu, kAxDmSq); CountingExperiment cexp(nom_nd, data_nd); - calc->SetL(kBaselineSBND); csurf_nom = new Surface(&cexp, calc, kAxSinSq2ThetaMuMu, kAxDmSq); // rsurf_nom->DrawContour(crit90, 2, kRed); @@ -198,8 +195,8 @@ void plot_multi() // SingleSampleExperiment expt_nd(preds_nd[univ], data_nd); // SingleSampleExperiment expt_fd(preds_fd[univ], data_fd); - // MultiExperimentSBN multiExpt({&expt_nd, &expt_fd}, {kSBND, kICARUS}); - // // MultiExperimentSBN multiExpt({&expt_fd}, {kICARUS}); + // MultiExperiment multiExpt({&expt_nd, &expt_fd}); + // // MultiExperiment multiExpt({&expt_fd}); // Surface surf(&multiExpt, calc, // kAxSinSq2ThetaMuMu, diff --git a/sbnana/CAFAna/sbn/sensitivities/post_spec.C b/sbnana/CAFAna/sbn/sensitivities/post_spec.C index 53b323d6..2533c5f2 100644 --- a/sbnana/CAFAna/sbn/sensitivities/post_spec.C +++ b/sbnana/CAFAna/sbn/sensitivities/post_spec.C @@ -1,9 +1,9 @@ +#include "sbnana/CAFAna/Prediction/PredictionInterp.h" #include "sbnana/CAFAna/Core/LoadFromFile.h" #include "sbnana/CAFAna/Core/OscCalcSterileApprox.h" #include "sbnana/CAFAna/Vars/FitVarsSterileApprox.h" -#include "sbnana/CAFAna/Prediction/PredictionInterp.h" #include "sbnana/CAFAna/Experiment/SingleSampleExperiment.h" -#include "sbnana/CAFAna/Experiment/MultiExperimentSBN.h" +#include "sbnana/CAFAna/Experiment/MultiExperiment.h" #include "sbnana/CAFAna/Experiment/CountingExperiment.h" #include "sbnana/CAFAna/Analysis/ExpInfo.h" #include "sbnana/CAFAna/Analysis/Surface.h" @@ -44,12 +44,12 @@ void post_spec(const std::string anatype = numuStr) for (auto s : systs) { for (auto n : syst_names) if (n == s->ShortName()) systs_to_process.push_back(s); } - + std::vector> all_systs_vec; all_systs_vec.push_back(systs_to_process); all_systs_vec.push_back(systs_flux); all_systs_vec.push_back(systs_genie); - + std::string n[] = {"all", "flux", "genie"}; const char* name_in; @@ -82,9 +82,9 @@ void post_spec(const std::string anatype = numuStr) } - PredictionInterp* p_nd = LoadFrom(fin.GetDirectory("pred_nd")).release(); - PredictionInterp* p_fd = LoadFrom(fin.GetDirectory("pred_fd")).release(); - PredictionInterp* p_ub = LoadFrom(fin.GetDirectory("pred_ub")).release(); + PredictionInterp* p_nd = LoadFrom(&fin, "pred_nd").release(); + PredictionInterp* p_fd = LoadFrom(&fin, "pred_fd").release(); + PredictionInterp* p_ub = LoadFrom(&fin, "pred_ub").release(); TLegend* leg_updn = new TLegend(.6, .6, .85, .85); leg_updn->SetFillStyle(0); @@ -179,7 +179,7 @@ void post_spec(const std::string anatype = numuStr) hists.push_back(p_nd->PredictSyst(&unosc, shifts).ToTH1(sbndPOT)); } double xbins[] = {0.2, 0.3, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.95, 1., 1.25, 1.5, 2., 2.5, 3.}; - TH1D *shifted = new TH1D(("h"+to_string(i)).c_str(), "hist",19,xbins); + TH1D *shifted = new TH1D(("h"+std::to_string(i)).c_str(), "hist",19,xbins); TH1D *lower = new TH1D("h2", "hist", 19, xbins); for (int k = 1; k <= 19; ++k ) { std::vector bincont; @@ -187,18 +187,18 @@ void post_spec(const std::string anatype = numuStr) std::sort(bincont.begin(),bincont.end()); shifted->SetBinContent(k, bincont[840]); lower->SetBinContent(k, bincont[160]); - } - + } + shifted->Write(("spect_nd_"+n[i]+"_+1").c_str(), TObject::kOverwrite); lower->Write(("spect_nd_"+n[i]+"_-1").c_str(), TObject::kOverwrite); - + SystShifts shifts2; std::vector hists2; for (int j = 0; j < 1000; ++j){ for(auto s : all_systs_vec[i]) shifts2.SetShift(s, gRandom->Gaus(0, postFit[s->ShortName()])); hists2.push_back(p_fd->PredictSyst(&unosc, shifts2).ToTH1(icarusPOT)); } - TH1D *shifted2 = new TH1D(("h"+to_string(i)).c_str(), "hist",19,xbins); + TH1D *shifted2 = new TH1D(("h"+std::to_string(i)).c_str(), "hist",19,xbins); TH1D *lower2 = new TH1D("h2", "hist", 19, xbins); for (int k = 1; k <= 19; ++k ) { std::vector bincont; @@ -206,8 +206,8 @@ void post_spec(const std::string anatype = numuStr) std::sort(bincont.begin(),bincont.end()); shifted2->SetBinContent(k, bincont[840]); lower2->SetBinContent(k, bincont[160]); - } - + } + shifted2->Write(("spect_fd_"+n[i]+"_+1").c_str(), TObject::kOverwrite); lower2->Write(("spect_fd_"+n[i]+"_-1").c_str(), TObject::kOverwrite); @@ -217,7 +217,7 @@ void post_spec(const std::string anatype = numuStr) for(auto s : all_systs_vec[i]) shifts3.SetShift(s, gRandom->Gaus(0, postFit[s->ShortName()])); hists3.push_back(p_ub->PredictSyst(&unosc, shifts3).ToTH1(uboonePOT)); } - TH1D *shifted3 = new TH1D(("h"+to_string(i)).c_str(), "hist",19,xbins); + TH1D *shifted3 = new TH1D(("h"+std::to_string(i)).c_str(), "hist",19,xbins); TH1D *lower3 = new TH1D("h2", "hist", 19, xbins); for (int k = 1; k <= 19; ++k ) { std::vector bincont; @@ -225,8 +225,8 @@ void post_spec(const std::string anatype = numuStr) std::sort(bincont.begin(),bincont.end()); shifted3->SetBinContent(k, bincont[840]); lower3->SetBinContent(k, bincont[160]); - } - + } + shifted3->Write(("spect_ub_"+n[i]+"_+1").c_str(), TObject::kOverwrite); lower3->Write(("spect_ub_"+n[i]+"_-1").c_str(), TObject::kOverwrite); } diff --git a/sbnana/CAFAna/sbn/sensitivities/spec.C b/sbnana/CAFAna/sbn/sensitivities/spec.C index 08d5478b..bbc4ce7b 100644 --- a/sbnana/CAFAna/sbn/sensitivities/spec.C +++ b/sbnana/CAFAna/sbn/sensitivities/spec.C @@ -2,14 +2,14 @@ // cafe event_numbers.C #include "sbnana/CAFAna/Core/SpectrumLoader.h" -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "cafanacore/Spectrum.h" #include "sbnana/CAFAna/Core/Binning.h" #include "sbnana/CAFAna/Core/Var.h" // #include "sbnana/CAFAna/Cuts/TruthCuts.h" #include "sbnana/CAFAna/Prediction/PredictionExtrap.h" #include "sbnana/CAFAna/Extrap/IExtrap.h" -//#include "sbnana/CAFAna/StandardRecord/StandardRecord.h" +//#include "sbnanaobj/StandardRecord/StandardRecord.h" #include "sbnana/CAFAna/Prediction/PredictionNoExtrap.h" #include "sbnana/CAFAna/Analysis/Calcs.h" #include "sbnana/CAFAna/Core/MultiVar.h" @@ -50,15 +50,15 @@ void spec(const std::string anatype = numuStr) std:: cout << "Run make_state_syst.C first!" << std::endl; return; } - std::cout << "Loading state from " << stateFname << std::endl; + std::cout << "Loading state from " << stateFname << std::endl; //Initialize systematics just so we can use common state file const std::vector& systs = GetSBNWeightSysts(); TFile fin(stateFname); - PredictionInterp& pred_nd = *ana::LoadFrom(fin.GetDirectory("pred_nd")).release(); - PredictionInterp& pred_fd = *ana::LoadFrom(fin.GetDirectory("pred_fd")).release(); - PredictionInterp& pred_ub = *ana::LoadFrom(fin.GetDirectory("pred_ub")).release(); + PredictionInterp& pred_nd = *ana::LoadFrom(&fin, "pred_nd").release(); + PredictionInterp& pred_fd = *ana::LoadFrom(&fin, "pred_fd").release(); + PredictionInterp& pred_ub = *ana::LoadFrom(&fin, "pred_ub").release(); std::cout << "Done reading in files" << std::endl; TFile* fOutput = new TFile(("output_spec_"+anatype+".root").c_str(),"RECREATE"); @@ -87,7 +87,7 @@ void spec(const std::string anatype = numuStr) TH1* hnumu_nd_signal_osc1 = pred_nd.PredictComponent(osc_nd_opt1, Flavors::kAllNuMu, Current::kCC, Sign::kBoth).ToTH1(pot); TH1* hnumu_nd_ncbg_unosc = pred_nd.PredictComponent(noosc_nd, Flavors::kAll, Current::kNC, Sign::kBoth).ToTH1(pot); TH1* hnumu_nd_ncbg_osc1 = pred_nd.PredictComponent(osc_nd_opt1, Flavors::kAll, Current::kNC, Sign::kBoth).ToTH1(pot); - + TH1* hnumu_nd_osc_ratio = (TH1*)hnumu_nd_signal_osc1->Clone(); hnumu_nd_osc_ratio->Add(hnumu_nd_ncbg_osc1); TH1* hnumu_nd_tot_unosc = (TH1*)hnumu_nd_signal_unosc->Clone(); @@ -104,7 +104,7 @@ void spec(const std::string anatype = numuStr) TH1* hnumu_fd_signal_osc1 = pred_fd.PredictComponent(osc_fd_opt1, Flavors::kAllNuMu, Current::kCC, Sign::kBoth).ToTH1(pot); TH1* hnumu_fd_ncbg_unosc = pred_fd.PredictComponent(noosc_fd, Flavors::kAll, Current::kNC, Sign::kBoth).ToTH1(pot); TH1* hnumu_fd_ncbg_osc1 = pred_fd.PredictComponent(osc_fd_opt1, Flavors::kAll, Current::kNC, Sign::kBoth).ToTH1(pot); - + TH1* hnumu_fd_osc_ratio = (TH1*)hnumu_fd_signal_osc1->Clone(); hnumu_fd_osc_ratio->Add(hnumu_fd_ncbg_osc1); TH1* hnumu_fd_tot_unosc = (TH1*)hnumu_fd_signal_unosc->Clone(); @@ -145,14 +145,14 @@ void spec(const std::string anatype = numuStr) hnumu_nd_signal_osc1->Write("hnumu_nd_signal_osc"); hnumu_nd_ncbg_unosc->Write("hnumu_nd_ncbg_unosc"); hnumu_nd_ncbg_osc1->Write("hnumu_nd_ncbg_osc"); - hnumu_nd_osc_ratio->Write("hnumu_nd_osc_ratio"); + hnumu_nd_osc_ratio->Write("hnumu_nd_osc_ratio"); hnumu_fd_signal_unosc->Write("hnumu_fd_signal_unosc"); hnumu_fd_signal_osc1->Write("hnumu_fd_signal_osc"); hnumu_fd_ncbg_unosc->Write("hnumu_fd_ncbg_unosc"); hnumu_fd_ncbg_osc1->Write("hnumu_fd_ncbg_osc"); hnumu_fd_osc_ratio->Write("hnumu_fd_osc_ratio"); - + hnumu_ub_signal_unosc->Write("hnumu_ub_signal_unosc"); hnumu_ub_signal_osc1->Write("hnumu_ub_signal_osc"); hnumu_ub_ncbg_unosc->Write("hnumu_ub_ncbg_unosc"); @@ -180,7 +180,7 @@ void spec(const std::string anatype = numuStr) TH1* hnue_nd_ncbg_unosc = pred_nd.PredictComponent(noosc_nd, Flavors::kAll, Current::kNC, Sign::kBoth).ToTH1(pot); TH1* hnue_nd_numubg_unosc = pred_nd.PredictComponent(noosc_nd, Flavors::kAllNuMu, Current::kCC, Sign::kBoth).ToTH1(pot); TH1* hnue_nd_nuebg_unosc = pred_nd.PredictComponent(noosc_nd, Flavors::kNuEToNuE, Current::kCC, Sign::kBoth).ToTH1(pot); - + TH1* hnue_nd_osc1_ratio = (TH1*)hnue_nd_signal_osc1->Clone(); TH1* hnue_nd_osc2_ratio = (TH1*)hnue_nd_signal_osc2->Clone(); TH1* hnue_nd_tot_unosc = (TH1*)hnue_nd_signal_unosc->Clone(); @@ -200,7 +200,7 @@ void spec(const std::string anatype = numuStr) osc_fd_nue1->SetL(kBaselineIcarus); osc_fd_nue1->calc.SetSinSq2ThetaMuE(0.003); osc_fd_nue1->calc.SetDmsq(1.2); - + OscCalcSterileApproxAdjustable* osc_fd_nue2 = DefaultSterileApproxCalc(); osc_fd_nue2->SetL(kBaselineIcarus); osc_fd_nue2->calc.SetSinSq2ThetaMuE(0.001); @@ -212,7 +212,7 @@ void spec(const std::string anatype = numuStr) TH1* hnue_fd_ncbg_unosc = pred_fd.PredictComponent(noosc_fd, Flavors::kAll, Current::kNC, Sign::kBoth).ToTH1(pot); TH1* hnue_fd_numubg_unosc = pred_fd.PredictComponent(noosc_fd, Flavors::kAllNuMu, Current::kCC, Sign::kBoth).ToTH1(pot); TH1* hnue_fd_nuebg_unosc = pred_fd.PredictComponent(noosc_fd, Flavors::kNuEToNuE, Current::kCC, Sign::kBoth).ToTH1(pot); - + TH1* hnue_fd_osc1_ratio = (TH1*)hnue_fd_signal_osc1->Clone(); TH1* hnue_fd_osc2_ratio = (TH1*)hnue_fd_signal_osc2->Clone(); TH1* hnue_fd_tot_unosc = (TH1*)hnue_fd_signal_unosc->Clone(); @@ -233,7 +233,7 @@ void spec(const std::string anatype = numuStr) osc_ub_nue1->SetL(kBaselineMicroBoone); osc_ub_nue1->calc.SetSinSq2ThetaMuE(0.003); osc_ub_nue1->calc.SetDmsq(1.2); - + OscCalcSterileApproxAdjustable* osc_ub_nue2 = DefaultSterileApproxCalc(); osc_ub_nue2->SetL(kBaselineMicroBoone); osc_ub_nue2->calc.SetSinSq2ThetaMuE(0.001); @@ -311,7 +311,7 @@ void spec(const std::string anatype = numuStr) hnue_fd_nuebg_unosc->Write("hnue_fd_nuebg_unosc"); hnue_fd_osc1_ratio->Write("hnue_fd_osc1_ratio"); hnue_fd_osc2_ratio->Write("hnue_fd_osc2_ratio"); - + hnue_ub_signal_unosc->Write("hnue_ub_signal_unosc"); hnue_ub_signal_osc1->Write("hnue_ub_signal_osc1"); hnue_ub_signal_osc2->Write("hnue_ub_signal_osc2"); @@ -327,7 +327,7 @@ void spec(const std::string anatype = numuStr) hnue_fd_nd_ratio1->Write("hnue_fd_nd_ratio1"); hnue_fd_nd_ratio2->Write("hnue_fd_nd_ratio2"); } - + fOutput->Close(); } - + diff --git a/sbnana/CAFAna/sbn/sensitivities/syst_contour.C b/sbnana/CAFAna/sbn/sensitivities/syst_contour.C index 6a5a6d26..4c51f2dc 100644 --- a/sbnana/CAFAna/sbn/sensitivities/syst_contour.C +++ b/sbnana/CAFAna/sbn/sensitivities/syst_contour.C @@ -1,9 +1,9 @@ +#include "sbnana/CAFAna/Prediction/PredictionInterp.h" #include "sbnana/CAFAna/Core/LoadFromFile.h" #include "sbnana/CAFAna/Core/OscCalcSterileApprox.h" #include "sbnana/CAFAna/Vars/FitVarsSterileApprox.h" -#include "sbnana/CAFAna/Prediction/PredictionInterp.h" #include "sbnana/CAFAna/Experiment/SingleSampleExperiment.h" -#include "sbnana/CAFAna/Experiment/MultiExperimentSBN.h" +#include "sbnana/CAFAna/Experiment/MultiExperiment.h" #include "sbnana/CAFAna/Experiment/CountingExperiment.h" #include "sbnana/CAFAna/Analysis/ExpInfo.h" #include "sbnana/CAFAna/Analysis/Surface.h" @@ -57,9 +57,9 @@ void syst_contour() TFile fin("cafe_state_syst_numu.root"); - PredictionInterp* p_nd = LoadFrom(fin.GetDirectory("pred_nd")).release(); - PredictionInterp* p_fd = LoadFrom(fin.GetDirectory("pred_fd")).release(); - PredictionInterp* p_ub = LoadFrom(fin.GetDirectory("pred_ub")).release(); + PredictionInterp* p_nd = LoadFrom(&fin, "pred_nd").release(); + PredictionInterp* p_fd = LoadFrom(&fin, "pred_fd").release(); + PredictionInterp* p_ub = LoadFrom(&fin, "pred_ub").release(); TLegend* leg_updn = new TLegend(.6, .6, .85, .85); leg_updn->SetFillStyle(0); @@ -95,26 +95,20 @@ void syst_contour() const FitAxis kAxSinSq2ThetaMuMu(&kFitSinSq2ThetaMuMu, 20/*40*/, 1e-3, 1, true); const FitAxis kAxDmSq(&kFitDmSqSterile, 40, 1e-2, 1e2, true); - calc->SetL(kBaselineSBND); const Spectrum data_nd = p_nd->Predict(calc).FakeData(sbndPOT); - calc->SetL(kBaselineIcarus); const Spectrum data_fd = p_fd->Predict(calc).FakeData(icarusPOT); - calc->SetL(kBaselineMicroBoone); const Spectrum data_ub = p_ub->Predict(calc).FakeData(uboonePOT); SingleSampleExperiment expt_nd(p_nd, data_nd); SingleSampleExperiment expt_fd(p_fd, data_fd); SingleSampleExperiment expt_ub(p_ub, data_ub); - MultiExperimentSBN multiExpt({&expt_nd, &expt_fd, &expt_ub}, {kSBND, kICARUS, kMicroBoone}); + MultiExperiment multiExpt({&expt_nd, &expt_fd, &expt_ub}); Surface surf_nom(&multiExpt, calc, kAxSinSq2ThetaMuMu, kAxDmSq); - calc->SetL(kBaselineSBND); Surface surf_nom_nd(&expt_nd, calc, kAxSinSq2ThetaMuMu, kAxDmSq); - calc->SetL(kBaselineIcarus); Surface surf_nom_fd(&expt_fd, calc, kAxSinSq2ThetaMuMu, kAxDmSq); - calc->SetL(kBaselineMicroBoone); Surface surf_nom_ub(&expt_ub, calc, kAxSinSq2ThetaMuMu, kAxDmSq); @@ -159,11 +153,8 @@ void syst_contour() Surface surf_syst(&multiExpt, calc, kAxSinSq2ThetaMuMu, kAxDmSq, {}, slist); - calc->SetL(kBaselineSBND); Surface surf_syst_nd(&expt_nd, calc, kAxSinSq2ThetaMuMu, kAxDmSq, {}, slist); - calc->SetL(kBaselineIcarus); Surface surf_syst_fd(&expt_fd, calc, kAxSinSq2ThetaMuMu, kAxDmSq, {}, slist); - calc->SetL(kBaselineMicroBoone); Surface surf_syst_ub(&expt_ub, calc, kAxSinSq2ThetaMuMu, kAxDmSq, {}, slist); std::string suffix = "big"; diff --git a/sbnana/CAFAna/sbn/sensitivities/syst_fit.C b/sbnana/CAFAna/sbn/sensitivities/syst_fit.C index 674d199e..5f3ef006 100644 --- a/sbnana/CAFAna/sbn/sensitivities/syst_fit.C +++ b/sbnana/CAFAna/sbn/sensitivities/syst_fit.C @@ -1,9 +1,9 @@ +#include "sbnana/CAFAna/Prediction/PredictionInterp.h" #include "sbnana/CAFAna/Core/LoadFromFile.h" #include "sbnana/CAFAna/Core/OscCalcSterileApprox.h" #include "sbnana/CAFAna/Vars/FitVarsSterileApprox.h" -#include "sbnana/CAFAna/Prediction/PredictionInterp.h" #include "sbnana/CAFAna/Experiment/SingleSampleExperiment.h" -#include "sbnana/CAFAna/Experiment/MultiExperimentSBN.h" +#include "sbnana/CAFAna/Experiment/MultiExperiment.h" #include "sbnana/CAFAna/Experiment/CountingExperiment.h" #include "sbnana/CAFAna/Analysis/ExpInfo.h" #include "sbnana/CAFAna/Analysis/Surface.h" @@ -40,7 +40,7 @@ void syst_fit(const std::string anatype = numuStr) for (auto s : wtsysts) { for (auto n : syst_names) if (n == s->ShortName()) systs_to_process.push_back(s); } - + std::vector systs; //for (const ISyst* s : det_systs) systs.push_back(s); for (const ISyst* s : systs_to_process) systs.push_back(s); @@ -59,46 +59,43 @@ void syst_fit(const std::string anatype = numuStr) std::cout << "Must specifiy nue or numu" << std::endl; return; } - + TFile fin(name_in); - - PredictionInterp* p_nd = LoadFrom(fin.GetDirectory("pred_nd")).release(); - PredictionInterp* p_fd = LoadFrom(fin.GetDirectory("pred_fd")).release(); - PredictionInterp* p_ub = LoadFrom(fin.GetDirectory("pred_ub")).release(); - + + PredictionInterp* p_nd = LoadFrom(&fin, "pred_nd").release(); + PredictionInterp* p_fd = LoadFrom(&fin, "pred_fd").release(); + PredictionInterp* p_ub = LoadFrom(&fin, "pred_ub").release(); + //std::vector bigsysts; - + //osc::NoOscillations unosc; //for(const ISyst* s: systs){ //if(fabs(p_fd->PredictSyst(&unosc, SystShifts(s, +1)).Integral(1e20)/p_fd->Predict(&unosc).Integral(1e20)-1) > .01) bigsysts.push_back(s); //} - + //std::cout << bigsysts.size() << " big systs out of " << systs.size() << std::endl; //for(const ISyst* s: bigsysts) std::cout << s->ShortName() << " "; //std::cout << std::endl; - + OscCalcSterileApproxAdjustable* calc = DefaultSterileApproxCalc(); - - calc->SetL(kBaselineSBND); + const Spectrum data_nd = p_nd->Predict(calc).FakeData(sbndPOT); - calc->SetL(kBaselineIcarus); const Spectrum data_fd = p_fd->Predict(calc).FakeData(icarusPOT); - calc->SetL(kBaselineMicroBoone); const Spectrum data_ub = p_ub->Predict(calc).FakeData(uboonePOT); - + SingleSampleExperiment expt_nd(p_nd, data_nd); SingleSampleExperiment expt_fd(p_fd, data_fd); SingleSampleExperiment expt_ub(p_ub, data_ub); - - MultiExperimentSBN multiExpt({&expt_nd, &expt_fd, &expt_ub}, {kSBND, kICARUS, kMicroBoone}); - + + MultiExperiment multiExpt({&expt_nd, &expt_fd, &expt_ub}); + std::vector> slists; //slists.push_back(bigsysts); slists.push_back(systs); //for(const ISyst* s: systs) slists.emplace_back(1, s); // and then each std::vector oscVars; - if (anatype == numuStr) { + if (anatype == numuStr) { oscVars = {&kFitDmSqSterile, &kFitSinSq2ThetaMuMu}; } else { @@ -118,7 +115,7 @@ void syst_fit(const std::string anatype = numuStr) std::vector prefit_err = fit_syst.GetPreFitErrors(); std::vector postfit = fit_syst.GetPostFitValues(); std::vector postfit_err = fit_syst.GetPostFitErrors(); - + // std::cout << "Parameters considered: " << std::endl; // for (const string st: pnames) { // std::cout << st << std::endl; @@ -156,7 +153,6 @@ void syst_fit(const std::string anatype = numuStr) std::cout << "Fitting ND only..." << std::endl; Fitter fit_nd(&expt_nd, oscVars, slist, Fitter::kCareful); OscCalcSterileApproxAdjustable* calc_nd = DefaultSterileApproxCalc(); - calc_nd->SetL(kBaselineSBND); SystShifts bestSysts_nd; double chi_nd = fit_nd.Fit(calc_nd, bestSysts_nd); std::vector prefitnd = fit_nd.GetPreFitValues(); @@ -177,7 +173,6 @@ void syst_fit(const std::string anatype = numuStr) std::cout << "Fitting FD only..." << std::endl; Fitter fit_fd(&expt_fd, oscVars, slist, Fitter::kCareful); OscCalcSterileApproxAdjustable* calc_fd = DefaultSterileApproxCalc(); - calc_fd->SetL(kBaselineIcarus); SystShifts bestSysts_fd; double chi_fd = fit_fd.Fit(calc_fd, bestSysts_fd); std::vector prefitfd = fit_fd.GetPreFitValues(); diff --git a/sbnana/CAFAna/sbn/sensitivities/syst_spec.C b/sbnana/CAFAna/sbn/sensitivities/syst_spec.C index 1056f47b..654c1ef7 100644 --- a/sbnana/CAFAna/sbn/sensitivities/syst_spec.C +++ b/sbnana/CAFAna/sbn/sensitivities/syst_spec.C @@ -1,9 +1,8 @@ +#include "sbnana/CAFAna/Prediction/PredictionInterp.h" #include "sbnana/CAFAna/Core/LoadFromFile.h" #include "sbnana/CAFAna/Core/OscCalcSterileApprox.h" #include "sbnana/CAFAna/Vars/FitVarsSterileApprox.h" -#include "sbnana/CAFAna/Prediction/PredictionInterp.h" #include "sbnana/CAFAna/Experiment/SingleSampleExperiment.h" -#include "sbnana/CAFAna/Experiment/MultiExperimentSBN.h" #include "sbnana/CAFAna/Experiment/CountingExperiment.h" #include "sbnana/CAFAna/Analysis/ExpInfo.h" #include "sbnana/CAFAna/Analysis/Surface.h" @@ -46,12 +45,12 @@ void syst_spec(const std::string anatype = numuStr) } //for (auto s : systs_to_process) std::cout << s->ShortName() << std::endl; - + std::vector> all_systs_vec; all_systs_vec.push_back(systs_to_process); all_systs_vec.push_back(systs_flux); all_systs_vec.push_back(systs_genie); - + std::string n[] = {"all", "flux", "genie"}; const char* name_in; @@ -72,10 +71,10 @@ void syst_spec(const std::string anatype = numuStr) TFile fin(name_in); TFile fout(name_out,"RECREATE"); - PredictionInterp* p_nd = LoadFrom(fin.GetDirectory("pred_nd")).release(); - PredictionInterp* p_fd = LoadFrom(fin.GetDirectory("pred_fd")).release(); - PredictionInterp* p_ub = LoadFrom(fin.GetDirectory("pred_ub")).release(); - + PredictionInterp* p_nd = LoadFrom(&fin, "pred_nd").release(); + PredictionInterp* p_fd = LoadFrom(&fin, "pred_fd").release(); + PredictionInterp* p_ub = LoadFrom(&fin, "pred_ub").release(); + TLegend* leg_updn = new TLegend(.6, .6, .85, .85); leg_updn->SetFillStyle(0); TH1* dummy = new TH1F("", "", 1, 0, 1); @@ -171,7 +170,7 @@ void syst_spec(const std::string anatype = numuStr) hists.push_back(p_nd->PredictSyst(&unosc, shifts).ToTH1(sbndPOT)); } double xbins[] = {0.2, 0.3, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.95, 1., 1.25, 1.5, 2., 2.5, 3.}; - TH1D *shifted = new TH1D(("h"+to_string(i)).c_str(), "hist",19,xbins); + TH1D *shifted = new TH1D(("h"+std::to_string(i)).c_str(), "hist",19,xbins); TH1D *lower = new TH1D("h2", "hist", 19, xbins); for (int k = 1; k <= 19; ++k ) { std::vector bincont; @@ -179,8 +178,8 @@ void syst_spec(const std::string anatype = numuStr) std::sort(bincont.begin(),bincont.end()); shifted->SetBinContent(k, bincont[840]); lower->SetBinContent(k, bincont[160]); - } - + } + shifted->Write(("spect_nd_"+n[i]+"_+1").c_str(), TObject::kOverwrite); lower->Write(("spect_nd_"+n[i]+"_-1").c_str(), TObject::kOverwrite); @@ -190,7 +189,7 @@ void syst_spec(const std::string anatype = numuStr) for(auto s : all_systs_vec[i]) shifts2.SetShift(s, gRandom->Gaus()); hists2.push_back(p_fd->PredictSyst(&unosc, shifts2).ToTH1(icarusPOT)); } - TH1D *shifted2 = new TH1D(("h"+to_string(i)).c_str(), "hist",19,xbins); + TH1D *shifted2 = new TH1D(("h"+std::to_string(i)).c_str(), "hist",19,xbins); TH1D *lower2 = new TH1D("h2", "hist", 19, xbins); for (int k = 1; k <= 19; ++k ) { std::vector bincont; @@ -198,8 +197,8 @@ void syst_spec(const std::string anatype = numuStr) std::sort(bincont.begin(),bincont.end()); shifted2->SetBinContent(k, bincont[840]); lower2->SetBinContent(k, bincont[160]); - } - + } + shifted2->Write(("spect_fd_"+n[i]+"_+1").c_str(), TObject::kOverwrite); lower2->Write(("spect_fd_"+n[i]+"_-1").c_str(), TObject::kOverwrite); @@ -209,7 +208,7 @@ void syst_spec(const std::string anatype = numuStr) for(auto s : all_systs_vec[i]) shifts3.SetShift(s, gRandom->Gaus()); hists3.push_back(p_ub->PredictSyst(&unosc, shifts3).ToTH1(uboonePOT)); } - TH1D *shifted3 = new TH1D(("h"+to_string(i)).c_str(), "hist",19,xbins); + TH1D *shifted3 = new TH1D(("h"+std::to_string(i)).c_str(), "hist",19,xbins); TH1D *lower3 = new TH1D("h2", "hist", 19, xbins); for (int k = 1; k <= 19; ++k ) { std::vector bincont; @@ -217,8 +216,8 @@ void syst_spec(const std::string anatype = numuStr) std::sort(bincont.begin(),bincont.end()); shifted3->SetBinContent(k, bincont[840]); lower3->SetBinContent(k, bincont[160]); - } - + } + shifted3->Write(("spect_ub_"+n[i]+"_+1").c_str(), TObject::kOverwrite); lower3->Write(("spect_ub_"+n[i]+"_-1").c_str(), TObject::kOverwrite); } diff --git a/sbnana/CAFAna/sbn/sensitivities/toysysts.h b/sbnana/CAFAna/sbn/sensitivities/toysysts.h index f693f8e8..f212a277 100644 --- a/sbnana/CAFAna/sbn/sensitivities/toysysts.h +++ b/sbnana/CAFAna/sbn/sensitivities/toysysts.h @@ -10,7 +10,7 @@ class ToyEnergyScaleSyst: public ISyst caf::SRSliceProxy* sr, double& weight) const override { - const double scale = 1 + .05*sigma; // 5% E scale syst. + const double scale = 1 + .05*sigma; // 5% E scale syst. sr->reco.reco_energy *= scale; } diff --git a/sbnana/CAFAna/test/test_GENIESyst.C b/sbnana/CAFAna/test/test_GENIESyst.C index 6929b84b..7280bec9 100644 --- a/sbnana/CAFAna/test/test_GENIESyst.C +++ b/sbnana/CAFAna/test/test_GENIESyst.C @@ -1,7 +1,7 @@ #include "sbnana/CAFAna/Core/Binning.h" #include "sbnana/CAFAna/Core/SpectrumLoader.h" #include "sbnana/CAFAna/Core/LoadFromFile.h" -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "cafanacore/Spectrum.h" #include "sbnana/CAFAna/Core/EnsembleSpectrum.h" #include "sbnana/CAFAna/Core/Var.h" #include "sbnana/CAFAna/Cuts/TruthCuts.h" @@ -79,7 +79,7 @@ void test_GENIESyst(){ //==== (Truth) Cut std::vector vec_Cuts = { - kIsNuSlice, + kIsNuSlice, cutIsQE, cutIsRes, cutIsDIS, @@ -247,7 +247,7 @@ void test_GENIESyst(){ h_3Dn->Draw("histsame"); h_CV->Draw("histsame"); - h_1Up->GetYaxis()->SetRangeUser(0., 1.1*max(h_3Up->GetMaximum(), h_3Dn->GetMaximum())); + h_1Up->GetYaxis()->SetRangeUser(0., 1.1*std::max(h_3Up->GetMaximum(), h_3Dn->GetMaximum())); //==== ratio c_ratio->cd(); @@ -322,7 +322,7 @@ void test_GENIESyst(){ TH1D *h_es = es->Universe(i).ToTH1(kPOTnominal); h_es->SetLineColor(kRed-10); if(i==0) lg_es->AddEntry(h_es, "Universes", "l"); - y_max = max(y_max, h_es->GetMaximum()); + y_max = std::max(y_max, h_es->GetMaximum()); c_es_rate->cd(); h_es->Draw("histsame"); diff --git a/sbnana/CAFAna/test/test_ensemble.C b/sbnana/CAFAna/test/test_ensemble.C index 19727c80..12f204a4 100644 --- a/sbnana/CAFAna/test/test_ensemble.C +++ b/sbnana/CAFAna/test/test_ensemble.C @@ -26,15 +26,14 @@ using namespace ana; -// Since I'm in the SBND group the SAM dataset works fine for me -const std::string sbnd_wildcard = "workshop_SBNWorkshop0421_prodoverlay_corsika_cosmics_proton_genie_nu_spill_gsimple-configf-v1_tpc_flat_caf_sbnd"; +const std::string wildcard = "/pnfs/icarus/persistent/users/jskim/mc/NUMI_Nu_Cosmics/flatcaf/v09_37_01_03p02/MultiSigmaAdded_RenamedPSet/*.root"; const std::string state_fname = "test_ensemble_state.root"; void test_ensemble(bool reload = false) { if(reload || TFile(state_fname.c_str()).IsZombie()){ - SpectrumLoader loader(sbnd_wildcard); + SpectrumLoader loader(wildcard); const Var kTrueE = SIMPLEVAR(truth.E); @@ -44,26 +43,25 @@ void test_ensemble(bool reload = false) const HistAxis axEnergy("True energy (GeV)", binsEnergy, kTrueE); - std::vector weis; - weis.reserve(100); + std::vector weis; + weis.reserve(101); - // We need these essentially as the list of knob names - const std::vector& systs = GetSBNGenieWeightSysts(); - for(int i = 0; i < 100; ++i) weis.push_back(GetUniverseWeight(systs, i)); + weis.push_back(kUnweighted); // nominal + for(int i = 0; i < 99; ++i) weis.push_back(GetUniverseWeight("multisim_Genie", i)); - EnsembleSpectrum sCC(loader, axEnergy, kNoSpillCut, kNumuSel && kIsNumuCC, weis); - EnsembleSpectrum sNC(loader, axEnergy, kNoSpillCut, kNumuSel && kIsNC, weis); + EnsembleSpectrum sCC(loader.Slices().Ensemble(weis)[kNumuSel][kIsNumuCC], axEnergy); + EnsembleSpectrum sNC(loader.Slices().Ensemble(weis)[kNumuSel][kIsNC], axEnergy); loader.Go(); TFile fout(state_fname.c_str(), "RECREATE"); - sCC.SaveTo(fout.mkdir("cc")); - sNC.SaveTo(fout.mkdir("nc")); + sCC.SaveTo(&fout, "cc"); + sNC.SaveTo(&fout, "nc"); } TFile fin(state_fname.c_str()); - EnsembleSpectrum* sCC = LoadFrom(fin.GetDirectory("cc")).release(); - EnsembleSpectrum* sNC = LoadFrom(fin.GetDirectory("nc")).release(); + EnsembleSpectrum* sCC = LoadFrom(&fin, "cc").release(); + EnsembleSpectrum* sNC = LoadFrom(&fin, "nc").release(); sCC->Nominal().ToTH1(kPOTnominal, kRed)->Draw("hist"); sNC->Nominal().ToTH1(kPOTnominal, kBlue)->Draw("hist same"); @@ -94,6 +92,7 @@ void test_ensemble(bool reload = false) TH1* hratio = ratio.Nominal().ToTH1(); hratio->Draw("hist ]["); hratio->GetYaxis()->SetTitle("CC / NC ratio"); + hratio->GetYaxis()->SetRangeUser(0, 10); for(unsigned int i = 0; i < ratio.NUniverses(); ++i){ ratio.Universe(i).ToTH1(kGray)->Draw("hist ][ same"); } diff --git a/sbnana/CAFAna/test/test_evtwgt.C b/sbnana/CAFAna/test/test_evtwgt.C index e6665e35..0fa7a0cc 100644 --- a/sbnana/CAFAna/test/test_evtwgt.C +++ b/sbnana/CAFAna/test/test_evtwgt.C @@ -1,6 +1,7 @@ -#include "sbnana/CAFAna/Core/Ratio.h" +#include "cafanacore/Ratio.h" +#include "sbnana/CAFAna/Core/HistAxis.h" #include "sbnana/CAFAna/Core/SpectrumLoader.h" -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "cafanacore/Spectrum.h" #include "sbnana/CAFAna/Core/SystShifts.h" #include "sbnana/CAFAna/Systs/SBNWeightSysts.h" using namespace ana; diff --git a/sbnana/CAFAna/test/test_multiverse.C b/sbnana/CAFAna/test/test_multiverse.C new file mode 100644 index 00000000..6affeb5b --- /dev/null +++ b/sbnana/CAFAna/test/test_multiverse.C @@ -0,0 +1,37 @@ +#include "sbnana/CAFAna/Core/Multiverse.h" + +#include "sbnana/CAFAna/Systs/SBNWeightSysts.h" + +#include "TFile.h" + +#include + +using namespace ana; + +void test_multiverse(bool remake = true) +{ + if(remake){ + const std::vector systs = GetSBNGenieWeightSysts(); + + const Multiverse& cross = Multiverse::Hypercross(systs, 3); + const Multiverse& gas = Multiverse::RandomGas(systs, 100, 42);//Multiverse::kTrulyRandom); + + std::cout << cross.LatexName() << std::endl << cross.ShortName() << std::endl; + std::cout << gas.LatexName() << std::endl << gas.ShortName() << std::endl; + + TFile fout("test_multiverse.root", "RECREATE"); + cross.SaveTo(&fout, "cross"); + gas.SaveTo(&fout, "gas"); + } + + std::cout << std::endl; + + GetSBNGenieWeightSysts(); // magic them into existence + + TFile fin("test_multiverse.root"); + const FitMultiverse& cross = *Multiverse::LoadFrom(&fin, "cross"); + const FitMultiverse& gas = *Multiverse::LoadFrom(&fin, "gas"); + + std::cout << cross.LatexName() << std::endl << cross.ShortName() << std::endl; + std::cout << gas.LatexName() << std::endl << gas.ShortName() << std::endl; +} diff --git a/sbnana/CAFAna/test/test_numi_systs.C b/sbnana/CAFAna/test/test_numi_systs.C index 64e1038e..0c6d51f8 100644 --- a/sbnana/CAFAna/test/test_numi_systs.C +++ b/sbnana/CAFAna/test/test_numi_systs.C @@ -1,5 +1,6 @@ #include "sbnana/CAFAna/Core/SpectrumLoader.h" -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "cafanacore/Spectrum.h" +#include "sbnana/CAFAna/Core/HistAxis.h" #include "sbnana/CAFAna/Core/Utilities.h" #include "sbnana/CAFAna/Systs/NuMIFluxSysts.h" @@ -25,7 +26,7 @@ void test_numi_systs() Binning::Simple(50, 0, 5), kTrueE); - Spectrum snom(loader, axis, kNoCut); + Spectrum snom(loader.Slices(), axis); std::vector sup, sdn; for(const ISyst* s: systs){ diff --git a/sbnana/CAFAna/test/test_oracle.C b/sbnana/CAFAna/test/test_oracle.C index cf847123..19c569bb 100644 --- a/sbnana/CAFAna/test/test_oracle.C +++ b/sbnana/CAFAna/test/test_oracle.C @@ -10,7 +10,7 @@ using namespace ana; void test_oracle() { - UniverseOracle oracle; + const UniverseOracle& oracle = UniverseOracle::Instance(); const unsigned int N = oracle.Systs().size(); unsigned int Nx = sqrt(N); @@ -23,7 +23,7 @@ void test_oracle() int i = 0; for(const std::string& name: oracle.Systs()){ - const std::vector& shifts = oracle.ShiftsForSyst(name); + const std::vector& shifts = oracle.ShiftsForSyst(name); std::cout << name << ": " << shifts.size() << " universes" << std::endl; for(int sigma = -3; sigma <= +3; ++sigma){ if(sigma == 0) continue; diff --git a/sbnana/CAFAna/test/test_tracks.C b/sbnana/CAFAna/test/test_tracks.C new file mode 100644 index 00000000..4cd3478f --- /dev/null +++ b/sbnana/CAFAna/test/test_tracks.C @@ -0,0 +1,74 @@ +// Recommend running with a large --stride argument to just use the first file +// in the dataset + +#include "sbnana/CAFAna/Core/Binning.h" +#include "sbnana/CAFAna/Core/SpectrumLoader.h" +#include "CAFAna/Core/Spectrum.h" +#include "sbnana/CAFAna/Core/LoadFromFile.h" +#include "sbnana/CAFAna/Core/Var.h" +#include "sbnana/CAFAna/Core/HistAxis.h" + +#include "sbnana/CAFAna/Cuts/TruthCuts.h" + +#include "sbnana/CAFAna/Systs/SBNWeightSysts.h" + +#include "sbnana/CAFAna/Analysis/ExpInfo.h" + +#include "sbnanaobj/StandardRecord/Proxy/SRProxy.h" + +#include "sbnana/SBNAna/Cuts/NumuCutsSBND202106.h" +#include "sbnana/SBNAna/Cuts/Cuts.h" + +#include "TCanvas.h" +#include "TFile.h" +#include "TH1.h" +#include "TPad.h" + +using namespace ana; + +// Since I'm in the SBND group the SAM dataset works fine for me +//const std::string sbnd_wildcard = "official_MCP2021A_CAF_prodgenie_nu_singleinteraction_tpc_sbnd_concat_caf_sbnd";// "official_MCP2021A_CAF_prodoverlay_corsika_cosmics_proton_genie_nu_spill_tpc_sbnd_concat_caf_sbnd";//workshop_SBNWorkshop0421_prodoverlay_corsika_cosmics_proton_genie_nu_spill_gsimple-configf-v1_tpc_flat_caf_sbnd"; + +//const std::string sbnd_wildcard = "/pnfs/icarus/scratch/users/jskim/mc/NUMI_Nu_Cosmics/flatcaf/v09_42_00/MultiSigmaAdded/*.root"; // actually icarus NuMI + +const std::string sbnd_wildcard = "/pnfs/icarus/scratch/users/jskim/mc/NUMI_Nu_Cosmics/flatcaf/v09_37_01_03p02/MultiSigmaAdded_FromConcat/*.root"; // concat icarus files + +const std::string state_fname = "test_tracks_state.root"; + +void test_tracks(bool reload = false) +{ + if(reload || TFile(state_fname.c_str()).IsZombie()){ + SpectrumLoader loader(sbnd_wildcard); + + const TrackVar kLength = SIMPLETRACKVAR(len); + const TrackCut kLengthCut = kLength>100; + + const Binning binsLength = Binning::Simple(30, 0, 300); + + const TrackHistAxis axLength("RecoLength", binsLength, kLength); + + auto& src = loader.Slices().Tracks(); + + Spectrum sAll(src, axLength); + Spectrum sLong(src[kLengthCut], axLength); + + loader.Go(); + + TFile fout(state_fname.c_str(), "RECREATE"); + sAll.SaveTo(&fout, "all"); + sLong.SaveTo(&fout, "long"); + } + + TFile fin(state_fname.c_str()); + Spectrum* sAll = LoadFrom(&fin, "all").release(); + Spectrum* sLong = LoadFrom(&fin, "long").release(); + + sAll->ToTH1(kPOTnominal, kRed)->Draw("hist"); + sLong->ToTH1(kPOTnominal, kBlue)->Draw("hist same"); + + // Redraw the nominals over the top + sAll->ToTH1(kPOTnominal, kRed)->Draw("hist same"); + sLong->ToTH1(kPOTnominal, kBlue)->Draw("hist same"); + + gPad->Print("test_tracks.pdf"); +} diff --git a/sbnana/CAFAna/test/test_unfold.C b/sbnana/CAFAna/test/test_unfold.C index 73e3d3d7..49e30296 100644 --- a/sbnana/CAFAna/test/test_unfold.C +++ b/sbnana/CAFAna/test/test_unfold.C @@ -6,6 +6,8 @@ #include "TH2.h" #include "TRandom3.h" +#include + using namespace ana; const Binning recobins = Binning::Simple(40, 0, 10); diff --git a/sbnana/CAFAna/test/test_xsec_flux.C b/sbnana/CAFAna/test/test_xsec_flux.C index 4f955eb3..d1050559 100644 --- a/sbnana/CAFAna/test/test_xsec_flux.C +++ b/sbnana/CAFAna/test/test_xsec_flux.C @@ -1,27 +1,31 @@ #include "sbnana/CAFAna/Core/SpectrumLoader.h" -#include "sbnana/CAFAna/Core/Ratio.h" -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "cafanacore/Ratio.h" +#include "cafanacore/Spectrum.h" #include "sbnana/CAFAna/XSec/Flux.h" -#include "sbnana/CAFAna/StandardRecord/Proxy/SRProxy.h" +#include "sbnanaobj/StandardRecord/Proxy/SRProxy.h" #include "TCanvas.h" #include "TFile.h" #include "TH2.h" +#include "TPad.h" + +#include using namespace ana; void test_xsec_flux() { - // SpectrumLoader loader("/icarus/data/users/mmr/CAFMaker/v09_20_00/NuMIBeamWindow/ICARUS_prod_2020A_00_numioffaxis_v09_10_01_reco2/ICARUS_prod_2020A_00_numioffaxis_v09_10_01_reco2_CAFMaker_out_flat.root"); + // Need to export SAM_EXPERIMENT=sbn + // SpectrumLoader loader("Official_icarusprod_2021C_NUMI_Nu_Cosmics_v09_37_01_03p01_caf"); - // The only file currently existing with the correct genie inttype filled - SpectrumLoader loader("/sbnd/app/users/bckhouse/dev/simulation_genie_icarus_numi_volDetEnclosure_20201215T090631_113-0083_gen_20201215T104338_filter_20201215T115238_g4_20201215T215526_detsim_20210113T201733_reco1_20210114T015949_reco2.caf.root"); + // Far faster + SpectrumLoader loader("/sbnd/data/users/bckhouse/icarusprod_2021C_NUMI_Nu_Cosmics_v09_37_01_03p01_caf/flat*.root"); - const Cut fidvol([](const caf::SRSliceProxy* sr) + const NuTruthCut fidvol([](const caf::SRTrueInteractionProxy* nu) { - const auto& v = sr->truth.position; + const auto& v = nu->position; // Didn't simulate the other cryostat return ((//( v.x < -71.1 - 25 && v.x > -369.33 + 25 ) || @@ -30,7 +34,7 @@ void test_xsec_flux() ( v.z > -895.95 + 30 && v.z < 895.95 - 50 ) )); }); - FluxTimesNuclei flux(loader, Binning::Simple(40, 0, 10), fidvol, 14); + FluxTimesNuclei flux(loader.NuTruths(), Binning::Simple(50, 0, 5), fidvol, 14); loader.Go(); @@ -56,4 +60,6 @@ void test_xsec_flux() hnom->SetLineColor(kRed); hnom->Draw("hist same"); } + + gPad->Print("test_xsec_flux.pdf"); } diff --git a/sbnana/CAFAna/tute/demo0.C b/sbnana/CAFAna/tute/demo0.C index 92a8ea48..9bc600c9 100644 --- a/sbnana/CAFAna/tute/demo0.C +++ b/sbnana/CAFAna/tute/demo0.C @@ -1,8 +1,9 @@ // Make a simple spectrum plot // cafe demo0.C +#include "cafanacore/Spectrum.h" #include "sbnana/CAFAna/Core/SpectrumLoader.h" -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "sbnana/CAFAna/Core/HistAxis.h" #include "sbnana/CAFAna/Core/Binning.h" #include "sbnana/CAFAna/Analysis/ExpInfo.h" // for kPOTnominal @@ -27,15 +28,15 @@ void demo0() // A Var is a little snippet of code that takes a "proxy" representing the // event record and returns a single number to plot - const Var kTruthEnergy([](const caf::SRProxy* sr) - { - return sr->mc.nu[0].E; - }); + const SpillVar kTruthEnergy([](const caf::SRSpillProxy* sr) + { + return sr->mc.nu[0].E; + }); // Define a spectrum, ie a histogram with associated POT information const Binning binsEnergy = Binning::Simple(50, 0, 5); - const HistAxis axEnergy("True energy (GeV)", binsEnergy, kTruthEnergy); - Spectrum sEnergy(loader, axEnergy, kNoCut); + const SpillHistAxis axEnergy("True energy (GeV)", binsEnergy, kTruthEnergy); + Spectrum sEnergy(loader, axEnergy); // This is the call that actually fills in the spectrum loader.Go(); diff --git a/sbnana/CAFAna/tute/demo0b.C b/sbnana/CAFAna/tute/demo0b.C index a0ee1b46..bb19bf5f 100644 --- a/sbnana/CAFAna/tute/demo0b.C +++ b/sbnana/CAFAna/tute/demo0b.C @@ -3,14 +3,15 @@ // Includes from demo0.C #include "sbnana/CAFAna/Core/SpectrumLoader.h" -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "cafanacore/Spectrum.h" #include "sbnana/CAFAna/Core/Binning.h" +#include "sbnana/CAFAna/Core/HistAxis.h" #include "sbnana/CAFAna/Core/Var.h" #include "sbnana/CAFAna/Analysis/ExpInfo.h" #include "sbnanaobj/StandardRecord/Proxy/SRProxy.h" // New includes -#include "sbnana/CAFAna/Core/Ratio.h" +#include "cafanacore/Ratio.h" #include "sbnana/CAFAna/Cuts/TruthCuts.h" // for kIsNC using namespace ana; @@ -31,8 +32,8 @@ void demo0b() // We will also use two different Vars. For such simple ones we can use this // shortcut macro. - const Var kTruthEnergy = SIMPLEVAR(truth[0].neutrino.energy); - const Var kTruthY = SIMPLEVAR(truth[0].neutrino.inelasticityY); + const Var kTruthEnergy = SIMPLEVAR(truth.E); + const Var kTruthY = SIMPLEVAR(truth.inelasticityY); // Define axes for the spectra we'll make const HistAxis axEnergy("True energy (GeV)", Binning::Simple(50, 0, 5), kTruthEnergy); @@ -40,26 +41,26 @@ void demo0b() // A Cut is the same as a Var but returns a boolean. Here we're selecting // truly numu CC interactions. - const Cut kIsNumuCC([](const caf::SRProxy* sr) + const Cut kIsNumuCC([](const caf::SRSliceProxy* sr) { - return (sr->truth[0].neutrino.iscc && - abs(sr->truth[0].neutrino.pdg) == 14); + return (sr->truth.iscc && + abs(sr->truth.pdg) == 14); }); // Can also make combinations of existing Cuts and Vars in the obvious // ways. kIsNC here comes from Cuts/TruthCuts.h. Really we should have just // used kIsNumuCC from there. - const Var kPdg = SIMPLEVAR(truth[0].neutrino.pdg); + const Var kPdg = SIMPLEVAR(truth.pdg); const Cut kIsNumuCC2 = (kPdg == 14 || kPdg == -14) && !kIsNC; - Spectrum sEnergySig(loaderSBND, axEnergy, kIsNumuCC); - Spectrum sEnergyBkg(loaderSBND, axEnergy, !kIsNumuCC); + Spectrum sEnergySig(loaderSBND.Slices()[ kIsNumuCC], axEnergy); + Spectrum sEnergyBkg(loaderSBND.Slices()[!kIsNumuCC], axEnergy); - Spectrum sEnergySigIc(loaderIcarus, axEnergy, kIsNumuCC); - Spectrum sEnergyBkgIc(loaderIcarus, axEnergy, !kIsNumuCC); + Spectrum sEnergySigIc(loaderIcarus.Slices()[ kIsNumuCC], axEnergy); + Spectrum sEnergyBkgIc(loaderIcarus.Slices()[!kIsNumuCC], axEnergy); - Spectrum sYSig(loaderSBND, axY, kIsNumuCC); - Spectrum sYBkg(loaderSBND, axY, !kIsNumuCC); + Spectrum sYSig(loaderSBND.Slices()[ kIsNumuCC], axY); + Spectrum sYBkg(loaderSBND.Slices()[!kIsNumuCC], axY); // Fill in the 4 ND spectra loaderSBND.Go(); diff --git a/sbnana/CAFAna/tute/demo1.C b/sbnana/CAFAna/tute/demo1.C index cdb71b0f..ec4e7872 100644 --- a/sbnana/CAFAna/tute/demo1.C +++ b/sbnana/CAFAna/tute/demo1.C @@ -2,7 +2,7 @@ // cafe demo1.C #include "sbnana/CAFAna/Core/SpectrumLoader.h" -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "CAFAna/Core/Spectrum.h" #include "sbnana/CAFAna/Core/Binning.h" #include "sbnana/CAFAna/Cuts/TruthCuts.h" #include "sbnana/CAFAna/Analysis/ExpInfo.h" @@ -29,13 +29,13 @@ void demo1(int step = 99) // Mocked up reconstruction const Var kRecoE = SIMPLEVAR(reco.reco_energy); // Mock selection efficiencies etc - const Var kWeight = SIMPLEVAR(reco.weight); + const Weight kWeight = SIMPLEWEIGHT(reco.weight); const HistAxis axEnergy("Reconstructed energy (GeV)", Binning::Simple(50, 0, 5), kRecoE); // These are 2D reco-vs-true distributions - OscillatableSpectrum sOscND(loaderSBND, axEnergy, kIsNumuCC, kNoShift, kWeight); - OscillatableSpectrum sOscFD(loaderIcarus, axEnergy, kIsNumuCC, kNoShift, kWeight); + OscillatableSpectrum sOscND(loaderSBND.Slices().Weighted(kWeight)[kIsNumuCC], axEnergy); + OscillatableSpectrum sOscFD(loaderIcarus.Slices().Weighted(kWeight)[kIsNumuCC], axEnergy); loaderSBND.Go(); loaderIcarus.Go(); diff --git a/sbnana/CAFAna/tute/demo1b.C b/sbnana/CAFAna/tute/demo1b.C index 2e2d9f88..1f1cea11 100644 --- a/sbnana/CAFAna/tute/demo1b.C +++ b/sbnana/CAFAna/tute/demo1b.C @@ -2,7 +2,7 @@ // cafe demo1b.C #include "sbnana/CAFAna/Core/SpectrumLoader.h" -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "CAFAna/Core/Spectrum.h" #include "sbnana/CAFAna/Core/Binning.h" #include "sbnana/CAFAna/Core/OscCalcSterileApprox.h" #include "sbnana/CAFAna/Cuts/TruthCuts.h" @@ -23,7 +23,7 @@ void demo1b() const std::string fnameIcarus = "/sbnd/data/users/bckhouse/sample_2.1_fitters/output_SBNOsc_NumuSelection_Proposal_Icarus.flat.root"; SpectrumLoader loaderIcarus(fnameIcarus); const Var kRecoE = SIMPLEVAR(reco.reco_energy); - const Var kWeight = SIMPLEVAR(reco.weight); + const Weight kWeight = SIMPLEWEIGHT(reco.weight); const HistAxis axEnergy("Reconstructed energy (GeV)", Binning::Simple(50, 0, 5), kRecoE); OscCalcSterileApprox calc; calc.SetDmsq(1); @@ -33,8 +33,8 @@ void demo1b() // A Prediction is an objects holding a variety of "OscillatableSpectrum" // objects, one for each original and final flavour combination. - PredictionNoExtrap pred(loaderIcarus, kNullLoader, kNullLoader, kNullLoader, - axEnergy, kNoCut, kNoShift, kWeight); + PredictionNoExtrap pred(loaderIcarus.Slices().Weighted(kWeight), kNullSliceSource, kNullSliceSource, kNullSliceSource, + axEnergy); // This call will fill all of the constituent parts of the prediction loaderIcarus.Go(); diff --git a/sbnana/CAFAna/tute/demo2.C b/sbnana/CAFAna/tute/demo2.C index 5726e92f..2b0240ee 100644 --- a/sbnana/CAFAna/tute/demo2.C +++ b/sbnana/CAFAna/tute/demo2.C @@ -2,7 +2,7 @@ // cafe demo2.C #include "sbnana/CAFAna/Core/SpectrumLoader.h" -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "CAFAna/Core/Spectrum.h" #include "sbnana/CAFAna/Core/Binning.h" #include "sbnana/CAFAna/Core/Var.h" #include "sbnana/CAFAna/Cuts/TruthCuts.h" @@ -16,7 +16,7 @@ #include "sbnana/CAFAna/Analysis/FitAxis.h" #include "sbnana/CAFAna/Analysis/Surface.h" #include "sbnana/CAFAna/Vars/FitVarsSterileApprox.h" -#include "sbnana/CAFAna/Experiment/MultiExperimentSBN.h" +#include "sbnana/CAFAna/Experiment/MultiExperiment.h" using namespace ana; @@ -33,12 +33,14 @@ void demo2(int step = 99) SpectrumLoader loaderIcarus(fnameIcarus); SpectrumLoader loaderSBND(fnameSBND); const Var kRecoE = SIMPLEVAR(reco.reco_energy); - const Var kWeight = SIMPLEVAR(reco.weight); + const Weight kWeight = SIMPLEWEIGHT(reco.weight); const HistAxis axEnergy("Reconstructed energy (GeV)", Binning::Simple(50, 0, 5), kRecoE); - PredictionNoExtrap predSBND(loaderSBND, kNullLoader, kNullLoader, kNullLoader, - axEnergy, kNoCut, kNoShift, kWeight); - PredictionNoExtrap predIcarus(loaderIcarus, kNullLoader, kNullLoader, kNullLoader, - axEnergy, kNoCut, kNoShift, kWeight); + PredictionNoExtrap predSBND(loaderSBND.Slices().Weighted(kWeight), + kNullSliceSource, kNullSliceSource, kNullSliceSource, + axEnergy); + PredictionNoExtrap predIcarus(loaderIcarus.Slices().Weighted(kWeight), + kNullSliceSource, kNullSliceSource, kNullSliceSource, + axEnergy); loaderSBND.Go(); loaderIcarus.Go(); @@ -108,9 +110,8 @@ void demo2(int step = 99) surfSBND.DrawContour(critSurf, kSolid, kRed); surfIcarus.DrawContour(critSurf, kSolid, kBlue); - // MultiExperimentSBN sums the chisqs from its constituent parts. It also - // makes sure to set the right baselines at the right times during the fit. - MultiExperimentSBN exptMulti({&exptSBND, &exptIcarus}, {kSBND, kICARUS}); + // MultiExperiment sums the chisqs from its constituent parts. + MultiExperiment exptMulti({&exptSBND, &exptIcarus}); Surface surfMulti(&exptMulti, &calc, kAxSinSq2ThetaMuMu, kAxDmSq); surfMulti.DrawContour(critSurf, kSolid, kMagenta); diff --git a/sbnana/CAFAna/tute/demo3.C b/sbnana/CAFAna/tute/demo3.C index 108f9525..75490779 100644 --- a/sbnana/CAFAna/tute/demo3.C +++ b/sbnana/CAFAna/tute/demo3.C @@ -2,7 +2,8 @@ // cafe demo3.C #include "sbnana/CAFAna/Core/SpectrumLoader.h" -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "CAFAna/Core/Spectrum.h" +#include "CAFAna/Core/HistAxis.h" #include "sbnana/CAFAna/Core/Binning.h" #include "sbnana/CAFAna/Analysis/ExpInfo.h" @@ -20,7 +21,7 @@ void demo3() const Var kRecoE = SIMPLEVAR(reco.reco_energy); const Var kWeight = SIMPLEVAR(reco.weight); const HistAxis axEnergy("True energy (GeV)", Binning::Simple(50, 0, 5), kRecoE); - Spectrum sNominal(loader, axEnergy, kNoCut, kNoShift, kWeight); + Spectrum sNominal(loader.Weighted(kWeight), axEnergy); // Systematics are implemented as objects that either compute a weight for // each event... @@ -30,7 +31,7 @@ void demo3() TailScaleSyst() : ISyst("tailScale", "High energy scale factor") {} // 50% 1sigma shift on normalization of events above 2GeV - void Shift(double sigma, caf::SRProxy* sr, double& weight) const + void Shift(double sigma, caf::SRSliceProxy* sr, double& weight) const { const double E = sr->reco.reco_energy; /**/ if(E > 2) weight *= 1+.5*sigma; @@ -47,7 +48,7 @@ void demo3() EnergyScaleSyst() : ISyst("energyScale", "Energy scale") {} // 20% 1sigma shift on all event energies - void Shift(double sigma, caf::SRProxy* sr, double& weight) const + void Shift(double sigma, caf::SRSliceProxy* sr, double& weight) const { sr->reco.reco_energy *= 1+.2*sigma; } diff --git a/sbnana/FlattenCAF/flatten_caf.cc b/sbnana/FlattenCAF/flatten_caf.cc index 903ec577..3b76c0d7 100644 --- a/sbnana/FlattenCAF/flatten_caf.cc +++ b/sbnana/FlattenCAF/flatten_caf.cc @@ -2,7 +2,7 @@ #include "sbnanaobj/StandardRecord/SRGlobal.h" #include "sbnanaobj/StandardRecord/Flat/FlatRecord.h" -#include "sbnana/CAFAna/Core/Progress.h" +#include "cafanacore/Progress.h" #include "TFile.h" #include "TH1.h" diff --git a/sbnana/SBNAna/Analysis/202106PAC/bar_sbnd.C b/sbnana/SBNAna/Analysis/202106PAC/bar_sbnd.C index 6419492f..92b77490 100644 --- a/sbnana/SBNAna/Analysis/202106PAC/bar_sbnd.C +++ b/sbnana/SBNAna/Analysis/202106PAC/bar_sbnd.C @@ -1,6 +1,7 @@ #include "sbnana/CAFAna/Core/SpectrumLoader.h" -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "cafanacore/Spectrum.h" #include "sbnana/CAFAna/Core/Binning.h" +#include "sbnana/CAFAna/Core/HistAxis.h" #include "sbnana/CAFAna/Core/Var.h" #include "sbnana/CAFAna/Cuts/TruthCuts.h" @@ -41,18 +42,18 @@ void bar_sbnd() const Cut kIsCosmic = SIMPLEVAR(truth.index) < 0; - const HistAxis axCount("", Binning::Simple(1, 0, 1), Constant(.5)); + const HistAxis axCount("", Binning::Simple(1, 0, 1), Var([](const caf::SRSliceProxy*){return .5;})); std::vector sNumuCC; std::vector sCosmic; std::vector sOther; - + Cut accumCut = kNoCut; for(auto& it: cuts){ accumCut = accumCut && it.second; - sNumuCC.push_back(new Spectrum(loader, axCount, kNumuSpillSel, accumCut && kIsNumuCC)); - sCosmic.push_back(new Spectrum(loader, axCount, kNumuSpillSel, accumCut && kIsCosmic)); - sOther.push_back(new Spectrum(loader, axCount, kNumuSpillSel, accumCut && !kIsNumuCC && !kIsCosmic)); + sNumuCC.push_back(new Spectrum(loader[kNumuSpillSel].Slices()[accumCut][kIsNumuCC], axCount)); + sCosmic.push_back(new Spectrum(loader[kNumuSpillSel].Slices()[accumCut][kIsCosmic], axCount)); + sOther.push_back(new Spectrum(loader[kNumuSpillSel].Slices()[accumCut][!kIsNumuCC && !kIsCosmic], axCount)); } loader.Go(); diff --git a/sbnana/SBNAna/Analysis/202106PAC/contours_icarus.C b/sbnana/SBNAna/Analysis/202106PAC/contours_icarus.C index 26b668d5..b2755b26 100644 --- a/sbnana/SBNAna/Analysis/202106PAC/contours_icarus.C +++ b/sbnana/SBNAna/Analysis/202106PAC/contours_icarus.C @@ -1,5 +1,5 @@ #include "sbnana/CAFAna/Core/SpectrumLoader.h" -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "cafanacore/Spectrum.h" #include "sbnana/CAFAna/Core/Binning.h" #include "sbnana/CAFAna/Core/Var.h" #include "sbnana/CAFAna/Core/OscCalcSterileApprox.h" @@ -69,7 +69,7 @@ void contours_icarus() const FitAxis kAxTh(&kFitSinSq2ThetaMuMu, 60, 1e-3, 1, true); const FitAxis kAxDmSq(&kFitDmSqSterile, 60, 1e-2, 1e2, true); - + SingleSampleExperiment expt(&pred, fake); Surface surf(&expt, calc, kAxTh, kAxDmSq); @@ -91,5 +91,5 @@ void contours_icarus() surf.GetGraphs(crit95pc)[0]->Write("fd_stat_95pct"); surf.GetGraphs(crit99pc)[0]->Write("fd_stat_99pct"); - expt.SaveTo(fout.mkdir("fd_expt")); + expt.SaveTo(fout, "fd_expt"); } diff --git a/sbnana/SBNAna/Analysis/202106PAC/contours_sbnd.C b/sbnana/SBNAna/Analysis/202106PAC/contours_sbnd.C index 59f7f52c..078e0fb3 100644 --- a/sbnana/SBNAna/Analysis/202106PAC/contours_sbnd.C +++ b/sbnana/SBNAna/Analysis/202106PAC/contours_sbnd.C @@ -1,5 +1,5 @@ #include "sbnana/CAFAna/Core/SpectrumLoader.h" -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "cafanacore/Spectrum.h" #include "sbnana/CAFAna/Core/Binning.h" #include "sbnana/CAFAna/Core/Var.h" #include "sbnana/CAFAna/Core/OscCalcSterileApprox.h" @@ -60,7 +60,7 @@ void contours_sbnd() const FitAxis kAxTh(&kFitSinSq2ThetaMuMu, 30, 1e-3, 1, true); const FitAxis kAxDmSq(&kFitDmSqSterile, 30, 1e-2, 1e2, true); - + SingleSampleExperiment expt(&pred, fake); Surface surf(&expt, calc, kAxTh, kAxDmSq); @@ -82,5 +82,5 @@ void contours_sbnd() surf.GetGraphs(crit95pc)[0]->Write("nd_stat_95pct"); surf.GetGraphs(crit99pc)[0]->Write("nd_stat_99pct"); - expt.SaveTo(fout.mkdir("nd_expt")); + expt.SaveTo(fout, "nd_expt"); } diff --git a/sbnana/SBNAna/Analysis/202106PAC/spectra_icarus.C b/sbnana/SBNAna/Analysis/202106PAC/spectra_icarus.C index ffebbc89..8ba3398a 100644 --- a/sbnana/SBNAna/Analysis/202106PAC/spectra_icarus.C +++ b/sbnana/SBNAna/Analysis/202106PAC/spectra_icarus.C @@ -1,6 +1,7 @@ #include "sbnana/CAFAna/Core/SpectrumLoader.h" -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "cafanacore/Spectrum.h" #include "sbnana/CAFAna/Core/Binning.h" +#include "sbnana/CAFAna/Core/HistAxis.h" #include "sbnana/CAFAna/Core/Var.h" #include "sbnana/CAFAna/Cuts/TruthCuts.h" @@ -14,6 +15,8 @@ #include "TH1.h" #include "TPad.h" +#include + using namespace ana; // This should be @@ -35,21 +38,21 @@ void spectra_icarus() const Var kTrueE = SIMPLEVAR(truth.E); const Var kRecoE = kTrueE; // TODO - const Var kCryostatWeight = Constant(2); // only using cryo0 + const SpillWeight kCryostatWeight([](const caf::SRSpillProxy*){return 2;}); // only using cryo0 const SpillCut kNumuSpillSel = kNoSpillCut; // TODO const Cut kNumuSel = kNuMuCC_FullSelection; const Cut kIsCosmic = SIMPLEVAR(truth.index) < 0; - // This looks much better than the official fit binning + // This looks much better than the official fit binning const Binning binsEnergy = Binning::Simple(30, 0, 3); const HistAxis axEnergy(/*Reconstructed*/"True energy (GeV)", binsEnergy, kRecoE); - Spectrum sTot(loader, axEnergy, kNumuSpillSel, kNumuSel, kNoShift, kCryostatWeight); - Spectrum sNC(loader, axEnergy, kNumuSpillSel, kNumuSel && kIsNC, kNoShift, kCryostatWeight); - // Spectrum sCosmic(loader, axEnergy, kNumuSpillSel, kNumuSel && kIsCosmic, kNoShift, kCryostatWeight); + Spectrum sTot(loader.Weighted(kCryostatWeight)[kNumuSpillSel].Slices()[kNumuSel], axEnergy); + Spectrum sNC(loader.Weighted(kCryostatWeight)[kNumuSpillSel].Slices()[kNumuSel][kIsNC], axEnergy); + // Spectrum sCosmic(loader.Weighted(kCryostatWeight)[kNumuSpillSel][kNumuSel][kIsCosmic], axEnergy); loader.Go(); diff --git a/sbnana/SBNAna/Analysis/202106PAC/spectra_sbnd.C b/sbnana/SBNAna/Analysis/202106PAC/spectra_sbnd.C index 3b0bec8b..1a59433d 100644 --- a/sbnana/SBNAna/Analysis/202106PAC/spectra_sbnd.C +++ b/sbnana/SBNAna/Analysis/202106PAC/spectra_sbnd.C @@ -1,6 +1,7 @@ #include "sbnana/CAFAna/Core/SpectrumLoader.h" -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "cafanacore/Spectrum.h" #include "sbnana/CAFAna/Core/Binning.h" +#include "sbnana/CAFAna/Core/HistAxis.h" #include "sbnana/CAFAna/Core/Var.h" #include "sbnana/CAFAna/Cuts/TruthCuts.h" @@ -15,6 +16,8 @@ #include "TH1.h" #include "TPad.h" +#include + using namespace ana; // Since I'm in the SBND group the SAM dataset works fine for me @@ -32,14 +35,14 @@ void spectra_sbnd() const Cut kIsCosmic = SIMPLEVAR(truth.index) < 0; - // This looks much better than the official fit binning + // This looks much better than the official fit binning const Binning binsEnergy = Binning::Simple(30, 0, 3); const HistAxis axEnergy(/*Reconstructed*/"True energy (GeV)", binsEnergy, kRecoE); - Spectrum sTot(loader, axEnergy, kNumuSpillSel, kNumuSel); - Spectrum sNC(loader, axEnergy, kNumuSpillSel, kNumuSel && kIsNC); - // Spectrum sCosmic(loader, axEnergy, kNumuSpillSel, kNumuSel && kIsCosmic); + Spectrum sTot(loader[kNumuSpillSel].Slices()[kNumuSel], axEnergy); + Spectrum sNC(loader[kNumuSpillSel].Slices()[kNumuSel][kIsNC], axEnergy); + // Spectrum sCosmic(loader[kNumuSpillSel].Slices[kNumuSel][kIsCosmic], axEnergy); loader.Go(); diff --git a/sbnana/SBNAna/CMakeLists.txt b/sbnana/SBNAna/CMakeLists.txt index e9734021..785d231e 100644 --- a/sbnana/SBNAna/CMakeLists.txt +++ b/sbnana/SBNAna/CMakeLists.txt @@ -1,11 +1,7 @@ -# SBNAna starts all its includes with just SBNAna/ -- allow that -include_directories(..) - -# But we also want to find the generated SRProxy.h under "StandardRecord/Proxy" - include_directories($ENV{MRB_BUILDDIR}/sbnana/sbnana/CAFAna/) - include_directories($ENV{SRPROXY_INC}) +include_directories($ENV{EIGEN_INC}) + # And expects assert() to still function even in the prof build add_definitions(-UNDEBUG) @@ -24,8 +20,6 @@ add_definitions(-Wno-vla) # add_subdirectory(Systs) cet_script(cafe) -# same place as cafe script so we can find it -cet_script(load_cafana_libs.C) #cet_script(rootlogon.C) install_headers() diff --git a/sbnana/SBNAna/Cuts/CMakeLists.txt b/sbnana/SBNAna/Cuts/CMakeLists.txt index 4bed5dfd..467fbaa3 100644 --- a/sbnana/SBNAna/Cuts/CMakeLists.txt +++ b/sbnana/SBNAna/Cuts/CMakeLists.txt @@ -1,6 +1,3 @@ -# Allow "StandardRecord/" to find the right directory -include_directories(..) - cet_make(LIBRARY_NAME SBNAnaCuts LIBRARIES CAFAnaCore SBNAnaVars diff --git a/sbnana/SBNAna/Cuts/Cuts.cxx b/sbnana/SBNAna/Cuts/Cuts.cxx index 7f411ae4..01bd8060 100644 --- a/sbnana/SBNAna/Cuts/Cuts.cxx +++ b/sbnana/SBNAna/Cuts/Cuts.cxx @@ -90,7 +90,7 @@ namespace ana{ { return slc->fmatch.present; }); - + const Cut kSlcFlashMatchCut([](const caf::SRSliceProxy *slc) { return (kSlcHasFlashMatch(slc) && slc->fmatch.score>0 && slc->fmatch.score<6); diff --git a/sbnana/SBNAna/Cuts/NumuCuts.cxx b/sbnana/SBNAna/Cuts/NumuCuts.cxx index 475cc35b..701148e3 100644 --- a/sbnana/SBNAna/Cuts/NumuCuts.cxx +++ b/sbnana/SBNAna/Cuts/NumuCuts.cxx @@ -6,7 +6,7 @@ namespace ana{ const Cut kNumuBasicQual([](const caf::SRSliceProxy* slc) - { // + { // bool hastrk = ( slc->reco.ntrk > 0 ); if (!hastrk) return hastrk; @@ -16,29 +16,29 @@ namespace ana{ }); const Cut kHasFlashMatch([](const caf::SRSliceProxy* slc) - { + { return ( slc->fmatch.present ); }); const Cut kFlashMatchScore([](const caf::SRSliceProxy* slc) - { - return ( slc->fmatch.time > 0 && + { + return ( slc->fmatch.time > 0 && slc->fmatch.score > 6 ); }); const Cut kFlashMatchNumuCut = kHasFlashMatch && kFlashMatchScore; - + const Cut kNumuTrkLen([](const caf::SRSliceProxy* slc) { // TO DO: Prim pandora trk len primary_track.length > fConfig.TrackLength bool hastrk = ( slc->reco.ntrk > 0 ); if (!hastrk) return hastrk; - + unsigned int muIdx = (unsigned int)kPrimMuonIdx(slc); double len = slc->reco.trk[muIdx].len; return (len > 50 ); }); - + // const Cut kNumuContND([](const caf::SRSliceProxy* slc) // { // TO DO: Trk end-point containment // bool hastrk = ( slc->reco.ntrk > 0 ); @@ -59,49 +59,49 @@ namespace ana{ // slc->reco.trk[muIdx].end.z > ( kNDBack -15 ) && // slc->reco.trk[muIdx].end.z < 15 && ) // }); - + // const Cut kNumuContFD([](const caf::SRSliceProxy* slc) // { // TO DO: Trk end-point containment // bool hastrk = ( slc->reco.ntrk > 0 ); // return ( hastrk ); // }); - + // const Cut kNumuVtxFidND([](const caf::SRSliceProxy* slc) // { // TO DO: Vtx Containment // bool hastrk = ( slc->reco.ntrk > 0 ); // return ( hastrk ); // }); - + // const Cut kNumuVtxFidFD([](const caf::SRSliceProxy* slc) // { // TO DO: Vtx Containment // bool hastrk = ( slc->reco.ntrk > 0 ); // return ( hastrk ); - // }); - + // }); + // const Cut kNumuMCSLen([](const caf::SRSliceProxy* slc) // { // TO DO: Prim trk MCS length - primary_track.mcs_momentum < 7. /*garbage value*/&& (fConfig.MCSTrackLength <0. || primary_track.length > fConfig.MCSTrackLength // bool hastrk = ( slc->reco.ntrk > 0 ); // return ( hastrk ); // }); - - + + // const Cut kNumuCRTHit([](const caf::SRSliceProxy* slc) // { // TO DO // bool hastrk = ( slc->reco.ntrk > 0 ); // return ( hastrk ); // }); - + // const Cut kNumuCRTTrk([](const caf::SRSliceProxy* slc) // { // TO DO // bool hastrk = ( slc->reco.ntrk > 0 ); // return ( hastrk ); // }); - + // const Cut kNumuCRTAct([](const caf::SRSliceProxy* slc) // { // TO DO // bool hastrk = ( slc->reco.ntrk > 0 ); // return ( hastrk ); - // }); + // }); } diff --git a/sbnana/SBNAna/Cuts/NumuCutsIcarus202106.cxx b/sbnana/SBNAna/Cuts/NumuCutsIcarus202106.cxx index 5bc520aa..6a12a44d 100644 --- a/sbnana/SBNAna/Cuts/NumuCutsIcarus202106.cxx +++ b/sbnana/SBNAna/Cuts/NumuCutsIcarus202106.cxx @@ -6,13 +6,13 @@ namespace ana { const Cut kIsNuSlice = ( kTruthIndex >= 0.f ); - + const Cut kIsCosmic = ( !kIsNuSlice ); - + const Cut kIsNuMuCC([](const caf::SRSliceProxy* slc) { return ( kIsNuSlice(slc) && slc->truth.iscc && ( slc->truth.pdg == 14 || slc->truth.pdg == -14 ) ); }); - + const Cut kIsNuOther = ( kIsNuSlice && !kIsNuMuCC ); const Cut kCryo0([](const caf::SRSliceProxy* slc) { @@ -58,7 +58,7 @@ namespace ana const Cut kPTrackContained([](const caf::SRSliceProxy* slc) { int Ind = kPTrackInd(slc); bool Contained(false); - if ( Ind >= 0 ) + if ( Ind >= 0 ) { auto const& trk = slc->reco.trk.at(Ind); Contained = ( !isnan(trk.end.x) && @@ -74,7 +74,7 @@ namespace ana const Cut kPTrackExiting([](const caf::SRSliceProxy* slc) { int Ind = kPTrackInd(slc); bool Exiting(false); - if ( Ind >= 0 ) + if ( Ind >= 0 ) { auto const& trk = slc->reco.trk.at(Ind); Exiting = !( !isnan(trk.end.x) && @@ -94,7 +94,7 @@ namespace ana const Cut kCosmic_Cryo0 = ( kIsCosmic && kCryo0 ); const Cut kNuOther_Cryo0 = ( kIsNuOther && kCryo0 ); - + const Cut kNuMuCC_TFiducial = ( kNuMuCC_Cryo0 && kTFiducial ); const Cut kNuMuCC_RFiducial = ( kNuMuCC_Cryo0 && kRFiducial ); @@ -106,31 +106,31 @@ namespace ana const Cut kNuOther_TFiducial = ( kNuOther_Cryo0 && kTFiducial ); const Cut kNuOther_RFiducial = ( kNuOther_Cryo0 && kRFiducial ); - + const Cut kNuMuCC_ClearCos = ( kNuMuCC_TFiducial && kNotClearCosmic ); const Cut kCosmic_ClearCos = ( kCosmic_RFiducial && kNotClearCosmic ); - + const Cut kNuOther_ClearCos = ( kNuOther_TFiducial && kNotClearCosmic ); - + const Cut kNuMuCC_NuScore = ( kNuMuCC_ClearCos && kNuScore ); - + const Cut kCosmic_NuScore = ( kCosmic_ClearCos && kNuScore ); const Cut kNuOther_NuScore = ( kNuOther_ClearCos && kNuScore ); - + const Cut kNuMuCC_FMScore = ( kNuMuCC_NuScore && kFMScore ); const Cut kCosmic_FMScore = ( kCosmic_NuScore && kFMScore ); const Cut kNuOther_FMScore = ( kNuOther_NuScore && kFMScore ); - + const Cut kNuMuCC_PTrack = ( kNuMuCC_FMScore && kPTrack ); const Cut kCosmic_PTrack = ( kCosmic_FMScore && kPTrack ); const Cut kNuOther_PTrack = ( kNuOther_FMScore && kPTrack ); - + // The full selection cut using only reco information. const Cut kNuMuCC_FullSelection = ( kCryo0 && kRFiducial && kNotClearCosmic && kNuScore && kFMScore && kPTrack ); diff --git a/sbnana/SBNAna/Cuts/NumuCutsIcarus202106.h b/sbnana/SBNAna/Cuts/NumuCutsIcarus202106.h index c9b2e3ef..b3b2a471 100644 --- a/sbnana/SBNAna/Cuts/NumuCutsIcarus202106.h +++ b/sbnana/SBNAna/Cuts/NumuCutsIcarus202106.h @@ -30,7 +30,7 @@ namespace ana extern const Cut kPTrack; extern const Cut kPTrackContained; - + extern const Cut kPTrackExiting; // "Successive" cuts for the selection. diff --git a/sbnana/SBNAna/Cuts/TruthCuts.cxx b/sbnana/SBNAna/Cuts/TruthCuts.cxx index 6431e111..937fa9b9 100644 --- a/sbnana/SBNAna/Cuts/TruthCuts.cxx +++ b/sbnana/SBNAna/Cuts/TruthCuts.cxx @@ -7,7 +7,7 @@ namespace ana{ //--------------------------------------------------------------- - // Slice cuts + // Slice cuts const Cut kTrueActiveVolumeND( [](const caf::SRSliceProxy* slc){ return kHasNu(slc) && PtInVolAbsX(slc->truth.position, avnd); @@ -91,7 +91,7 @@ namespace ana{ }); //--------------------------------------------------------------- - // Spill cuts + // Spill cuts const SpillCut kIsCosmicSpill([](const caf::SRSpillProxy* sr) { return (sr->mc.nnu == 0); diff --git a/sbnana/SBNAna/Cuts/TruthCuts.h b/sbnana/SBNAna/Cuts/TruthCuts.h index 9d2d9268..4a69ad5f 100644 --- a/sbnana/SBNAna/Cuts/TruthCuts.h +++ b/sbnana/SBNAna/Cuts/TruthCuts.h @@ -15,7 +15,7 @@ namespace ana extern const Cut kIsCC; extern const Cut kIsNC; - + extern const Cut kTrueActiveVolumeND; extern const Cut kTrueFiducialVolumeND; extern const Cut kTrueActiveVolumeFDCryo1; diff --git a/sbnana/SBNAna/Cuts/VolumeDefinitions.h b/sbnana/SBNAna/Cuts/VolumeDefinitions.h index edcd1ec3..6715e8ab 100644 --- a/sbnana/SBNAna/Cuts/VolumeDefinitions.h +++ b/sbnana/SBNAna/Cuts/VolumeDefinitions.h @@ -24,7 +24,7 @@ const FidVol fvndAbs{ +1.5, +175., // x -175., +175., // y +30., +450.}; // z -// Sometimes (e.g. plotting) we want the full volume +// Sometimes (e.g. plotting) we want the full volume const FidVol fvnd{ -175., +175., // x -175., +175., // y +30., +450.}; // z diff --git a/sbnana/SBNAna/Vars/Binnings.cxx b/sbnana/SBNAna/Vars/Binnings.cxx index 204d5b9b..0c99d51c 100644 --- a/sbnana/SBNAna/Vars/Binnings.cxx +++ b/sbnana/SBNAna/Vars/Binnings.cxx @@ -10,8 +10,8 @@ namespace ana 1000., 1250., 1500., 1750., 2000., 2250., 2500., 2750., 3000., 3250., 3500., 3750., - 4000., 4250., 4500., 4750., 5000.}; - + 4000., 4250., 4500., 4750., 5000.}; + const std::vector kLowEnergyGeVEdges = {.1, .2, .3, .4, .5, .75, 1., 1.25, 1.5, 1.75, 2., 2.25, 2.5, 2.75, diff --git a/sbnana/SBNAna/Vars/CMakeLists.txt b/sbnana/SBNAna/Vars/CMakeLists.txt index 87b47668..94ccc197 100644 --- a/sbnana/SBNAna/Vars/CMakeLists.txt +++ b/sbnana/SBNAna/Vars/CMakeLists.txt @@ -1,6 +1,3 @@ -# Allow "StandardRecord/" to find the right directory -include_directories(..) - cet_make(LIBRARY_NAME SBNAnaVars LIBRARIES CAFAnaCore sbnanaobj_StandardRecordProxy diff --git a/sbnana/SBNAna/Vars/NumuVars.h b/sbnana/SBNAna/Vars/NumuVars.h index 8f5c367c..a702b7c4 100644 --- a/sbnana/SBNAna/Vars/NumuVars.h +++ b/sbnana/SBNAna/Vars/NumuVars.h @@ -1,5 +1,5 @@ #pragma once -// Specific variables for the Numu event selection. +// Specific variables for the Numu event selection. #include "sbnana/CAFAna/Core/Var.h" diff --git a/sbnana/SBNAna/Vars/NumuVarsIcarus202106.h b/sbnana/SBNAna/Vars/NumuVarsIcarus202106.h index 8f21f4c0..fd2561ad 100644 --- a/sbnana/SBNAna/Vars/NumuVarsIcarus202106.h +++ b/sbnana/SBNAna/Vars/NumuVarsIcarus202106.h @@ -11,7 +11,7 @@ namespace ana extern const Var kMuMaxTrack; extern const Var kPTrackInd; - + extern const Var kRecoMuonP; extern const Var kTrueMuonP; diff --git a/sbnana/SBNAna/Vars/NumuVarsSBND202106.cxx b/sbnana/SBNAna/Vars/NumuVarsSBND202106.cxx index 3ef64011..d1407131 100644 --- a/sbnana/SBNAna/Vars/NumuVarsSBND202106.cxx +++ b/sbnana/SBNAna/Vars/NumuVarsSBND202106.cxx @@ -11,8 +11,8 @@ namespace ana // const Var kIsTrackAtSlc([](const caf::SRSliceProxy *slc, const FidVol& vol) // { // double dist = sqrt((slc->reco.trk.start.x - slc->vertex.x)^2 + (slc->reco.trk.start.y - slc->vertex.y)^2 + (slc->reco.trk.start.z - slc->vertex.z)^2); -// return (dist < 10); -// +// return (dist < 10); +// // }); // const Var kIsTrackContained([](const caf::SRSliceProxy *slc, const FidVol& vol) @@ -33,7 +33,7 @@ namespace ana for(unsigned int trkidx = 0; trkidx < slc->reco.trk.size(); ++trkidx){ const caf::SRTrackProxy& trk = slc->reco.trk[trkidx]; if(trk.bestplane == -1) continue; - + //atslc dist = sqrt((pow(trk.start.x - slc->vertex.x,2)) + (pow(trk.start.y - slc->vertex.y,2)) + (pow(trk.start.z - slc->vertex.z,2))); atslc = dist < 10; @@ -42,14 +42,14 @@ namespace ana //contained //contained = ( vol.xmin < trk.end.x && trk.end.x < vol.xmax && vol.ymin < trk.end.y && trk.end.y < vol.ymax && vol.zmin < trk.end.z && trk.end.z < vol.zmax); //The following definition reproduce the numbers from SBNSoftware/sbncode/blob/develop/sbncode/NuMuSelection/jupyter-ana/selection.py - //instead of using the defined Fiducial Volume check implemented in sbnana/SBNAna/Cuts/VolumeDefinitions.h + //instead of using the defined Fiducial Volume check implemented in sbnana/SBNAna/Cuts/VolumeDefinitions.h contained = ( (-199.15 + 10) < trk.end.x && trk.end.x < (199.15 - 10) && (-200. + 10) < trk.end.y && trk.end.y < (200. - 10) && (0.0 + 10) < trk.end.z && trk.end.z < (500. - 50)); //bestplane.chi2 chi2_proton = trk.chi2pid[trk.bestplane].chi2_proton; chi2_muon = trk.chi2pid[trk.bestplane].chi2_muon; - maybe_muon_exiting = !contained && trk.len > 100; + maybe_muon_exiting = !contained && trk.len > 100; maybe_muon_contained = contained && chi2_proton > 60 && chi2_muon < 30 && trk.len > 50; if(!maybe_muon_contained && !maybe_muon_exiting) continue; @@ -57,24 +57,24 @@ namespace ana if(trk.len > longest){ longest = trk.len; best_idx = trkidx; - } + } } return best_idx; }); const Var kPrimaryMuonTrkP([](const caf::SRSliceProxy *slc) { - //bool contained; + //bool contained; //int ptrkid = kPrimaryMuonTrkIdx(slc); //const caf::SRTrackProxy& ptrk = slc->reco.trk[ptrkid]; //contained = ( (-199.15 + 10) < ptrk.end.x && ptrk.end.x < (199.15 - 10) && (-200. + 10) < ptrk.end.y && ptrk.end.y < (200. - 10) && (0.0 + 10) < ptrk.end.z && ptrk.end.z < (500. - 50)); //if(contained) return ptrk.rangeP.p_muon; - //else return ptrk.mcsP.fwdP_muon; + //else return ptrk.mcsP.fwdP_muon; float recop(-5.f); bool contained(false); - + if ( kPrimaryMuonTrkIdx(slc) >= 0 ){ auto const& ptrk = slc->reco.trk.at(kPrimaryMuonTrkIdx(slc)); contained = ( (-199.15 + 10) < ptrk.end.x && ptrk.end.x < (199.15 - 10) && (-200. + 10) < ptrk.end.y && ptrk.end.y < (200. - 10) && (0.0 + 10) < ptrk.end.z && ptrk.end.z < (500. - 50)); diff --git a/sbnana/SBNAna/Vars/NumuVarsSBND202106.h b/sbnana/SBNAna/Vars/NumuVarsSBND202106.h index 6e5aa0ad..527dba5f 100644 --- a/sbnana/SBNAna/Vars/NumuVarsSBND202106.h +++ b/sbnana/SBNAna/Vars/NumuVarsSBND202106.h @@ -1,5 +1,5 @@ #pragma once -// Specific variables for the Numu event selection. +// Specific variables for the Numu event selection. #include "sbnana/CAFAna/Core/Var.h" diff --git a/sbnana/SBNAna/Vars/Vars.cxx b/sbnana/SBNAna/Vars/Vars.cxx index 429dc003..7db635ec 100644 --- a/sbnana/SBNAna/Vars/Vars.cxx +++ b/sbnana/SBNAna/Vars/Vars.cxx @@ -16,8 +16,8 @@ namespace ana const SpillVar kEvt = SIMPLESPILLVAR(hdr.evt); // const Var kSlc = SIMPLEVAR(hdr.subevt); - const Var kCounting = kUnweighted; - const SpillVar kSpillCounting = kSpillUnweighted; + const Var kCounting([](const caf::SRSliceProxy*){return 1;}); + const SpillVar kSpillCounting([](const caf::SRSpillProxy*){return 1;}); // There can be more than one crt hit per spill so the variables are vectors. diff --git a/sbnana/SBNAna/Vars/Vars.h b/sbnana/SBNAna/Vars/Vars.h index 22d7d734..983fd8b5 100644 --- a/sbnana/SBNAna/Vars/Vars.h +++ b/sbnana/SBNAna/Vars/Vars.h @@ -12,12 +12,12 @@ namespace ana // Return the event number extern const SpillVar kEvt; - extern const SpillMultiVar kCRTHitX; - extern const SpillMultiVar kCRTHitY; - extern const SpillMultiVar kCRTHitZ; - extern const SpillMultiVar kCRTHitPE; - extern const SpillMultiVar kCRTHitTime; - extern const SpillMultiVar kCRTHitTimeFD; + extern const SpillMultiVar kCRTHitX; + extern const SpillMultiVar kCRTHitY; + extern const SpillMultiVar kCRTHitZ; + extern const SpillMultiVar kCRTHitPE; + extern const SpillMultiVar kCRTHitTime; + extern const SpillMultiVar kCRTHitTimeFD; // // Return the slice number // extern const SliceVar kSlc; diff --git a/sbnana/SBNAna/anademo/CRUMBS_demo/CRUMBS_demo.C b/sbnana/SBNAna/anademo/CRUMBS_demo/CRUMBS_demo.C index cce21ab8..cd78e1af 100644 --- a/sbnana/SBNAna/anademo/CRUMBS_demo/CRUMBS_demo.C +++ b/sbnana/SBNAna/anademo/CRUMBS_demo/CRUMBS_demo.C @@ -1,5 +1,6 @@ -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "cafanacore/Spectrum.h" #include "sbnana/CAFAna/Core/SpectrumLoader.h" +#include "sbnana/CAFAna/Core/HistAxis.h" #include "sbnanaobj/StandardRecord/Proxy/SRProxy.h" using namespace ana; @@ -18,9 +19,9 @@ void CRUMBS_demo() const Binning binsCRUMBSScore = Binning::Simple(20,-1,1); const Binning binsSliceNTracks = Binning::Simple(10,0,10); - Spectrum specCRUMBSScore = Spectrum("CRUMBS Score", binsCRUMBSScore, loader, kCRUMBSScore, kNoSpillCut, kNonUnambiguousSlice); - Spectrum specBestCRUMBSScore = Spectrum("Best CRUMBS Score", binsCRUMBSScore, loader, kBestCRUMBSScore, kHasNonUnambiguousSlice); - Spectrum specBestCRUMBSSliceNTracks = Spectrum("# Tracks", binsSliceNTracks, loader, kBestCRUMBSSliceNTracks, kHasNonUnambiguousSlice && kBestCRUMBSSliceCut); + Spectrum specCRUMBSScore = Spectrum(loader.Slices()[kNonUnambiguousSlice], HistAxis("CRUMBS Score", binsCRUMBSScore, kCRUMBSScore)); + Spectrum specBestCRUMBSScore = Spectrum(loader[kHasNonUnambiguousSlice], SpillHistAxis("Best CRUMBS Score", binsCRUMBSScore, kBestCRUMBSScore)); + Spectrum specBestCRUMBSSliceNTracks = Spectrum(loader[kHasNonUnambiguousSlice][kBestCRUMBSSliceCut], SpillHistAxis("# Tracks", binsSliceNTracks, kBestCRUMBSSliceNTracks)); loader.Go(); diff --git a/sbnana/SBNAna/anademo/ana01.C b/sbnana/SBNAna/anademo/ana01.C index be9f741b..c8b67668 100644 --- a/sbnana/SBNAna/anademo/ana01.C +++ b/sbnana/SBNAna/anademo/ana01.C @@ -1,7 +1,8 @@ -// Make a plot with cuts +// Make a plot with cuts #include "sbnana/CAFAna/Core/SpectrumLoader.h" -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "cafanacore/Spectrum.h" #include "sbnana/CAFAna/Core/Binning.h" +#include "sbnana/CAFAna/Core/HistAxis.h" using namespace ana; @@ -35,7 +36,7 @@ void ana01() }); // ---- CUTS ----- - // A Cut returns a boolean per slice + // A Cut returns a boolean per slice const Cut kLong ([](const caf::SRSliceProxy* slc) { bool pass = false; @@ -49,14 +50,14 @@ void ana01() const Binning binsN = Binning::Simple(10, 0, 10); const Binning binsLen = Binning::Simple(50, 0, 500); - // axis( ,Binning,Var) + // axis( <Title>,Binning,Var) const HistAxis axNTrk("Number of Tracks", binsN, kNTrk); const HistAxis axLen ("1st Track Length", binsLen, kTrkLen); - // spectrum(Spectrumloader,HistAxis,Cut) - Spectrum sNTracks (loader, axNTrk, kNoCut); - Spectrum sTrkLenAll(loader, axLen, kNoCut); - Spectrum sTrkLen50 (loader, axLen, kLong); + // spectrum(Spectrumloader,HistAxis) + Spectrum sNTracks (loader.Slices(), axNTrk); + Spectrum sTrkLenAll(loader.Slices(), axLen); + Spectrum sTrkLen50 (loader.Slices()[kLong], axLen); // This is the call that actually fills in the spectrum loader.Go(); diff --git a/sbnana/SBNAna/anademo/demo_2020Workshop/demo.h b/sbnana/SBNAna/anademo/demo_2020Workshop/demo.h index b5615ce1..0fe7e51c 100644 --- a/sbnana/SBNAna/anademo/demo_2020Workshop/demo.h +++ b/sbnana/SBNAna/anademo/demo_2020Workshop/demo.h @@ -1,8 +1,8 @@ #include "sbnana/CAFAna/Core/Binning.h" #include "sbnanaobj/StandardRecord/Proxy/SRProxy.h" -#include "SBNAna/Vars/NumuVars.h" -#include "SBNAna/Cuts/TruthCuts.h" +#include "sbnana/SBNAna/Vars/NumuVars.h" +#include "sbnana/SBNAna/Cuts/TruthCuts.h" using namespace ana; @@ -27,17 +27,17 @@ const Var kPrimTrkCosth([](const caf::SRSliceProxy *slc) -> double // Slice Vertex position const Var kSlcVtxX([](const caf::SRSliceProxy *slc) -> double { - return slc->slc.vertex.x; + return slc->vertex.x; }); const Var kSlcVtxY([](const caf::SRSliceProxy *slc) -> double { - return slc->slc.vertex.y; + return slc->vertex.y; }); const Var kSlcVtxZ([](const caf::SRSliceProxy *slc) -> double { - return slc->slc.vertex.z; + return slc->vertex.z; }); // These are examples of useful structs to @@ -51,7 +51,7 @@ struct PlotDef }; // In this example, we are making the following Spectra -std::vector<PlotDef> plots = +std::vector<PlotDef> plots = {{"count", "", Binning::Simple(3,0,3), kCounting}, {"mucosth", "cos#theta", Binning::Simple(10,-1,1), kPrimTrkCosth}, {"vtxx", "X (cm)", Binning::Simple(10,-200,200), kSlcVtxX}, @@ -72,9 +72,9 @@ struct SelDef // See Cuts/TruthCuts to check out these cuts const Cut kSig = kIsNumu && !kIsNC; -// We are making the Spectra defined above -// for 3 different selections. -std::vector<SelDef> sels = +// We are making the Spectra defined above +// for 3 different selections. +std::vector<SelDef> sels = {{"nocut", "All Slices", kNoCut, kBlack}, {"sig", "True NumuCC", kSig, kRed+1}, {"bkg", "Not NumuCC", !kSig, kAzure+2}, @@ -82,7 +82,7 @@ std::vector<SelDef> sels = // If you wanted to add a new cut, define an // expression for kYourCut (see examples in SBNAna/Cuts) -// and then add the following lines to the sels vector: +// and then add the following lines to the sels vector: /* {"all_yourcut", "All Slices", kYourCut, kBlack}, */ /* {"sig_yourcut", "True NumuCC", (kSig && kYourCut), kRed+1}, */ /* {"bkg_yourcut", "Not NumuCC", (!kSig && kYourCut), kAzure+2}, */ diff --git a/sbnana/SBNAna/anademo/demo_2020Workshop/make_demo.C b/sbnana/SBNAna/anademo/demo_2020Workshop/make_demo.C index 504abf84..b41b4fa4 100644 --- a/sbnana/SBNAna/anademo/demo_2020Workshop/make_demo.C +++ b/sbnana/SBNAna/anademo/demo_2020Workshop/make_demo.C @@ -1,12 +1,15 @@ // Make a few spectra with different cuts. #include "sbnana/CAFAna/Core/SpectrumLoader.h" -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "sbnana/CAFAna/Core/HistAxis.h" +#include "cafanacore/Spectrum.h" #include "demo.h" #include "TFile.h" +#include <iostream> + using namespace ana; void make_demo() @@ -27,7 +30,7 @@ void make_demo() for(unsigned int iSel = 0; iSel < kNSel; ++iSel){ for(unsigned int jVar = 0; jVar < kNVar; ++jVar){ - specs[iSel][jVar] = new Spectrum(plots[jVar].label, plots[jVar].bins, loader, plots[jVar].var, sels[iSel].cut); + specs[iSel][jVar] = new Spectrum(loader.Slices()[sels[iSel].cut], HistAxis(plots[jVar].label, plots[jVar].bins, plots[jVar].var)); } } @@ -41,7 +44,7 @@ void make_demo() for( unsigned int jVar = 0; jVar < kNVar; ++jVar ){ std::string mysuffix = sels[iSel].suffix + "_" + plots[jVar].suffix; std::cout << "Saving spctra: " << mysuffix << std::endl; - specs[iSel][jVar]->SaveTo( fout.mkdir(mysuffix.c_str()) ); + specs[iSel][jVar]->SaveTo(&fout, mysuffix); } } diff --git a/sbnana/SBNAna/anademo/demo_2020Workshop/plot_demo.C b/sbnana/SBNAna/anademo/demo_2020Workshop/plot_demo.C index 42f06828..db8c3280 100644 --- a/sbnana/SBNAna/anademo/demo_2020Workshop/plot_demo.C +++ b/sbnana/SBNAna/anademo/demo_2020Workshop/plot_demo.C @@ -1,4 +1,4 @@ -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "cafanacore/Spectrum.h" #include "sbnana/CAFAna/Core/LoadFromFile.h" #include "demo.h" @@ -22,7 +22,7 @@ void plot_demo(std::string inFile) // I want to make a plot for each var for(unsigned int iVar = 0; iVar < kNVar; ++iVar){ - + TCanvas *c = new TCanvas(plots[iVar].suffix.c_str(),plots[iVar].suffix.c_str()); std::vector<TH1*> hists; @@ -44,7 +44,7 @@ void plot_demo(std::string inFile) hists[0]->GetYaxis()->CenterTitle(); hists[0]->Draw("hist"); - for(unsigned int jSel = 0; jSel < kNSel; ++jSel) + for(unsigned int jSel = 0; jSel < kNSel; ++jSel) hists[jSel]->Draw("hist same"); hists[0]->Draw("hist same"); l->Draw(); diff --git a/sbnana/SBNAna/anademo/demo_exposure.C b/sbnana/SBNAna/anademo/demo_exposure.C index 2a52eb4a..e1b040f3 100644 --- a/sbnana/SBNAna/anademo/demo_exposure.C +++ b/sbnana/SBNAna/anademo/demo_exposure.C @@ -1,5 +1,5 @@ #include "sbnana/CAFAna/Core/SpectrumLoader.h" -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "cafanacore/Spectrum.h" #include "sbnana/CAFAna/Core/Binning.h" #include "sbnana/CAFAna/Core/Var.h" diff --git a/sbnana/SBNAna/anademo/rootlogon.C b/sbnana/SBNAna/anademo/rootlogon.C index 7a3ed506..4de6358d 100755 --- a/sbnana/SBNAna/anademo/rootlogon.C +++ b/sbnana/SBNAna/anademo/rootlogon.C @@ -152,7 +152,7 @@ void CenterTitles(TH1* histo) { histo->GetXaxis()->CenterTitle(); histo->GetYaxis()->CenterTitle(); - histo->GetZaxis()->CenterTitle(); + histo->GetZaxis()->CenterTitle(); } #endif diff --git a/sbnana/SBNAna/ananue/PAC2020/SBND/helper.h b/sbnana/SBNAna/ananue/PAC2020/SBND/helper.h index 1b204b9e..5f154dfe 100644 --- a/sbnana/SBNAna/ananue/PAC2020/SBND/helper.h +++ b/sbnana/SBNAna/ananue/PAC2020/SBND/helper.h @@ -2,17 +2,17 @@ #include "sbnana/CAFAna/Core/Binning.h" #include "sbnana/CAFAna/Core/Cut.h" -#include "sbnana/CAFAna/Core/Ratio.h" +#include "cafanacore/Ratio.h" #include "sbnanaobj/StandardRecord/Proxy/SRProxy.h" -#include "SBNAna/Cuts/Cuts.h" -#include "SBNAna/Cuts/NueCuts.h" -#include "SBNAna/Cuts/TruthCuts.h" -#include "SBNAna/Cuts/VolumeDefinitions.h" -#include "SBNAna/Vars/Binnings.h" -#include "SBNAna/Vars/NueVars.h" -#include "SBNAna/Vars/TruthVars.h" -#include "SBNAna/Vars/Vars.h" +#include "sbnana/SBNAna/Cuts/Cuts.h" +#include "sbnana/SBNAna/Cuts/NueCuts.h" +#include "sbnana/SBNAna/Cuts/TruthCuts.h" +#include "sbnana/SBNAna/Cuts/VolumeDefinitions.h" +#include "sbnana/SBNAna/Vars/Binnings.h" +#include "sbnana/SBNAna/Vars/NueVars.h" +#include "sbnana/SBNAna/Vars/TruthVars.h" +#include "sbnana/SBNAna/Vars/Vars.h" #include <fstream> diff --git a/sbnana/SBNAna/ananue/PAC2020/SBND/make_spectra_eff_spill.C b/sbnana/SBNAna/ananue/PAC2020/SBND/make_spectra_eff_spill.C index ac4b3d14..b2ef2870 100644 --- a/sbnana/SBNAna/ananue/PAC2020/SBND/make_spectra_eff_spill.C +++ b/sbnana/SBNAna/ananue/PAC2020/SBND/make_spectra_eff_spill.C @@ -1,7 +1,8 @@ // Make a few spectra with different cuts. -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "cafanacore/Spectrum.h" #include "sbnana/CAFAna/Core/SpectrumLoader.h" +#include "sbnana/CAFAna/Core/HistAxis.h" #include "helper_eff_spill.h" @@ -61,7 +62,7 @@ void make_spectra_eff_spill(const std::string fname = "etyley_caf_NuEOverlay_caf for (unsigned int iSel = 0; iSel < kNSel; ++iSel) { for (unsigned int jType = 0; jType < kNType; ++jType) { for (unsigned int lVar = 0; lVar < kNVar; ++lVar) { - specs[iSel][jType][lVar] = new Spectrum(plots[lVar].label, plots[lVar].bins, loader, plots[lVar].var, types[jType].cut && sels[iSel].cut); + specs[iSel][jType][lVar] = new Spectrum(loader[types[jType].cut][sels[iSel].cut], SpillHistAxis(plots[lVar].label, plots[lVar].bins, plots[lVar].var)); } } } @@ -81,7 +82,7 @@ void make_spectra_eff_spill(const std::string fname = "etyley_caf_NuEOverlay_caf const double thisPOT(spec->POT()); if (thisPOT < std::numeric_limits<double>::epsilon()) spec->OverridePOT(cosmicPOT); - spec->SaveTo(fout.mkdir(mysuffix.c_str())); + spec->SaveTo(&fout, mysuffix); } } } @@ -90,7 +91,7 @@ void make_spectra_eff_spill(const std::string fname = "etyley_caf_NuEOverlay_caf // for( unsigned int jVar = 0; jVar < kNVarSpill; ++jVar ){ // std::string mysuffix = sels_spill[iSel].suffix + "_" + plots_spill[jVar].suffix; // std::cout << "Saving spectra: " << mysuffix << std::endl; - // specsSpill[iSel][jVar]->SaveTo( fout.mkdir(mysuffix.c_str()) ); + // specsSpill[iSel][jVar]->SaveTo(&fout, mysuffix); // } // } } diff --git a/sbnana/SBNAna/ananue/PAC2020/SBND/make_spectra_pur_slc_cumulative.C b/sbnana/SBNAna/ananue/PAC2020/SBND/make_spectra_pur_slc_cumulative.C index 1320287d..f9dd86d4 100644 --- a/sbnana/SBNAna/ananue/PAC2020/SBND/make_spectra_pur_slc_cumulative.C +++ b/sbnana/SBNAna/ananue/PAC2020/SBND/make_spectra_pur_slc_cumulative.C @@ -1,7 +1,8 @@ // Make a few spectra with different cuts. -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "cafanacore/Spectrum.h" #include "sbnana/CAFAna/Core/SpectrumLoader.h" +#include "sbnana/CAFAna/Core/HistAxis.h" #include "helper_pur_slc_cumulative.h" @@ -63,7 +64,7 @@ void make_spectra_pur_slc_cumulative(const std::string fname = "etyley_caf_NuEOv kCumulative = kCumulative && sels[iSel].cut; for (unsigned int jType = 0; jType < kNType; ++jType) { for (unsigned int lVar = 0; lVar < kNVar; ++lVar) { - specs[iSel][jType][lVar] = new Spectrum(plots[lVar].label, plots[lVar].bins, loader, plots[lVar].var, kCRTHitVetoND && kSpillSingleNu, types[jType].cut && kCumulative); + specs[iSel][jType][lVar] = new Spectrum(loader[kCRTHitVetoND && kSpillSingleNu].Slices()[types[jType].cut][kCumulative], HistAxis(plots[lVar].label, plots[lVar].bins, plots[lVar].var)); } } } @@ -83,7 +84,7 @@ void make_spectra_pur_slc_cumulative(const std::string fname = "etyley_caf_NuEOv const double thisPOT(spec->POT()); if (thisPOT < std::numeric_limits<double>::epsilon()) spec->OverridePOT(cosmicPOT); - spec->SaveTo(fout.mkdir(mysuffix.c_str())); + spec->SaveTo(&fout, mysuffix); } } } diff --git a/sbnana/SBNAna/ananue/PAC2020/SBND/plot_spectra_eff_spill.C b/sbnana/SBNAna/ananue/PAC2020/SBND/plot_spectra_eff_spill.C index 914719b2..22f44982 100644 --- a/sbnana/SBNAna/ananue/PAC2020/SBND/plot_spectra_eff_spill.C +++ b/sbnana/SBNAna/ananue/PAC2020/SBND/plot_spectra_eff_spill.C @@ -1,5 +1,5 @@ #include "sbnana/CAFAna/Core/LoadFromFile.h" -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "cafanacore/Spectrum.h" #include "helper_eff_spill.h" diff --git a/sbnana/SBNAna/ananue/PAC2020/SBND/plot_spectra_pur_slc_cumulative.C b/sbnana/SBNAna/ananue/PAC2020/SBND/plot_spectra_pur_slc_cumulative.C index 50c01ca0..4cc80a33 100644 --- a/sbnana/SBNAna/ananue/PAC2020/SBND/plot_spectra_pur_slc_cumulative.C +++ b/sbnana/SBNAna/ananue/PAC2020/SBND/plot_spectra_pur_slc_cumulative.C @@ -1,5 +1,5 @@ #include "sbnana/CAFAna/Core/LoadFromFile.h" -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "cafanacore/Spectrum.h" #include "helper_pur_slc_cumulative.h" diff --git a/sbnana/SBNAna/ananue/eventselection/helper_nuesel_icarus.h b/sbnana/SBNAna/ananue/eventselection/helper_nuesel_icarus.h index 7e657334..7cb403cf 100644 --- a/sbnana/SBNAna/ananue/eventselection/helper_nuesel_icarus.h +++ b/sbnana/SBNAna/ananue/eventselection/helper_nuesel_icarus.h @@ -1,16 +1,16 @@ -#pragma once +#pragma once #include "sbnana/CAFAna/Core/Binning.h" #include "sbnana/CAFAna/Core/Cut.h" #include "sbnanaobj/StandardRecord/Proxy/SRProxy.h" -#include "SBNAna/Vars/Binnings.h" -#include "SBNAna/Vars/NueVars.h" -#include "SBNAna/Vars/TruthVars.h" -#include "SBNAna/Vars/Vars.h" -#include "SBNAna/Cuts/Cuts.h" -#include "SBNAna/Cuts/NueCuts.h" -#include "SBNAna/Cuts/TruthCuts.h" +#include "sbnana/SBNAna/Vars/Binnings.h" +#include "sbnana/SBNAna/Vars/NueVars.h" +#include "sbnana/SBNAna/Vars/TruthVars.h" +#include "sbnana/SBNAna/Vars/Vars.h" +#include "sbnana/SBNAna/Cuts/Cuts.h" +#include "sbnana/SBNAna/Cuts/NueCuts.h" +#include "sbnana/SBNAna/Cuts/TruthCuts.h" #include "TStyle.h" @@ -183,7 +183,7 @@ const SpillCut kFullSpillCut([](const caf::SRSpillProxy* sr) { // ---------------------------------------------------------------------------------------------- // Plots -std::vector<PlotDef> plots_slice = +std::vector<PlotDef> plots_slice = {{"count", "Number of slices", Binning::Simple(3,0,3), kCounting}, {"openangle", "Opening angle", kOpenAngleBinning, kRecoShower_OpenAngle}, {"startx", "Shower start position X (cm)", kPositionXFDBinning, kRecoShower_StartX}, @@ -195,9 +195,9 @@ std::vector<PlotDef> plots_slice = {"vtxx", "Slice vertex X (cm)", kPositionXFDBinning, kSlcVtxX}, {"vtxy", "Slice vertes Y (cm)", kPositionYFDBinning, kSlcVtxY}, {"vtxz", "Slice vertex Z (cm)", kPositionZFDBinning, kSlcVtxZ}, - {"conversion", "Conversion gap (cm)", kGapBinning, kRecoShower_ConversionGap}, - {"bestdedx", "Best plane dEdx (MeV)", kDedxBinning, kRecoShower_BestdEdx}, - {"bestenergy", "Best plane energy (MeV)", kEnergyBinning, kRecoShower_BestEnergy}, + {"conversion", "Conversion gap (cm)", kGapBinning, kRecoShower_ConversionGap}, + {"bestdedx", "Best plane dEdx (MeV)", kDedxBinning, kRecoShower_BestdEdx}, + {"bestenergy", "Best plane energy (MeV)", kEnergyBinning, kRecoShower_BestEnergy}, {"density", "Shower density (MeV/cm)", kDensityBinning, kRecoShower_Density}, {"energy", "Shower energy (MeV)", kNueEnergyBinning, kRecoShower_Energy}, {"lengthshw", "Shower length (cm)", kLengthBinning, kRecoShower_Length}, @@ -207,7 +207,7 @@ std::vector<PlotDef> plots_slice = {"truthenergy","True #nu energy (GeV)", kLowEnergyGeVBinning, kTruthEnergy}, }; -std::vector<PlotDefSpill> plots_spill = +std::vector<PlotDefSpill> plots_spill = {{"count", "Number of spills", Binning::Simple(3,0,3), kSpillCounting}, { "nuenergy", "True Neutrino Energy (GeV)", kLowEnergyGeVBinning, kTruthNuEnergy }, { "leptonenergy", "True Lepton Energy (GeV)", kLowEnergyGeVBinning, kTruthLeptonEnergy } diff --git a/sbnana/SBNAna/ananue/eventselection/make_eventstable_nuesel_icarus.C b/sbnana/SBNAna/ananue/eventselection/make_eventstable_nuesel_icarus.C index 2591b75a..81b3489c 100644 --- a/sbnana/SBNAna/ananue/eventselection/make_eventstable_nuesel_icarus.C +++ b/sbnana/SBNAna/ananue/eventselection/make_eventstable_nuesel_icarus.C @@ -1,8 +1,8 @@ /////////////////////////////////////////////////////////////////////// // Author: Diana Patricia Mendez // // Contact: dmendezme@bnl.gov // -// Last edited: January 15 2021 // -// // +// Last edited: January 15 2021 // +// // // Makes summary event count tables from the spectra produced by // // make_spectra.C // // Setting N1table to true will make a table of the N1 cuts only // @@ -10,7 +10,7 @@ #pragma once -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "cafanacore/Spectrum.h" #include "sbnana/CAFAna/Core/LoadFromFile.h" #include "helper_nuesel_icarus.h" @@ -49,7 +49,7 @@ void make_eventstable_nuesel_icarus(bool crtveto = true) // } const unsigned int kNSel = sels.size(); - + std::vector<std::string> names_cut; std::vector<float> events_nue; std::vector<float> events_numu; @@ -63,7 +63,7 @@ void make_eventstable_nuesel_icarus(bool crtveto = true) unsigned int endLoop = kNSel; if(crtveto) endLoop = kNSel+2; // add one for crtveto and one for the N-1 crtveto - for(unsigned int iSel = 0; iSel < endLoop; iSel++){ + for(unsigned int iSel = 0; iSel < endLoop; iSel++){ // std::string mysuffixall; std::string mysuffix; @@ -88,7 +88,7 @@ void make_eventstable_nuesel_icarus(bool crtveto = true) } } names_cut.push_back(cutname); - + std::cout << "cutname: " << cutname << ", mysuffix: " << mysuffix << std::endl; Spectrum *spec_allnue = LoadFromFile<Spectrum>(inFile_nue, "nue_nocut_count").release(); Spectrum *spec_nue = LoadFromFile<Spectrum>(inFile_nue, "nue_"+mysuffix).release(); @@ -126,7 +126,7 @@ void make_eventstable_nuesel_icarus(bool crtveto = true) float itotbkg = htotbkg->Integral(); float itotal = htotal->Integral(); float ieff = inue / iallnue; - float ipur = inue / (inue + itotbkg); + float ipur = inue / (inue + itotbkg); events_nue.push_back(inue); events_numu.push_back(inumu); @@ -137,13 +137,13 @@ void make_eventstable_nuesel_icarus(bool crtveto = true) events_total.push_back(itotal); if(iSel==0){ eff.push_back(0.); - pur.push_back(0.); + pur.push_back(0.); } else{ eff.push_back(ieff); pur.push_back(ipur); } - + } // iSel simple // print single cuts only table diff --git a/sbnana/SBNAna/ananue/eventselection/make_spectra_nuesel_icarus.C b/sbnana/SBNAna/ananue/eventselection/make_spectra_nuesel_icarus.C index e6a8e3e9..1d33e5e3 100644 --- a/sbnana/SBNAna/ananue/eventselection/make_spectra_nuesel_icarus.C +++ b/sbnana/SBNAna/ananue/eventselection/make_spectra_nuesel_icarus.C @@ -1,16 +1,17 @@ /////////////////////////////////////////////////////////////////////// // Author: Diana Patricia Mendez // // Contact: dmendezme@bnl.gov // -// Last edited: January 15 2021 // -// // -// Makes spectra of the variables defined in helper with specific // +// Last edited: January 15 2021 // +// // +// Makes spectra of the variables defined in helper with specific // // cuts applied to the sample(s). // // Takes a CAF from where to read the data and outputs a ROOT file // // containing the resulted histograms // /////////////////////////////////////////////////////////////////////// #include "sbnana/CAFAna/Core/SpectrumLoader.h" -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "sbnana/CAFAna/Core/HistAxis.h" +#include "cafanacore/Spectrum.h" #include "helper_nuesel_icarus.h" @@ -99,15 +100,16 @@ void make_spectra_nuesel_icarus(std::string finname = "nucosmics", int setno = 1 for(unsigned int iSel = 0; iSel < kNSel; ++iSel){ for(unsigned int iType = 0; iType < kNType; ++iType){ for(unsigned int jVar = 0; jVar < kNVar; ++jVar){ - specs[iSel][iType][jVar] = new Spectrum(plots[jVar].label, plots[jVar].bins, loader, plots[jVar].var, sels[iSel].cut && types[iType].cut); - specsveto[iSel][iType][jVar] = new Spectrum(plots[jVar].label, plots[jVar].bins, loader, plots[jVar].var, kCRTHitVetoFD, sels[iSel].cut && types[iType].cut); // Add CRT veto + const HistAxis ax(plots[jVar].label, plots[jVar].bins, plots[jVar].var); + specs[iSel][iType][jVar] = new Spectrum(loader.Slices()[sels[iSel].cut][types[iType].cut], ax); + specsveto[iSel][iType][jVar] = new Spectrum(loader[kCRTHitVetoFD].Slices()[sels[iSel].cut][types[iType].cut], ax); // Add CRT veto } } } for(unsigned int iSel = 0; iSel < kNSelCRTSpill; ++iSel){ for(unsigned int jVar = 0; jVar < kNVarCRTSpill; ++jVar){ - specscrtspill[iSel][jVar] = new Spectrum(crtplots_spill[jVar].label, crtplots_spill[jVar].bins, loader, crtplots_spill[jVar].var, crtsels_spill[iSel].cut); + // specscrtspill[iSel][jVar] = new Spectrum(loader[crtsels_spill[iSel].cut], SpillHistAxis(crtplots_spill[jVar].label, crtplots_spill[jVar].bins, crtplots_spill[jVar].var)); } } // actually make the spectra @@ -132,8 +134,8 @@ void make_spectra_nuesel_icarus(std::string finname = "nucosmics", int setno = 1 specveto->OverridePOT(cosmicPOT); } } // fake cosmics pot - spec->SaveTo(fout.mkdir(mysuffix.c_str())); - specveto->SaveTo(fout.mkdir(mysuffixveto.c_str())); + spec->SaveTo(&fout, mysuffix); + specveto->SaveTo(&fout, mysuffixveto); } } } @@ -141,8 +143,8 @@ void make_spectra_nuesel_icarus(std::string finname = "nucosmics", int setno = 1 for( unsigned int iSel = 0; iSel < kNSelCRTSpill; ++iSel ){ for( unsigned int jVar = 0; jVar < kNVarCRTSpill; ++jVar ){ std::string mysuffix = crtsels_spill[iSel].suffix + "_" + crtplots_spill[jVar].suffix; - std::cout << "Saving spectra: " << mysuffix << std::endl; - specscrtspill[iSel][jVar]->SaveTo( fout.mkdir(mysuffix.c_str()) ); + // std::cout << "Saving spectra: " << mysuffix << std::endl; + // specscrtspill[iSel][jVar]->SaveTo(&fout, mysuffix); } } diff --git a/sbnana/SBNAna/ananue/eventselection/plot_spectra_nuesel_icarus.C b/sbnana/SBNAna/ananue/eventselection/plot_spectra_nuesel_icarus.C index e821727c..db9e67a7 100644 --- a/sbnana/SBNAna/ananue/eventselection/plot_spectra_nuesel_icarus.C +++ b/sbnana/SBNAna/ananue/eventselection/plot_spectra_nuesel_icarus.C @@ -1,8 +1,8 @@ /////////////////////////////////////////////////////////////////////// // Author: Diana Patricia Mendez // // Contact: dmendezme@bnl.gov // -// Last edited: January 15 2021 // -// // +// Last edited: January 15 2021 // +// // // Plots the spectra produced by make_spectra.C // // Setting effpur to true will plot a split canvas, with the spectra // // at the top and efficiency and purity at the bottom. // @@ -11,7 +11,7 @@ #pragma once #include "../../../CAFAna/rootlogon.C" -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "cafanacore/Spectrum.h" #include "sbnana/CAFAna/Core/LoadFromFile.h" #include "helper_nuesel_icarus.h" @@ -180,7 +180,7 @@ void plot_spectra_nuesel_icarus( float iother = hother->Integral(); float itotbkg = htotbkg->Integral(); - // Make a simple canvas, with only one pad + // Make a simple canvas, with only one pad TCanvas *cEvents = new TCanvas(plots[iVar].suffix.c_str(),plots[iVar].suffix.c_str(), 700, 500); if(iVar==0){ // fake stacking hnumu->Add(hnc); @@ -198,7 +198,7 @@ void plot_spectra_nuesel_icarus( hother->GetYaxis()->SetRangeUser(1.,100 * GetHistMax({hnue,hnumu,hnc,htotcos,hother})); } else{ - hother->GetYaxis()->SetRangeUser(0.,1.3 * GetHistMax({hnue,hnumu,hnc,htotcos,hother})); + hother->GetYaxis()->SetRangeUser(0.,1.3 * GetHistMax({hnue,hnumu,hnc,htotcos,hother})); } hother->GetYaxis()->SetTitle("Slices"); hother->Draw("hist same"); @@ -290,7 +290,7 @@ void plot_spectra_nuesel_icarus( float integral = hist_crt->Integral(); TCanvas *cEventsCRT = new TCanvas(crtplots_spill[iVar].suffix.c_str(),crtplots_spill[iVar].suffix.c_str(), 700, 500); - hist_crt->GetYaxis()->SetRangeUser(0.,1.3 * hist_crt->GetMaximum()); + hist_crt->GetYaxis()->SetRangeUser(0.,1.3 * hist_crt->GetMaximum()); hist_crt->GetYaxis()->SetTitle("Spills"); Simulation(true); cEventsCRT->Update(); diff --git a/sbnana/SBNAna/ananue/eventselection/tools_nuesel_icarus.h b/sbnana/SBNAna/ananue/eventselection/tools_nuesel_icarus.h index d21a0426..8ab7ff59 100644 --- a/sbnana/SBNAna/ananue/eventselection/tools_nuesel_icarus.h +++ b/sbnana/SBNAna/ananue/eventselection/tools_nuesel_icarus.h @@ -1,4 +1,4 @@ -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "cafanacore/Spectrum.h" #include "sbnana/CAFAna/Core/LoadFromFile.h" #include "TCanvas.h" @@ -187,9 +187,9 @@ namespace ana{ leg->AddEntry(h2, name2,"l"); leg->AddEntry(h2, TString::Format("%.2f",iBkg),""); //leg->AddEntry(h2, TString::Format("Ratio=%.2f",iRatio),""); - leg->SetBorderSize(0); //no border for legend - leg->SetFillColor(0); //fill colour is white - leg->SetFillStyle(0); //fill colour is white + leg->SetBorderSize(0); //no border for legend + leg->SetFillColor(0); //fill colour is white + leg->SetFillStyle(0); //fill colour is white leg->SetTextSize(0.04); leg->Draw(); @@ -197,7 +197,7 @@ namespace ana{ //-------------------------------------------------- void DrawIntEffPurLegend(TH1D* g1, char *name1, TH1D* g2, char *name2){ - + float int1 = g1->Integral(); float int2 = g2->Integral(); TLegend *leg = new TLegend(.65,.2,.85,.3); @@ -265,7 +265,7 @@ namespace ana{ pText2->Draw(); } - // Efficiency and purity graphs + // Efficiency and purity graphs //----------------------------------------------------------------- TH1D* EffOrPurHistogram(TH1* hSelSignal, TH1* hSelBack, TH1* hSignal, bool geteff) { diff --git a/sbnana/SBNAna/ananue/helper.h b/sbnana/SBNAna/ananue/helper.h index ec666606..082626e6 100644 --- a/sbnana/SBNAna/ananue/helper.h +++ b/sbnana/SBNAna/ananue/helper.h @@ -1,15 +1,15 @@ -#pragma once +#pragma once #include "sbnana/CAFAna/Core/Binning.h" #include "sbnana/CAFAna/Core/Cut.h" #include "sbnanaobj/StandardRecord/Proxy/SRProxy.h" -#include "SBNAna/Vars/Binnings.h" -#include "SBNAna/Vars/NueVars.h" -#include "SBNAna/Vars/Vars.h" -#include "SBNAna/Cuts/Cuts.h" -#include "SBNAna/Cuts/NueCuts.h" -#include "SBNAna/Cuts/TruthCuts.h" +#include "sbnana/SBNAna/Vars/Binnings.h" +#include "sbnana/SBNAna/Vars/NueVars.h" +#include "sbnana/SBNAna/Vars/Vars.h" +#include "sbnana/SBNAna/Cuts/Cuts.h" +#include "sbnana/SBNAna/Cuts/NueCuts.h" +#include "sbnana/SBNAna/Cuts/TruthCuts.h" using namespace ana; @@ -40,10 +40,10 @@ const Binning kTimeBinning = Binning::Simple(70,0.,3500); // // In this example, we are making the following Spectra -std::vector<PlotDef> plots = +std::vector<PlotDef> plots = {{"count", "", Binning::Simple(3,0,3), kCounting}, - {"bestenergy", "Best plane energy (GeV)", kLowEnergyBinningGeV, kRecoShower_BestEnergy}, - {"conversion", "Conversion gap (cm)", kGapBinning, kRecoShower_ConversionGap}, + {"bestenergy", "Best plane energy (GeV)", kLowEnergyBinningGeV, kRecoShower_BestEnergy}, + {"conversion", "Conversion gap (cm)", kGapBinning, kRecoShower_ConversionGap}, {"density", "Shower density (MeV/cm)", kDensityBinning, kRecoShower_Density}, {"energy", "Energy (MeV)", kNueEnergyBinning, kRecoShower_Energy}, {"length", "Length (cm)", kLengthBinning, kRecoShower_Length}, diff --git a/sbnana/SBNAna/ananue/make_spectra.C b/sbnana/SBNAna/ananue/make_spectra.C index a49d6c65..4b363bca 100644 --- a/sbnana/SBNAna/ananue/make_spectra.C +++ b/sbnana/SBNAna/ananue/make_spectra.C @@ -1,12 +1,15 @@ // Make a few spectra with different cuts. #include "sbnana/CAFAna/Core/SpectrumLoader.h" -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "sbnana/CAFAna/Core/HistAxis.h" +#include "cafanacore/Spectrum.h" #include "helper.h" #include "TFile.h" +#include <iostream> + using namespace ana; void make_spectra() @@ -29,15 +32,15 @@ void make_spectra() for(unsigned int iSel = 0; iSel < kNSel; ++iSel){ for(unsigned int jVar = 0; jVar < kNVar; ++jVar){ - specs[iSel][jVar] = new Spectrum(plots[jVar].label, plots[jVar].bins, loader, plots[jVar].var, sels[iSel].cut); + specs[iSel][jVar] = new Spectrum(loader.Slices()[sels[iSel].cut], HistAxis(plots[jVar].label, plots[jVar].bins, plots[jVar].var)); } } // Example spectra with both SpillCut and Cut - Spectrum *s0 = new Spectrum("crthitx__flashtrig", kPositionXFDBinning, loader, kCRTHitX, kFlashTrigger); // SpillMultiVar with SpillCut - Spectrum *s1 = new Spectrum("shwlen__firstevt_longshw", kLengthBinning, loader, kRecoShower_Length, kFirstEvents, !kShortShower); // (Slice)Var with SpillCut and (Slice)Cut - Spectrum *s2 = new Spectrum("shwlen__flashtrig_longshw", kLengthBinning, loader, kRecoShower_Length, kFlashTrigger, !kShortShower); // (Slice)Var with SpillCut and (Slice)Cut - Spectrum *s3 = new Spectrum("shwlen__flashtrig_shortshw", kLengthBinning, loader, kRecoShower_Length, kFlashTrigger, kShortShower); // (Slice)Var with SpillCut and (Slice)Cut + // Spectrum *s0 = new Spectrum(loader[kFlashTrigger], SpillHistAxis("crthitx__flashtrig", kPositionXFDBinning, kCRTHitX)); // SpillMultiVar with SpillCut + Spectrum *s1 = new Spectrum(loader[kFirstEvents].Slices()[!kShortShower], HistAxis("shwlen__firstevt_longshw", kLengthBinning, kRecoShower_Length)); // (Slice)Var with SpillCut and (Slice)Cut + Spectrum *s2 = new Spectrum(loader[kFlashTrigger].Slices()[!kShortShower], HistAxis("shwlen__flashtrig_longshw", kLengthBinning, kRecoShower_Length)); // (Slice)Var with SpillCut and (Slice)Cut + Spectrum *s3 = new Spectrum(loader[kFlashTrigger].Slices()[kShortShower], HistAxis("shwlen__flashtrig_shortshw", kLengthBinning, kRecoShower_Length)); // (Slice)Var with SpillCut and (Slice)Cut // This is the call that actually fills in the spectra loader.Go(); @@ -49,13 +52,13 @@ void make_spectra() for( unsigned int jVar = 0; jVar < kNVar; ++jVar ){ std::string mysuffix = sels[iSel].suffix + "_" + plots[jVar].suffix; std::cout << "Saving spectra: " << mysuffix << std::endl; - specs[iSel][jVar]->SaveTo( fout.mkdir(mysuffix.c_str()) ); + specs[iSel][jVar]->SaveTo(&fout, mysuffix); } } - s0->SaveTo( fout.mkdir("s0")); - s1->SaveTo( fout.mkdir("s1")); - s2->SaveTo( fout.mkdir("s2")); - s3->SaveTo( fout.mkdir("s3")); + // s0->SaveTo(&fout, "s0"); + s1->SaveTo(&fout, "s1"); + s2->SaveTo(&fout, "s2"); + s3->SaveTo(&fout, "s3"); } diff --git a/sbnana/SBNAna/ananue/plot_spectra.C b/sbnana/SBNAna/ananue/plot_spectra.C index 450c6aeb..9e1d8388 100644 --- a/sbnana/SBNAna/ananue/plot_spectra.C +++ b/sbnana/SBNAna/ananue/plot_spectra.C @@ -1,4 +1,4 @@ -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "cafanacore/Spectrum.h" #include "sbnana/CAFAna/Core/LoadFromFile.h" #include "helper.h" @@ -23,7 +23,7 @@ void plot_spectra(std::string inFile) // I want to make a plot for each var for(unsigned int iVar = 0; iVar < kNVar; ++iVar){ - + TCanvas *c = new TCanvas(plots[iVar].suffix.c_str(),plots[iVar].suffix.c_str()); std::vector<TH1*> hists; @@ -47,7 +47,7 @@ void plot_spectra(std::string inFile) hists[0]->GetYaxis()->CenterTitle(); hists[0]->Draw("hist"); - for(unsigned int jSel = 0; jSel < kNSel; ++jSel) + for(unsigned int jSel = 0; jSel < kNSel; ++jSel) hists[jSel]->Draw("hist same"); hists[0]->Draw("hist same"); l->Draw(); diff --git a/sbnana/SBNAna/ananumu/AnaBasics/eventsel.h b/sbnana/SBNAna/ananumu/AnaBasics/eventsel.h index 2f82a4d4..ca8e7f2f 100644 --- a/sbnana/SBNAna/ananumu/AnaBasics/eventsel.h +++ b/sbnana/SBNAna/ananumu/AnaBasics/eventsel.h @@ -1,20 +1,13 @@ #include "sbnana/CAFAna/Core/Binning.h" #include "sbnanaobj/StandardRecord/Proxy/SRProxy.h" -#include "SBNAna/Vars/Vars.h" -#include "SBNAna/Vars/NumuVars.h" -#include "SBNAna/Cuts/NumuCuts.h" -#include "SBNAna/Cuts/TruthCuts.h" +#include "sbnana/SBNAna/Vars/Vars.h" +#include "sbnana/SBNAna/Vars/NumuVars.h" +#include "sbnana/SBNAna/Cuts/NumuCuts.h" +#include "sbnana/SBNAna/Cuts/TruthCuts.h" using namespace ana; - -// Useful for counting the number of events that pass a cut -const Var kCounting([](const caf::SRSliceProxy *slc) - { - return 1; - }); - // Costh of the numu primary track (See Vars/NumuVars.cxx) const Var kPrimTrkCosth([](const caf::SRSliceProxy *slc) { @@ -29,7 +22,7 @@ const Var kPrimTrkCRTdist([](const caf::SRSliceProxy *slc) { int muIdx = kPrimMuonIdx(slc); if( muIdx < 0 ) return -5.; - + return (double)slc->reco.trk[muIdx].crthit.distance; }); @@ -45,7 +38,7 @@ struct PlotDef }; // In this example, we are making the following Spectra -std::vector<PlotDef> plots = +std::vector<PlotDef> plots = {{"count", "", Binning::Simple(3,0,3), kCounting}, {"mucosth", "cos#theta", Binning::Simple(50,-1,1), kPrimTrkCosth}, {"vtxx", "X (cm)", Binning::Simple(50,-200,200), kSlcVtxX}, @@ -68,9 +61,9 @@ struct SelDef // See Cuts/TruthCuts to check out these cuts const Cut kSig = kIsNumu && !kIsNC; -// We are making the Spectra defined above -// for 3 different selections. -std::vector<SelDef> sels = +// We are making the Spectra defined above +// for 3 different selections. +std::vector<SelDef> sels = {{"nocut", "All Slices", kNoCut, kBlack}, {"sig", "True NumuCC", kSig, kRed+1}, {"bkg", "Not NumuCC", !kSig, kAzure+2}, @@ -78,7 +71,7 @@ std::vector<SelDef> sels = // If you wanted to add a new cut, define an // expression for kYourCut (see examples in SBNAna/Cuts) -// and then add the following lines to the sels vector: +// and then add the following lines to the sels vector: /* {"all_yourcut", "All Slices", kYourCut, kBlack}, */ /* {"sig_yourcut", "True NumuCC", (kSig && kYourCut), kRed+1}, */ /* {"bkg_yourcut", "Not NumuCC", (!kSig && kYourCut), kAzure+2}, */ diff --git a/sbnana/SBNAna/ananumu/AnaBasics/make_eventsel.C b/sbnana/SBNAna/ananumu/AnaBasics/make_eventsel.C index 3ce0d2d7..57997919 100644 --- a/sbnana/SBNAna/ananumu/AnaBasics/make_eventsel.C +++ b/sbnana/SBNAna/ananumu/AnaBasics/make_eventsel.C @@ -1,12 +1,15 @@ // Make a few spectra with different cuts. #include "sbnana/CAFAna/Core/SpectrumLoader.h" -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "sbnana/CAFAna/Core/HistAxis.h" +#include "cafanacore/Spectrum.h" #include "eventsel.h" #include "TFile.h" +#include <iostream> + using namespace ana; void make_eventsel() @@ -28,7 +31,7 @@ void make_eventsel() for(unsigned int iSel = 0; iSel < kNSel; ++iSel){ for(unsigned int jVar = 0; jVar < kNVar; ++jVar){ - specs[iSel][jVar] = new Spectrum(plots[jVar].label, plots[jVar].bins, loader, plots[jVar].var, sels[iSel].cut); + specs[iSel][jVar] = new Spectrum(loader.Slices()[sels[iSel].cut], HistAxis(plots[jVar].label, plots[jVar].bins, plots[jVar].var)); } } @@ -42,7 +45,7 @@ void make_eventsel() for( unsigned int jVar = 0; jVar < kNVar; ++jVar ){ std::string mysuffix = sels[iSel].suffix + "_" + plots[jVar].suffix; std::cout << "Saving spctra: " << mysuffix << std::endl; - specs[iSel][jVar]->SaveTo( fout.mkdir(mysuffix.c_str()) ); + specs[iSel][jVar]->SaveTo(&fout, mysuffix); } } diff --git a/sbnana/SBNAna/ananumu/AnaBasics/plot_eventsel.C b/sbnana/SBNAna/ananumu/AnaBasics/plot_eventsel.C index 70d912b0..d401ed87 100644 --- a/sbnana/SBNAna/ananumu/AnaBasics/plot_eventsel.C +++ b/sbnana/SBNAna/ananumu/AnaBasics/plot_eventsel.C @@ -1,4 +1,4 @@ -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "cafanacore/Spectrum.h" #include "sbnana/CAFAna/Core/LoadFromFile.h" #include "eventsel.h" @@ -22,7 +22,7 @@ void plot_eventsel(std::string inFile) // I want to make a plot for each var for(unsigned int iVar = 0; iVar < kNVar; ++iVar){ - + TCanvas *c = new TCanvas(plots[iVar].suffix.c_str(),plots[iVar].suffix.c_str()); std::vector<TH1*> hists; @@ -44,7 +44,7 @@ void plot_eventsel(std::string inFile) hists[0]->GetYaxis()->CenterTitle(); hists[0]->Draw("hist"); - for(unsigned int jSel = 0; jSel < kNSel; ++jSel) + for(unsigned int jSel = 0; jSel < kNSel; ++jSel) hists[jSel]->Draw("hist same"); hists[0]->Draw("hist same"); l->Draw(); diff --git a/sbnana/SBNAna/ananumu/XSecSelection/eventsel.h b/sbnana/SBNAna/ananumu/XSecSelection/eventsel.h index 23fe81da..62718b30 100644 --- a/sbnana/SBNAna/ananumu/XSecSelection/eventsel.h +++ b/sbnana/SBNAna/ananumu/XSecSelection/eventsel.h @@ -33,7 +33,7 @@ const Var kPrimTrkCRTdist([](const caf::SRSliceProxy *slc) { int muIdx = kPrimMuonIdx(slc); if( muIdx < 0 ) return -5.; - + return (double)slc->reco.trk[muIdx].crthit.distance; }); @@ -49,7 +49,7 @@ struct PlotDef }; // In this example, we are making the following Spectra -std::vector<PlotDef> plots = +std::vector<PlotDef> plots = {{"count", "", Binning::Simple(3,0,3), kCounting}, {"count_scale", "", Binning::Simple(3,0,3), kCounting_scale}, {"mucosth", "cos#theta", Binning::Simple(50,-1,1), kPrimTrkCosth}, @@ -87,7 +87,7 @@ const Cut kIsNuMuCC([](const caf::SRSliceProxy* slc) { }); const Cut kIsNuOther = ( kIsNuSlice && !kIsNuMuCC ); -const Cut kNoCut_numucc = kNoCut && kIsNuMuCC; +const Cut kNoCut_numucc = kNoCut && kIsNuMuCC; const Cut kNoCut_cosmic = kNoCut && kIsCosmic; const Cut kNoCut_othernu = kNoCut && kIsNuOther; const Cut kPreSelection_numucc = kSlcNuScoreCut && kInFV && kIsNuMuCC; @@ -103,8 +103,8 @@ const Cut kALLCuts_numucc = kSlcNuScoreCut && kInFV && kSlcFlashMatchTimeCut && const Cut kALLCuts_cosmic = kSlcNuScoreCut && kInFV && kSlcFlashMatchTimeCut && kSlcFlashMatchScoreCut && kHasPrimaryMuonTrk && kCRTTrackAngleCut && kCRTHitDistanceCut && kIsCosmic; const Cut kALLCuts_othernu = kSlcNuScoreCut && kInFV && kSlcFlashMatchTimeCut && kSlcFlashMatchScoreCut && kHasPrimaryMuonTrk && kCRTTrackAngleCut && kCRTHitDistanceCut && kIsNuOther; -// We are making the Spectra defined above -std::vector<SelDef> sels = +// We are making the Spectra defined above +std::vector<SelDef> sels = {{"nocut_numucc", "All Slices", kNoCut_numucc, kRed}, {"nocut_cosmic", "All Slices", kNoCut_cosmic, kRed+1}, {"nocut_othernu", "All Slices", kNoCut_othernu, kRed+2}, @@ -124,7 +124,7 @@ std::vector<SelDef> sels = // If you wanted to add a new cut, define an // expression for kYourCut (see examples in SBNAna/Cuts) -// and then add the following lines to the sels vector: +// and then add the following lines to the sels vector: /* {"all_yourcut", "All Slices", kYourCut, kBlack}, */ /* {"sig_yourcut", "True NumuCC", (kSig && kYourCut), kRed+1}, */ /* {"bkg_yourcut", "Not NumuCC", (!kSig && kYourCut), kAzure+2}, */ diff --git a/sbnana/SBNAna/ananumu/XSecSelection/make_eventsel.C b/sbnana/SBNAna/ananumu/XSecSelection/make_eventsel.C index b06e12ec..3b44fcfe 100644 --- a/sbnana/SBNAna/ananumu/XSecSelection/make_eventsel.C +++ b/sbnana/SBNAna/ananumu/XSecSelection/make_eventsel.C @@ -1,12 +1,15 @@ // Make a few spectra with different cuts. #include "sbnana/CAFAna/Core/SpectrumLoader.h" -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "sbnana/CAFAna/Core/HistAxis.h" +#include "cafanacore/Spectrum.h" #include "eventsel.h" #include "TFile.h" +#include <iostream> + using namespace ana; void make_eventsel() @@ -30,7 +33,7 @@ void make_eventsel() for(unsigned int iSel = 0; iSel < kNSel; ++iSel){ for(unsigned int jVar = 0; jVar < kNVar; ++jVar){ - specs[iSel][jVar] = new Spectrum(plots[jVar].label, plots[jVar].bins, loader, plots[jVar].var, sels[iSel].cut); + specs[iSel][jVar] = new Spectrum(loader.Slices()[sels[iSel].cut], HistAxis(plots[jVar].label, plots[jVar].bins, plots[jVar].var)); } } @@ -45,7 +48,7 @@ void make_eventsel() for( unsigned int jVar = 0; jVar < kNVar; ++jVar ){ std::string mysuffix = sels[iSel].suffix + "_" + plots[jVar].suffix; std::cout << "Saving spctra: " << mysuffix << std::endl; - specs[iSel][jVar]->SaveTo( fout.mkdir(mysuffix.c_str()) ); + specs[iSel][jVar]->SaveTo( &fout, mysuffix ); } } diff --git a/sbnana/SBNAna/ananumu/XSecSelection/plot_eventsel.C b/sbnana/SBNAna/ananumu/XSecSelection/plot_eventsel.C index 62d45a11..c401fecb 100644 --- a/sbnana/SBNAna/ananumu/XSecSelection/plot_eventsel.C +++ b/sbnana/SBNAna/ananumu/XSecSelection/plot_eventsel.C @@ -1,4 +1,4 @@ -#include "sbnana/CAFAna/Core/Spectrum.h" +#include "cafanacore/Spectrum.h" #include "sbnana/CAFAna/Core/LoadFromFile.h" #include "eventsel.h" @@ -22,7 +22,7 @@ void plot_eventsel(std::string inFile) // I want to make a plot for each var for(unsigned int iVar = 0; iVar < kNVar; ++iVar){ - + TCanvas *c = new TCanvas(plots[iVar].suffix.c_str(),plots[iVar].suffix.c_str()); std::vector<TH1*> hists; @@ -44,7 +44,7 @@ void plot_eventsel(std::string inFile) hists[0]->GetYaxis()->CenterTitle(); hists[0]->Draw("hist"); - for(unsigned int jSel = 0; jSel < kNSel; ++jSel) + for(unsigned int jSel = 0; jSel < kNSel; ++jSel) hists[jSel]->Draw("hist same"); hists[0]->Draw("hist same"); l->Draw(); diff --git a/sbnana/SBNAna/build_dicts.sh b/sbnana/SBNAna/build_dicts.sh index 96fa44b9..15d51f14 100755 --- a/sbnana/SBNAna/build_dicts.sh +++ b/sbnana/SBNAna/build_dicts.sh @@ -10,7 +10,7 @@ LIBDIR=$MRB_INSTALL/sbnana/$SBNANA_VERSION/${CET_SUBDIR}.${MRB_QUALS/:/.}/lib/ DIRS="Cuts Vars" -find $DIRS -name '*.h' | sed 's:\(.*\):#include "SBNAna/\1":' > classes.h +find $DIRS -name '*.h' | sed 's:\(.*\):#include "sbnana/SBNAna/\1":' > classes.h genreflex classes.h \ -s classes_def.xml \ diff --git a/sbnana/SBNAna/cafe b/sbnana/SBNAna/cafe index 0e4746e5..d1787627 100755 --- a/sbnana/SBNAna/cafe +++ b/sbnana/SBNAna/cafe @@ -1,11 +1,16 @@ #!/bin/env python +from __future__ import print_function + # Welcome banner -print('** Common Analysis Format Executor -- SBN edition **') +print('** NOvA Common Analysis Format Executor **') import os, sys import argparse import tempfile +import getpass +import datetime +import subprocess import code @@ -18,12 +23,12 @@ def makeParser(): help = 'quit at end of job') parser.add_argument('-bq', action = 'store_true', help = 'shorthand for -b -q') - parser.add_argument('-nr', '--no-recompile', action = 'store_true', - help = "don't unconditionally recompile, ie .C+ not .C++") stridegroup = parser.add_argument_group('dataset modifiers') stridegroup.add_argument('-s', '--stride', metavar='N', type=int, help = 'use only every Nth file of datasets') + stridegroup.add_argument('-l', '--limit', metavar='N', type=int, + help = 'use only the first N files of datasets') stridegroup.add_argument('-o', '--offset', metavar='M', type=int, help = 'skip first M files of dataset (for use with -s)') stridegroup.add_argument('-ss', '--snapshot', action = 'store_true', @@ -53,15 +58,6 @@ def makeParser(): return parser -def libsPath(): - if 'SBNANA_FQ_DIR' in os.environ: - # ups product - return os.environ['SBNANA_FQ_DIR']+'/bin/load_cafana_libs.C' - else: - # checked out under mrb - return os.environ['SBNANA_DIR']+'/sbnana/SBNAna/load_cafana_libs.C' - - def escapeArg(arg): try: # If it's "true" or "false" or we can parse it as a number, @@ -75,61 +71,32 @@ def escapeArg(arg): def toFunctionParams(args): """Comma seperated list of parameters""" - return "("+','.join([escapeArg(a) for a in args])+")" + return "("+', '.join([escapeArg(a) for a in args])+")" if __name__ == '__main__': - # This is a bit of a hack. If you start cafe with no script argument, - # this will make it think it's opening a ROOT file. The eventual effect is - # just to start ROOT with the right libraries loaded. - sys.argv += ' ' + # Hack to allow the case of `cafe' with no script argument + sys.argv += [' '] parser = makeParser() opts = vars(parser.parse_args()) - if opts['bq']: - opts['batch'] = True - opts['quit'] = True - - # Suppress splash screen and default rootlogon (load_libs calls the - # official one) - exe = 'root' - rootargs = ['-l', '-n'] script = opts['script.C'] - while script[-1] == '+': script = script[:-1] # Strip back to raw .C - # Drop the last argument, because it's the space hack from above - args = opts['args'][:-1] - if opts['batch']: rootargs.append('-b') - if opts['quit']: rootargs.append('-q') + if script != ' ': opts['args'] = opts['args'][:-1] # drop the stray space - if opts['gdb']: - exe = 'gdb' - rootargs = ['--args', 'root.exe'] + rootargs - if opts['valgrind']: - exe = 'valgrind' - rootargs = ['--leak-check=no', - '--suppressions='+os.environ['ROOTSYS']+'/etc/valgrind-root.supp', - 'root.exe'] + rootargs - if opts['leakcheck']: - exe = 'valgrind' - rootargs = ['--leak-check=full', - '--suppressions='+os.environ['ROOTSYS']+'/etc/valgrind-root.supp', - 'root.exe'] + rootargs - if opts['massif']: - exe = 'valgrind' - rootargs = ['--tool=massif', - '--suppressions='+os.environ['ROOTSYS']+'/etc/valgrind-root.supp', - 'root.exe'] + rootargs - if opts['totalview']: - exe = 'totalview' - rootargs = ['root.exe', '-a'] + rootargs + if opts['bq']: + opts['batch'] = True + opts['quit'] = True if opts['gdb'] or opts['valgrind'] or opts['leakcheck'] or opts['massif'] or opts['totalview']: # Disable the default backtrace printouts since presumably the user # intends to get their own os.environ['CAFE_NO_BACKTRACE'] = '1' + else: + # Otherwise need to opt-in, since we don't have a root.exe command line + os.environ['CAFE_YES_BACKTRACE'] = '1' if opts['prof']: os.environ['CPUPROFILE'] = tempfile.mkstemp()[1] # 'perf/cprof.prof' @@ -139,6 +106,11 @@ if __name__ == '__main__': print('Illegal value for --stride:', opts['stride']) sys.exit(1) os.environ['CAFANA_STRIDE'] = str(opts['stride']) + if opts['limit'] != None: + if opts['limit'] <= 0: + print('Illegal value for --limit:', opts['limit']) + sys.exit(1) + os.environ['CAFANA_LIMIT'] = str(opts['limit']) if opts['offset'] != None: if opts['stride'] == None: print('Cannot specify --offset without --stride') @@ -151,8 +123,25 @@ if __name__ == '__main__': if opts['snapshot']: os.environ['CAFANA_USE_SNAPSHOTS'] = 'yes' + path = [os.environ['SBNANA_INC'], + os.environ['SBNANAOBJ_INC'], + os.environ['CAFANACORE_INC'], + os.environ['OSCLIB_INC'], + os.environ['SRPROXY_INC'], + os.environ['ROOT_INC'], + os.environ['STAN_MATH_INC'], + os.environ['BOOST_INC'], + os.environ['EIGEN_INC'], + os.environ['OSCLIB_INC']] + if script.endswith('.py'): - for a in ['gdb', 'valgrind', 'leakcheck', 'massif', 'totalview', 'prof']: + + # Take manual control of $ROOT_INCLUDE_PATH so we can decide what is + # and isn't accesssible. + os.environ['ROOT_INCLUDE_PATH'] = ':'.join(path) + + for a in ['gdb', 'valgrind', 'leakcheck', 'massif', 'totalview', 'prof', + 'numubarccinc', 'numucc2p2h', 'nuebarccinc', 'numubarccpi0', 'numuccpi0', 'ndid']: if opts[a]: print('Warning: option --'+a, 'not supported for python scripts') @@ -160,38 +149,145 @@ if __name__ == '__main__': import ROOT ROOT.gROOT.SetBatch(True) - # Add cafana.py to the path - if 'SBNANA_FQ_DIR' in os.environ: - # ups product - sys.path.append(os.environ['SBNANA_FQ_DIR']+'/bin/') - else: - # checked out under mrb - sys.path.append(os.environ['SBNANA_DIR']+'/sbnana/CAFAna/') - - sys.argv = args + sys.argv = opts['args'] exec(open(script).read()) if not opts['quit']: code.interact(banner='press Ctrl-D to quit') sys.exit(0) - if (script.endswith('.C') or script.endswith('.C+')): - # Usually use .C++ to ensure the macro will always be recompiled, with - # no possibility of version skew. .C+ if the speed-freak option has - # been enabled. - suffix = '+' if opts['no_recompile'] else '++' + d = tempfile.TemporaryDirectory('', 'cafana_'+getpass.getuser()+'_'+datetime.datetime.now().strftime('%Y%m%d_%H%M%S')+'_') + + # Suppress splash screen and default rootlogon + args = ['-l', '-n'] + if opts['batch']: args += ['-b'] + if opts['quit']: args += ['-q'] - # root, then library loading, then script, then the function parameters - rootargs.append(libsPath()) - rootargs.append(script+suffix+toFunctionParams(args)) + if script.endswith('.C'): + inc = os.path.abspath(script) + bname = os.path.basename(script) + fname = bname[0:bname.find('.')] else: - # Not a .C script. Maybe the user's trying to open a root file. In any - # case, just pass through all the arguments uninterpreted. - rootargs.append(libsPath()) - if script != ' ': rootargs.append(script) - rootargs += args + inc = '/dev/null' # harmless to include + fname = 'void' # harmless to "execute" + args += [script] + opts['args'] + opts['args'] = [] + + with open(d.name+'/'+fname+'.cxx', 'w') as fsrc: + fsrc.write('''// Autogenerated by cafe +#include "{INC}" // the user's macro + +#include "TRint.h" +#include "TROOT.h" +#include "TSystem.h" + +#include <iostream> + +int main(int argc, char** argv) +{{ + // Do this at runtime so the profiler library is unloaded before our main + // libraries, meaning that the code in ProfilerSupport runs at the right time + // (after the profile file is made). This does mean that we aren't able to + // profile library loading/startup. + if(gSystem->Getenv("CPUPROFILE")){{ + // We were passed the --prof option + const std::string cpuprof = gSystem->Getenv("CPUPROFILE"); + + std::cout << "Profiling enabled." << std::endl; + + const char* pd = getenv("GPERFTOOLS_DIR"); + if(pd){{ + gSystem->Load((std::string(pd)+"/lib/libprofiler.so").c_str()); + // Somehow the library load manages to corrupt the env var? Put it back. + gSystem->Setenv("CPUPROFILE", cpuprof.c_str()); + }} + else{{ + std::cout << "Couldn't find gperftools library" << std::endl; + }} + }} + + TRint app("cafe", &argc, argv); + app.SetPrompt("cafe [%d] "); + gROOT->Macro("$SBNANA_FQ_DIR/bin/rootlogon.C"); + gROOT->ForceStyle(); + {FUNC}{ARGS}; // execute the user's macro + app.Run(); + return 0; +}} +'''.format(INC = inc, + FUNC = fname, + ARGS = toFunctionParams(opts['args']))) + + libdirs = [os.environ['SBNANAOBJ_LIB'], + os.environ['SBNANA_LIB'], + os.environ['OSCLIB_LIB'], + os.environ['CAFANACORE_LIB'], + os.environ['BOOST_LIB'], + os.environ['TBB_LIB'],] + + libs = ['tbb', + 'Minuit2', + 'OscLib', + 'sbnanaobj_StandardRecordProxy', + 'CAFAnaCoreExt', + 'CAFAnaCore', + 'CAFAnaUnfold', + 'CAFAnaVars', + 'CAFAnaCuts', + 'CAFAnaSysts', + 'CAFAnaExtrap', + 'CAFAnaPrediction', + 'CAFAnaExperiment', + 'CAFAnaAnalysis', + 'CAFAnaXSec', + 'SBNAnaCuts', + 'SBNAnaVars', + ] + + 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 -DTBB_INTERFACE_NEW '+incs +# print(compile_cmd) + ret = subprocess.run(compile_cmd, shell=True).returncode + if ret != 0: sys.exit(ret) + + print('Linking macro...') + libdirstr = ' '.join(['-L '+l for l in libdirs]) + libstr = ' '.join(['-l '+l for l in libs]) + link_cmd = 'g++ '+d.name+'/'+fname+'.o'+' -o '+d.name+'/'+fname+' '+libdirstr+' '+libstr+' `root-config --libs` -lEG' +# print(link_cmd) + ret = subprocess.run(link_cmd, shell=True).returncode + if ret != 0: sys.exit(ret) + + cmd = [d.name+'/'+fname] + args + + if opts['gdb']: cmd = ['gdb', '--args'] + cmd + + # Suppressions file for various valgrind modes + supp = os.environ['ROOTSYS']+'/etc/valgrind-root.supp' + + if opts['valgrind']: + cmd = ['valgrind', '--leak-check=no', '--suppressions='+supp] + cmd + + if opts['leakcheck']: + cmd = ['valgrind', '--leak-check=full', '--suppressions='+supp] + cmd + + if opts['massif']: + cmd = ['valgrind', '--tool=massif', '--suppressions='+supp] + cmd + + if opts['totalview']: cmd = ['totalview'] + cmd + + print('Executing macro...') + p = subprocess.Popen(cmd) + while True: + try: + p.wait() + break + except KeyboardInterrupt: + # We want to forward the signal to the subprocess so it can + # potentially be handled gracefully rather than quitting python + # itself. + p.terminate() - # Show the user what we're doing in case we got it wrong - print(exe, ' '.join(rootargs)) - # Replace the whole process - os.execvp(exe, [exe]+rootargs) + # Return back the script's return code to the system + sys.exit(p.returncode) diff --git a/sbnana/SBNAna/load_cafana_libs.C b/sbnana/SBNAna/load_cafana_libs.C deleted file mode 100644 index ca2a17bb..00000000 --- a/sbnana/SBNAna/load_cafana_libs.C +++ /dev/null @@ -1,135 +0,0 @@ -// -*- mode: c++; c-basic-offset: 2; -*- -void load(std::string lib) -{ - std::cout << "." << std::flush; - int ret = gSystem->Load(("lib"+lib).c_str()); - // In case of error, exit immediately with the error clearly showing, instead - // of with a confusing secondary error about a page of output later. - if(ret != 0){ - std::cout << std::endl << "gSystem->Load(lib"+lib+") failed with code " << ret << std::endl; - exit(ret); - } -} - -void load_cafana_libs() -{ - // All the CINT exception handler does is obfuscate the stack. With this, - // uncaught exceptions immediately show a useful backtrace under gdb. - // G__SetCatchException(0); - - TString qmrb = gSystem->Getenv("MRB_QUALS"); - // Mirror the optimization settings in use elsewhere - if(qmrb.Contains("debug")) { - gSystem->SetAclicMode(TSystem::kDebug); - } - else{ - gSystem->SetAclicMode(TSystem::kOpt); - } - - // This magic incantation prevents ROOT doing slow cleanup work in - // TList::RecursiveRemove() under ~TH1(). It also tends to lead to shutdown - // crashes. This seems like a good compromise: go fast in batch mode - // (probably fitting) and slow but not crashy in interactive move (probably - // want to see the plots). - if(gROOT->IsBatch()) gROOT->SetMustClean(false); - - // Colorize error messages. Would be better if we could just pick up the - // flags novasoft uses, but they don't seem to be in any env var. - gSystem->SetFlagsDebug(TString(gSystem->GetFlagsDebug())+" -fdiagnostics-color=auto"); - gSystem->SetFlagsOpt(TString(gSystem->GetFlagsOpt())+" -fdiagnostics-color=auto -UNDEBUG"); // match gcc's maxopt behaviour of retaining assert() - - std::string incdir; - if(getenv("SBNANA_INC")){ - // ups product - incdir = std::string(getenv("SBNANA_INC")); - } - else{ - // local mrb checkout - char* mrbi = getenv("MRB_INSTALL"); - if(!mrbi){ - std::cout << "$MRB_INSTALL is not set" << std::endl; - exit(1); - } - char* sbnv = getenv("SBNANA_VERSION"); - if(!sbnv){ - std::cout << "$SBNANA_VERSION is not set" << std::endl; - exit(1); - } - - incdir = std::string(mrbi)+"/sbnana/"+std::string(sbnv)+"/include/"; - } - - TString includes = "-I"+incdir+" -I$ROOTSYS/include -I$SRPROXY_INC -I$OSCLIB_INC -I$EIGEN_INC"; - - // List of libraries to load. Dependency order. - const std::vector<std::string> libs = - { - "Minuit2", - // "StandardRecord", - "sbnanaobj_StandardRecordProxy", - // "StandardRecord_dict", - "OscLib", - "CAFAnaCore", - "CAFAnaUnfold", - "CAFAnaVars", - "CAFAnaCuts", - "SBNAnaVars", - "SBNAnaCuts", - "CAFAnaSysts", - "CAFAnaExtrap", - "CAFAnaPrediction", - "CAFAnaExperiment", - "CAFAnaAnalysis", - }; - - // Actually load the libraries - std::cout << "Loading libraries"; - for(const std::string& lib: libs) load(lib); - std::cout << std::endl; - - - gSystem->SetIncludePath(includes); - - // Doesn't seem to work - // gSystem->Setenv("IFDH_DEBUG", "0"); // shut ifdh up - - // Pick up standard style - if(getenv("SBNANA_FQ_DIR")){ - gROOT->Macro("${SBNANA_FQ_DIR}/bin/rootlogon.C"); - } - else{ - gROOT->Macro("${MRB_BUILDDIR}/sbnana/bin/rootlogon.C"); - } - gROOT->ForceStyle(); - - TRint* rint = dynamic_cast<TRint*>(gApplication); - if(rint) rint->SetPrompt("cafe [%d] "); - - - // Do this last so that the profiler library is unloaded before our main - // libraries, meaning that the code in ProfilerSupport runs at the right time - // (after the profile file is made). This does mean that we aren't able to - // profile library loading/startup. The ideal solution would be to make a - // mini-library for just ProfilerSupport. - if(gSystem->Getenv("CPUPROFILE")){ - // We were passed the --prof option - const std::string cpuprof = gSystem->Getenv("CPUPROFILE"); - - std::cout << "Profiling enabled." << std::endl; - - if(!qmrb.Contains("debug")){ - std::cout << "Note: profiling works much better in debug mode." << std::endl; - } - - const char* pd = getenv("GPERFTOOLS_DIR"); - if(pd){ - gSystem->Load((std::string(pd)+"/lib/libprofiler.so").c_str()); - // Apparently the library load manages to corrupt the env var? Put it - // back. - gSystem->Setenv("CPUPROFILE", cpuprof.c_str()); - } - else{ - std::cout << "Couldn't find gperftools library" << std::endl; - } - } -} diff --git a/ups/product_deps b/ups/product_deps index 90f1a8d1..7605b582 100644 --- a/ups/product_deps +++ b/ups/product_deps @@ -39,6 +39,7 @@ sbnanaobj v09_19_00 ifdhc v2_6_6 # For CAFAna osclib v00.17 +cafanacore v02.00 # flux syst histograms etc sbndata v01_03 @@ -50,11 +51,11 @@ end_product_list # We now define allowed qualifiers and the corresponding qualifiers for the dependencies. # Make the table by adding columns before "notes". -qualifier sbnanaobj ifdhc osclib sbndata notes -e20:debug e20:debug e20:debug:p392 e20:debug:n309:stanfree -nq- -nq- -e20:prof e20:prof e20:prof:p392 e20:prof:n309:stanfree -nq- -nq- -c7:debug c7:debug c7:debug:p392 c7:debug:n309:stanfree -nq- -nq- -c7:prof c7:prof c7:prof:p392 c7:prof:n309:stanfree -nq- -nq- +qualifier sbnanaobj ifdhc sbndata osclib cafanacore notes +e20:debug e20:debug e20:debug:p392 -nq- e20:debug:n311:stan e20:debug:n311 -nq- +e20:prof e20:prof e20:prof:p392 -nq- e20:prof:n311:stan e20:prof:n311 -nq- +c7:debug c7:debug c7:debug:p392 -nq- c7:debug:n311:stan c7:debug:n311 -nq- +c7:prof c7:prof c7:prof:p392 -nq- c7:prof:n311:stan c7:prof:n311 -nq- end_qualifier_list # Preserve tabs and formatting in emacs and vi / vim: