diff --git a/.gitignore b/.gitignore index 7a0b6309a..427aa46e2 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,13 @@ Unfolding/Unfolder .DS_Store stv_root_dict_rdict.pcm *.o -*~ \ No newline at end of file +*.so +*.pcm +*.d +*.in +*ACLiC* +*~ + +python/env +python/*.pyc +python/__pycache__ \ No newline at end of file diff --git a/Makefile b/Makefile index 7f02c73f8..da63a0819 100644 --- a/Makefile +++ b/Makefile @@ -29,7 +29,8 @@ LIB_DIR := lib ROOT_DICTIONARY := $(LIB_DIR)/dictionaries.o SHARED_LIB := $(LIB_DIR)/libXSecAnalyzer.$(SHARED_LIB_SUFFIX) -CXXFLAGS := $(shell root-config --cflags) -O3 -I$(INCLUDE_DIR) +#CXXFLAGS := $(shell root-config --cflags) -O3 -I$(INCLUDE_DIR) #normal mode +CXXFLAGS := $(shell root-config --cflags) -O0 -g -I$(INCLUDE_DIR) #debug mode LDFLAGS := $(shell root-config --libs) -L$(LIB_DIR) -lXSecAnalyzer # Source files to use when building the main shared library diff --git a/cafana/CMakeLists.txt b/cafana/CMakeLists.txt new file mode 100644 index 000000000..364bd51b0 --- /dev/null +++ b/cafana/CMakeLists.txt @@ -0,0 +1,25 @@ +cmake_minimum_required(VERSION 3.25) +project(cafana) + +option(BUILD_DOC "Build documentation" ON) + +# Check if Doxygen is installed. +#find_package(Doxygen PATHS ${DOXYGEN_PATH}) +#if (DOXYGEN_FOUND) +# Set input and output files +set(DOXYGEN_IN ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in) +set(DOXYGEN_OUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile) + +# Request to configure the file +configure_file(${DOXYGEN_IN} ${DOXYGEN_OUT} @ONLY) + +# Add a custom target to run Doxygen +add_custom_target(doc + COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_OUT} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Generating API documentation with Doxygen" + VERBATIM +) +#else (DOXYGEN_FOUND) +# message("Doxygen need to be installed to generate the doxygen documentation") +#endif (DOXYGEN_FOUND) \ No newline at end of file diff --git a/cafana/README.md b/cafana/README.md new file mode 100644 index 000000000..0ebfcf499 --- /dev/null +++ b/cafana/README.md @@ -0,0 +1,27 @@ +## CAFAna + +CAFAna is a framework for parsing the standard output of SBN CAF files. [sbnana](https://github.com/SBNSoftware/sbnana) is the main repository for the SBN software suite, which contains `cafe`. + +## Setup +Setup `sbnana` to get access to `cafe` executable. +```bash +source /cvmfs/sbnd.opensciencegrid.org/products/sbnd/setup_sbnd.sh +ups list -aK+ sbnana #Use most recent version > 10_00_00 +setup sbnana v10_00_00 -q e26:prof +``` + +## Usage +The macros should be setup to store the event classifications into `event_type` branch. `is_signal` identifies if the event is reconstructed as signal. These are both essential for `ProcessNTuples` to work. +```bash +cafe -bq +``` + +## Example + +```bash +cafe -bq xsec_analyzer.C +``` + +## Output + +The output is a ROOT file with the name `xsec_analyzer.root`. The file contains a tree with the name `xsec_analyzer`. This is used as input for `ProcessNTuples` to feed into downstream fitting tools. diff --git a/cafana/include/analysis.h b/cafana/include/analysis.h new file mode 100644 index 000000000..d79ea98a9 --- /dev/null +++ b/cafana/include/analysis.h @@ -0,0 +1,199 @@ +/** + * @file analysis.h + * @brief Header file for the Analysis class, a class designed to streamline + * the running of multiple samples through CAFAna. + * @details The Analysis class operates under the principle that the full + * dataset in an analysis is comprised of multiple samples, each of which + * represents a different component of the signal or background. Under this + * paradigm, an analysis consists of running the same set of variables/cuts + * on each sample, and then combining the results at the end. The Analysis + * class is designed to facilitate this process by allowing the user to + * specify the variables and cuts to be applied to each sample, along with the + * full list of samples to be run. The class then handles the running of the + * samples and the storing of the results. + * @author mueller@fnal.gov + */ +#ifndef ANALYSIS_H +#define ANALYSIS_H +#include +#include + +#include "sbnana/CAFAna/Core/SpectrumLoader.h" +#include "sbnana/CAFAna/Core/Tree.h" +#include "sbnana/CAFAna/Core/Cut.h" +#include "sbnana/CAFAna/Core/Spectrum.h" + +#include "TDirectory.h" +#include "TFile.h" + +/** + * @namespace ana + * @brief Namespace for the Analysis class and related functions. + * @details The ana namespace contains the Analysis class, which is designed + * to streamline the running of multiple samples through CAFAna. The namespace + * is also used to organize analysis-related functions and variables within + * CAFAna. + */ +namespace ana +{ + /** + * @struct Sample + * @brief Struct to store information about a sample in the analysis. + * @details This struct is used to store information about a sample in the + * analysis, including the name of the sample, the SpectrumLoader object + * representing the sample, and a boolean indicating whether the sample is + * a simulation sample. The simulation flag is used to determine if truth + * information is available for the sample. + */ + struct Sample + { + std::string name; + ana::SpectrumLoader * loader; + bool is_sim; + }; + + /** + * @struct TreeSet + * @brief Struct to store information about a set of variables that comprise + * a Tree in the analysis. + * @details This struct is used to store information about a set of variables + * that comprise a Tree in the analysis. The Tree is used to store the results + * of the analysis in a TTree in the output ROOT file. The struct contains the + * name of the Tree, the names of the variables, the SpillMultiVars that + * implement the variables, and a boolean indicating whether the Tree + * represents a simulation sample. The simulation flag is used to determine + * if truth information is present in the Tree. + */ + struct TreeSet + { + std::string name; + std::vector names; + std::vector vars; + bool is_sim; + }; + + /** + * @class Analysis + * @brief Class designed to streamline the running of multiple samples + * through CAFAna. + * @details The Analysis class operates under the principle that the full + * dataset in an analysis is comprised of multiple samples, each of which + * represents a different component of the signal or background. Under this + * paradigm, an analysis consists of running the same set of variables/cuts + * on each sample, and then combining the results at the end. The Analysis + * class is designed to facilitate this process by allowing the user to + * specify the variables and cuts to be applied to each sample, along with + * the full list of samples to be run. The class then handles the running of + * the samples and the storing of the results. + */ + class Analysis + { + public: + Analysis(std::string name); + void AddLoader(std::string name, ana::SpectrumLoader * loader, bool is_sim); + void AddTree(std::string name, std::map & vars, bool is_sim); + void Go(); + private: + std::string name; + std::vector samples; + std::vector trees; + }; + + /** + * @brief Default constructor for the Analysis class. + * @details This constructor initializes an instance of the Analysis class + * with a default name. + * @param name The name of the Analysis class. This name is used in the + * creation of the output ROOT file. + * @return A new instance of the Analysis class. + */ + Analysis::Analysis(std::string name) + { + this->name = name; + } + + /** + * @brief Add a SpectrumLoader to the Analysis class. + * @details This function allows the user to add a SpectrumLoader to the + * Analysis class. The SpectrumLoader represents a sample in the analysis, + * and is used to load the data from the ROOT file and apply the cuts and + * variables to the data. + * @param name The name of the SpectrumLoader to be added to the Analysis + * class. + * @param loader The SpectrumLoader to be added to the Analysis class. + * @param is_sim A boolean indicating whether the SpectrumLoader represents + * a simulation sample, which is principally used to determine if truth + * information is available. + * @return void + */ + void Analysis::AddLoader(std::string name, ana::SpectrumLoader * loader, bool is_sim) + { + samples.push_back({name, loader, is_sim}); + } + + /** + * @brief Add a Tree to the Analysis class (set of variables and names). + * @details This function allows the user to add a new Tree to the Analysis + * class. A Tree is a set of variables with associated names that are + * applied to the data in the SpectrumLoader. The Tree is used to store the + * results of the analysis in a TTree in the output ROOT file. + * @param names A vector of strings containing the names of the variables + * to use in the Tree. + * @param vars A vector of SpillMultiVar objects implementing the variables + * to use in the Tree. + * @param is_sim A boolean indicating whether the Tree represents a + * simulation sample, which is principally used to determine if truth + * information is available. + * @return void + */ + void Analysis::AddTree(std::string name, std::map & vars, bool is_sim) + { + std::vector n; + std::vector v; + for(const auto & [name, var] : vars) + { + n.push_back(name); + v.push_back(var); + } + trees.push_back({name, n, v, is_sim}); + } + + /** + * @brief Run the analysis on the specified samples. + * @details This function runs the analysis on the configured samples by + * looping over each sample, creating the Trees for each sample, then + * running the analysis on the sample to populate the Trees with the + * results of the analysis. The results are stored in a TFile in the output + * ROOT file in a parent directory named "events" and a subdirectory for + * each sample. + * @return void + */ + void Analysis::Go() + { + TFile * f = new TFile(std::string(name + ".root").c_str(), "RECREATE"); + TDirectory * dir = f->mkdir("events"); + dir->cd(); + + for(const Sample & s : samples) + { + TDirectory * subdir = dir->mkdir(s.name.c_str()); + subdir->cd(); + std::vector sbruce_trees; + for(const TreeSet & t : trees) + { + if(t.is_sim && !s.is_sim) + continue; + sbruce_trees.push_back(new ana::Tree(t.name, t.names, *s.loader, t.vars, ana::kNoSpillCut, true)); + } + s.loader->Go(); + for(const ana::Tree * t : sbruce_trees) + { + t->SaveTo(subdir); + delete t; + } + dir->cd(); + } + f->Close(); + } +} +#endif // ANALYSIS_H \ No newline at end of file diff --git a/cafana/include/pandora/definitions.h b/cafana/include/pandora/definitions.h new file mode 100644 index 000000000..f90c27560 --- /dev/null +++ b/cafana/include/pandora/definitions.h @@ -0,0 +1,33 @@ +/** + * @file xsec_analyzer/pandora/definitions.h + * @brief Definitions of analysis variables. + * @details This file contains definitions of analysis variables which can be + * used to extract information from slices. Each variable is implemented + * as a function which takes a slice object as an argument and returns a + * double. These variables are intended to define slice definitions. + * @author brindenc@fnal.gov + */ + +#ifndef DEFINITIONS_H +#define DEFINITIONS_H + +#include "sbnanaobj/StandardRecord/Proxy/SRProxy.h" +#include "sbnana/SBNAna/Cuts/TruthCuts.h" + +#include "slice_cuts.h" + +using namespace ana; + +namespace defs +{ + int kEventType(const caf::SRSliceProxy & slc) + { + if (kTrueActiveVolumeND(&slc) && kIsNumu(&slc) && kIsCC(&slc)) return 0; //numucc + else if (kTrueActiveVolumeND(&slc) & kIsNC(&slc)) return 1; //NC + else if (kTrueActiveVolumeND(&slc) & kIsNue(&slc) & kIsCC(&slc)) return 2; //nuecc + else if (!kIsNu(&slc)) return 3; //Cosmic + else if (!kTrueActiveVolumeND(&slc) & kIsNu(&slc)) return 4; //Out of volume + else return -1; //Other + } +} +#endif // DEFINITIONS_H \ No newline at end of file diff --git a/cafana/include/pandora/pfp_variables.h b/cafana/include/pandora/pfp_variables.h new file mode 100644 index 000000000..1027bbe4a --- /dev/null +++ b/cafana/include/pandora/pfp_variables.h @@ -0,0 +1,157 @@ +/** + * @file pfp_variables.h + * @brief Header file for definitions of variables which act on single + * pfps. + * @details This file contains definitions of variables which act on single + * pfps. Each variable is implemented as a function which takes a pfp + * object as an argument and returns a double. These variables are intended to + * be used to define more complex variables which act on slices. + * @author mueller@fnal.gov +*/ +#ifndef PFP_VARIABLES_H +#define PFP_VARIABLES_H +#define ELECTRON_MASS 0.5109989461 +#define MUON_MASS 105.6583745 +#define PION_MASS 139.57039 +#define PROTON_MASS 938.2720813 + +#include "sbnana/SBNAna/Cuts/VolumeDefinitions.h" + +#include + +/** + * @namespace pvars + * @brief Namespace for organizing generic variables which act on single + * pfps. + * @details This namespace is intended to be used for organizing variables which + * act on single pfps. Each variable is implemented as a function which + * takes a pfp object as an argument and returns a double. The function + * should be templated on the type of pfp object if the variable is + * intended to be used on both true and reconstructed pfps. + * @note The namespace is intended to be used in conjunction with the + * vars namespace, which is used for organizing variables which act on + * interactions. + */ +namespace pfpvars +{ + //Shower variables + + // -direction + template + double kShowerDirx(const T & p) {return p.shw.dir.x;} + template + double kShowerDiry(const T & p) {return p.shw.dir.y;} + template + double kShowerDirz(const T & p) {return p.shw.dir.z;} + + // -other properties (still important) + template + double kShowerEnergy(const T & p) {return p.shw.bestplane_energy;} + template + double kShowerdEdx(const T & p) {return p.shw.bestplane_dEdx;} + template + double kShowerConversionGap(const T & p) {return p.shw.conversion_gap;} + template + double kShowerLength(const T & p) {return p.shw.len;} + + //Track variables + + // -direction + template + double kTrackDirx(const T & p) {return p.trk.dir.x;} + template + double kTrackDiry(const T & p) {return p.trk.dir.y;} + template + double kTrackDirz(const T & p) {return p.trk.dir.z;} + + // -other properties (still important) + template + bool kTrackCont(const T & p) {return (PtInVolAbsX(p.trk.start,fvndExit) && PtInVolAbsX(p.trk.end,fvndExit));} + + template + int kTrackBestPlane(const T & p) {return p.trk.bestplane;} + + template + double kTrackLength(const T & p) {return p.trk.len;} + + // -momentum + template + double kTrackMomPion(const T & p){ + if (kTrackCont(p)) return p.trk.rangeP.p_pion; + else return p.trk.mcsP.fwdP_pion; + } + template + double kTrackMomMuon(const T & p){ + if (kTrackCont(p)) return p.trk.rangeP.p_muon; + else return p.trk.mcsP.fwdP_muon; + } + template + double kTrackMomProton(const T & p){ + if (kTrackCont(p)) return p.trk.rangeP.p_proton; + else return p.trk.mcsP.fwdP_proton; + } + + // -chi2 scores + template + double kTrackChi2Muon(const T & p) { + return p.trk.chi2pid[kTrackBestPlane(p)].chi2_muon; + } + template + double kTrackChi2Pion(const T & p) { + return p.trk.chi2pid[kTrackBestPlane(p)].chi2_pion; + } + template + double kTrackChi2Proton(const T & p) { + return p.trk.chi2pid[kTrackBestPlane(p)].chi2_proton; + } + + /** + * @brief Find the PDG value using chi2. + * @details This function finds the PDG value using the chi2 method. + * @param p the pfp to apply the variable on. + * @return the PDG value (13 for muon, 211 for pion, 2212 for proton). + */ + template + double kTrackPDG(const T & p) { + if ((kTrackLength(p) > 32) && (kTrackChi2Muon(p) < 18) && (kTrackChi2Proton(p) > 87)){ + return 13; + } + else if (kTrackChi2Proton(p) < 97){ + return 2212; + } + else if ((!std::isnan(kTrackChi2Muon(p))) && (!std::isnan(kTrackChi2Pion(p))) && (!std::isnan(kTrackChi2Proton(p)))){ + return 211; + } + else return 0; + } + + //PFP variables + template + double kPFPTrackScore(const T & p) {return p.trackScore;} + + template + double kPFPEnergy(const T & p) { + if (kPFPTrackScore(p) < 0.5) return kShowerEnergy(p); + else if(!std::isnan(kPFPTrackScore(p))){ + if (kTrackPDG(p) == 13) return TMath::Sqrt(TMath::Power(MUON_MASS,2) + TMath::Power(kTrackMomMuon(p),2)); + else if (kTrackPDG(p) == 211) return TMath::Sqrt(TMath::Power(PION_MASS,2) + TMath::Power(kTrackMomPion(p),2)); + else if (kTrackPDG(p) == 2212) return TMath::Sqrt(TMath::Power(PROTON_MASS,2) + TMath::Power(kTrackMomProton(p),2)); + } + else return 0.0; + } + + template + double kPFPKineticEnergy(const T & p){ + if (kPFPTrackScore(p) < 0.5) return kShowerEnergy(p); + else if(!std::isnan(kPFPTrackScore(p))){ + if (kTrackPDG(p) == 13) return kPFPEnergy(p) - MUON_MASS; + else if (kTrackPDG(p) == 211) return kPFPEnergy(p) - PION_MASS; + else if (kTrackPDG(p) == 2212) return kPFPEnergy(p) - PROTON_MASS; + } + else return 0.0; + } + + +} +#endif // PFP_VARIABLES_H + diff --git a/cafana/include/pandora/slice_cuts.h b/cafana/include/pandora/slice_cuts.h new file mode 100644 index 000000000..bd5f54ab6 --- /dev/null +++ b/cafana/include/pandora/slice_cuts.h @@ -0,0 +1,71 @@ +/** + * @file cuts.h + * @brief Header file for definitions of analysis cuts. + * @details This file contains definitions of analysis cuts which can be used + * to select interactions/slices. Each cut is implemented as a function which takes an + * interaction/slice object as an argument and returns a boolean. These are the + * building blocks for defining more complex selections. + * @author brindenc@fnal.gov +*/ +#ifndef SLICE_CUTS_H +#define SLICE_CUTS_H +#include +#include +#include +#include + +#include "pfp_variables.h" +#include "slice_variables.h" + +const FidVol fvnumucc = {0, 190., + -190., 190., + 10., 450.}; + +namespace slicecuts +{ + /** + * @brief Apply no cut; all interactions/slices passed. + * @details This is a placeholder function for a cut which does not apply + * any selection criteria. It is intended to be used in cases where a cut + * function is required, but no selection is desired. + * @tparam T the type of object (true or reco). + * @param obj the interaction/slice to select on. + * @return true (always). + */ + template + bool kNoCut(const T & obj) { return true; } + + bool kIsFV(const caf::SRSliceProxy & slc) + { + return PtInVolAbsX(slc.vertex, fvnumucc); + } + + bool kPrecut(const caf::SRSliceProxy & slc) + { + return ((slicevars::kNuScore(slc) > 0.5) && kIsFV(slc)); + } + + bool kCosmicCut(const caf::SRSliceProxy & slc) + { + return slicevars::kOpt0Score(slc) > 320; + } + + bool kTrackCut(const caf::SRSliceProxy & slc) + { + return slicevars::kNTracks(slc) > 0; + } + + bool kMuonCut(const caf::SRSliceProxy & slc) + { + return slicevars::kLeadingMuonMom(slc) > 0; + } + + bool kIsSignal(const caf::SRSliceProxy & slc) + { + return kPrecut(slc) & kCosmicCut(slc) & kTrackCut(slc) & kMuonCut(slc); + } + + + +} +#endif // SLICE_CUTS_H \ No newline at end of file diff --git a/cafana/include/pandora/slice_variables.h b/cafana/include/pandora/slice_variables.h new file mode 100644 index 000000000..de35eb4d2 --- /dev/null +++ b/cafana/include/pandora/slice_variables.h @@ -0,0 +1,163 @@ +/** + * @file variables.h + * @brief Header file for definitions of analysis variables. + * @details This file contains definitions of analysis variables which can be + * used to extract information from interactions. Each variable is implemented + * as a function which takes an object as an argument and returns a + * double. Building blocks for constructing the xsec_analyzer tree. + * @author brindenc@fnal.gov +*/ + +#ifndef SLICE_VARIABLES_H +#define SLICE_VARIABLES_H +#define ELECTRON_MASS 0.5109989461 +#define MUON_MASS 105.6583745 +#define PION_MASS 139.57039 +#define PROTON_MASS 938.2720813 + +#include "sbnanaobj/StandardRecord/Proxy/SRProxy.h" +#include "sbnanaobj/StandardRecord/SRSlice.h" +#include "sbnanaobj/StandardRecord/SRSliceRecoBranch.h" +#include "sbnanaobj/StandardRecord/Proxy/EpilogFwd.h" + +#include "sbnana/CAFAna/Core/Var.h" +#include "sbnana/SBNAna/Vars/TruthVars.h" + +#include "pfp_variables.h" +//#include "slice_cuts.h" + +#include +#include + +/** + * @namespace slicevars + * @brief Namespace for organizing generic variables which act on interactions and + * slices. + * @details This namespace is intended to be used for organizing variables which + * act on interactions and slices. Each variable is implemented as a function which takes + * an object as an argument and returns a double. The function + * should be templated on the type of object if the variable is + * intended to be used on both true and reconstructed interactions. + * @note The namespace is intended to be used in conjunction with the + * pfpvars namespace, which is used for organizing variables which act on single + * particles and pfps. + */ +namespace slicevars +{ + int kSliceIndex(const caf::SRSliceProxy & slc){ + return slc.self; + } + + /** + * @brief Finds the index corresponding to the leading particle of the specified + * particle type. + * @details The leading particle is defined as the particle with the highest + * kinetic energy. If the slice is a true slice, the initial kinetic + * energy is used instead of the CSDA kinetic energy. + * @tparam T the type of slice (true or reco). + * @param obj the slice to operate on. + * @param pgd of the particle type. + * @return the index of the leading particle (highest KE). + */ + size_t kLeadingTrackIndex(const caf::SRSliceProxy & slc, uint16_t pdg) + { + double leading_ke(0); + size_t index(-1); + for(size_t i(0); i < slc.reco.npfp; ++i) + { + const auto & p = slc.reco.pfp[i]; + const int _pdg = pfpvars::kTrackPDG(p); + const double trk_score = pfpvars::kPFPTrackScore(p); + if(_pdg == pdg && trk_score > 0.5) + { + const double energy = pfpvars::kPFPKineticEnergy(p); + if(energy > leading_ke) + { + leading_ke = energy; + index = i; + } + } + } + return index; + } + + /** + * @brief Score of how neutrino-like the slice is according to pandora + * @details This variable is based on the neutrino score assigned by pandora. + * @param obj the slice to apply the variable on. + * @return the neutrino score. + */ + double kNuScore(const caf::SRSliceProxy & slc){ return slc.nu_score; }; + + double kOpt0Score(const caf::SRSliceProxy & slc){ return slc.opt0.score; }; + + double kNuVx(const caf::SRSliceProxy & slc){return slc.vertex.x;}; + double kNuVy(const caf::SRSliceProxy & slc){return slc.vertex.y;}; + double kNuVz(const caf::SRSliceProxy & slc){return slc.vertex.z;}; + + double kNPFP(const caf::SRSliceProxy & slc){return slc.reco.npfp;}; + + double kNTracks(const caf::SRSliceProxy & slc) + { + int n_tracks = 0; + for(size_t i(0); i < slc.reco.npfp; ++i) + { + const auto & p = slc.reco.pfp[i]; + if(pfpvars::kPFPTrackScore(p) > 0.6) n_tracks++; + } + return n_tracks; + } + + // Leading muon variables + double kLeadingMuonMom(const caf::SRSliceProxy & slc) + { + const size_t index = kLeadingTrackIndex(slc, 13); + if(index == -1) return 0; + + const auto & p = slc.reco.pfp[index]; + return pfpvars::kTrackMomMuon(p); + } + + // Leading muon costheta + double kLeadingMuonCostheta(const caf::SRSliceProxy & slc) + { + const size_t index = kLeadingTrackIndex(slc, 13); + if(index == -1) return 9999; + + const auto & p = slc.reco.pfp[index]; + return pfpvars::kTrackDirz(p); + } + + // True leading muon variables + double kTrueLeadingMuonMom(const caf::SRSliceProxy & slc) + { + double mom(0); + for(size_t i(0); i < slc.truth.prim.size(); ++i) + { + const auto & p = slc.truth.prim[i]; + if(std::abs(p.pdg) == 13) + { + double _mom = TMath::Sqrt(TMath::Power(p.genp.x, 2) + TMath::Power(p.genp.y, 2) + TMath::Power(p.genp.z, 2)); + if(_mom > mom) mom = _mom; + } + } + return mom; + } + + // True leading muon costheta + double kTrueLeadingMuonCostheta(const caf::SRSliceProxy & slc) + { + double costheta(9999); + for(size_t i(0); i < slc.truth.prim.size(); ++i) + { + const auto & p = slc.truth.prim[i]; + if(std::abs(p.pdg) == 13) + { + costheta = p.genp.z / TMath::Sqrt(TMath::Power(p.genp.x, 2) + TMath::Power(p.genp.y, 2) + TMath::Power(p.genp.z, 2)); + } + } + return costheta; + } + +} // namespace vars +#endif // SLICE_VARIABLES_H \ No newline at end of file diff --git a/cafana/include/pandora/syst.h b/cafana/include/pandora/syst.h new file mode 100644 index 000000000..7eb3fa760 --- /dev/null +++ b/cafana/include/pandora/syst.h @@ -0,0 +1,67 @@ +/** + * @file syst.h + * @brief Definitions of parameters to do systematic weights. + * @details This file contains definitions of parameters to store systematic weights. + * @author brindenc@fnal.gov + */ + +#ifndef SYST_H +#define SYST_H + +#include "sbnana/CAFAna/Core/ISyst.h" +#include "sbnana/CAFAna/Core/SpectrumLoader.h" +#include "sbnana/CAFAna/Core/Tree.h" +#include "sbnana/CAFAna/Core/Var.h" +#include "sbnana/CAFAna/Core/Cut.h" + +#include "sbnana/CAFAna/Systs/SBNWeightSysts.h" +#include "sbnana/CAFAna/Systs/UniverseOracle.h" + +#include "slice_cuts.h" +#include "slice_variables.h" + +using namespace ana; +namespace syst{ + //const Var kTrueLeadingMuonCostheta = SIMPLEVAR(slicevars::kTrueLeadingMuonCostheta); + //const Var kTrueE = SIMPLEVAR(truth.E); + + // Get systematic weights and names + const std::vector genie_names = GetSBNGenieWeightNames(); + const std::vector genie_systs = GetSBNGenieWeightSysts(); + //const std::vector detsysts = GetDetectorSysts(); + + // Define systematic names + const std::vector flux_names{ "expskin_Flux", "horncurrent_Flux", "nucleoninexsec_Flux", "nucleonqexsec_Flux", "nucleontotxsec_Flux", "pioninexsec_Flux", "pionqexsec_Flux", "piontotxsec_Flux", "piplus_Flux", "piminus_Flux", "kplus_Flux", "kminus_Flux", "kzero_Flux" }; + const std::vector xsec_multisim_names{ + "GENIEReWeight_SBN_v1_multisim_ZExpAVariationResponse", + "GENIEReWeight_SBN_v1_multisim_RPA_CCQE", + "GENIEReWeight_SBN_v1_multisim_CoulombCCQE", + "GENIEReWeight_SBN_v1_multisim_NormCCMEC", + "GENIEReWeight_SBN_v1_multisim_NormNCMEC", + "GENIEReWeight_SBN_v1_multisim_NCELVariationResponse", + "GENIEReWeight_SBN_v1_multisim_CCRESVariationResponse", + "GENIEReWeight_SBN_v1_multisim_NCRESVariationResponse", + "GENIEReWeight_SBN_v1_multisim_NonRESBGvpCC1pi", + "GENIEReWeight_SBN_v1_multisim_NonRESBGvpCC2pi", + "GENIEReWeight_SBN_v1_multisim_NonRESBGvpNC1pi", + "GENIEReWeight_SBN_v1_multisim_NonRESBGvpNC2pi", + "GENIEReWeight_SBN_v1_multisim_NonRESBGvnCC1pi", + "GENIEReWeight_SBN_v1_multisim_NonRESBGvnCC2pi", + "GENIEReWeight_SBN_v1_multisim_NonRESBGvnNC1pi", + "GENIEReWeight_SBN_v1_multisim_NonRESBGvnNC2pi", + "GENIEReWeight_SBN_v1_multisim_NonRESBGvbarpCC1pi", + "GENIEReWeight_SBN_v1_multisim_NonRESBGvbarpCC2pi", + "GENIEReWeight_SBN_v1_multisim_NonRESBGvbarpNC1pi", + "GENIEReWeight_SBN_v1_multisim_NonRESBGvbarpNC2pi", + "GENIEReWeight_SBN_v1_multisim_NonRESBGvbarnCC1pi", + "GENIEReWeight_SBN_v1_multisim_NonRESBGvbarnCC2pi", + "GENIEReWeight_SBN_v1_multisim_NonRESBGvbarnNC1pi", + "GENIEReWeight_SBN_v1_multisim_NonRESBGvbarnNC2pi", + "GENIEReWeight_SBN_v1_multisim_COHVariationResponse", + "GENIEReWeight_SBN_v1_multisim_DISBYVariationResponse", + "GENIEReWeight_SBN_v1_multisim_FSI_pi_VariationResponse", + "GENIEReWeight_SBN_v1_multisim_FSI_N_VariationResponse", + }; + +} +#endif // SYST_H diff --git a/cafana/include/preprocessor.h b/cafana/include/preprocessor.h new file mode 100644 index 000000000..a2e94eec1 --- /dev/null +++ b/cafana/include/preprocessor.h @@ -0,0 +1,140 @@ +/** + * @file preprocessor.h + * @brief Header file for preprocessor macros that streamline variable + * declarations. + * @author mueller@fnal.gov +*/ +#ifndef PREPROCESSOR_H +#define PREPROCESSOR_H +#include "sbnana/CAFAna/Core/MultiVar.h" + +/** + * @brief Preprocessor wrapper for looping over reco interactions and + * broadcasting a function over the reco interactions. + * @details This macro declares a lambda function that broadcasts a function + * over the reco interactions and returns a vector of the results of the + * function. + * @param VAR function to broadcast over the interactions. + * @param SEL function to select interactions. + * @return a vector with the result of VAR called on each reco interaction + * passing the cut SEL. + */ +#define SPINEVAR_RR(VAR,SEL) \ + [](const caf::SRSpillProxy* sr) \ + { \ + std::vector var; \ + bool is_mc(sr->ndlp_true != 0); \ + for(auto const& i : sr->dlp) \ + { \ + if(SEL(i) && (i.match.size() > 0 || !is_mc)) \ + var.push_back(VAR(i)); \ + } \ + return var; \ + } + +/** + * @brief Preprocessor wrapper for looping over reco interactions and + * broadcasting a function over the matching true interactions. + * @details This macro declares a lambda function that broadcasts a function + * over the reco interactions and returns a vector of the results of the + * function for each true interaction. + * @param VAR function to broadcast over the interactions. + * @param SEL function to select interactions. + * @return a vector with the result of VAR called on each true interaction that + * is matched to by a reco interaction passing the cut SEL. + */ +#define SPINEVAR_RT(VAR,SEL) \ + [](const caf::SRSpillProxy* sr) \ + { \ + std::vector var; \ + bool is_mc(sr->ndlp_true != 0); \ + for(auto const& i : sr->dlp) \ + { \ + if(SEL(i) && (i.match.size() > 0 || !is_mc)) \ + var.push_back(i.match.size() > 0 ? VAR(sr->dlp_true[i.match[0]]) : -1.0); \ + } \ + return var; \ + } + +/** + * @brief Preprocessor wrapper for looping over true interactions and + * broadcasting a function over the matching reco interactions. + * @details This macro declares a lambda function that broadcasts a function + * over the true interactions and returns a vector of the results of the + * function for each reco interaction. + * @param VAR function to broadcast over the interactions. + * @param SEL function to select interactions. + * @return a vector with the result of VAR called on each reco interaction that + * is matched to by a true interaction passing the cut SEL. + */ +#define SPINEVAR_TR(VAR,SEL) \ + [](const caf::SRSpillProxy* sr) \ + { \ + std::vector var; \ + for(auto const& i : sr->dlp_true) \ + { \ + if(SEL(i) && i.match.size() > 0) \ + var.push_back(VAR(sr->dlp[i.match[0]])); \ + } \ + return var; \ + } + +/** + * @brief Preprocessor wrapper for looping over true interactions and + * broadcasting a function over the true interactions. + * @details This macro declares a lambda function that broadcasts a function + * over the true interactions and returns a vector of the results of the + * function. + * @param VAR function to broadcast over the interactions. + * @param SEL function to select interactions. + * @return a vector with the result of VAR called on each true interaction + * passing the cut SEL. + */ +#define SPINEVAR_TT(VAR,SEL) \ + [](const caf::SRSpillProxy* sr) \ + { \ + std::vector var; \ + for(auto const& i : sr->dlp_true) \ + { \ + if(SEL(i) && i.match.size() > 0) \ + var.push_back(VAR(i)); \ + } \ + return var; \ + } + +/** + * @brief Preprocessor wrapper for looping over slices and broadcasting + * a function over the slices. + * @details This macro declares a lambda function that broadcasts a function + * over the slices and returns a vector of the results of the function. + * @param VAR function to broadcast over the interactions. + * @param SEL function to select interactions. + * @return a vector with the result of VAR called on each true interaction + * passing the cut SEL. + */ + +#define PANDORAVAR(VAR,SEL) \ + [](const caf::SRSpillProxy* sr) \ + { \ + std::vector var; \ + for(auto const& i : sr->slc) \ + { \ + if(SEL(i)) \ + var.push_back(VAR(i)); \ + } \ + return var; \ + } + +#define PANDORAMULTIVAR(VAR,SEL) \ + [](const caf::SRSpillProxy* sr) \ + { \ + std::vector var; \ + for(auto const& i : sr->slc) \ + { \ + auto res = VAR(i); \ + if(SEL(i)) \ + var.insert(var.end(), res.begin(), res.end()); \ + } \ + return var; \ + } +#endif // PREPROCESSOR_H \ No newline at end of file diff --git a/cafana/include/utilities.h b/cafana/include/utilities.h new file mode 100644 index 000000000..39cb6f73d --- /dev/null +++ b/cafana/include/utilities.h @@ -0,0 +1,86 @@ +/** + * @file utilities.h + * @brief Header file for definitions of utility functions for supporting + * analysis variables and cuts. + * @details This file contains definitions of utility functions which are used + * to support the implementation of analysis variables and cuts. These functions + * are intended to be used to simplify the implementation of variables and cuts + * by providing common functionality which can be reused across multiple + * variables and cuts. + * @author mueller@fnal.gov + */ +#ifndef UTILITIES_H +#define UTILITIES_H + +#include + +#include "include/particle_variables.h" +#include "include/particle_cuts.h" + +/** + * @namespace utilities + * @brief Namespace for organizing utility functions for supporting analysis + * variables and cuts. + * @details This namespace is intended to be used for organizing utility + * functions which are used to support the implementation of analysis variables + * and cuts. These functions are intended to be used to simplify the + * implementation of variables and cuts by providing common functionality which + * can be reused across multiple variables and cuts. + * @note The namespace is intended to be used in conjunction with the + * vars and cuts namespaces, which are used for organizing variables and cuts + * which act on interactions. + */ +namespace utilities +{ + /** + * @brief Count the primaries of the interaction with cuts applied to each particle. + * @tparam T the type of interaction (true or reco). + * @param obj the interaction to find the topology of. + * @return the count of primaries of each particle type within the + * interaction. + */ + template + std::vector count_primaries(const T & obj) + { + std::vector counts(5, 0); + for(auto &p : obj.particles) + { + if(pcuts::final_state_signal(p)) + ++counts[p.pid]; + } + return counts; + } + + /** + * @brief Finds the index corresponding to the leading particle of the specifed + * particle type. + * @details The leading particle is defined as the particle with the highest + * kinetic energy. If the interaction is a true interaction, the initial kinetic + * energy is used instead of the CSDA kinetic energy. + * @tparam T the type of interaction (true or reco). + * @param obj the interaction to operate on. + * @param pid of the particle type. + * @return the index of the leading particle (highest KE). + */ + template + size_t sleading_particle_index(const T & obj, uint16_t pid) + { + double leading_ke(0); + size_t index(0); + for(size_t i(0); i < obj.particles.size(); ++i) + { + const auto & p = obj.particles[i]; + double energy(p.csda_ke); + if constexpr (std::is_same_v) + energy = pvars::ke_init(p); + if(p.pid == pid && energy > leading_ke) + { + leading_ke = energy; + index = i; + } + } + return index; + } + +} +#endif // UTILITIES_H \ No newline at end of file diff --git a/cafana/xsec_analyzer.C b/cafana/xsec_analyzer.C new file mode 100644 index 000000000..93e917122 --- /dev/null +++ b/cafana/xsec_analyzer.C @@ -0,0 +1,151 @@ +/** + * @file example.C + * @brief Convert flat CAFs into xsec_analyzer format. + * @details This macro slices CAFAna files for use in xsec_analyzer. The macro configures + * some basic variables and cuts, then runs the analysis over a single sample. + * No cuts are applied as this is done upstream automatically. + * @author brindenc@fnal.gov +*/ + +#include "include/pandora/slice_variables.h" +#include "include/pandora/slice_cuts.h" +#include "include/pandora/definitions.h" +#include "include/pandora/syst.h" +#include "include/analysis.h" +#include "include/preprocessor.h" + +#include "sbnana/CAFAna/Core/SpectrumLoader.h" +#include "sbnana/CAFAna/Core/Tree.h" +#include "sbnana/CAFAna/Core/Cut.h" +#include "sbnana/CAFAna/Core/Spectrum.h" +#include "TDirectory.h" +#include "TFile.h" + + +std::string out_fname = "/exp/sbnd/data/users/brindenc/xsec_analysis/test/sbruce_med/test1/xsec_analyzer_med"; + +void xsec_analyzer() +{ + /** + * @brief Create an instance of the Analysis class. + * @details This creates an instance of the Analysis class, which is used + * to run the analysis on the specified samples. The name of the analysis, + * and therefor the name of the output file, is specified as an argument to + * the constructor. + */ + //ana::Analysis analysis("/exp/sbnd/data/users/brindenc/xsec_analysis/test/sbruce/xsec_analyzer"); + ana::Analysis analysis(out_fname); + + /** + * @brief Add a sample to the analysis. + * @details This adds a sample to the analysis by creating a SpectrumLoader + * object and adding it to the Analysis class. The SpectrumLoader object + * represents the sample in the analysis, and is used to load the data from + * the ROOT file and apply the cuts and variables. The name passed to the + * AddLoader function is used to create a directory in the output ROOT file + * to store the results of the analysis. + */ + //ana::SpectrumLoader var00("/exp/sbnd/data/users/brindenc/xsec_analysis/test/bnb_small/small_syst.root"); + ana::SpectrumLoader var00("/exp/sbnd/data/users/brindenc/ML/bnb_cosmics/v09_89_01/syst/caf/caf_bnb_cosmics_dirt_0.flat.caf.root"); + analysis.AddLoader("nominal", &var00, true); + + /** + * @brief Add a set of variables for slices to the analysis. + * @details This adds a set of variables to the analysis by creating a + * map of variable names and SpillMultiVars that provide the functionality + * to calculate the variables. These names are used in the TTree that is + * created by the Tree class to store the results of the analysis. + */ + std::map slice; + + // Double variables + slice.insert({"leading_muon_momentum", ana::SpillMultiVar(PANDORAVAR(slicevars::kLeadingMuonMom,slicecuts::kNoCut))}); + slice.insert({"leading_muon_costheta", ana::SpillMultiVar(PANDORAVAR(slicevars::kLeadingMuonCostheta,slicecuts::kNoCut))}); + slice.insert({"true_leading_muon_momentum", ana::SpillMultiVar(PANDORAVAR(slicevars::kTrueLeadingMuonMom,slicecuts::kNoCut))}); + slice.insert({"true_leading_muon_costheta", ana::SpillMultiVar(PANDORAVAR(slicevars::kTrueLeadingMuonCostheta,slicecuts::kNoCut))}); + + // Integer variables + slice.insert({"event_type", ana::SpillMultiVar(PANDORAVAR(defs::kEventType,slicecuts::kNoCut))}); + slice.insert({"is_signal", ana::SpillMultiVar(PANDORAVAR(slicecuts::kIsSignal,slicecuts::kNoCut))}); + slice.insert({"Slice", ana::SpillMultiVar(PANDORAVAR(slicevars::kSliceIndex,slicecuts::kNoCut))}); + + analysis.AddTree("slice", slice, true); + + // Add the header tree + const SpillVar kIsMC = SIMPLESPILLVAR(hdr.ismc); + std::vector header_vars = {kIsMC}; + Tree hdrtree("header", {"is_mc"}, var00, header_vars, kNoSpillCut, true); + + // Add systematics + + // Get systematic weights and names + std::vector> min_max; + for(size_t i = 0; i < syst::genie_names.size(); ++i) min_max.emplace_back(-3, 3); + + // Initlaize storage for the trees + std::vector multisim_names; + std::vector> univsKnobs; + std::vector nuniverses; + //std::vector detsyst_names; + //std::vector> min_max_det; + // Load the knobs + for(const auto& name: syst::flux_names) { + // Hard code nuniv at 1000 for now since asking UniverseOracle breaks for + // piplus, piminus, kplus, kminus, and kzero. + if (name != syst::flux_names[0]) continue; + multisim_names.push_back(name); + size_t nuniv = 1000; + nuniverses.push_back(nuniv); + univsKnobs.emplace_back(); + for(size_t i = 0; i < nuniv; ++i) + univsKnobs.back().push_back(GetUniverseWeight(name, i)); + } + for(const auto& name: syst::xsec_multisim_names) { + if (name != syst::flux_names[0]) continue; + multisim_names.push_back(name); + size_t nuniv = 100; + nuniverses.push_back(nuniv); + univsKnobs.emplace_back(); + for(size_t i = 0; i < nuniv; ++i) + univsKnobs.back().push_back(GetUniverseWeight(name, i)); + } + //TODO: Add detsysts + // for(size_t i = 0; i < detsysts.size(); ++i) + // { + // min_max_det.emplace_back(-3,3); + // const ISyst* detsyst = detsysts[i]; + // detsyst_names.push_back(detsyst->ShortName()+"_multisigma"); + // } + + // Add the trees + //NSigmasTree detsysttree("detsystTree", detsyst_names, var00, detsysts, min_max_det, kNoSpillCut, kNoCut, kNoShift, true, true); + //NSigmasTree nsigtree("multisigmaTree", syst::genie_names, var00, syst::genie_systs, min_max, kNoSpillCut, kNoCut, kNoShift, true, true); + //NUniversesTree nunivtree("multisimTree", multisim_names, var00, univsKnobs, nuniverses, kNoSpillCut, kNoCut, kNoShift, true, true); + NUniversesTree nunivtree("multisimTree", std::vector{syst::flux_names[0]}, var00, univsKnobs, nuniverses, kNoSpillCut, kNoCut, kNoShift, true, true); + + /** + * @brief Run the analysis. + * @details This runs the analysis on the samples specified by the + * SpectrumLoaders and variables added to the Analysis class. It loops over + * each sample (here only one), applies the cuts and variables to the data, + * and stores the results in a TFile. + */ + analysis.Go(); + + //Write the trees + std::string out_fname_root = out_fname + ".root"; //why tf is c++ so dumb? + TFile fout(out_fname_root.c_str(), "UPDATE"); + TDirectory* dir = fout.mkdir("systs"); + //nsigtree.SaveTo(dir); + nunivtree.SaveTo(dir); + //detsysttree.SaveTo(dir); + + //Write the header tree to event/nominal folder + TDirectory* dir2 = fout.GetDirectory("events/nominal"); + if (!dir2) { + // Handle the error, directory does not exist + std::cerr << "Directory 'events/nominal' does not exist." << std::endl; + return; + } + hdrtree.SaveTo(dir2); +} \ No newline at end of file diff --git a/configs/SBND_CC1muX_bin_config.txt b/configs/SBND_CC1muX_bin_config.txt new file mode 100644 index 000000000..66c20da4d --- /dev/null +++ b/configs/SBND_CC1muX_bin_config.txt @@ -0,0 +1,42 @@ +SBND_CC1muX_1D +stv_tree +SBND_CC1muX +19 +0 0 "MC_Signal && true_leading_muon_costheta >= -1.000000 && true_leading_muon_costheta < -0.500000" +0 0 "MC_Signal && true_leading_muon_costheta >= -0.500000 && true_leading_muon_costheta < 0.000000" +0 0 "MC_Signal && true_leading_muon_costheta >= 0.000000 && true_leading_muon_costheta < 0.270000" +0 0 "MC_Signal && true_leading_muon_costheta >= 0.270000 && true_leading_muon_costheta < 0.450000" +0 0 "MC_Signal && true_leading_muon_costheta >= 0.450000 && true_leading_muon_costheta < 0.620000" +0 0 "MC_Signal && true_leading_muon_costheta >= 0.620000 && true_leading_muon_costheta < 0.760000" +0 0 "MC_Signal && true_leading_muon_costheta >= 0.760000 && true_leading_muon_costheta < 0.860000" +0 0 "MC_Signal && true_leading_muon_costheta >= 0.860000 && true_leading_muon_costheta < 0.940000" +0 0 "MC_Signal && true_leading_muon_costheta >= 0.940000 && true_leading_muon_costheta < 1.000000" +0 1 "MC_Signal && true_leading_muon_momentum >= 0.000000 && true_leading_muon_momentum < 0.300000" +0 1 "MC_Signal && true_leading_muon_momentum >= 0.300000 && true_leading_muon_momentum < 0.500000" +0 1 "MC_Signal && true_leading_muon_momentum >= 0.500000 && true_leading_muon_momentum < 0.700000" +0 1 "MC_Signal && true_leading_muon_momentum >= 0.700000 && true_leading_muon_momentum < 0.900000" +0 1 "MC_Signal && true_leading_muon_momentum >= 0.900000 && true_leading_muon_momentum < 1.100000" +0 1 "MC_Signal && true_leading_muon_momentum >= 1.100000 && true_leading_muon_momentum < 1.300000" +0 1 "MC_Signal && true_leading_muon_momentum >= 1.300000 && true_leading_muon_momentum < 1.500000" +0 1 "MC_Signal && true_leading_muon_momentum >= 1.500000 && true_leading_muon_momentum < 2.000000" +0 1 "MC_Signal && true_leading_muon_momentum >= 2.000000 && true_leading_muon_momentum < 3.000000" +1 -1 "!MC_Signal" +18 +0 0 "Selected && leading_muon_costheta >= -1.000000 && leading_muon_costheta < -0.500000" +0 0 "Selected && leading_muon_costheta >= -0.500000 && leading_muon_costheta < 0.000000" +0 0 "Selected && leading_muon_costheta >= 0.000000 && leading_muon_costheta < 0.270000" +0 0 "Selected && leading_muon_costheta >= 0.270000 && leading_muon_costheta < 0.450000" +0 0 "Selected && leading_muon_costheta >= 0.450000 && leading_muon_costheta < 0.620000" +0 0 "Selected && leading_muon_costheta >= 0.620000 && leading_muon_costheta < 0.760000" +0 0 "Selected && leading_muon_costheta >= 0.760000 && leading_muon_costheta < 0.860000" +0 0 "Selected && leading_muon_costheta >= 0.860000 && leading_muon_costheta < 0.940000" +0 0 "Selected && leading_muon_costheta >= 0.940000 && leading_muon_costheta < 1.000000" +0 1 "Selected && leading_muon_momentum >= 0.000000 && leading_muon_momentum < 0.300000" +0 1 "Selected && leading_muon_momentum >= 0.300000 && leading_muon_momentum < 0.500000" +0 1 "Selected && leading_muon_momentum >= 0.500000 && leading_muon_momentum < 0.700000" +0 1 "Selected && leading_muon_momentum >= 0.700000 && leading_muon_momentum < 0.900000" +0 1 "Selected && leading_muon_momentum >= 0.900000 && leading_muon_momentum < 1.100000" +0 1 "Selected && leading_muon_momentum >= 1.100000 && leading_muon_momentum < 1.300000" +0 1 "Selected && leading_muon_momentum >= 1.300000 && leading_muon_momentum < 1.500000" +0 1 "Selected && leading_muon_momentum >= 1.500000 && leading_muon_momentum < 2.000000" +0 1 "Selected && leading_muon_momentum >= 2.000000 && leading_muon_momentum < 3.000000" diff --git a/configs/SBND_CC1muX_bin_config_overflow.txt b/configs/SBND_CC1muX_bin_config_overflow.txt new file mode 100644 index 000000000..c5ec95362 --- /dev/null +++ b/configs/SBND_CC1muX_bin_config_overflow.txt @@ -0,0 +1,44 @@ +SBND_CC1muX_1D +stv_tree +SBND_CC1muX +20 +0 0 "MC_Signal && true_leading_muon_costheta >= -1.000000 && true_leading_muon_costheta < -0.500000" +0 0 "MC_Signal && true_leading_muon_costheta >= -0.500000 && true_leading_muon_costheta < 0.000000" +0 0 "MC_Signal && true_leading_muon_costheta >= 0.000000 && true_leading_muon_costheta < 0.270000" +0 0 "MC_Signal && true_leading_muon_costheta >= 0.270000 && true_leading_muon_costheta < 0.450000" +0 0 "MC_Signal && true_leading_muon_costheta >= 0.450000 && true_leading_muon_costheta < 0.620000" +0 0 "MC_Signal && true_leading_muon_costheta >= 0.620000 && true_leading_muon_costheta < 0.760000" +0 0 "MC_Signal && true_leading_muon_costheta >= 0.760000 && true_leading_muon_costheta < 0.860000" +0 0 "MC_Signal && true_leading_muon_costheta >= 0.860000 && true_leading_muon_costheta < 0.940000" +0 0 "MC_Signal && true_leading_muon_costheta >= 0.940000 && true_leading_muon_costheta < 1.000000" +0 1 "MC_Signal && true_leading_muon_momentum >= 0.000000 && true_leading_muon_momentum < 0.300000" +0 1 "MC_Signal && true_leading_muon_momentum >= 0.300000 && true_leading_muon_momentum < 0.500000" +0 1 "MC_Signal && true_leading_muon_momentum >= 0.500000 && true_leading_muon_momentum < 0.700000" +0 1 "MC_Signal && true_leading_muon_momentum >= 0.700000 && true_leading_muon_momentum < 0.900000" +0 1 "MC_Signal && true_leading_muon_momentum >= 0.900000 && true_leading_muon_momentum < 1.100000" +0 1 "MC_Signal && true_leading_muon_momentum >= 1.100000 && true_leading_muon_momentum < 1.300000" +0 1 "MC_Signal && true_leading_muon_momentum >= 1.300000 && true_leading_muon_momentum < 1.500000" +0 1 "MC_Signal && true_leading_muon_momentum >= 1.500000 && true_leading_muon_momentum < 2.000000" +0 1 "MC_Signal && true_leading_muon_momentum >= 2.000000 && true_leading_muon_momentum < 3.000000" +0 1 "MC_Signal && true_leading_muon_momentum >= 3.000000 && true_leading_muon_momentum < 10000.000000" +1 -1 "!SBND_CC1muX_MC_Signal" +19 +0 0 "Selected && leading_muon_costheta >= -1.000000 && leading_muon_costheta < -0.500000" +0 0 "Selected && leading_muon_costheta >= -0.500000 && leading_muon_costheta < 0.000000" +0 0 "Selected && leading_muon_costheta >= 0.000000 && leading_muon_costheta < 0.270000" +0 0 "Selected && leading_muon_costheta >= 0.270000 && leading_muon_costheta < 0.450000" +0 0 "Selected && leading_muon_costheta >= 0.450000 && leading_muon_costheta < 0.620000" +0 0 "Selected && leading_muon_costheta >= 0.620000 && leading_muon_costheta < 0.760000" +0 0 "Selected && leading_muon_costheta >= 0.760000 && leading_muon_costheta < 0.860000" +0 0 "Selected && leading_muon_costheta >= 0.860000 && leading_muon_costheta < 0.940000" +0 0 "Selected && leading_muon_costheta >= 0.940000 && leading_muon_costheta < 1.000000" +0 1 "Selected && leading_muon_momentum >= 0.000000 && leading_muon_momentum < 0.300000" +0 1 "Selected && leading_muon_momentum >= 0.300000 && leading_muon_momentum < 0.500000" +0 1 "Selected && leading_muon_momentum >= 0.500000 && leading_muon_momentum < 0.700000" +0 1 "Selected && leading_muon_momentum >= 0.700000 && leading_muon_momentum < 0.900000" +0 1 "Selected && leading_muon_momentum >= 0.900000 && leading_muon_momentum < 1.100000" +0 1 "Selected && leading_muon_momentum >= 1.100000 && leading_muon_momentum < 1.300000" +0 1 "Selected && leading_muon_momentum >= 1.300000 && leading_muon_momentum < 1.500000" +0 1 "Selected && leading_muon_momentum >= 1.500000 && leading_muon_momentum < 2.000000" +0 1 "Selected && leading_muon_momentum >= 2.000000 && leading_muon_momentum < 3.000000" +0 1 "Selected && leading_muon_momentum >= 3.000000 && leading_muon_momentum < 10000.000000" diff --git a/configs/SBND_CC1muX_slice_config.txt b/configs/SBND_CC1muX_slice_config.txt new file mode 100644 index 000000000..f84242947 --- /dev/null +++ b/configs/SBND_CC1muX_slice_config.txt @@ -0,0 +1,53 @@ +3 +"muon cos#theta" "" "\cos\theta_{\mu}" "" +"p_{#mu}" " (GeV)" "p_{\mu}" " (GeV)" +"bin number" "bin number" "" "" +3 +"events" +1 0 10 -1 -0.5 0 0.27 0.45 0.62 0.76 0.86 0.94 1 +0 +9 +0 1 1 +1 1 2 +2 1 3 +3 1 4 +4 1 5 +5 1 6 +6 1 7 +7 1 8 +8 1 9 +"events" +1 1 10 0 0.3 0.5 0.7 0.9 1.1 1.3 1.5 2 3 +0 +9 +9 1 1 +10 1 2 +11 1 3 +12 1 4 +13 1 5 +14 1 6 +15 1 7 +16 1 8 +17 1 9 +"events" +1 2 19 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 +0 +18 +0 1 1 +1 1 2 +2 1 3 +3 1 4 +4 1 5 +5 1 6 +6 1 7 +7 1 8 +8 1 9 +9 1 10 +10 1 11 +11 1 12 +12 1 13 +13 1 14 +14 1 15 +15 1 16 +16 1 17 +17 1 18 \ No newline at end of file diff --git a/configs/SBND_CC1muX_slice_config_overflow.txt b/configs/SBND_CC1muX_slice_config_overflow.txt new file mode 100644 index 000000000..74e95f94d --- /dev/null +++ b/configs/SBND_CC1muX_slice_config_overflow.txt @@ -0,0 +1,55 @@ +3 +"muon cos#theta" "" "\cos\theta_{\mu}" "" +"p_{#mu}" " (GeV)" "p_{\mu}" " (GeV)" +"bin number" "bin number" "" "" +3 +"events" +1 0 10 -1 -0.5 0 0.27 0.45 0.62 0.76 0.86 0.94 1 +0 +9 +0 1 1 +1 1 2 +2 1 3 +3 1 4 +4 1 5 +5 1 6 +6 1 7 +7 1 8 +8 1 9 +"events" +1 1 11 0 0.3 0.5 0.7 0.9 1.1 1.3 1.5 2 3 10000 +0 +10 +9 1 1 +10 1 2 +11 1 3 +12 1 4 +13 1 5 +14 1 6 +15 1 7 +16 1 8 +17 1 9 +18 1 10 +"events" +1 2 20 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 +0 +19 +0 1 1 +1 1 2 +2 1 3 +3 1 4 +4 1 5 +5 1 6 +6 1 7 +7 1 8 +8 1 9 +9 1 10 +10 1 11 +11 1 12 +12 1 13 +13 1 14 +14 1 15 +15 1 16 +16 1 17 +17 1 18 +18 1 19 \ No newline at end of file diff --git a/configs/file_properties.txt b/configs/file_properties.txt index c94615122..42e68a800 100644 --- a/configs/file_properties.txt +++ b/configs/file_properties.txt @@ -1,49 +1,18 @@ -# Trigger counts and POT exposures are taken from the searching4nues -# spreadsheet: tinyurl.com/pelee-nue-ntuples -# file_name run file_type [triggers POT (for data only)] -# -# Open beam-on data -# /exp/uboone/data/users/barrow/CC2P/stv-data_bnb_mcc9.1_v08_00_00_25_reco2_C1_beam_good_reco2_5e19.root 1 onBNB 10080350 4.54e19 -# /exp/uboone/data/users/barrow/CC2P/stv-data_bnb_mcc9.1_v08_00_00_25_reco2_G1_beam_good_reco2_1e19.root 3 onBNB 2271036 9.43e18 -# -# Beam-off data -/exp/uboone/data/users/barrow/CC2P/stv-data_extbnb_mcc9.1_v08_00_00_25_reco2_C_all_reco2.root 1 extBNB 65498807 0 -/exp/uboone/data/users/barrow/CC2P/stv-data_extbnb_mcc9.1_v08_00_00_25_reco2_D_E_all_reco2.root 2 extBNB 152404890 0 -/exp/uboone/data/users/barrow/CC2P/stv-data_extbnb_mcc9.1_v08_00_00_25_reco2_F_G_all_reco2.root 3 extBNB 214555174 0 -# +#TODO: Make a separate file for sbnd and uboone + +# Dummy file +/exp/sbnd/data/users/brindenc/xsec_analysis/test/sbruce_med/test1/cc1mux_med.root 1 numuMC # Full beam-on data -/exp/uboone/data/users/barrow/CC2P/stv-run1_neutrinoselection_filt_numu_ALL.root 1 onBNB 36139233 1.62e20 -/exp/uboone/data/users/barrow/CC2P/stv-run2_neutrinoselection_filt_numu_ALL.root 2 onBNB 62045760 2.62e20 -/exp/uboone/data/users/barrow/CC2P/stv-run3_neutrinoselection_filt_numu_ALL.root 3 onBNB 61012955 2.55e20 -# -# Dirt MC samples -/exp/uboone/data/users/barrow/CC2P/stv-prodgenie_bnb_dirt_overlay_mcc9.1_v08_00_00_26_run1_reco2_reco2.root 1 dirtMC -/exp/uboone/data/users/barrow/CC2P/stv-prodgenie_dirt_overlay_v08_00_00_35_all_run2_reco2_reco2.root 2 dirtMC -/exp/uboone/data/users/barrow/CC2P/stv-prodgenie_bnb_dirt_overlay_mcc9.1_v08_00_00_26_run3_reco2_reco2.root 3 dirtMC -# -# Intrinsic nue MC samples -/exp/uboone/data/users/barrow/CC2P/stv-prodgenie_bnb_intrinsice_nue_uboone_overlay_mcc9.1_v08_00_00_26_run1_reco2_reco2.root 1 nueMC -/exp/uboone/data/users/barrow/CC2P/stv-prodgenie_bnb_intrinsic_nue_overlay_run2_v08_00_00_35_run2a_reco2_reco2.root 2 nueMC -/exp/uboone/data/users/barrow/CC2P/stv-prodgenie_bnb_intrinsice_nue_uboone_overlay_mcc9.1_v08_00_00_26_run3_reco2_reco2.root 3 nueMC -# -# numu MC samples -/exp/uboone/data/users/barrow/CC2P/stv-prodgenie_bnb_nu_uboone_overlay_mcc9.1_v08_00_00_26_filter_run1_reco2_reco2.root 1 numuMC -/exp/uboone/data/users/barrow/CC2P/stv-prodgenie_bnb_nu_uboone_overlay_mcc9.1_v08_00_00_26_filter_run2_reco2_D1D2_reco2.root 2 numuMC -/exp/uboone/data/users/barrow/CC2P/stv-prodgenie_bnb_nu_uboone_overlay_mcc9.1_v08_00_00_26_filter_run3_reco2_G_reco2.root 3 numuMC -# detVar MC samples -/exp/uboone/data/users/barrow/CC2P/stv-high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_CVextra_reco2_reco2.root 3 detVarCVExtra -/exp/uboone/data/users/barrow/CC2P/stv-high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_CV_reco2_reco2.root 3 detVarCV -/exp/uboone/data/users/barrow/CC2P/stv-high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_dEdx_reco2_reco2.root 3 detVarWMdEdx -/exp/uboone/data/users/barrow/CC2P/stv-high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_LYAttenuation_reco2_reco2.root 3 detVarLYatten -/exp/uboone/data/users/barrow/CC2P/stv-high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_LYDown_reco2_reco2.root 3 detVarLYdown -/exp/uboone/data/users/barrow/CC2P/stv-high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_LYRayleigh_reco2_reco2.root 3 detVarLYrayl -/exp/uboone/data/users/barrow/CC2P/stv-high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_Recombination_reco2_reco2.root 3 detVarRecomb2 -/exp/uboone/data/users/barrow/CC2P/stv-high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_SCE_reco2_reco2.root 3 detVarSCE -/exp/uboone/data/users/barrow/CC2P/stv-high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_ThetaXZ_reco2_reco2.root 3 detVarWMAngleXZ -/exp/uboone/data/users/barrow/CC2P/stv-high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_ThetaYZ_reco2_reco2.root 3 detVarWMAngleYZ -/exp/uboone/data/users/barrow/CC2P/stv-high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_X_reco2_reco2.root 3 detVarWMX -/exp/uboone/data/users/barrow/CC2P/stv-high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_YZ_reco2_reco2.root 3 detVarWMYZ -# NuWro numuMC -/exp/uboone/data/users/barrow/CC2P/stv-high_stat_prodgenie_bnb_nu_overlay_DetVar_Run1_NuWro_reco2_reco2.root 1 altCVMC -/exp/uboone/data/users/barrow/CC2P/stv-high_stat_prodgenie_bnb_nu_overlay_DetVar_Run2_NuWro_reco2_reco2.root 2 altCVMC -/exp/uboone/data/users/barrow/CC2P/stv-high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_NuWro_reco2_reco2.root 3 altCVMC +#my_on_beam_data.root RUN_NUMBER onBNB #trigs #POT +/exp/sbnd/data/users/brindenc/xsec_analysis/test/sbruce_med/test1/cc1mux_med_copy.root 1 onBNB 1000 3.724e16 +# Dirt +#my_on_beam_data.root RUN_NUMBER onBNB #trigs #POT +#/exp/sbnd/data/users/brindenc/xsec_analysis/test/sbruce_med/test1/cc1mux_med_copy2.root 1 dirtMC 1000 3.724e16 +/exp/sbnd/data/users/brindenc/xsec_analysis/test/sbruce_med/test1/cc1mux_med_copy2.root 1 dirtMC 3.724e16 +# Intrinsic nue +#my_on_beam_data.root RUN_NUMBER onBNB #trigs #POT +#/exp/sbnd/data/users/brindenc/xsec_analysis/test/sbruce_med/test1/cc1mux_med_copy3.root 1 nueMC 1000 3.724e16 +/exp/sbnd/data/users/brindenc/xsec_analysis/test/sbruce_med/test1/cc1mux_med_copy3.root 1 nueMC 3.724e16 +# Beam-off data +#my_off_beam_data.root RUN_NUMBER extBNB #trigs #POT +/exp/sbnd/data/users/brindenc/xsec_analysis/test/sbruce_med/test1/cc1mux_med_copy4.root 1 extBNB 1000 0 \ No newline at end of file diff --git a/configs/files_to_process.txt b/configs/files_to_process.txt index 66c70edcb..c647c89d9 100644 --- a/configs/files_to_process.txt +++ b/configs/files_to_process.txt @@ -1,64 +1,3 @@ -# All beam-on data (slimmed only with nslice == 1 requirement) -/uboone/data/users/davidc/searchingfornues/v08_00_00_41/cc0pinp/0617/nslice/run1_neutrinoselection_filt_numu_ALL.root -/uboone/data/users/davidc/searchingfornues/v08_00_00_41/cc0pinp/0617/nslice/run2_neutrinoselection_filt_numu_ALL.root -/uboone/data/users/davidc/searchingfornues/v08_00_00_41/cc0pinp/0617/nslice/run3_neutrinoselection_filt_numu_ALL.root +#TODO: Make a separate file for sbnd and uboone -# Run 1 open and beam-off data -/uboone/data/users/davidc/searchingfornues/v08_00_00_43/0702/run1/data_bnb_mcc9.1_v08_00_00_25_reco2_C1_beam_good_reco2_5e19.root -/uboone/data/users/davidc/searchingfornues/v08_00_00_43/0702/run1/data_extbnb_mcc9.1_v08_00_00_25_reco2_C_all_reco2.root - -# Run 2 beam-off data -/uboone/data/users/davidc/searchingfornues/v08_00_00_43/0702/run2/data_extbnb_mcc9.1_v08_00_00_25_reco2_D_E_all_reco2.root - -# Run 3 open and beam-off data -/uboone/data/users/davidc/searchingfornues/v08_00_00_43/0702/run3/data_bnb_mcc9.1_v08_00_00_25_reco2_G1_beam_good_reco2_1e19.root -/uboone/data/users/davidc/searchingfornues/v08_00_00_43/0702/run3/data_extbnb_mcc9.1_v08_00_00_25_reco2_F_G_all_reco2.root - -# Run 1 CV MC -/pnfs/uboone/persistent/users/davidc/searchingfornues/v08_00_00_43/0928/prodgenie_bnb_nu_uboone_overlay_mcc9.1_v08_00_00_26_filter_run1_reco2_reco2.root -/pnfs/uboone/persistent/users/davidc/searchingfornues/v08_00_00_43/0928/prodgenie_bnb_intrinsice_nue_uboone_overlay_mcc9.1_v08_00_00_26_run1_reco2_reco2.root -/pnfs/uboone/persistent/users/davidc/searchingfornues/v08_00_00_43/0928/prodgenie_bnb_dirt_overlay_mcc9.1_v08_00_00_26_run1_reco2_reco2.root - -# Run 2 CV MC -/pnfs/uboone/persistent/users/davidc/searchingfornues/v08_00_00_43/0928/prodgenie_bnb_nu_uboone_overlay_mcc9.1_v08_00_00_26_filter_run2_reco2_D1D2_reco2.root -/pnfs/uboone/persistent/users/davidc/searchingfornues/v08_00_00_43/0928/prodgenie_bnb_intrinsic_nue_overlay_run2_v08_00_00_35_run2a_reco2_reco2.root -/pnfs/uboone/persistent/users/davidc/searchingfornues/v08_00_00_43/0928/prodgenie_dirt_overlay_v08_00_00_35_all_run2_reco2_reco2.root - -# Run 3 CV MC -/pnfs/uboone/persistent/users/davidc/searchingfornues/v08_00_00_43/0928/prodgenie_bnb_nu_uboone_overlay_mcc9.1_v08_00_00_26_filter_run3_reco2_G_reco2.root -/pnfs/uboone/persistent/users/davidc/searchingfornues/v08_00_00_43/0928/prodgenie_bnb_intrinsice_nue_uboone_overlay_mcc9.1_v08_00_00_26_run3_reco2_reco2.root -/pnfs/uboone/persistent/users/davidc/searchingfornues/v08_00_00_43/0928/prodgenie_bnb_dirt_overlay_mcc9.1_v08_00_00_26_run3_reco2_reco2.root - -# NuWro MC -/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run1_NuWro_reco2_reco2.root -/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run2_NuWro_reco2_reco2.root -/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_NuWro_reco2_reco2.root - -# Run 1 high-stats detVar -/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run1_CV_reco2_reco2.root -/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run1_dEdx_reco2_reco2.root -/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run1_LYAttenuation_reco2_reco2.root -/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run1_LYDown_reco2_reco2.root -/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run1_LYRayleigh_reco2_reco2.root -/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run1_Overlay_reco2_reco2.root -/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run1_Recombination_reco2_reco2.root -/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run1_SCE_reco2_reco2.root -/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run1_ThetaXZ_reco2_reco2.root -/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run1_ThetaYZ_reco2_reco2.root -/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run1_X_reco2_reco2.root -/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run1_YZ_reco2_reco2.root - -# Run 3 high-stats detVar -/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_CVextra_reco2_reco2.root -/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_CV_reco2_reco2.root -/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_dEdx_reco2_reco2.root -/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_LYAttenuation_reco2_reco2.root -/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_LYDown_reco2_reco2.root -/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_LYRayleigh_reco2_reco2.root -/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_Overlay_reco2_reco2.root -/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_Recombination_reco2_reco2.root -/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_SCE_reco2_reco2.root -/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_ThetaXZ_reco2_reco2.root -/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_ThetaYZ_reco2_reco2.root -/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_X_reco2_reco2.root -/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_YZ_reco2_reco2.root +/exp/sbnd/data/users/brindenc/xsec_analysis/test/sbruce_med/test1/cc1mux_med.root diff --git a/configs/sbnd_xsec_config.txt b/configs/sbnd_xsec_config.txt new file mode 100644 index 000000000..ea2247e0b --- /dev/null +++ b/configs/sbnd_xsec_config.txt @@ -0,0 +1,6 @@ +UnivFile /exp/sbnd/data/users/brindenc/xsec_analysis/test/sbruce_med/test1/uni_med2.root +SystFile /exp/sbnd/app/users/brindenc/xsec_analyzer/configs/systcalc.conf +#FPFile /exp/sbnd/app/users/brindenc/xsec_analyzer/configs/file_properties.txt +#Unfold DAgostini fm 0.025 +Unfold WienerSVD 1 second-deriv +#Prediction uBTune "MicroBooNE Tune" univ CV diff --git a/configs/systcalc_full_sbnd.conf b/configs/systcalc_full_sbnd.conf new file mode 100644 index 000000000..54a9e955a --- /dev/null +++ b/configs/systcalc_full_sbnd.conf @@ -0,0 +1,74 @@ +# flux FluxRW weight_flux_all 0#1 +# reint RW weight_reint_all 0#1 +# xsec_multi RW weight_All_UBGenie 0#1 + +#All cross section weights +xsec_GENIEReWeight_SBN_v1_multisim_ZExpAVariationResponse RW weight_GENIEReWeight_SBN_v1_multisim_ZExpAVariationResponse 1 +# xsec_GENIEReWeight_SBN_v1_multisim_RPA_CCQE RW weight_GENIEReWeight_SBN_v1_multisim_RPA_CCQE 0 +# xsec_GENIEReWeight_SBN_v1_multisim_CoulombCCQE RW weight_GENIEReWeight_SBN_v1_multisim_CoulombCCQE 0 +# xsec_GENIEReWeight_SBN_v1_multisim_NormCCMEC RW weight_GENIEReWeight_SBN_v1_multisim_NormCCMEC 0 +# xsec_GENIEReWeight_SBN_v1_multisim_NormNCMEC RW weight_GENIEReWeight_SBN_v1_multisim_NormNCMEC 0 +# xsec_GENIEReWeight_SBN_v1_multisim_NCELVariationResponse RW weight_GENIEReWeight_SBN_v1_multisim_NCELVariationResponse 0 +# xsec_GENIEReWeight_SBN_v1_multisim_CCRESVariationResponse RW weight_GENIEReWeight_SBN_v1_multisim_CCRESVariationResponse 0 +# xsec_GENIEReWeight_SBN_v1_multisim_NCRESVariationResponse RW weight_GENIEReWeight_SBN_v1_multisim_NCRESVariationResponse 0 +# xsec_GENIEReWeight_SBN_v1_multisim_NonRESBGvpCC1pi RW weight_GENIEReWeight_SBN_v1_multisim_NonRESBGvpCC1pi 0 +# xsec_GENIEReWeight_SBN_v1_multisim_NonRESBGvpCC2pi RW weight_GENIEReWeight_SBN_v1_multisim_NonRESBGvpCC2pi 0 +# xsec_GENIEReWeight_SBN_v1_multisim_NonRESBGvpNC1pi RW weight_GENIEReWeight_SBN_v1_multisim_NonRESBGvpNC1pi 0 +# xsec_GENIEReWeight_SBN_v1_multisim_NonRESBGvpNC2pi RW weight_GENIEReWeight_SBN_v1_multisim_NonRESBGvpNC2pi 0 +# xsec_GENIEReWeight_SBN_v1_multisim_NonRESBGvnCC1pi RW weight_GENIEReWeight_SBN_v1_multisim_NonRESBGvnCC1pi 0 +# xsec_GENIEReWeight_SBN_v1_multisim_NonRESBGvnCC2pi RW weight_GENIEReWeight_SBN_v1_multisim_NonRESBGvnCC2pi 0 +# xsec_GENIEReWeight_SBN_v1_multisim_NonRESBGvnNC1pi RW weight_GENIEReWeight_SBN_v1_multisim_NonRESBGvnNC1pi 0 +# xsec_GENIEReWeight_SBN_v1_multisim_NonRESBGvnNC2pi RW weight_GENIEReWeight_SBN_v1_multisim_NonRESBGvnNC2pi 0 +# xsec_GENIEReWeight_SBN_v1_multisim_NonRESBGvbarpCC1pi RW weight_GENIEReWeight_SBN_v1_multisim_NonRESBGvbarpCC1pi 0 +# xsec_GENIEReWeight_SBN_v1_multisim_NonRESBGvbarpCC2pi RW weight_GENIEReWeight_SBN_v1_multisim_NonRESBGvbarpCC2pi 0 +# xsec_GENIEReWeight_SBN_v1_multisim_NonRESBGvbarpNC1pi RW weight_GENIEReWeight_SBN_v1_multisim_NonRESBGvbarpNC1pi 0 +# xsec_GENIEReWeight_SBN_v1_multisim_NonRESBGvbarpNC2pi RW weight_GENIEReWeight_SBN_v1_multisim_NonRESBGvbarpNC2pi 0 +# xsec_GENIEReWeight_SBN_v1_multisim_NonRESBGvbarnCC1pi RW weight_GENIEReWeight_SBN_v1_multisim_NonRESBGvbarnCC1pi 0 +# xsec_GENIEReWeight_SBN_v1_multisim_NonRESBGvbarnCC2pi RW weight_GENIEReWeight_SBN_v1_multisim_NonRESBGvbarnCC2pi 0 +# xsec_GENIEReWeight_SBN_v1_multisim_NonRESBGvbarnNC1pi RW weight_GENIEReWeight_SBN_v1_multisim_NonRESBGvbarnNC1pi 0 +# xsec_GENIEReWeight_SBN_v1_multisim_NonRESBGvbarnNC2pi RW weight_GENIEReWeight_SBN_v1_multisim_NonRESBGvbarnNC2pi 0 +# xsec_GENIEReWeight_SBN_v1_multisim_COHVariationResponse RW weight_GENIEReWeight_SBN_v1_multisim_COHVariationResponse 0 +# xsec_GENIEReWeight_SBN_v1_multisim_DISBYVariationResponse RW weight_GENIEReWeight_SBN_v1_multisim_DISBYVariationResponse 0 +# xsec_GENIEReWeight_SBN_v1_multisim_FSI_pi_VariationResponse RW weight_GENIEReWeight_SBN_v1_multisim_FSI_pi_VariationResponse 0 +# xsec_GENIEReWeight_SBN_v1_multisim_FSI_N_VariationRespons RW weight_GENIEReWeight_SBN_v1_multisim_FSI_N_VariationRespons 0 + +#All flux weights +# flux_expskin_Flux FluxRW expskin_Flux 0 +# flux_horncurrent_Flux FluxRW horncurrent_Flux 0 +# flux_nucleoninexsec_Flux FluxRW nucleoninexsec_Flux 0 +# flux_nucleonqexsec_Flux FluxRW nucleonqexsec_Flux 0 +# flux_nucleontotxsec_Flux FluxRW nucleontotxsec_Flux 0 +# flux_pioninexsec_Flux FluxRW pioninexsec_Flux 0 +# flux_pionqexsec_Flux FluxRW pionqexsec_Flux 0 +# flux_piontotxsec_Flux FluxRW piontotxsec_Flux 0 +# flux_piplus_Flux FluxRW piplus_Flux 0 +# flux_piminus_Flux FluxRW piminus_Flux 0 +# flux_kplus_Flux FluxRW kplus_Flux 0 +# flux_kminus_Flux FluxRW kminus_Flux 0 +# flux_kzero_Flux FluxRW kzero_Flux 0 + +#Detector variations + +#POT and numTargets +# POT MCFullCorr 0.02 +# numTargets MCFullCorr 0.01 + +#Stats +# MCstats MCstat +# EXTstats EXTstat +# BNBstats BNBstat + +# xsec_unisim sum + +# xsec_total sum 5 xsec_multi xsec_unisim xsec_xsr_scc_Fa3_SCC +# xsec_xsr_scc_Fv3_SCC NuWroGenie + +# detVar_total sum 9 detVarLYatten detVarLYdown detVarLYrayl detVarRecomb2 +# detVarSCE detVarWMAngleXZ detVarWMAngleYZ detVarWMX detVarWMYZ + +# DataStats sum 2 EXTstats BNBstats + +# PredTotal sum 8 detVar_total flux reint xsec_total POT numTargets +# MCstats EXTstats + +# total sum 2 PredTotal BNBstats diff --git a/configs/systcalc_singlesyst_sbnd.conf b/configs/systcalc_singlesyst_sbnd.conf new file mode 100644 index 000000000..5fecb411a --- /dev/null +++ b/configs/systcalc_singlesyst_sbnd.conf @@ -0,0 +1,7 @@ +xsec_GENIEReWeight_SBN_v1_multisim_ZExpAVariationResponse RW weight_GENIEReWeight_SBN_v1_multisim_ZExpAVariationResponse 1 + +MCstats MCstat +BNBstats BNBstat +EXTstats EXTstat + +total sum 4 MCstats BNBstats EXTstats xsec_GENIEReWeight_SBN_v1_multisim_ZExpAVariationResponse \ No newline at end of file diff --git a/configs/systcalc_stat_sbnd.conf b/configs/systcalc_stat_sbnd.conf new file mode 100644 index 000000000..a9d012751 --- /dev/null +++ b/configs/systcalc_stat_sbnd.conf @@ -0,0 +1,5 @@ +MCstats MCstat +EXTstats EXTstat +BNBstats BNBstat + +total sum 3 MCstats BNBstats EXTstats diff --git a/configs/uboone_file_properties.txt b/configs/uboone_file_properties.txt new file mode 100644 index 000000000..c94615122 --- /dev/null +++ b/configs/uboone_file_properties.txt @@ -0,0 +1,49 @@ +# Trigger counts and POT exposures are taken from the searching4nues +# spreadsheet: tinyurl.com/pelee-nue-ntuples +# file_name run file_type [triggers POT (for data only)] +# +# Open beam-on data +# /exp/uboone/data/users/barrow/CC2P/stv-data_bnb_mcc9.1_v08_00_00_25_reco2_C1_beam_good_reco2_5e19.root 1 onBNB 10080350 4.54e19 +# /exp/uboone/data/users/barrow/CC2P/stv-data_bnb_mcc9.1_v08_00_00_25_reco2_G1_beam_good_reco2_1e19.root 3 onBNB 2271036 9.43e18 +# +# Beam-off data +/exp/uboone/data/users/barrow/CC2P/stv-data_extbnb_mcc9.1_v08_00_00_25_reco2_C_all_reco2.root 1 extBNB 65498807 0 +/exp/uboone/data/users/barrow/CC2P/stv-data_extbnb_mcc9.1_v08_00_00_25_reco2_D_E_all_reco2.root 2 extBNB 152404890 0 +/exp/uboone/data/users/barrow/CC2P/stv-data_extbnb_mcc9.1_v08_00_00_25_reco2_F_G_all_reco2.root 3 extBNB 214555174 0 +# +# Full beam-on data +/exp/uboone/data/users/barrow/CC2P/stv-run1_neutrinoselection_filt_numu_ALL.root 1 onBNB 36139233 1.62e20 +/exp/uboone/data/users/barrow/CC2P/stv-run2_neutrinoselection_filt_numu_ALL.root 2 onBNB 62045760 2.62e20 +/exp/uboone/data/users/barrow/CC2P/stv-run3_neutrinoselection_filt_numu_ALL.root 3 onBNB 61012955 2.55e20 +# +# Dirt MC samples +/exp/uboone/data/users/barrow/CC2P/stv-prodgenie_bnb_dirt_overlay_mcc9.1_v08_00_00_26_run1_reco2_reco2.root 1 dirtMC +/exp/uboone/data/users/barrow/CC2P/stv-prodgenie_dirt_overlay_v08_00_00_35_all_run2_reco2_reco2.root 2 dirtMC +/exp/uboone/data/users/barrow/CC2P/stv-prodgenie_bnb_dirt_overlay_mcc9.1_v08_00_00_26_run3_reco2_reco2.root 3 dirtMC +# +# Intrinsic nue MC samples +/exp/uboone/data/users/barrow/CC2P/stv-prodgenie_bnb_intrinsice_nue_uboone_overlay_mcc9.1_v08_00_00_26_run1_reco2_reco2.root 1 nueMC +/exp/uboone/data/users/barrow/CC2P/stv-prodgenie_bnb_intrinsic_nue_overlay_run2_v08_00_00_35_run2a_reco2_reco2.root 2 nueMC +/exp/uboone/data/users/barrow/CC2P/stv-prodgenie_bnb_intrinsice_nue_uboone_overlay_mcc9.1_v08_00_00_26_run3_reco2_reco2.root 3 nueMC +# +# numu MC samples +/exp/uboone/data/users/barrow/CC2P/stv-prodgenie_bnb_nu_uboone_overlay_mcc9.1_v08_00_00_26_filter_run1_reco2_reco2.root 1 numuMC +/exp/uboone/data/users/barrow/CC2P/stv-prodgenie_bnb_nu_uboone_overlay_mcc9.1_v08_00_00_26_filter_run2_reco2_D1D2_reco2.root 2 numuMC +/exp/uboone/data/users/barrow/CC2P/stv-prodgenie_bnb_nu_uboone_overlay_mcc9.1_v08_00_00_26_filter_run3_reco2_G_reco2.root 3 numuMC +# detVar MC samples +/exp/uboone/data/users/barrow/CC2P/stv-high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_CVextra_reco2_reco2.root 3 detVarCVExtra +/exp/uboone/data/users/barrow/CC2P/stv-high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_CV_reco2_reco2.root 3 detVarCV +/exp/uboone/data/users/barrow/CC2P/stv-high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_dEdx_reco2_reco2.root 3 detVarWMdEdx +/exp/uboone/data/users/barrow/CC2P/stv-high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_LYAttenuation_reco2_reco2.root 3 detVarLYatten +/exp/uboone/data/users/barrow/CC2P/stv-high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_LYDown_reco2_reco2.root 3 detVarLYdown +/exp/uboone/data/users/barrow/CC2P/stv-high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_LYRayleigh_reco2_reco2.root 3 detVarLYrayl +/exp/uboone/data/users/barrow/CC2P/stv-high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_Recombination_reco2_reco2.root 3 detVarRecomb2 +/exp/uboone/data/users/barrow/CC2P/stv-high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_SCE_reco2_reco2.root 3 detVarSCE +/exp/uboone/data/users/barrow/CC2P/stv-high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_ThetaXZ_reco2_reco2.root 3 detVarWMAngleXZ +/exp/uboone/data/users/barrow/CC2P/stv-high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_ThetaYZ_reco2_reco2.root 3 detVarWMAngleYZ +/exp/uboone/data/users/barrow/CC2P/stv-high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_X_reco2_reco2.root 3 detVarWMX +/exp/uboone/data/users/barrow/CC2P/stv-high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_YZ_reco2_reco2.root 3 detVarWMYZ +# NuWro numuMC +/exp/uboone/data/users/barrow/CC2P/stv-high_stat_prodgenie_bnb_nu_overlay_DetVar_Run1_NuWro_reco2_reco2.root 1 altCVMC +/exp/uboone/data/users/barrow/CC2P/stv-high_stat_prodgenie_bnb_nu_overlay_DetVar_Run2_NuWro_reco2_reco2.root 2 altCVMC +/exp/uboone/data/users/barrow/CC2P/stv-high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_NuWro_reco2_reco2.root 3 altCVMC diff --git a/configs/uboone_files_to_process.txt b/configs/uboone_files_to_process.txt new file mode 100644 index 000000000..66c70edcb --- /dev/null +++ b/configs/uboone_files_to_process.txt @@ -0,0 +1,64 @@ +# All beam-on data (slimmed only with nslice == 1 requirement) +/uboone/data/users/davidc/searchingfornues/v08_00_00_41/cc0pinp/0617/nslice/run1_neutrinoselection_filt_numu_ALL.root +/uboone/data/users/davidc/searchingfornues/v08_00_00_41/cc0pinp/0617/nslice/run2_neutrinoselection_filt_numu_ALL.root +/uboone/data/users/davidc/searchingfornues/v08_00_00_41/cc0pinp/0617/nslice/run3_neutrinoselection_filt_numu_ALL.root + +# Run 1 open and beam-off data +/uboone/data/users/davidc/searchingfornues/v08_00_00_43/0702/run1/data_bnb_mcc9.1_v08_00_00_25_reco2_C1_beam_good_reco2_5e19.root +/uboone/data/users/davidc/searchingfornues/v08_00_00_43/0702/run1/data_extbnb_mcc9.1_v08_00_00_25_reco2_C_all_reco2.root + +# Run 2 beam-off data +/uboone/data/users/davidc/searchingfornues/v08_00_00_43/0702/run2/data_extbnb_mcc9.1_v08_00_00_25_reco2_D_E_all_reco2.root + +# Run 3 open and beam-off data +/uboone/data/users/davidc/searchingfornues/v08_00_00_43/0702/run3/data_bnb_mcc9.1_v08_00_00_25_reco2_G1_beam_good_reco2_1e19.root +/uboone/data/users/davidc/searchingfornues/v08_00_00_43/0702/run3/data_extbnb_mcc9.1_v08_00_00_25_reco2_F_G_all_reco2.root + +# Run 1 CV MC +/pnfs/uboone/persistent/users/davidc/searchingfornues/v08_00_00_43/0928/prodgenie_bnb_nu_uboone_overlay_mcc9.1_v08_00_00_26_filter_run1_reco2_reco2.root +/pnfs/uboone/persistent/users/davidc/searchingfornues/v08_00_00_43/0928/prodgenie_bnb_intrinsice_nue_uboone_overlay_mcc9.1_v08_00_00_26_run1_reco2_reco2.root +/pnfs/uboone/persistent/users/davidc/searchingfornues/v08_00_00_43/0928/prodgenie_bnb_dirt_overlay_mcc9.1_v08_00_00_26_run1_reco2_reco2.root + +# Run 2 CV MC +/pnfs/uboone/persistent/users/davidc/searchingfornues/v08_00_00_43/0928/prodgenie_bnb_nu_uboone_overlay_mcc9.1_v08_00_00_26_filter_run2_reco2_D1D2_reco2.root +/pnfs/uboone/persistent/users/davidc/searchingfornues/v08_00_00_43/0928/prodgenie_bnb_intrinsic_nue_overlay_run2_v08_00_00_35_run2a_reco2_reco2.root +/pnfs/uboone/persistent/users/davidc/searchingfornues/v08_00_00_43/0928/prodgenie_dirt_overlay_v08_00_00_35_all_run2_reco2_reco2.root + +# Run 3 CV MC +/pnfs/uboone/persistent/users/davidc/searchingfornues/v08_00_00_43/0928/prodgenie_bnb_nu_uboone_overlay_mcc9.1_v08_00_00_26_filter_run3_reco2_G_reco2.root +/pnfs/uboone/persistent/users/davidc/searchingfornues/v08_00_00_43/0928/prodgenie_bnb_intrinsice_nue_uboone_overlay_mcc9.1_v08_00_00_26_run3_reco2_reco2.root +/pnfs/uboone/persistent/users/davidc/searchingfornues/v08_00_00_43/0928/prodgenie_bnb_dirt_overlay_mcc9.1_v08_00_00_26_run3_reco2_reco2.root + +# NuWro MC +/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run1_NuWro_reco2_reco2.root +/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run2_NuWro_reco2_reco2.root +/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_NuWro_reco2_reco2.root + +# Run 1 high-stats detVar +/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run1_CV_reco2_reco2.root +/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run1_dEdx_reco2_reco2.root +/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run1_LYAttenuation_reco2_reco2.root +/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run1_LYDown_reco2_reco2.root +/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run1_LYRayleigh_reco2_reco2.root +/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run1_Overlay_reco2_reco2.root +/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run1_Recombination_reco2_reco2.root +/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run1_SCE_reco2_reco2.root +/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run1_ThetaXZ_reco2_reco2.root +/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run1_ThetaYZ_reco2_reco2.root +/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run1_X_reco2_reco2.root +/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run1_YZ_reco2_reco2.root + +# Run 3 high-stats detVar +/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_CVextra_reco2_reco2.root +/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_CV_reco2_reco2.root +/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_dEdx_reco2_reco2.root +/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_LYAttenuation_reco2_reco2.root +/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_LYDown_reco2_reco2.root +/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_LYRayleigh_reco2_reco2.root +/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_Overlay_reco2_reco2.root +/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_Recombination_reco2_reco2.root +/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_SCE_reco2_reco2.root +/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_ThetaXZ_reco2_reco2.root +/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_ThetaYZ_reco2_reco2.root +/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_X_reco2_reco2.root +/uboone/data/users/apapadop/searchingfornues/high_stat_prodgenie_bnb_nu_overlay_DetVar_Run3_YZ_reco2_reco2.root diff --git a/configs/systcalc.conf b/configs/uboone_systcalc.conf similarity index 100% rename from configs/systcalc.conf rename to configs/uboone_systcalc.conf diff --git a/configs/systcalc_unfold_fd.conf b/configs/uboone_systcalc_unfold_fd.conf similarity index 100% rename from configs/systcalc_unfold_fd.conf rename to configs/uboone_systcalc_unfold_fd.conf diff --git a/configs/xsec_config.txt b/configs/uboone_xsec_config.txt similarity index 100% rename from configs/xsec_config.txt rename to configs/uboone_xsec_config.txt diff --git a/include/XSecAnalyzer/Binning/BinSchemeBase.hh b/include/XSecAnalyzer/Binning/BinSchemeBase.hh index afbf13d72..c761501c1 100644 --- a/include/XSecAnalyzer/Binning/BinSchemeBase.hh +++ b/include/XSecAnalyzer/Binning/BinSchemeBase.hh @@ -41,4 +41,13 @@ class BinSchemeBase { /// Name of the TDirectoryFile that will store the output histograms /// when univmake is run for this binning scheme std::string out_tdir_name_; + + /// Print the binning scheme + void Print(){ + std::cout << "Binning scheme: " << bin_scheme_name_ << '\n'; + std::cout << "Selection: " << selection_name_ << '\n'; + std::cout << "Output TDirectory: " << out_tdir_name_ << '\n'; + std::cout << "Output config prefix: " << out_config_prefix_ << '\n'; + std::cout << "Input TTree: " << ntuple_ttree_name_ << '\n'; + } }; diff --git a/include/XSecAnalyzer/Binning/SBND_CC1muX_BinScheme.hh b/include/XSecAnalyzer/Binning/SBND_CC1muX_BinScheme.hh new file mode 100644 index 000000000..f3e5d52c4 --- /dev/null +++ b/include/XSecAnalyzer/Binning/SBND_CC1muX_BinScheme.hh @@ -0,0 +1,12 @@ +#pragma once + +// XSecAnalyzer includes +#include "XSecAnalyzer/Binning/BinSchemeBase.hh" + +class SBND_CC1muX_BinScheme : public BinSchemeBase { + + public: + + SBND_CC1muX_BinScheme(); + virtual void DefineBlocks() override; +}; diff --git a/include/XSecAnalyzer/Branches.hh b/include/XSecAnalyzer/Branches.hh deleted file mode 100644 index d71819fbb..000000000 --- a/include/XSecAnalyzer/Branches.hh +++ /dev/null @@ -1,434 +0,0 @@ -#pragma once - -// ROOT includes -#include "TTree.h" -#include "AnalysisEvent.hh" - -void SetBranchAddress(TTree& etree, std::string BranchName, void* Variable) { - etree.SetBranchAddress(BranchName.c_str(),Variable); -} - -// Helper function to set branch addresses for reading information -// from the Event TTree -void set_event_branch_addresses(TTree& etree, AnalysisEvent& ev) -{ - // Reco PDG code of primary PFParticle in slice (i.e., the neutrino - // candidate) - SetBranchAddress(etree, "slpdg", &ev.nu_pdg_ ); - - // Number of neutrino slices identified by the SliceID. Allowed values - // are zero or one. - //SetBranchAddress(etree,"nslice",&ev.nslice_); - SetBranchAddress(etree, "nslice", &ev.nslice_ ); - - // Topological score - SetBranchAddress(etree, "topological_score", &ev.topological_score_ ); - SetBranchAddress(etree, "CosmicIP", &ev.cosmic_impact_parameter_ ); - //SetBranchAddress(etree, "CosmicIPAll3D", &ev.CosmicIPAll3D_ ); - - // Reconstructed neutrino vertex position (with corrections for - // space charge applied) - SetBranchAddress(etree, "reco_nu_vtx_sce_x", &ev.nu_vx_ ); - SetBranchAddress(etree, "reco_nu_vtx_sce_y", &ev.nu_vy_ ); - SetBranchAddress(etree, "reco_nu_vtx_sce_z", &ev.nu_vz_ ); - - // Reconstructed object counts - SetBranchAddress(etree, "n_pfps", &ev.num_pf_particles_ ); - SetBranchAddress(etree, "n_tracks", &ev.num_tracks_ ); - SetBranchAddress(etree, "n_showers", &ev.num_showers_ ); - - // PFParticle properties - set_object_input_branch_address( etree, "pfp_generation_v", - ev.pfp_generation_ ); - - set_object_input_branch_address( etree, "pfp_trk_daughters_v", - ev.pfp_trk_daughters_count_ ); - - set_object_input_branch_address( etree, "pfp_shr_daughters_v", - ev.pfp_shr_daughters_count_ ); - - set_object_input_branch_address( etree, "trk_score_v", ev.pfp_track_score_ ); - set_object_input_branch_address( etree, "pfpdg", ev.pfp_reco_pdg_ ); - set_object_input_branch_address( etree, "pfnhits", ev.pfp_hits_ ); - set_object_input_branch_address( etree, "pfnplanehits_U", ev.pfp_hitsU_ ); - set_object_input_branch_address( etree, "pfnplanehits_V", ev.pfp_hitsV_ ); - set_object_input_branch_address( etree, "pfnplanehits_Y", ev.pfp_hitsY_ ); - - // Backtracked PFParticle properties - set_object_input_branch_address( etree, "backtracked_pdg", ev.pfp_true_pdg_ ); - set_object_input_branch_address( etree, "backtracked_e", ev.pfp_true_E_ ); - set_object_input_branch_address( etree, "backtracked_px", ev.pfp_true_px_ ); - set_object_input_branch_address( etree, "backtracked_py", ev.pfp_true_py_ ); - set_object_input_branch_address( etree, "backtracked_pz", ev.pfp_true_pz_ ); - - // Shower properties - // These are excluded from some ntuples to ensure blindness for the LEE - // analyses. We will skip them when not available. - bool has_shower_branches = ( etree.GetBranch("shr_pfp_id_v") != nullptr ); - if ( has_shower_branches ) { - set_object_input_branch_address( etree, "shr_pfp_id_v", ev.shower_pfp_id_ ); - set_object_input_branch_address( etree, "shr_start_x_v", ev.shower_startx_ ); - set_object_input_branch_address( etree, "shr_start_y_v", ev.shower_starty_ ); - set_object_input_branch_address( etree, "shr_start_z_v", ev.shower_startz_ ); - // Shower start distance from reco neutrino vertex (pre-calculated for - // convenience) - set_object_input_branch_address( etree, "shr_dist_v", - ev.shower_start_distance_ ); - } - else { - // When the shower information is not available, delete the owned vectors - // to signal that the associated branches should not be written to the - // output TTree - ev.shower_pfp_id_.reset( nullptr ); - ev.shower_startx_.reset( nullptr ); - ev.shower_starty_.reset( nullptr ); - ev.shower_startz_.reset( nullptr ); - ev.shower_start_distance_.reset( nullptr ); - } - - // Track properties - set_object_input_branch_address( etree, "trk_pfp_id_v", ev.track_pfp_id_ ); - set_object_input_branch_address( etree, "trk_len_v", ev.track_length_ ); - set_object_input_branch_address( etree, "trk_sce_start_x_v", ev.track_startx_ ); - set_object_input_branch_address( etree, "trk_sce_start_y_v", ev.track_starty_ ); - set_object_input_branch_address( etree, "trk_sce_start_z_v", ev.track_startz_ ); - - // Track start distance from reco neutrino vertex (pre-calculated for - // convenience) - set_object_input_branch_address( etree, "trk_distance_v", - ev.track_start_distance_ ); - - set_object_input_branch_address( etree, "trk_sce_end_x_v", ev.track_endx_ ); - set_object_input_branch_address( etree, "trk_sce_end_y_v", ev.track_endy_ ); - set_object_input_branch_address( etree, "trk_sce_end_z_v", ev.track_endz_ ); - - set_object_input_branch_address( etree, "trk_dir_x_v", ev.track_dirx_ ); - set_object_input_branch_address( etree, "trk_dir_y_v", ev.track_diry_ ); - set_object_input_branch_address( etree, "trk_dir_z_v", ev.track_dirz_ ); - - set_object_input_branch_address( etree, "trk_theta_v", ev.track_theta_ ); - set_object_input_branch_address( etree, "trk_phi_v", ev.track_phi_ ); - - set_object_input_branch_address( etree, "trk_energy_proton_v", - ev.track_kinetic_energy_p_ ); - - set_object_input_branch_address( etree, "trk_range_muon_mom_v", - ev.track_range_mom_mu_ ); - - set_object_input_branch_address( etree, "trk_mcs_muon_mom_v", - ev.track_mcs_mom_mu_ ); - - // Some ntuples exclude the old proton chi^2 PID score. Only include it - // in the output if this branch is available. - bool has_chipr = ( etree.GetBranch("trk_pid_chipr_v") != nullptr ); - if ( has_chipr ) { - set_object_input_branch_address( etree, "trk_pid_chipr_v", - ev.track_chi2_proton_ ); - } - else { - ev.track_chi2_proton_.reset( nullptr ); - } - - // Log-likelihood-based particle ID information - set_object_input_branch_address( etree, "trk_llr_pid_v", ev.track_llr_pid_ ); - - set_object_input_branch_address( etree, "trk_llr_pid_u_v", - ev.track_llr_pid_U_ ); - - set_object_input_branch_address( etree, "trk_llr_pid_v_v", - ev.track_llr_pid_V_ ); - - set_object_input_branch_address( etree, "trk_llr_pid_y_v", - ev.track_llr_pid_Y_ ); - - set_object_input_branch_address( etree, "trk_llr_pid_score_v", - ev.track_llr_pid_score_ ); - - // MC truth information for the neutrino - SetBranchAddress(etree, "nu_pdg", &ev.mc_nu_pdg_ ); - SetBranchAddress(etree, "true_nu_vtx_x", &ev.mc_nu_vx_ ); - SetBranchAddress(etree, "true_nu_vtx_y", &ev.mc_nu_vy_ ); - SetBranchAddress(etree, "true_nu_vtx_z", &ev.mc_nu_vz_ ); - SetBranchAddress(etree, "nu_e", &ev.mc_nu_energy_ ); - SetBranchAddress(etree, "ccnc", &ev.mc_nu_ccnc_ ); - SetBranchAddress(etree, "interaction", &ev.mc_nu_interaction_type_ ); - - //============================================= - //DB Added to match Samantha's Signal defintion - - SetBranchAddress(etree, "true_nu_vtx_sce_x", &ev.mc_nu_sce_vx_ ); - SetBranchAddress(etree, "true_nu_vtx_sce_y", &ev.mc_nu_sce_vy_ ); - SetBranchAddress(etree, "true_nu_vtx_sce_z", &ev.mc_nu_sce_vz_ ); - - //============================================= - - // MC truth information for the final-state primary particles - set_object_input_branch_address( etree, "mc_pdg", ev.mc_nu_daughter_pdg_ ); - set_object_input_branch_address( etree, "mc_E", ev.mc_nu_daughter_energy_ ); - set_object_input_branch_address( etree, "mc_px", ev.mc_nu_daughter_px_ ); - set_object_input_branch_address( etree, "mc_py", ev.mc_nu_daughter_py_ ); - set_object_input_branch_address( etree, "mc_pz", ev.mc_nu_daughter_pz_ ); - - // GENIE and other systematic variation weights - bool has_genie_mc_weights = ( etree.GetBranch("weightSpline") != nullptr ); - if ( has_genie_mc_weights ) { - SetBranchAddress(etree, "weightSpline", &ev.spline_weight_ ); - SetBranchAddress(etree, "weightTune", &ev.tuned_cv_weight_ ); - } - - bool has_weight_map = ( etree.GetBranch("weights") != nullptr ); - if ( has_weight_map ) { - set_object_input_branch_address( etree, "weights", ev.mc_weights_map_ ); - } - else { - ev.mc_weights_map_.reset( nullptr ); - } - - // Purity and completeness of the backtracked hits in the neutrino slice - bool has_pfp_backtracked_purity = ( etree.GetBranch("nu_purity_from_pfp") - != nullptr ); - if ( has_pfp_backtracked_purity ) { - - SetBranchAddress(etree, "nu_completeness_from_pfp", - &ev.nu_completeness_from_pfp_ ); - - SetBranchAddress(etree, "nu_purity_from_pfp", &ev.nu_purity_from_pfp_ ); - - } - -} - -// Helper function to set branch addresses for the output TTree -void set_event_output_branch_addresses(TTree& out_tree, AnalysisEvent& ev, - bool create = false) -{ - // Signal definition flags - set_output_branch_address( out_tree, "is_mc", &ev.is_mc_, create, "is_mc/O" ); - - // Event weights - set_output_branch_address( out_tree, "spline_weight", - &ev.spline_weight_, create, "spline_weight/F" ); - - set_output_branch_address( out_tree, "tuned_cv_weight", - &ev.tuned_cv_weight_, create, "tuned_cv_weight/F" ); - - // If MC weights are available, prepare to store them in the output TTree - if ( ev.mc_weights_map_ ) { - - // Make separate branches for the various sets of systematic variation - // weights in the map - for ( auto& pair : *ev.mc_weights_map_ ) { - - // Prepend "weight_" to the name of the vector of weights in the map - std::string weight_branch_name = "weight_" + pair.first; - - // Store a pointer to the vector of weights (needed to set the branch - // address properly) in the temporary map of pointers - ev.mc_weights_ptr_map_[ weight_branch_name ] = &pair.second; - - // Set the branch address for this vector of weights - set_object_output_branch_address< std::vector >( out_tree, - weight_branch_name, ev.mc_weights_ptr_map_.at(weight_branch_name), - create ); - } - } - - // Backtracked neutrino purity and completeness - set_output_branch_address( out_tree, "nu_completeness_from_pfp", - &ev.nu_completeness_from_pfp_, create, "nu_completeness_from_pfp/F" ); - - set_output_branch_address( out_tree, "nu_purity_from_pfp", - &ev.nu_purity_from_pfp_, create, "nu_purity_from_pfp/F" ); - - // Number of neutrino slices identified by the SliceID - set_output_branch_address( out_tree, "nslice", &ev.nslice_, create, - "nslice/I" ); - - // *** Branches copied directly from the input *** - - // Cosmic rejection parameters for numu CC inclusive selection - set_output_branch_address( out_tree, "topological_score", - &ev.topological_score_, create, "topological_score/F" ); - - set_output_branch_address( out_tree, "CosmicIP", - &ev.cosmic_impact_parameter_, create, "CosmicIP/F" ); - - // Reconstructed neutrino vertex position - set_output_branch_address( out_tree, "reco_nu_vtx_sce_x", - &ev.nu_vx_, create, "reco_nu_vtx_sce_x/F" ); - - set_output_branch_address( out_tree, "reco_nu_vtx_sce_y", - &ev.nu_vy_, create, "reco_nu_vtx_sce_y/F" ); - - set_output_branch_address( out_tree, "reco_nu_vtx_sce_z", - &ev.nu_vz_, create, "reco_nu_vtx_sce_z/F" ); - - // MC truth information for the neutrino - set_output_branch_address( out_tree, "mc_nu_pdg", &ev.mc_nu_pdg_, - create, "mc_nu_pdg/I" ); - - set_output_branch_address( out_tree, "mc_nu_vtx_x", &ev.mc_nu_vx_, - create, "mc_nu_vtx_x/F" ); - - set_output_branch_address( out_tree, "mc_nu_vtx_y", &ev.mc_nu_vy_, - create, "mc_nu_vtx_y/F" ); - - set_output_branch_address( out_tree, "mc_nu_vtx_z", &ev.mc_nu_vz_, - create, "mc_nu_vtx_z/F" ); - - set_output_branch_address( out_tree, "mc_nu_energy", &ev.mc_nu_energy_, - create, "mc_nu_energy/F" ); - - set_output_branch_address( out_tree, "mc_ccnc", &ev.mc_nu_ccnc_, - create, "mc_ccnc/I" ); - - set_output_branch_address( out_tree, "mc_interaction", - &ev.mc_nu_interaction_type_, create, "mc_interaction/I" ); - - // PFParticle properties - set_object_output_branch_address< std::vector >( out_tree, - "pfp_generation_v", ev.pfp_generation_, create ); - - set_object_output_branch_address< std::vector >( out_tree, - "pfp_trk_daughters_v", ev.pfp_trk_daughters_count_, create ); - - set_object_output_branch_address< std::vector >( out_tree, - "pfp_shr_daughters_v", ev.pfp_shr_daughters_count_, create ); - - set_object_output_branch_address< std::vector >( out_tree, - "trk_score_v", ev.pfp_track_score_, create ); - - set_object_output_branch_address< std::vector >( out_tree, - "pfpdg", ev.pfp_reco_pdg_, create ); - - set_object_output_branch_address< std::vector >( out_tree, - "pfnhits", ev.pfp_hits_, create ); - - set_object_output_branch_address< std::vector >( out_tree, - "pfnplanehits_U", ev.pfp_hitsU_, create ); - - set_object_output_branch_address< std::vector >( out_tree, - "pfnplanehits_V", ev.pfp_hitsV_, create ); - - set_object_output_branch_address< std::vector >( out_tree, - "pfnplanehits_Y", ev.pfp_hitsY_, create ); - - // Backtracked PFParticle properties - set_object_output_branch_address< std::vector >( out_tree, - "backtracked_pdg", ev.pfp_true_pdg_, create ); - - set_object_output_branch_address< std::vector >( out_tree, - "backtracked_e", ev.pfp_true_E_, create ); - - set_object_output_branch_address< std::vector >( out_tree, - "backtracked_px", ev.pfp_true_px_, create ); - - set_object_output_branch_address< std::vector >( out_tree, - "backtracked_py", ev.pfp_true_py_, create ); - - set_object_output_branch_address< std::vector >( out_tree, - "backtracked_pz", ev.pfp_true_pz_, create ); - - // Shower properties - // For some ntuples, reconstructed shower information is excluded. - // In such cases, skip writing these branches to the output TTree. - if ( ev.shower_startx_ ) { - set_object_output_branch_address< std::vector >( out_tree, - "shr_start_x_v", ev.shower_startx_, create ); - - set_object_output_branch_address< std::vector >( out_tree, - "shr_start_y_v", ev.shower_starty_, create ); - - set_object_output_branch_address< std::vector >( out_tree, - "shr_start_z_v", ev.shower_startz_, create ); - - // Shower start distance from reco neutrino vertex (pre-calculated for - // convenience) - set_object_output_branch_address< std::vector >( out_tree, - "shr_dist_v", ev.shower_start_distance_, create ); - } - - // Track properties - set_object_output_branch_address< std::vector >( out_tree, - "trk_len_v", ev.track_length_, create ); - - set_object_output_branch_address< std::vector >( out_tree, - "trk_sce_start_x_v", ev.track_startx_, create ); - - set_object_output_branch_address< std::vector >( out_tree, - "trk_sce_start_y_v", ev.track_starty_, create ); - - set_object_output_branch_address< std::vector >( out_tree, - "trk_sce_start_z_v", ev.track_startz_, create ); - - // Track start distance from reco neutrino vertex (pre-calculated for - // convenience) - set_object_output_branch_address< std::vector >( out_tree, - "trk_distance_v", ev.track_start_distance_, create ); - - set_object_output_branch_address< std::vector >( out_tree, - "trk_sce_end_x_v", ev.track_endx_, create ); - - set_object_output_branch_address< std::vector >( out_tree, - "trk_sce_end_y_v", ev.track_endy_, create ); - - set_object_output_branch_address< std::vector >( out_tree, - "trk_sce_end_z_v", ev.track_endz_, create ); - - set_object_output_branch_address< std::vector >( out_tree, - "trk_dir_x_v", ev.track_dirx_, create ); - - set_object_output_branch_address< std::vector >( out_tree, - "trk_dir_y_v", ev.track_diry_, create ); - - set_object_output_branch_address< std::vector >( out_tree, - "trk_dir_z_v", ev.track_dirz_, create ); - - set_object_output_branch_address< std::vector >( out_tree, - "trk_energy_proton_v", ev.track_kinetic_energy_p_, create ); - - set_object_output_branch_address< std::vector >( out_tree, - "trk_range_muon_mom_v", ev.track_range_mom_mu_, create ); - - set_object_output_branch_address< std::vector >( out_tree, - "trk_mcs_muon_mom_v", ev.track_mcs_mom_mu_, create ); - - // Some ntuples exclude the old chi^2 proton PID score. Only include it in - // the output if it is available. - if ( ev.track_chi2_proton_ ) { - set_object_output_branch_address< std::vector >( out_tree, - "trk_pid_chipr_v", ev.track_chi2_proton_, create ); - } - - // Log-likelihood-based particle ID information - set_object_output_branch_address< std::vector >( out_tree, - "trk_llr_pid_v", ev.track_llr_pid_, create ); - - set_object_output_branch_address< std::vector >( out_tree, - "trk_llr_pid_u_v", ev.track_llr_pid_U_, create ); - - set_object_output_branch_address< std::vector >( out_tree, - "trk_llr_pid_v_v", ev.track_llr_pid_V_, create ); - - set_object_output_branch_address< std::vector >( out_tree, - "trk_llr_pid_y_v", ev.track_llr_pid_Y_, create ); - - set_object_output_branch_address< std::vector >( out_tree, - "trk_llr_pid_score_v", ev.track_llr_pid_score_, create ); - - // MC truth information for the final-state primary particles - set_object_output_branch_address< std::vector >( out_tree, "mc_pdg", - ev.mc_nu_daughter_pdg_, create ); - - set_object_output_branch_address< std::vector >( out_tree, "mc_E", - ev.mc_nu_daughter_energy_, create ); - - set_object_output_branch_address< std::vector >( out_tree, "mc_px", - ev.mc_nu_daughter_px_, create ); - - set_object_output_branch_address< std::vector >( out_tree, "mc_py", - ev.mc_nu_daughter_py_, create ); - - set_object_output_branch_address< std::vector >( out_tree, "mc_pz", - ev.mc_nu_daughter_pz_, create ); -} diff --git a/include/XSecAnalyzer/AnalysisEvent.hh b/include/XSecAnalyzer/Event/AnalysisEvent.hh similarity index 86% rename from include/XSecAnalyzer/AnalysisEvent.hh rename to include/XSecAnalyzer/Event/AnalysisEvent.hh index 35cb69dc0..f6d551739 100644 --- a/include/XSecAnalyzer/AnalysisEvent.hh +++ b/include/XSecAnalyzer/Event/AnalysisEvent.hh @@ -1,19 +1,20 @@ #pragma once // STV analysis includes -#include "TreeUtils.hh" -#include "FiducialVolume.hh" -#include "Constants.hh" +#include "XSecAnalyzer/TreeUtils.hh" +#include "XSecAnalyzer/FiducialVolume.hh" +#include "XSecAnalyzer/Constants.hh" #include #include #include "TVector3.h" +#include "TChain.h" class AnalysisEvent{ public: AnalysisEvent() {} - ~AnalysisEvent() {} + virtual ~AnalysisEvent() {} // Event scores needed for numu CC selection float topological_score_ = BOGUS; @@ -156,5 +157,19 @@ public: bool is_mc_ = false; //================================================================================================================ - // ** Reconstructed observables ** -}; + + // SBND specific variables. Due to using AnalysisEvent in selections + // numuCC selection variables + double leading_muon_costheta_ = BOGUS; + double leading_muon_momentum_ = BOGUS; + double leading_muon_momentum_truth_ = BOGUS; + double leading_muon_costheta_truth_ = BOGUS; + + // Only loaded as doubles since that's all CAFana supports ( : + double event_type_ = BOGUS; + double is_signal_ = BOGUS; //based on reco info only + + // Helper function to set the branch addresses for the AnalysisEvent + virtual void set_event_branch_addresses( TTree& etree) = 0; + virtual void set_event_output_branch_addresses(TTree& out_tree, bool create_them) = 0; +}; \ No newline at end of file diff --git a/include/XSecAnalyzer/Event/AnalysisEventFactory.hh b/include/XSecAnalyzer/Event/AnalysisEventFactory.hh new file mode 100644 index 000000000..3796caa9a --- /dev/null +++ b/include/XSecAnalyzer/Event/AnalysisEventFactory.hh @@ -0,0 +1,22 @@ +/* +Description: Factory function to create appropriate event based on experiment +Date: 2024-10-16 +Authors: Brinden Carlson (bcarlson1@ufl.edu) +*/ + +#include "AnalysisEvent.hh" +#include "SBNDEvent.hh" +#include "uBooNEEvent.hh" + +// Factory function to create appropriate event based on experiment type +std::unique_ptr create_event(const std::string& experiment) { + if (experiment == "sbnd") { + return std::make_unique(); + } + else if (experiment == "uboone") { + return std::make_unique(); + } + // Add more experiments here with else if + std::cerr << "Invalid experiment name: " << experiment << std::endl; + return nullptr; // or throw an error +} \ No newline at end of file diff --git a/include/XSecAnalyzer/Event/SBNDEvent.hh b/include/XSecAnalyzer/Event/SBNDEvent.hh new file mode 100644 index 000000000..458ad4183 --- /dev/null +++ b/include/XSecAnalyzer/Event/SBNDEvent.hh @@ -0,0 +1,222 @@ +/* +Description: Implementation of AnalysisEvent class for SBND +Date: 2024-10-16 +Authors: Brinden Carlson (bcarlson1@ufl.edu) +*/ + +#include "AnalysisEvent.hh" + +class SBNDEvent : public AnalysisEvent { +public: + SBNDEvent() { + //FIXME: Get rid of this to autodetect for SBND + weight_TunedCentralValue_UBGenie->push_back(1.0); + weight_splines_general_Spline->push_back(1.0); + } + ~SBNDEvent() {} + + // Declare member variables for SBND + //FIXME: Load MC from CAFAna even though it's shorter than number of slices + bool is_mc_ = true; //default to MC + + // Flux systematic weights + MyPointer> expskin_Flux_; + MyPointer> horncurrent_Flux_; + MyPointer> nucleoninexsec_Flux_; + MyPointer> nucleonqexsec_Flux_; + MyPointer> nucleontotxsec_Flux_; + MyPointer> pioninexsec_Flux_; + MyPointer> pionqexsec_Flux_; + MyPointer> piontotxsec_Flux_; + MyPointer> piplus_Flux_; + MyPointer> piminus_Flux_; + MyPointer> kplus_Flux_; + MyPointer> kminus_Flux_; + MyPointer> kzero_Flux_; + + // xsec systematic weights + MyPointer> GENIEReWeight_SBN_v1_multisim_ZExpAVariationResponse_; + MyPointer> GENIEReWeight_SBN_v1_multisim_RPA_CCQE_; + MyPointer> GENIEReWeight_SBN_v1_multisim_CoulombCCQE_; + MyPointer> GENIEReWeight_SBN_v1_multisim_NormCCMEC_; + MyPointer> GENIEReWeight_SBN_v1_multisim_NormNCMEC_; + MyPointer> GENIEReWeight_SBN_v1_multisim_NCELVariationResponse_; + MyPointer> GENIEReWeight_SBN_v1_multisim_CCRESVariationResponse_; + MyPointer> GENIEReWeight_SBN_v1_multisim_NCRESVariationResponse_; + MyPointer> GENIEReWeight_SBN_v1_multisim_NonRESBGvpCC1pi_; + MyPointer> GENIEReWeight_SBN_v1_multisim_NonRESBGvpCC2pi_; + MyPointer> GENIEReWeight_SBN_v1_multisim_NonRESBGvpNC1pi_; + MyPointer> GENIEReWeight_SBN_v1_multisim_NonRESBGvpNC2pi_; + MyPointer> GENIEReWeight_SBN_v1_multisim_NonRESBGvnCC1pi_; + MyPointer> GENIEReWeight_SBN_v1_multisim_NonRESBGvnCC2pi_; + MyPointer> GENIEReWeight_SBN_v1_multisim_NonRESBGvnNC1pi_; + MyPointer> GENIEReWeight_SBN_v1_multisim_NonRESBGvnNC2pi_; + MyPointer> GENIEReWeight_SBN_v1_multisim_NonRESBGvbarpCC1pi_; + MyPointer> GENIEReWeight_SBN_v1_multisim_NonRESBGvbarpCC2pi_; + MyPointer> GENIEReWeight_SBN_v1_multisim_NonRESBGvbarpNC1pi_; + MyPointer> GENIEReWeight_SBN_v1_multisim_NonRESBGvbarpNC2pi_; + MyPointer> GENIEReWeight_SBN_v1_multisim_NonRESBGvbarnCC1pi_; + MyPointer> GENIEReWeight_SBN_v1_multisim_NonRESBGvbarnCC2pi_; + MyPointer> GENIEReWeight_SBN_v1_multisim_NonRESBGvbarnNC1pi_; + MyPointer> GENIEReWeight_SBN_v1_multisim_NonRESBGvbarnNC2pi_; + MyPointer> GENIEReWeight_SBN_v1_multisim_COHVariationResponse_; + MyPointer> GENIEReWeight_SBN_v1_multisim_DISBYVariationResponse_; + MyPointer> GENIEReWeight_SBN_v1_multisim_FSI_pi_VariationResponse_; + MyPointer> GENIEReWeight_SBN_v1_multisim_FSI_N_VariationResponse_; + + //Dummy weights for uBooNE + MyPointer> weight_TunedCentralValue_UBGenie; + MyPointer> weight_splines_general_Spline; + + // Helper function to set branch addresses for reading information + // from the Event TTree + void set_event_branch_addresses( TTree& etree) override + { + //Header info + //SetBranchAddress(etree, "is_mc", &this->is_mc_); + + //SetBranchAddress(etree, "nu_score", &this->topological_score_ ); + //Muon selection variables + SetBranchAddress(etree, "leading_muon_costheta", &this->leading_muon_costheta_); + SetBranchAddress(etree, "leading_muon_momentum", &this->leading_muon_momentum_); + SetBranchAddress(etree, "is_signal", &this->is_signal_); + + // Set the branch addresses for the truth information + SetBranchAddress(etree, "true_leading_muon_costheta", &this->leading_muon_costheta_truth_); + SetBranchAddress(etree, "true_leading_muon_momentum", &this->leading_muon_momentum_truth_); + SetBranchAddress(etree, "event_type", &this->event_type_); + + bool has_flux_weights = etree.GetBranch("expskin_Flux") != nullptr; + //std::cout << "has_flux_weights: " << has_flux_weights << std::endl; + if ( has_flux_weights ) { + //std::cout << "Setting branch address for multisim weights" << std::endl; + set_object_input_branch_address( etree, "expskin_Flux", this->expskin_Flux_ ); + // set_object_input_branch_address( etree, "horncurrent_Flux", this->horncurrent_Flux_ ); + // set_object_input_branch_address( etree, "nucleoninexsec_Flux", this->nucleoninexsec_Flux_ ); + // set_object_input_branch_address( etree, "nucleonqexsec_Flux", this->nucleonqexsec_Flux_ ); + // set_object_input_branch_address( etree, "nucleontotxsec_Flux", this->nucleontotxsec_Flux_ ); + // set_object_input_branch_address( etree, "pioninexsec_Flux", this->pioninexsec_Flux_ ); + // set_object_input_branch_address( etree, "pionqexsec_Flux", this->pionqexsec_Flux_ ); + // set_object_input_branch_address( etree, "piontotxsec_Flux", this->piontotxsec_Flux_ ); + // set_object_input_branch_address( etree, "piplus_Flux", this->piplus_Flux_ ); + // set_object_input_branch_address( etree, "piminus_Flux", this->piminus_Flux_ ); + // set_object_input_branch_address( etree, "kplus_Flux", this->kplus_Flux_ ); + // set_object_input_branch_address( etree, "kminus_Flux", this->kminus_Flux_ ); + // set_object_input_branch_address( etree, "kzero_Flux", this->kzero_Flux_ ); + } + + // bool has_xsec_weights = etree.GetBranch("GENIEReWeight_SBN_v1_multisim_ZExpAVariationResponse") != nullptr; + // std::cout << "has_xsec_weights: " << has_xsec_weights << std::endl; + // if (has_xsec_weights) { + // set_object_input_branch_address(etree, "GENIEReWeight_SBN_v1_multisim_ZExpAVariationResponse", this->GENIEReWeight_SBN_v1_multisim_ZExpAVariationResponse_); + // set_object_input_branch_address(etree, "GENIEReWeight_SBN_v1_multisim_RPA_CCQE", this->GENIEReWeight_SBN_v1_multisim_RPA_CCQE_); + // set_object_input_branch_address(etree, "GENIEReWeight_SBN_v1_multisim_CoulombCCQE", this->GENIEReWeight_SBN_v1_multisim_CoulombCCQE_); + // set_object_input_branch_address(etree, "GENIEReWeight_SBN_v1_multisim_NormCCMEC", this->GENIEReWeight_SBN_v1_multisim_NormCCMEC_); + // set_object_input_branch_address(etree, "GENIEReWeight_SBN_v1_multisim_NormNCMEC", this->GENIEReWeight_SBN_v1_multisim_NormNCMEC_); + // set_object_input_branch_address(etree, "GENIEReWeight_SBN_v1_multisim_NCELVariationResponse", this->GENIEReWeight_SBN_v1_multisim_NCELVariationResponse_); + // set_object_input_branch_address(etree, "GENIEReWeight_SBN_v1_multisim_CCRESVariationResponse", this->GENIEReWeight_SBN_v1_multisim_CCRESVariationResponse_); + // set_object_input_branch_address(etree, "GENIEReWeight_SBN_v1_multisim_NCRESVariationResponse", this->GENIEReWeight_SBN_v1_multisim_NCRESVariationResponse_); + // set_object_input_branch_address(etree, "GENIEReWeight_SBN_v1_multisim_NonRESBGvpCC1pi", this->GENIEReWeight_SBN_v1_multisim_NonRESBGvpCC1pi_); + // set_object_input_branch_address(etree, "GENIEReWeight_SBN_v1_multisim_NonRESBGvpCC2pi", this->GENIEReWeight_SBN_v1_multisim_NonRESBGvpCC2pi_); + // set_object_input_branch_address(etree, "GENIEReWeight_SBN_v1_multisim_NonRESBGvpNC1pi", this->GENIEReWeight_SBN_v1_multisim_NonRESBGvpNC1pi_); + // set_object_input_branch_address(etree, "GENIEReWeight_SBN_v1_multisim_NonRESBGvpNC2pi", this->GENIEReWeight_SBN_v1_multisim_NonRESBGvpNC2pi_); + // set_object_input_branch_address(etree, "GENIEReWeight_SBN_v1_multisim_NonRESBGvnCC1pi", this->GENIEReWeight_SBN_v1_multisim_NonRESBGvnCC1pi_); + // set_object_input_branch_address(etree, "GENIEReWeight_SBN_v1_multisim_NonRESBGvnCC2pi", this->GENIEReWeight_SBN_v1_multisim_NonRESBGvnCC2pi_); + // set_object_input_branch_address(etree, "GENIEReWeight_SBN_v1_multisim_NonRESBGvnNC1pi", this->GENIEReWeight_SBN_v1_multisim_NonRESBGvnNC1pi_); + // set_object_input_branch_address(etree, "GENIEReWeight_SBN_v1_multisim_NonRESBGvnNC2pi", this->GENIEReWeight_SBN_v1_multisim_NonRESBGvnNC2pi_); + // set_object_input_branch_address(etree, "GENIEReWeight_SBN_v1_multisim_NonRESBGvbarpCC1pi", this->GENIEReWeight_SBN_v1_multisim_NonRESBGvbarpCC1pi_); + // set_object_input_branch_address(etree, "GENIEReWeight_SBN_v1_multisim_NonRESBGvbarpCC2pi", this->GENIEReWeight_SBN_v1_multisim_NonRESBGvbarpCC2pi_); + // set_object_input_branch_address(etree, "GENIEReWeight_SBN_v1_multisim_NonRESBGvbarpNC1pi", this->GENIEReWeight_SBN_v1_multisim_NonRESBGvbarpNC1pi_); + // set_object_input_branch_address(etree, "GENIEReWeight_SBN_v1_multisim_NonRESBGvbarpNC2pi", this->GENIEReWeight_SBN_v1_multisim_NonRESBGvbarpNC2pi_); + // set_object_input_branch_address(etree, "GENIEReWeight_SBN_v1_multisim_NonRESBGvbarnCC1pi", this->GENIEReWeight_SBN_v1_multisim_NonRESBGvbarnCC1pi_); + // set_object_input_branch_address(etree, "GENIEReWeight_SBN_v1_multisim_NonRESBGvbarnCC2pi", this->GENIEReWeight_SBN_v1_multisim_NonRESBGvbarnCC2pi_); + // set_object_input_branch_address(etree, "GENIEReWeight_SBN_v1_multisim_NonRESBGvbarnNC1pi", this->GENIEReWeight_SBN_v1_multisim_NonRESBGvbarnNC1pi_); + // set_object_input_branch_address(etree, "GENIEReWeight_SBN_v1_multisim_NonRESBGvbarnNC2pi", this->GENIEReWeight_SBN_v1_multisim_NonRESBGvbarnNC2pi_); + // set_object_input_branch_address(etree, "GENIEReWeight_SBN_v1_multisim_COHVariationResponse", this->GENIEReWeight_SBN_v1_multisim_COHVariationResponse_); + // set_object_input_branch_address(etree, "GENIEReWeight_SBN_v1_multisim_DISBYVariationResponse", this->GENIEReWeight_SBN_v1_multisim_DISBYVariationResponse_); + // set_object_input_branch_address(etree, "GENIEReWeight_SBN_v1_multisim_FSI_pi_VariationResponse", this->GENIEReWeight_SBN_v1_multisim_FSI_pi_VariationResponse_); + // set_object_input_branch_address(etree, "GENIEReWeight_SBN_v1_multisim_FSI_N_VariationResponse", this->GENIEReWeight_SBN_v1_multisim_FSI_N_VariationResponse_); + // } + + // Set branch addresses for spline and tuned CV weights + bool has_genie_mc_weights = etree.GetBranch("weightSpline") != nullptr; + if ( has_genie_mc_weights ) { + SetBranchAddress(etree, "weightSpline", &this->spline_weight_ ); + SetBranchAddress(etree, "weightTune", &this->tuned_cv_weight_ ); + } + + } + + // Helper function to set branch addresses for the output TTree + void set_event_output_branch_addresses(TTree &out_tree, bool create = false) override + { + // Header info + //FIXME: Have is_mc actually load from the CAFAna file + set_output_branch_address( out_tree, "is_mc", &this->is_mc_, create, "is_mc/O" ); + + //Muon selection variables + set_output_branch_address( out_tree, "leading_muon_costheta", &this->leading_muon_costheta_, create, "leading_muon_costheta/D" ); + set_output_branch_address( out_tree, "leading_muon_momentum", &this->leading_muon_momentum_, create, "leading_muon_momentum/D" ); + set_output_branch_address( out_tree, "is_signal", &this->is_signal_, create, "is_signal/D" ); + + // Set the branch addresses for the truth information + set_output_branch_address( out_tree, "true_leading_muon_costheta", &this->leading_muon_costheta_truth_, create, "true_leading_muon_costheta/D" ); + set_output_branch_address( out_tree, "true_leading_muon_momentum", &this->leading_muon_momentum_truth_, create, "true_leading_muon_momentum/D" ); + set_output_branch_address( out_tree, "event_type", &this->event_type_, create, "event_type/D" ); + + // Set the branch addresses for the flux weights + if ( !this->expskin_Flux_.empty() ) { + set_object_output_branch_address< std::vector >( out_tree, "weight_expskin_Flux", this->expskin_Flux_, create ); + // set_object_output_branch_address< std::vector >( out_tree, "weight_horncurrent_Flux", this->horncurrent_Flux_, create ); + // set_object_output_branch_address< std::vector >( out_tree, "weight_nucleoninexsec_Flux", this->nucleoninexsec_Flux_, create ); + // set_object_output_branch_address< std::vector >( out_tree, "weight_nucleonqexsec_Flux", this->nucleonqexsec_Flux_, create ); + // set_object_output_branch_address< std::vector >( out_tree, "weight_nucleontotxsec_Flux", this->nucleontotxsec_Flux_, create ); + // set_object_output_branch_address< std::vector >( out_tree, "weight_pioninexsec_Flux", this->pioninexsec_Flux_, create ); + // set_object_output_branch_address< std::vector >( out_tree, "weight_pionqexsec_Flux", this->pionqexsec_Flux_, create ); + // set_object_output_branch_address< std::vector >( out_tree, "weight_piontotxsec_Flux", this->piontotxsec_Flux_, create ); + // set_object_output_branch_address< std::vector >( out_tree, "weight_piplus_Flux", this->piplus_Flux_, create ); + // set_object_output_branch_address< std::vector >( out_tree, "weight_piminus_Flux", this->piminus_Flux_, create ); + // set_object_output_branch_address< std::vector >( out_tree, "weight_kplus_Flux", this->kplus_Flux_, create ); + // set_object_output_branch_address< std::vector >( out_tree, "weight_kminus_Flux", this->kminus_Flux_, create ); + // set_object_output_branch_address< std::vector >( out_tree, "weight_kzero_Flux", this->kzero_Flux_, create ); + } + + // Set the branch addresses for the xsec weights + // if ( !this->GENIEReWeight_SBN_v1_multisim_ZExpAVariationResponse_.empty()){ + // set_object_output_branch_address>(out_tree, "weight_GENIEReWeight_SBN_v1_multisim_ZExpAVariationResponse", this->GENIEReWeight_SBN_v1_multisim_ZExpAVariationResponse_, create); + // set_object_output_branch_address>(out_tree, "weight_GENIEReWeight_SBN_v1_multisim_RPA_CCQE", this->GENIEReWeight_SBN_v1_multisim_RPA_CCQE_, create); + // set_object_output_branch_address>(out_tree, "weight_GENIEReWeight_SBN_v1_multisim_CoulombCCQE", this->GENIEReWeight_SBN_v1_multisim_CoulombCCQE_, create); + // set_object_output_branch_address>(out_tree, "weight_GENIEReWeight_SBN_v1_multisim_NormCCMEC", this->GENIEReWeight_SBN_v1_multisim_NormCCMEC_, create); + // set_object_output_branch_address>(out_tree, "weight_GENIEReWeight_SBN_v1_multisim_NormNCMEC", this->GENIEReWeight_SBN_v1_multisim_NormNCMEC_, create); + // set_object_output_branch_address>(out_tree, "weight_GENIEReWeight_SBN_v1_multisim_NCELVariationResponse", this->GENIEReWeight_SBN_v1_multisim_NCELVariationResponse_, create); + // set_object_output_branch_address>(out_tree, "weight_GENIEReWeight_SBN_v1_multisim_CCRESVariationResponse", this->GENIEReWeight_SBN_v1_multisim_CCRESVariationResponse_, create); + // set_object_output_branch_address>(out_tree, "weight_GENIEReWeight_SBN_v1_multisim_NCRESVariationResponse", this->GENIEReWeight_SBN_v1_multisim_NCRESVariationResponse_, create); + // set_object_output_branch_address>(out_tree, "weight_GENIEReWeight_SBN_v1_multisim_NonRESBGvpCC1pi", this->GENIEReWeight_SBN_v1_multisim_NonRESBGvpCC1pi_, create); + // set_object_output_branch_address>(out_tree, "weight_GENIEReWeight_SBN_v1_multisim_NonRESBGvpCC2pi", this->GENIEReWeight_SBN_v1_multisim_NonRESBGvpCC2pi_, create); + // set_object_output_branch_address>(out_tree, "weight_GENIEReWeight_SBN_v1_multisim_NonRESBGvpNC1pi", this->GENIEReWeight_SBN_v1_multisim_NonRESBGvpNC1pi_, create); + // set_object_output_branch_address>(out_tree, "weight_GENIEReWeight_SBN_v1_multisim_NonRESBGvpNC2pi", this->GENIEReWeight_SBN_v1_multisim_NonRESBGvpNC2pi_, create); + // set_object_output_branch_address>(out_tree, "weight_GENIEReWeight_SBN_v1_multisim_NonRESBGvnCC1pi", this->GENIEReWeight_SBN_v1_multisim_NonRESBGvnCC1pi_, create); + // set_object_output_branch_address>(out_tree, "weight_GENIEReWeight_SBN_v1_multisim_NonRESBGvnCC2pi", this->GENIEReWeight_SBN_v1_multisim_NonRESBGvnCC2pi_, create); + // set_object_output_branch_address>(out_tree, "weight_GENIEReWeight_SBN_v1_multisim_NonRESBGvnNC1pi", this->GENIEReWeight_SBN_v1_multisim_NonRESBGvnNC1pi_, create); + // set_object_output_branch_address>(out_tree, "weight_GENIEReWeight_SBN_v1_multisim_NonRESBGvnNC2pi", this->GENIEReWeight_SBN_v1_multisim_NonRESBGvnNC2pi_, create); + // set_object_output_branch_address>(out_tree, "weight_GENIEReWeight_SBN_v1_multisim_NonRESBGvbarpCC1pi", this->GENIEReWeight_SBN_v1_multisim_NonRESBGvbarpCC1pi_, create); + // set_object_output_branch_address>(out_tree, "weight_GENIEReWeight_SBN_v1_multisim_NonRESBGvbarpCC2pi", this->GENIEReWeight_SBN_v1_multisim_NonRESBGvbarpCC2pi_, create); + // set_object_output_branch_address>(out_tree, "weight_GENIEReWeight_SBN_v1_multisim_NonRESBGvbarpNC1pi", this->GENIEReWeight_SBN_v1_multisim_NonRESBGvbarpNC1pi_, create); + // set_object_output_branch_address>(out_tree, "weight_GENIEReWeight_SBN_v1_multisim_NonRESBGvbarpNC2pi", this->GENIEReWeight_SBN_v1_multisim_NonRESBGvbarpNC2pi_, create); + // set_object_output_branch_address>(out_tree, "weight_GENIEReWeight_SBN_v1_multisim_NonRESBGvbarnCC1pi", this->GENIEReWeight_SBN_v1_multisim_NonRESBGvbarnCC1pi_, create); + // set_object_output_branch_address>(out_tree, "weight_GENIEReWeight_SBN_v1_multisim_NonRESBGvbarnCC2pi", this->GENIEReWeight_SBN_v1_multisim_NonRESBGvbarnCC2pi_, create); + // set_object_output_branch_address>(out_tree, "weight_GENIEReWeight_SBN_v1_multisim_NonRESBGvbarnNC1pi", this->GENIEReWeight_SBN_v1_multisim_NonRESBGvbarnNC1pi_, create); + // set_object_output_branch_address>(out_tree, "weight_GENIEReWeight_SBN_v1_multisim_NonRESBGvbarnNC2pi", this->GENIEReWeight_SBN_v1_multisim_NonRESBGvbarnNC2pi_, create); + // set_object_output_branch_address>(out_tree, "weight_GENIEReWeight_SBN_v1_multisim_COHVariationResponse", this->GENIEReWeight_SBN_v1_multisim_COHVariationResponse_, create); + // set_object_output_branch_address>(out_tree, "weight_GENIEReWeight_SBN_v1_multisim_DISBYVariationResponse", this->GENIEReWeight_SBN_v1_multisim_DISBYVariationResponse_, create); + // set_object_output_branch_address>(out_tree, "weight_GENIEReWeight_SBN_v1_multisim_FSI_pi_VariationResponse", this->GENIEReWeight_SBN_v1_multisim_FSI_pi_VariationResponse_, create); + // set_object_output_branch_address>(out_tree, "weight_GENIEReWeight_SBN_v1_multisim_FSI_N_VariationResponse", this->GENIEReWeight_SBN_v1_multisim_FSI_N_VariationResponse_, create); + // } + + // Set the branch addresses for the spline and tuned CV weights + set_output_branch_address( out_tree, "spline_weight", &this->spline_weight_, create, "spline_weight/F" ); + set_output_branch_address( out_tree, "tuned_cv_weight", &this->tuned_cv_weight_, create, "tuned_cv_weight/F" ); + set_object_output_branch_address>(out_tree, "weight_TunedCentralValue_UBGenie", this->weight_TunedCentralValue_UBGenie, create); + set_object_output_branch_address>(out_tree, "weight_splines_general_Spline", this->weight_splines_general_Spline, create); + } +}; \ No newline at end of file diff --git a/include/XSecAnalyzer/Event/uBooNEEvent.hh b/include/XSecAnalyzer/Event/uBooNEEvent.hh new file mode 100644 index 000000000..00d8c7402 --- /dev/null +++ b/include/XSecAnalyzer/Event/uBooNEEvent.hh @@ -0,0 +1,441 @@ +/* +Description: Implementation of AnalysisEvent class for MicroBooNE +Date: 2024-10-16 +Authors: Steven Gardiner +*/ + +#include "AnalysisEvent.hh" + +class uBooNEEvent : public AnalysisEvent { +public: + uBooNEEvent() {} + ~uBooNEEvent() {} + + // Helper function to set branch addresses for reading information + // from the Event TTree + void set_event_branch_addresses(TTree& etree) override + { + std::cout<< "Setting branch addresses for uBooNEEvent" << std::endl; + // Reco PDG code of primary PFParticle in slice (i.e., the neutrino + // candidate) + SetBranchAddress(etree, "slpdg", &this->nu_pdg_ ); + + // Number of neutrino slices identified by the SliceID. Allowed values + // are zero or one. + //SetBranchAddress(etree,"nslice",&this->nslice_); + SetBranchAddress(etree, "nslice", &this->nslice_ ); + + // Topological score + SetBranchAddress(etree, "topological_score", &this->topological_score_ ); + SetBranchAddress(etree, "CosmicIP", &this->cosmic_impact_parameter_ ); + //SetBranchAddress(etree, "CosmicIPAll3D", &this->CosmicIPAll3D_ ); + + // Reconstructed neutrino vertex position (with corrections for + // space charge applied) + SetBranchAddress(etree, "reco_nu_vtx_sce_x", &this->nu_vx_ ); + SetBranchAddress(etree, "reco_nu_vtx_sce_y", &this->nu_vy_ ); + SetBranchAddress(etree, "reco_nu_vtx_sce_z", &this->nu_vz_ ); + + // Reconstructed object counts + SetBranchAddress(etree, "n_pfps", &this->num_pf_particles_ ); + SetBranchAddress(etree, "n_tracks", &this->num_tracks_ ); + SetBranchAddress(etree, "n_showers", &this->num_showers_ ); + + // PFParticle properties + set_object_input_branch_address( etree, "pfp_generation_v", + this->pfp_generation_ ); + + set_object_input_branch_address( etree, "pfp_trk_daughters_v", + this->pfp_trk_daughters_count_ ); + + set_object_input_branch_address( etree, "pfp_shr_daughters_v", + this->pfp_shr_daughters_count_ ); + + set_object_input_branch_address( etree, "trk_score_v", this->pfp_track_score_ ); + set_object_input_branch_address( etree, "pfpdg", this->pfp_reco_pdg_ ); + set_object_input_branch_address( etree, "pfnhits", this->pfp_hits_ ); + set_object_input_branch_address( etree, "pfnplanehits_U", this->pfp_hitsU_ ); + set_object_input_branch_address( etree, "pfnplanehits_V", this->pfp_hitsV_ ); + set_object_input_branch_address( etree, "pfnplanehits_Y", this->pfp_hitsY_ ); + + // Backtracked PFParticle properties + set_object_input_branch_address( etree, "backtracked_pdg", this->pfp_true_pdg_ ); + set_object_input_branch_address( etree, "backtracked_e", this->pfp_true_E_ ); + set_object_input_branch_address( etree, "backtracked_px", this->pfp_true_px_ ); + set_object_input_branch_address( etree, "backtracked_py", this->pfp_true_py_ ); + set_object_input_branch_address( etree, "backtracked_pz", this->pfp_true_pz_ ); + + // Shower properties + // These are excluded from some ntuples to ensure blindness for the LEE + // analyses. We will skip them when not available. + bool has_shower_branches = ( etree.GetBranch("shr_pfp_id_v") != nullptr ); + if ( has_shower_branches ) { + set_object_input_branch_address( etree, "shr_pfp_id_v", this->shower_pfp_id_ ); + set_object_input_branch_address( etree, "shr_start_x_v", this->shower_startx_ ); + set_object_input_branch_address( etree, "shr_start_y_v", this->shower_starty_ ); + set_object_input_branch_address( etree, "shr_start_z_v", this->shower_startz_ ); + // Shower start distance from reco neutrino vertex (pre-calculated for + // convenience) + set_object_input_branch_address( etree, "shr_dist_v", + this->shower_start_distance_ ); + } + else { + // When the shower information is not available, delete the owned vectors + // to signal that the associated branches should not be written to the + // output TTree + this->shower_pfp_id_.reset( nullptr ); + this->shower_startx_.reset( nullptr ); + this->shower_starty_.reset( nullptr ); + this->shower_startz_.reset( nullptr ); + this->shower_start_distance_.reset( nullptr ); + } + + // Track properties + set_object_input_branch_address( etree, "trk_pfp_id_v", this->track_pfp_id_ ); + set_object_input_branch_address( etree, "trk_len_v", this->track_length_ ); + set_object_input_branch_address( etree, "trk_sce_start_x_v", this->track_startx_ ); + set_object_input_branch_address( etree, "trk_sce_start_y_v", this->track_starty_ ); + set_object_input_branch_address( etree, "trk_sce_start_z_v", this->track_startz_ ); + + // Track start distance from reco neutrino vertex (pre-calculated for + // convenience) + set_object_input_branch_address( etree, "trk_distance_v", + this->track_start_distance_ ); + + set_object_input_branch_address( etree, "trk_sce_end_x_v", this->track_endx_ ); + set_object_input_branch_address( etree, "trk_sce_end_y_v", this->track_endy_ ); + set_object_input_branch_address( etree, "trk_sce_end_z_v", this->track_endz_ ); + + set_object_input_branch_address( etree, "trk_dir_x_v", this->track_dirx_ ); + set_object_input_branch_address( etree, "trk_dir_y_v", this->track_diry_ ); + set_object_input_branch_address( etree, "trk_dir_z_v", this->track_dirz_ ); + + set_object_input_branch_address( etree, "trk_theta_v", this->track_theta_ ); + set_object_input_branch_address( etree, "trk_phi_v", this->track_phi_ ); + + set_object_input_branch_address( etree, "trk_energy_proton_v", + this->track_kinetic_energy_p_ ); + + set_object_input_branch_address( etree, "trk_range_muon_mom_v", + this->track_range_mom_mu_ ); + + set_object_input_branch_address( etree, "trk_mcs_muon_mom_v", + this->track_mcs_mom_mu_ ); + + // Some ntuples exclude the old proton chi^2 PID score. Only include it + // in the output if this branch is available. + bool has_chipr = ( etree.GetBranch("trk_pid_chipr_v") != nullptr ); + if ( has_chipr ) { + set_object_input_branch_address( etree, "trk_pid_chipr_v", + this->track_chi2_proton_ ); + } + else { + this->track_chi2_proton_.reset( nullptr ); + } + + // Log-likelihood-based particle ID information + set_object_input_branch_address( etree, "trk_llr_pid_v", this->track_llr_pid_ ); + + set_object_input_branch_address( etree, "trk_llr_pid_u_v", + this->track_llr_pid_U_ ); + + set_object_input_branch_address( etree, "trk_llr_pid_v_v", + this->track_llr_pid_V_ ); + + set_object_input_branch_address( etree, "trk_llr_pid_y_v", + this->track_llr_pid_Y_ ); + + set_object_input_branch_address( etree, "trk_llr_pid_score_v", + this->track_llr_pid_score_ ); + + // MC truth information for the neutrino + SetBranchAddress(etree, "nu_pdg", &this->mc_nu_pdg_ ); + SetBranchAddress(etree, "true_nu_vtx_x", &this->mc_nu_vx_ ); + SetBranchAddress(etree, "true_nu_vtx_y", &this->mc_nu_vy_ ); + SetBranchAddress(etree, "true_nu_vtx_z", &this->mc_nu_vz_ ); + SetBranchAddress(etree, "nu_e", &this->mc_nu_energy_ ); + SetBranchAddress(etree, "ccnc", &this->mc_nu_ccnc_ ); + SetBranchAddress(etree, "interaction", &this->mc_nu_interaction_type_ ); + + //============================================= + //DB Added to match Samantha's Signal defintion + + SetBranchAddress(etree, "true_nu_vtx_sce_x", &this->mc_nu_sce_vx_ ); + SetBranchAddress(etree, "true_nu_vtx_sce_y", &this->mc_nu_sce_vy_ ); + SetBranchAddress(etree, "true_nu_vtx_sce_z", &this->mc_nu_sce_vz_ ); + + //============================================= + + // MC truth information for the final-state primary particles + set_object_input_branch_address( etree, "mc_pdg", this->mc_nu_daughter_pdg_ ); + set_object_input_branch_address( etree, "mc_E", this->mc_nu_daughter_energy_ ); + set_object_input_branch_address( etree, "mc_px", this->mc_nu_daughter_px_ ); + set_object_input_branch_address( etree, "mc_py", this->mc_nu_daughter_py_ ); + set_object_input_branch_address( etree, "mc_pz", this->mc_nu_daughter_pz_ ); + + // GENIE and other systematic variation weights + bool has_genie_mc_weights = ( etree.GetBranch("weightSpline") != nullptr ); + if ( has_genie_mc_weights ) { + SetBranchAddress(etree, "weightSpline", &this->spline_weight_ ); + SetBranchAddress(etree, "weightTune", &this->tuned_cv_weight_ ); + } + + bool has_weight_map = ( etree.GetBranch("weights") != nullptr ); + if ( has_weight_map ) { + set_object_input_branch_address( etree, "weights", this->mc_weights_map_ ); + } + else { + this->mc_weights_map_.reset( nullptr ); + } + + // Purity and completeness of the backtracked hits in the neutrino slice + bool has_pfp_backtracked_purity = ( etree.GetBranch("nu_purity_from_pfp") + != nullptr ); + if ( has_pfp_backtracked_purity ) { + + SetBranchAddress(etree, "nu_completeness_from_pfp", + &this->nu_completeness_from_pfp_ ); + + SetBranchAddress(etree, "nu_purity_from_pfp", &this->nu_purity_from_pfp_ ); + + } + } + + // Helper function to set branch addresses for the output TTree + void set_event_output_branch_addresses(TTree& out_tree, bool create = false) override + { + std::cout << "create " << create << std::endl; + // Signal definition flags + set_output_branch_address( out_tree, "is_mc", &this->is_mc_, create, "is_mc/O" ); + // Event weights + set_output_branch_address( out_tree, "spline_weight", + &this->spline_weight_, create, "spline_weight/F" ); + + std::cout<< "(-1) setting output branch addresses for uBooNEEvent" << std::endl; + set_output_branch_address( out_tree, "tuned_cv_weight", + &this->tuned_cv_weight_, create, "tuned_cv_weight/F" ); + std::cout << "(0) setting output branch addresses for uBooNEEvent" << std::endl; + + // If MC weights are available, prepare to store them in the output TTree + if (!this->mc_weights_map_.empty() ) { + + // Make separate branches for the various sets of systematic variation + // weights in the map + for ( auto& pair : *this->mc_weights_map_ ) { + + // Prepend "weight_" to the name of the vector of weights in the map + std::string weight_branch_name = "weight_" + pair.first; + + // Store a pointer to the vector of weights (needed to set the branch + // address properly) in the temporary map of pointers + this->mc_weights_ptr_map_[ weight_branch_name ] = &pair.second; + + // Set the branch address for &this vector of weights + set_object_output_branch_address< std::vector >( out_tree, + weight_branch_name, this->mc_weights_ptr_map_.at(weight_branch_name), + create ); + } + } + std::cout << "(1) setting output branch addresses for uBooNEEvent" << std::endl; + + // Backtracked neutrino purity and completeness + set_output_branch_address( out_tree, "nu_completeness_from_pfp", + &this->nu_completeness_from_pfp_, create, "nu_completeness_from_pfp/F" ); + + set_output_branch_address( out_tree, "nu_purity_from_pfp", + &this->nu_purity_from_pfp_, create, "nu_purity_from_pfp/F" ); + + // Number of neutrino slices identified by the SliceID + set_output_branch_address( out_tree, "nslice", &this->nslice_, create, + "nslice/I" ); + + // *** Branches copied directly from the input *** + + // Cosmic rejection parameters for numu CC inclusive selection + set_output_branch_address( out_tree, "topological_score", + &this->topological_score_, create, "topological_score/F" ); + + set_output_branch_address( out_tree, "CosmicIP", + &this->cosmic_impact_parameter_, create, "CosmicIP/F" ); + + // Reconstructed neutrino vertex position + set_output_branch_address( out_tree, "reco_nu_vtx_sce_x", + &this->nu_vx_, create, "reco_nu_vtx_sce_x/F" ); + + set_output_branch_address( out_tree, "reco_nu_vtx_sce_y", + &this->nu_vy_, create, "reco_nu_vtx_sce_y/F" ); + + set_output_branch_address( out_tree, "reco_nu_vtx_sce_z", + &this->nu_vz_, create, "reco_nu_vtx_sce_z/F" ); + + // MC truth information for the neutrino + set_output_branch_address( out_tree, "mc_nu_pdg", &this->mc_nu_pdg_, + create, "mc_nu_pdg/I" ); + + set_output_branch_address( out_tree, "mc_nu_vtx_x", &this->mc_nu_vx_, + create, "mc_nu_vtx_x/F" ); + + set_output_branch_address( out_tree, "mc_nu_vtx_y", &this->mc_nu_vy_, + create, "mc_nu_vtx_y/F" ); + + set_output_branch_address( out_tree, "mc_nu_vtx_z", &this->mc_nu_vz_, + create, "mc_nu_vtx_z/F" ); + + set_output_branch_address( out_tree, "mc_nu_energy", &this->mc_nu_energy_, + create, "mc_nu_energy/F" ); + + set_output_branch_address( out_tree, "mc_ccnc", &this->mc_nu_ccnc_, + create, "mc_ccnc/I" ); + + set_output_branch_address( out_tree, "mc_interaction", + &this->mc_nu_interaction_type_, create, "mc_interaction/I" ); + + // PFParticle properties + set_object_output_branch_address< std::vector >( out_tree, + "pfp_generation_v", this->pfp_generation_, create ); + + set_object_output_branch_address< std::vector >( out_tree, + "pfp_trk_daughters_v", this->pfp_trk_daughters_count_, create ); + + set_object_output_branch_address< std::vector >( out_tree, + "pfp_shr_daughters_v", this->pfp_shr_daughters_count_, create ); + + set_object_output_branch_address< std::vector >( out_tree, + "trk_score_v", this->pfp_track_score_, create ); + + set_object_output_branch_address< std::vector >( out_tree, + "pfpdg", this->pfp_reco_pdg_, create ); + + set_object_output_branch_address< std::vector >( out_tree, + "pfnhits", this->pfp_hits_, create ); + + set_object_output_branch_address< std::vector >( out_tree, + "pfnplanehits_U", this->pfp_hitsU_, create ); + + set_object_output_branch_address< std::vector >( out_tree, + "pfnplanehits_V", this->pfp_hitsV_, create ); + + set_object_output_branch_address< std::vector >( out_tree, + "pfnplanehits_Y", this->pfp_hitsY_, create ); + + // Backtracked PFParticle properties + set_object_output_branch_address< std::vector >( out_tree, + "backtracked_pdg", this->pfp_true_pdg_, create ); + + set_object_output_branch_address< std::vector >( out_tree, + "backtracked_e", this->pfp_true_E_, create ); + + set_object_output_branch_address< std::vector >( out_tree, + "backtracked_px", this->pfp_true_px_, create ); + + set_object_output_branch_address< std::vector >( out_tree, + "backtracked_py", this->pfp_true_py_, create ); + + set_object_output_branch_address< std::vector >( out_tree, + "backtracked_pz", this->pfp_true_pz_, create ); + + // Shower properties + // For some ntuples, reconstructed shower information is excluded. + // In such cases, skip writing these branches to the output TTree. + if ( this->shower_startx_ ) { + set_object_output_branch_address< std::vector >( out_tree, + "shr_start_x_v", this->shower_startx_, create ); + + set_object_output_branch_address< std::vector >( out_tree, + "shr_start_y_v", this->shower_starty_, create ); + + set_object_output_branch_address< std::vector >( out_tree, + "shr_start_z_v", this->shower_startz_, create ); + + // Shower start distance from reco neutrino vertex (pre-calculated for + // convenience) + set_object_output_branch_address< std::vector >( out_tree, + "shr_dist_v", this->shower_start_distance_, create ); + } + + // Track properties + set_object_output_branch_address< std::vector >( out_tree, + "trk_len_v", this->track_length_, create ); + + set_object_output_branch_address< std::vector >( out_tree, + "trk_sce_start_x_v", this->track_startx_, create ); + + set_object_output_branch_address< std::vector >( out_tree, + "trk_sce_start_y_v", this->track_starty_, create ); + + set_object_output_branch_address< std::vector >( out_tree, + "trk_sce_start_z_v", this->track_startz_, create ); + + // Track start distance from reco neutrino vertex (pre-calculated for + // convenience) + set_object_output_branch_address< std::vector >( out_tree, + "trk_distance_v", this->track_start_distance_, create ); + + set_object_output_branch_address< std::vector >( out_tree, + "trk_sce_end_x_v", this->track_endx_, create ); + + set_object_output_branch_address< std::vector >( out_tree, + "trk_sce_end_y_v", this->track_endy_, create ); + + set_object_output_branch_address< std::vector >( out_tree, + "trk_sce_end_z_v", this->track_endz_, create ); + + set_object_output_branch_address< std::vector >( out_tree, + "trk_dir_x_v", this->track_dirx_, create ); + + set_object_output_branch_address< std::vector >( out_tree, + "trk_dir_y_v", this->track_diry_, create ); + + set_object_output_branch_address< std::vector >( out_tree, + "trk_dir_z_v", this->track_dirz_, create ); + + set_object_output_branch_address< std::vector >( out_tree, + "trk_energy_proton_v", this->track_kinetic_energy_p_, create ); + + set_object_output_branch_address< std::vector >( out_tree, + "trk_range_muon_mom_v", this->track_range_mom_mu_, create ); + + set_object_output_branch_address< std::vector >( out_tree, + "trk_mcs_muon_mom_v", this->track_mcs_mom_mu_, create ); + + // Some ntuples exclude the old chi^2 proton PID score. Only include it in + // the output if it is available. + if ( this->track_chi2_proton_ ) { + set_object_output_branch_address< std::vector >( out_tree, + "trk_pid_chipr_v", this->track_chi2_proton_, create ); + } + + // Log-likelihood-based particle ID information + set_object_output_branch_address< std::vector >( out_tree, + "trk_llr_pid_v", this->track_llr_pid_, create ); + + set_object_output_branch_address< std::vector >( out_tree, + "trk_llr_pid_u_v", this->track_llr_pid_U_, create ); + + set_object_output_branch_address< std::vector >( out_tree, + "trk_llr_pid_v_v", this->track_llr_pid_V_, create ); + + set_object_output_branch_address< std::vector >( out_tree, + "trk_llr_pid_y_v", this->track_llr_pid_Y_, create ); + + set_object_output_branch_address< std::vector >( out_tree, + "trk_llr_pid_score_v", this->track_llr_pid_score_, create ); + + // MC truth information for the final-state primary particles + set_object_output_branch_address< std::vector >( out_tree, "mc_pdg", + this->mc_nu_daughter_pdg_, create ); + + set_object_output_branch_address< std::vector >( out_tree, "mc_E", + this->mc_nu_daughter_energy_, create ); + + set_object_output_branch_address< std::vector >( out_tree, "mc_px", + this->mc_nu_daughter_px_, create ); + + set_object_output_branch_address< std::vector >( out_tree, "mc_py", + this->mc_nu_daughter_py_, create ); + + set_object_output_branch_address< std::vector >( out_tree, "mc_pz", + this->mc_nu_daughter_pz_, create ); + } + +}; \ No newline at end of file diff --git a/include/XSecAnalyzer/FilePropertiesManager.hh b/include/XSecAnalyzer/FilePropertiesManager.hh index 93c0867bc..712a45542 100644 --- a/include/XSecAnalyzer/FilePropertiesManager.hh +++ b/include/XSecAnalyzer/FilePropertiesManager.hh @@ -108,7 +108,6 @@ class FilePropertiesManager { // Get a const reference to the singleton instance of the // FilePropertiesManager inline static FilePropertiesManager& Instance() { - // Create the FilePropertiesManager object using a static variable. // This ensures that the singleton instance is only created once. static std::unique_ptr @@ -204,7 +203,7 @@ class FilePropertiesManager { std::string in_file_name( input_table_file_name ); if ( in_file_name.empty() ) { in_file_name = analysis_path_ + "/configs/file_properties.txt"; - std::cout << "Provided FPM_CONFIG name is empty. Using default: " + std::cout << "Provided FPM_CONFIG name is empty. Using default: " << in_file_name << '\n'; } diff --git a/include/XSecAnalyzer/Functions.hh b/include/XSecAnalyzer/Functions.hh index 3a58c8f93..5c16419ea 100644 --- a/include/XSecAnalyzer/Functions.hh +++ b/include/XSecAnalyzer/Functions.hh @@ -1,7 +1,6 @@ #pragma once #include "Constants.hh" -#include "AnalysisEvent.hh" #include "FiducialVolume.hh" #include "TVector2.h" diff --git a/include/XSecAnalyzer/MCC9SystematicsCalculator.hh b/include/XSecAnalyzer/MCC9SystematicsCalculator.hh index bb9d5ed40..b7d868a4f 100644 --- a/include/XSecAnalyzer/MCC9SystematicsCalculator.hh +++ b/include/XSecAnalyzer/MCC9SystematicsCalculator.hh @@ -21,7 +21,8 @@ class MCC9SystematicsCalculator : public SystematicsCalculator { MCC9SystematicsCalculator( const std::string& input_respmat_file_name, const std::string& syst_cfg_file_name = "", - const std::string& respmat_tdirectoryfile_name = "" ); + const std::string& respmat_tdirectoryfile_name = "", + const std::string& cv_univ_name = "weight_TunedCentralValue_UBGenie" ); virtual double evaluate_observable( const Universe& univ, int reco_bin, int flux_universe_index = -1 ) const override; @@ -46,9 +47,10 @@ class MCC9SystematicsCalculator : public SystematicsCalculator { MCC9SystematicsCalculator::MCC9SystematicsCalculator( const std::string& input_respmat_file_name, const std::string& syst_cfg_file_name, - const std::string& respmat_tdirectoryfile_name ) + const std::string& respmat_tdirectoryfile_name, + const std::string& cv_univ_name ) : SystematicsCalculator( input_respmat_file_name, - syst_cfg_file_name, respmat_tdirectoryfile_name ) + syst_cfg_file_name, respmat_tdirectoryfile_name, cv_univ_name ) { } diff --git a/include/XSecAnalyzer/Selections/SBND_CC1muX.hh b/include/XSecAnalyzer/Selections/SBND_CC1muX.hh new file mode 100644 index 000000000..a6396aa7b --- /dev/null +++ b/include/XSecAnalyzer/Selections/SBND_CC1muX.hh @@ -0,0 +1,30 @@ +#pragma once + +// XSecAnalyzer includes +#include "XSecAnalyzer/Selections/SelectionBase.hh" +#include "XSecAnalyzer/Selections/SBND_EventCategories.hh" + +class SBND_CC1muX : public SelectionBase { + +public: + + SBND_CC1muX(); + + virtual int categorize_event( AnalysisEvent* event ) override final; + virtual bool selection( AnalysisEvent* event ) override final; + virtual bool define_signal( AnalysisEvent* event ) override final; + virtual void compute_reco_observables( AnalysisEvent* event ) override final; + virtual void compute_true_observables( AnalysisEvent* event ) override final; + virtual void define_output_branches() override final; + virtual void define_constants() override final; + virtual void define_category_map() override final; + virtual void reset() override final; + +private: + + double leading_muon_momentum; + double leading_muon_costheta; + double leading_muon_momentum_truth; + double leading_muon_costheta_truth; + +}; diff --git a/include/XSecAnalyzer/Selections/SBND_EventCategories.hh b/include/XSecAnalyzer/Selections/SBND_EventCategories.hh new file mode 100644 index 000000000..01bfb5eb8 --- /dev/null +++ b/include/XSecAnalyzer/Selections/SBND_EventCategories.hh @@ -0,0 +1,24 @@ +#pragma once + +// Standard library includes +#include +#include + +// Enum used to label event categories of interest for analysis plots in +// the CC0pi 1p/2p/Np/Xp analyses +enum SBND_EventCategory { + + // Unable to categorize (e.g., because the event is real data and thus + // has no MC truth information) + kUnknown = -1, + + // Inclusive numu CC event + kNuMuCC = 0, + kNC = 1, + kNuECC = 2, + kCosmic = 3, + kOOFV = 4, + +}; + +extern std::map< int, std::pair< std::string, int > > CC1muX_MAP; diff --git a/include/XSecAnalyzer/Selections/SelectionBase.hh b/include/XSecAnalyzer/Selections/SelectionBase.hh index 472e6cd0c..69e1ab813 100644 --- a/include/XSecAnalyzer/Selections/SelectionBase.hh +++ b/include/XSecAnalyzer/Selections/SelectionBase.hh @@ -9,7 +9,7 @@ #include "TVector3.h" // XSecAnalyzer includes -#include "XSecAnalyzer/AnalysisEvent.hh" +#include "XSecAnalyzer/Event/AnalysisEvent.hh" #include "XSecAnalyzer/FiducialVolume.hh" #include "XSecAnalyzer/Constants.hh" #include "XSecAnalyzer/STVTools.hh" @@ -34,6 +34,15 @@ public: inline const std::map< int, std::pair< std::string, int > >& category_map() const { return categ_map_; } + // Print selection map to stdout + void print_category_map(){ + std::cout << "Printing category map for selection: " << selection_name_ << '\n'; + std::cout << "Length of map: " << categ_map_.size() << '\n'; + for ( auto& [key, value] : categ_map_ ) { + std::cout << key << " => " << value.first << '\n'; + } + } + protected: // Sets the branch address for output TTree variables managed by this diff --git a/include/XSecAnalyzer/SliceBinning.hh b/include/XSecAnalyzer/SliceBinning.hh index aec5a0807..379d4dc88 100644 --- a/include/XSecAnalyzer/SliceBinning.hh +++ b/include/XSecAnalyzer/SliceBinning.hh @@ -348,6 +348,15 @@ SliceBinning::SliceBinning( const std::string& config_file_name ) { new TH1D( slice_hist_name.c_str(), slice_title.c_str(), num_bins, bin_edges.data() ) ); + // Print data + std::cout << "\t\t\tCreating 1D histogram with " << num_bins << " bins" + << " from " << bin_edges.front() << " to " << bin_edges.back() + << " for title " << slice_title << std::endl; + for ( int b = 1; b <= num_bins; ++b ) { + std::cout << "\t\tBin " << b << ": " << temp_hist->GetBinLowEdge( b ) + << " < " << temp_hist->GetXaxis()->GetTitle() << " < " + << temp_hist->GetBinLowEdge( b + 1 ) << std::endl; + } // Move the ready-to-use histogram into the member smart pointer cur_slice.hist_.swap( temp_hist ); @@ -407,6 +416,9 @@ SliceBinning::SliceBinning( const std::string& config_file_name ) { // reco bin int root_bin_idx = cur_slice.hist_->GetBin( av_bin_indices.front(), av_bin_indices.at(1), av_bin_indices.at(2) ); + // Print data for the current reco bin + std::cout << "\t\tGlobal bin " << root_bin_idx << " is matched to " << rmm_reco_bin_idx << " in this slice" + << " with active bin indices " << av_bin_indices.front() << ", " << av_bin_indices.at(1) << ", " << av_bin_indices.at(2) << std::endl; // Store the indices for both kinds of bins at the appropriate place // in the bin map diff --git a/include/XSecAnalyzer/SystematicsCalculator.hh b/include/XSecAnalyzer/SystematicsCalculator.hh index 0d23997c9..279d4e8a4 100644 --- a/include/XSecAnalyzer/SystematicsCalculator.hh +++ b/include/XSecAnalyzer/SystematicsCalculator.hh @@ -139,9 +139,11 @@ class SystematicsCalculator { public: + //FIXME: have cv_univ_name selected based on experiment SystematicsCalculator( const std::string& input_respmat_file_name, const std::string& syst_cfg_file_name = "", - const std::string& respmat_tdirectoryfile_name = "" ); + const std::string& respmat_tdirectoryfile_name = "", + const std::string& cv_univ_name = "weight_TunedCentralValue_UBGenie" ); void load_universes( TDirectoryFile& total_subdir ); @@ -254,7 +256,7 @@ class SystematicsCalculator { int flux_u_index = -1 ) const; // Central value universe name - const std::string CV_UNIV_NAME = "weight_TunedCentralValue_UBGenie"; + std::string CV_UNIV_NAME; // Beginning of the subdirectory name for the TDirectoryFile containing the // POT-summed histograms for the various universes across all analysis diff --git a/include/XSecAnalyzer/TreeUtils.hh b/include/XSecAnalyzer/TreeUtils.hh index 0ca9b3c7c..1d6a3d16f 100644 --- a/include/XSecAnalyzer/TreeUtils.hh +++ b/include/XSecAnalyzer/TreeUtils.hh @@ -2,10 +2,14 @@ // ROOT includes #include "TTree.h" +#include //#include "AnalysisEvent.hh" // **** Helper code to facilitate setting TTree branch addresses, etc. **** +// Helper function to set the branch addresses for the AnalysisEvent +void SetBranchAddress(TTree& etree, std::string BranchName, void* Variable); + // A std::unique_ptr with redundant storage of a bare pointer to the managed // object. This is a hacky workaround for setting TTree branch addresses for // objects managed by a std::unique_ptr. @@ -19,6 +23,10 @@ template class MyPointer : public std::unique_ptr { return bare_ptr_; } + bool empty() const { + return this->get() == nullptr; + } + protected: T* bare_ptr_ = nullptr; diff --git a/include/XSecAnalyzer/TruthSystematicsCalculator.hh b/include/XSecAnalyzer/TruthSystematicsCalculator.hh index c0c1c1bbe..72f69ab52 100644 --- a/include/XSecAnalyzer/TruthSystematicsCalculator.hh +++ b/include/XSecAnalyzer/TruthSystematicsCalculator.hh @@ -14,7 +14,8 @@ class TruthSystematicsCalculator : public SystematicsCalculator { TruthSystematicsCalculator( const std::string& input_respmat_file_name, const std::string& syst_cfg_file_name = "", - const std::string& respmat_tdirectoryfile_name = "" ); + const std::string& respmat_tdirectoryfile_name = "", + const std::string& cv_univ_name = "weight_TunedCentralValue_UBGenie" ); virtual double evaluate_observable( const Universe& univ, int true_bin, int flux_universe_index = -1 ) const override; @@ -33,9 +34,10 @@ class TruthSystematicsCalculator : public SystematicsCalculator { TruthSystematicsCalculator::TruthSystematicsCalculator( const std::string& input_respmat_file_name, const std::string& syst_cfg_file_name, - const std::string& respmat_tdirectoryfile_name ) + const std::string& respmat_tdirectoryfile_name, + const std::string& cv_univ_name ) : SystematicsCalculator( input_respmat_file_name, - syst_cfg_file_name, respmat_tdirectoryfile_name ) + syst_cfg_file_name, respmat_tdirectoryfile_name, cv_univ_name ) { } diff --git a/include/XSecAnalyzer/UniverseMaker.hh b/include/XSecAnalyzer/UniverseMaker.hh index 3bf656e33..0641966cd 100644 --- a/include/XSecAnalyzer/UniverseMaker.hh +++ b/include/XSecAnalyzer/UniverseMaker.hh @@ -104,7 +104,9 @@ inline void apply_cv_correction_weights( const std::string& wgt_name, // No extra weight factors needed return; } - else throw std::runtime_error( "Unrecognized weight name" ); + //FIXME: Assume SBND and uBooNE don't share the same weights + else return; + //else throw std::runtime_error( "Unrecognized weight name" ); } // Enum used to label bin types in true space @@ -256,7 +258,7 @@ class Universe { hist_true_ = std::make_unique< TH1D >( (hist_name_prefix + "_true").c_str(), "; true bin number; events", num_true_bins, 0., num_true_bins ); - + hist_reco_ = std::make_unique< TH1D >( (hist_name_prefix + "_reco").c_str(), "; reco bin number; events", num_reco_bins, 0., num_reco_bins ); @@ -264,7 +266,7 @@ class Universe { hist_2d_ = std::make_unique< TH2D >( (hist_name_prefix + "_2d").c_str(), "; true bin number; reco bin number; counts", num_true_bins, 0., num_true_bins, num_reco_bins, 0., num_reco_bins ); - + hist_reco2d_ = std::make_unique< TH2D >( (hist_name_prefix + "_reco2d").c_str(), "; reco bin number; reco bin number; counts", num_reco_bins, 0., diff --git a/python/README.md b/python/README.md new file mode 100644 index 000000000..fc6e3df53 --- /dev/null +++ b/python/README.md @@ -0,0 +1,19 @@ +# Description +This directory contains the python scripts that are used to analyze the various root files output from `xsec_analyzer`. + +# Setup +## First time setup +Ensure that you have python setup on your machine. You can check this by running `python --version` in your terminal. + +If it is installed, you can run the following command to install the required packages: +```bash +source init.sh +``` + +## Setup area +If you have already run the above command, at least once, you should have a virtual environment setup in the `venv` directory. You can activate this environment by running: +```bash +setup.sh +``` + + diff --git a/python/init.sh b/python/init.sh new file mode 100644 index 000000000..bf5c2e9c8 --- /dev/null +++ b/python/init.sh @@ -0,0 +1,9 @@ +python -m venv env +source env/bin/activate +which python +pip install --upgrade pip +pip install wheel setuptools +pip install -r requirements.txt + +export PYTHONPATH=$PYTHONPATH:$PWD +export MPLCONFIGDIR=$PWD/.config/matplotlib \ No newline at end of file diff --git a/python/post.ipynb b/python/post.ipynb new file mode 100644 index 000000000..d0b1f6b7e --- /dev/null +++ b/python/post.ipynb @@ -0,0 +1,238 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 0. Setup packages and Constants" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The autoreload extension is already loaded. To reload it, use:\n", + " %reload_ext autoreload\n" + ] + } + ], + "source": [ + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "import uproot\n", + "import numpy as np\n", + "import sys\n", + "from tqdm import tqdm\n", + "\n", + "# Utils\n", + "from utils import plotters\n", + "\n", + "plt.style.use('./utils/style.mplstyle')\n", + "\n", + "\n", + "\n", + "%load_ext autoreload\n", + "%autoreload 2" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "#Path to the ROOT file containing the cross section histograms\n", + "DATA_PATH = '/exp/sbnd/data/users/brindenc/xsec_analysis/test/sbruce/cc1mux_med_weight.root'" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# 1. Load the data" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [], + "source": [ + "tree = uproot.open(DATA_PATH)['stv_tree;1']\n", + "keys = tree.keys() #display all keys in the ROOT file\n", + "weight_keys = [key for key in keys if 'weight' in key]\n", + "multisim_keys = [key for key in keys if 'multisim' in key]\n", + "flux_keys = [key for key in keys if 'Flux' in key]" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [], + "source": [ + "#Example\n", + "leading_muon_momentum = tree['leading_muon_momentum'].array(library='pd')\n", + "leading_muon_costheta = tree['leading_muon_costheta'].array(library='pd')\n", + "true_leading_muon_momentum = tree['true_leading_muon_momentum'].array(library='pd')\n", + "true_leading_muon_costheta = tree['true_leading_muon_costheta'].array(library='pd')" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(np.int64(0), np.int64(0), np.int64(0), np.int64(0))" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "leading_muon_costheta.isna().sum(), leading_muon_momentum.isna().sum(),true_leading_muon_costheta.isna().sum(), true_leading_muon_momentum.isna().sum()" + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(np.int64(0), np.int64(0))" + ] + }, + "execution_count": 51, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "(leading_muon_momentum < 0).sum(), (true_leading_muon_momentum < 0).sum()" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [], + "source": [ + "weights = tree.arrays(weight_keys,library='pd')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 50, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "45it [01:32, 2.07s/it]\n" + ] + } + ], + "source": [ + "break_flag = False\n", + "for i, key in tqdm(enumerate(weight_keys)):\n", + " for j in range(len(weights[key])):\n", + " # if j > 1 or i > 1:\n", + " # print(f'Breaking at {key} and {j}')\n", + " # break\n", + " if (np.sum((weights[key][j]) < 0)):\n", + " print(f'Negative weight found in {key} at index {j}')\n", + " break_flag = True\n", + " break\n", + " if break_flag: break" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "np.int64(0)" + ] + }, + "execution_count": 39, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "np.sum((weights.iloc[0][weight_keys[0]]) <= 0)" + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "np.float64(0.0)" + ] + }, + "execution_count": 49, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "min(weights['weight_GENIEReWeight_SBN_v1_multisim_RPA_CCQE'][26])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "env", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.19" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/python/requirements.txt b/python/requirements.txt new file mode 100644 index 000000000..06afabfa7 --- /dev/null +++ b/python/requirements.txt @@ -0,0 +1,11 @@ +ipykernel +matplotlib +uproot +numpy +pandas +hist +tqdm +jupyter +ipywidgets +awkward-pandas +hist \ No newline at end of file diff --git a/python/setup.sh b/python/setup.sh new file mode 100644 index 000000000..61be2893f --- /dev/null +++ b/python/setup.sh @@ -0,0 +1,4 @@ +source env/bin/activate + +export PYTHONPATH=$PWD #only use current directory to ensure correct version(s) is used +export MPLCONFIGDIR=$PWD/.config/matplotlib \ No newline at end of file diff --git a/python/uni.ipynb b/python/uni.ipynb new file mode 100644 index 000000000..ce949a51f --- /dev/null +++ b/python/uni.ipynb @@ -0,0 +1,1140 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 0. Setup packages and Constants" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "import uproot\n", + "import numpy as np\n", + "import sys\n", + "from tqdm import tqdm\n", + "\n", + "# Utils\n", + "from utils import plotters\n", + "\n", + "plt.style.use('./utils/style.mplstyle')\n", + "\n", + "%load_ext autoreload\n", + "%autoreload 2" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "6" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "#Path to the ROOT file containing the universe covariance matrices\n", + "DATA_PATH = '/exp/sbnd/data/users/brindenc/xsec_analysis/test/sbruce/uni_med_weight4.root'\n", + "\n", + "#Bin indices for the covariance matrix\n", + "P_BINS = np.arange(0, 10)\n", + "COSTHETA_OVERFLOW_BINS = np.arange(10, 20)\n", + "COSTHETA_BINS = np.arange(10,19)\n", + "CAT_BINS = np.arange(0,6)\n", + "len(CAT_BINS)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# 1. Load the data" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "tree = uproot.open(DATA_PATH)\n", + "keys = tree.keys()\n", + "#tree.keys() #display all keys in the ROOT file" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "568930" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "len(keys)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "
\n", + "
\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "19\n", + "\n", + "\n", + " reco bin number\n", + "\n", + "\n", + "\n", + "
\n", + "
\n", + "Regular(19, 0, 19, name='xaxis', label=' reco bin number')
\n", + "
\n", + "Weight() Σ=WeightedSum(value=250, variance=250)\n", + "\n", + "
\n", + "
\n", + "" + ], + "text/plain": [ + "Hist(Regular(19, 0, 19, name='xaxis', label=' reco bin number'), storage=Weight()) # Sum: WeightedSum(value=250, variance=250)" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "key = 'SBND_CC1muX_1D/+exp+sbnd+data+users+brindenc+xsec_analysis+test+sbruce+cc1mux_med_weight_copy.root/unweighted_0_reco;1'\n", + "tree[key].to_hist()" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "0it [00:00, ?it/s]" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "568930it [12:51, 737.80it/s]\n" + ] + } + ], + "source": [ + "p_nan_keys = []\n", + "costheta_nan_keys = []\n", + "wrong_length_keys = []\n", + "dir_keys = []\n", + "non_hist_keys = []\n", + "accepted_keys = []\n", + "negative_keys = []\n", + "zero_keys = []\n", + "class_names = []\n", + "\n", + "twod_nan_keys = []\n", + "twod_non_square_keys = []\n", + "twod_valid_keys = []\n", + "\n", + "\n", + "#Check for nan values in the universes\n", + "for i,_key in tqdm(enumerate(keys)):\n", + " is_valid = True\n", + " # if i > 100000:\n", + " # break\n", + " #print(i,_key)\n", + " _tree = tree[_key]\n", + " #skip directories\n", + " if '.root/' not in _key: \n", + " dir_keys.append(_key)\n", + " continue\n", + " \n", + " #skip non-histograms\n", + " if _tree.classname == 'TH1D':\n", + " \n", + " #Check if the histogram has the correct number of bins\n", + " if (len(_tree.to_numpy()[0]) != (len(P_BINS) + len(COSTHETA_BINS))) \\\n", + " and (len(_tree.to_numpy()[0]) != (len(P_BINS) + len(COSTHETA_OVERFLOW_BINS))): #account for overflow bin \n", + " \n", + " #print(f'Incorrect number of bins for {_key}')\n", + " wrong_length_keys.append(_key)\n", + " is_valid=False\n", + " #Which keys do we use depends on which length it matches\n", + " if len(_tree.to_numpy()[0]) == (len(P_BINS) + len(COSTHETA_BINS)):\n", + " costheta_bins = COSTHETA_BINS\n", + " elif len(_tree.to_numpy()[0]) == (len(P_BINS) + len(COSTHETA_OVERFLOW_BINS)):\n", + " costheta_bins = COSTHETA_OVERFLOW_BINS\n", + " \n", + " #Get universe values for the momentum histogram\n", + " p_vals = _tree.to_numpy()[0][P_BINS]\n", + " if np.isnan(p_vals).sum() > 0:\n", + " p_nan_keys.append(_key)\n", + " break\n", + " \n", + " #Get universe values for the costheta histogram\n", + " costheta_vals = _tree.to_numpy()[0][costheta_bins]\n", + " if np.isnan(costheta_vals).sum() > 0:\n", + " costheta_nan_keys.append(_key)\n", + " break\n", + " \n", + " #Check for negative values\n", + " if (p_vals < 0).sum() > 0:\n", + " negative_keys.append(_key)\n", + " break\n", + " if (costheta_vals < 0).sum() > 0:\n", + " negative_keys.append(_key)\n", + " break\n", + " \n", + " #Check for zero values\n", + " if (p_vals == 0).sum() > 0:\n", + " zero_keys.append(_key)\n", + " if (costheta_vals == 0).sum() > 0:\n", + " zero_keys.append(_key)\n", + " if is_valid:\n", + " accepted_keys.append(_key)\n", + " elif _tree.classname == 'TH2D':\n", + " #print(_tree.to_numpy()[0].shape)\n", + " #Get number of bins, which should match either len(P_BINS) + len(COSTHETA_OVERFLOW_BINS) or len(P_BINS) + len(COSTHETA_BINS)\n", + " nxbins = _tree.to_numpy()[0].shape[0] \n", + " nybins = _tree.to_numpy()[0].shape[1]\n", + " if nxbins != nybins:\n", + " #print(f'array shape: {_tree.to_numpy()[0].shape} for {_key}')\n", + " #raise ValueError('Histogram is not square')\n", + " twod_non_square_keys.append(_key)\n", + " #continue\n", + " if ((nxbins != (len(P_BINS) + len(COSTHETA_BINS)))\\\n", + " and (nxbins != (len(COSTHETA_OVERFLOW_BINS) + len(P_BINS)))\\\n", + " and (nxbins != len(CAT_BINS))):\n", + " print(f'Incorrect number of x bins for {_key}: {nxbins}')\n", + " wrong_length_keys.append(_key)\n", + " break\n", + " if ((nybins != (len(P_BINS) + len(COSTHETA_BINS)))\\\n", + " and (nybins != (len(COSTHETA_OVERFLOW_BINS) + len(P_BINS)))\\\n", + " and (nybins != len(CAT_BINS))):\n", + " print(f'Incorrect number of y bins for {_key}: {nybins}')\n", + " wrong_length_keys.append(_key)\n", + " break\n", + "\n", + " # Convert to numpy array for processing (assumes appropriate method exists)\n", + " vals = _tree.to_numpy()[0] # 2d array\n", + "\n", + " # Check for NaN values\n", + " if np.isnan(vals).sum() > 0:\n", + " twod_nan_keys.append(_key)\n", + " break\n", + "\n", + " # Check for negative values\n", + " if (vals < 0).sum() > 0:\n", + " negative_keys.append(_key)\n", + " break\n", + "\n", + " # Check for zero values\n", + " if (vals == 0).sum() > 0:\n", + " zero_keys.append(_key)\n", + " if is_valid:\n", + " twod_valid_keys.append(_key)\n", + " else:\n", + " non_hist_keys.append(_key)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "len of p_nan_keys: 0\n", + " len of costheta_nan_keys: 0\n", + " len of wrong_length_keys: 0\n", + " len of dir_keys: 94840\n", + " len of non_hist_keys: 0\n", + " len of accepted_keys: 158030\n", + " len of negative_keys: 0\n", + " len of zero_keys: 316060\n", + " len of class_names: 0\n", + " len of twod_nan_keys: 0\n", + " len of twod_non_square_keys: 158030\n", + " len of twod_valid_keys: 316060\n" + ] + } + ], + "source": [ + "print(f'len of p_nan_keys: {len(p_nan_keys)}\\n',\n", + " f'len of costheta_nan_keys: {len(costheta_nan_keys)}\\n',\n", + " f'len of wrong_length_keys: {len(wrong_length_keys)}\\n',\n", + " f'len of dir_keys: {len(dir_keys)}\\n',\n", + " f'len of non_hist_keys: {len(non_hist_keys)}\\n',\n", + " f'len of accepted_keys: {len(accepted_keys)}\\n',\n", + " f'len of negative_keys: {len(negative_keys)}\\n',\n", + " f'len of zero_keys: {len(zero_keys)}\\n',\n", + " f'len of class_names: {len(class_names)}\\n',\n", + " f'len of twod_nan_keys: {len(twod_nan_keys)}\\n',\n", + " f'len of twod_non_square_keys: {len(twod_non_square_keys)}\\n',\n", + " f'len of twod_valid_keys: {len(twod_valid_keys)}')" + ] + }, + { + "cell_type": "code", + "execution_count": 58, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "
\n", + "
\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "20\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "19\n", + "\n", + "\n", + " true bin number\n", + "\n", + "\n", + " reco bin number\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
\n", + "
\n", + "Regular(20, 0, 20, name='xaxis', label=' true bin number')
\n", + "Regular(19, 0, 19, name='yaxis', label=' reco bin number')
\n", + "
\n", + "Weight() Σ=WeightedSum(value=472, variance=472)\n", + "\n", + "
\n", + "
\n", + "" + ], + "text/plain": [ + "Hist(\n", + " Regular(20, 0, 20, name='xaxis', label=' true bin number'),\n", + " Regular(19, 0, 19, name='yaxis', label=' reco bin number'),\n", + " storage=Weight()) # Sum: WeightedSum(value=472, variance=472)" + ] + }, + "execution_count": 58, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "key = twod_non_square_keys[-2]\n", + "tree[key].to_hist()" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(20, 19)" + ] + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "key = twod_non_square_keys[0]\n", + "tree[key].to_numpy()[0].shape" + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "
\n", + "
\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "19\n", + "\n", + "\n", + " reco bin number\n", + "\n", + "\n", + "\n", + "
\n", + "
\n", + "Regular(19, 0, 19, name='xaxis', label=' reco bin number')
\n", + "
\n", + "Weight() Σ=WeightedSum(value=250, variance=250)\n", + "\n", + "
\n", + "
\n", + "" + ], + "text/plain": [ + "Hist(Regular(19, 0, 19, name='xaxis', label=' reco bin number'), storage=Weight()) # Sum: WeightedSum(value=250, variance=250)" + ] + }, + "execution_count": 59, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "key = accepted_keys[0]\n", + "tree[key].to_hist()" + ] + }, + { + "cell_type": "code", + "execution_count": 60, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "
\n", + "
\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "20\n", + "\n", + "\n", + " true bin number\n", + "\n", + "\n", + "\n", + "
\n", + "
\n", + "Regular(20, 0, 20, name='xaxis', label=' true bin number')
\n", + "
\n", + "Weight() Σ=WeightedSum(value=3664, variance=3664)\n", + "\n", + "
\n", + "
\n", + "" + ], + "text/plain": [ + "Hist(Regular(20, 0, 20, name='xaxis', label=' true bin number'), storage=Weight()) # Sum: WeightedSum(value=3664, variance=3664)" + ] + }, + "execution_count": 60, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "key = accepted_keys[1]\n", + "tree[key].to_hist()" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 31, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.imshow(tree[key].to_numpy()[0])\n", + "plt.colorbar()" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'SBND_CC1muX_1D/+exp+sbnd+data+users+brindenc+xsec_analysis+test+sbruce+cc1mux_med_weight.root/weight_GENIEReWeight_SBN_v1_multisim_COHVariationResponse_64_true2d;1'" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "_key" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(19, 20)" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "len(tree['SBND_CC1muX_1D/+exp+sbnd+data+users+brindenc+xsec_analysis+test+sbruce+cc1mux_med_weight.root/unweighted_0_reco;1'].to_numpy()[0]),\\\n", + "len(tree['SBND_CC1muX_1D/+exp+sbnd+data+users+brindenc+xsec_analysis+test+sbruce+cc1mux_med_weight.root/unweighted_0_reco;1'].to_numpy()[1])" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(0, 6, 663, 0, 0, 332, 0, 0)" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "len(wrong_length_keys),len(dir_keys),len(non_hist_keys),len(p_nan_keys),len(costheta_nan_keys),len(accepted_keys),len(negative_keys),len(zero_keys)" + ] + }, + { + "cell_type": "code", + "execution_count": 81, + "metadata": {}, + "outputs": [ + { + "ename": "IndexError", + "evalue": "list index out of range", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mIndexError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[81], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m wrong_length_th1d \u001b[38;5;241m=\u001b[39m tree[\u001b[43mwrong_length_keys\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m0\u001b[39;49m\u001b[43m]\u001b[49m]\u001b[38;5;241m.\u001b[39mto_numpy()\n\u001b[1;32m 2\u001b[0m correct_length_th1d \u001b[38;5;241m=\u001b[39m tree[accepted_keys[\u001b[38;5;241m0\u001b[39m]]\u001b[38;5;241m.\u001b[39mto_numpy()\n\u001b[1;32m 3\u001b[0m \u001b[38;5;28mlen\u001b[39m(wrong_length_th1d[\u001b[38;5;241m0\u001b[39m]), \u001b[38;5;28mlen\u001b[39m(P_BINS) \u001b[38;5;241m+\u001b[39m \u001b[38;5;28mlen\u001b[39m(COSTHETA_BINS), \u001b[38;5;28mlen\u001b[39m(correct_length_th1d[\u001b[38;5;241m0\u001b[39m])\n", + "\u001b[0;31mIndexError\u001b[0m: list index out of range" + ] + } + ], + "source": [ + "wrong_length_th1d = tree[wrong_length_keys[0]].to_numpy()\n", + "correct_length_th1d = tree[accepted_keys[0]].to_numpy()\n", + "len(wrong_length_th1d[0]), len(P_BINS) + len(COSTHETA_BINS), len(correct_length_th1d[0])" + ] + }, + { + "cell_type": "code", + "execution_count": 68, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(array([11., 4., 9., 9., 19., 16., 13., 22., 22., 21., 33., 25., 21.,\n", + " 9., 4., 4., 6., 1.]),\n", + " 'SBND_CC1muX_1D/+exp+sbnd+data+users+brindenc+xsec_analysis+test+sbruce+cc1mux_med_weight.root/unweighted_0_reco;1')" + ] + }, + "execution_count": 68, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "correct_length_th1d[0],accepted_keys[0]" + ] + }, + { + "cell_type": "code", + "execution_count": 69, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(19, 19)" + ] + }, + "execution_count": 69, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "len(wrong_length_th1d[1]),len(tree[key].to_numpy()[1])" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(array([1., 3., 1., 0., 3., 1., 1., 0., 1., 0., 1., 4., 0., 1., 0., 0., 0.,\n", + " 1.]),\n", + " array([ 1. , 2.77777778, 4.55555556, 6.33333333, 8.11111111,\n", + " 9.88888889, 11.66666667, 13.44444444, 15.22222222, 17. ,\n", + " 18.77777778, 20.55555556, 22.33333333, 24.11111111, 25.88888889,\n", + " 27.66666667, 29.44444444, 31.22222222, 33. ]),\n", + " )" + ] + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAhsAAAGjCAYAAACFVtc4AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAXNElEQVR4nO3df2xV9f348RdiaRWhBHATYoVZq3NLINjoVNJgtkQxxhGI05gYB+rcotk0uGTDiYrMYQaar1OXfWIcKolui3E6FHXTZRhdBKdRCKgz4qCicaCs5efFyfn+YdrIaMFe7qvtLY9HchPvOfee+yr3nfjMvefeO6goiiIAAJIc1tcDAAADm9gAAFKJDQAgldgAAFKJDQAgldgAAFKJDQAgldgAAFId3tcDRETs2bMn3n///Rg2bFgMGjSor8cBAL6Aoihi69atMXbs2DjssO5fv+gXsfH+++9HQ0NDX48BAJShtbU1jj322G7394vYGDZsWER8Nuzw4cP7eBoA4Itob2+PhoaGzv+Pd6dfxEbHWyfDhw8XGwBQZQ50CoQTRAGAVGIDAEglNgCAVGIDAEglNgCAVGIDAEglNgCAVBWJjY8++ii+9KUvxaBBg+KEE06oxCEBgAGiIrFx3XXXxebNmytxKABggDno2HjuuefigQceiO9973uVmAcAGGAOKjZ27twZ3//+9+NrX/ta/PjHP67UTADAAHJQv40yb968WLduXSxfvjxqamoqNRMAMICU/crGqlWr4vbbb49Zs2ZFS0tLJWcCAAaQsl7Z2LNnT1xxxRUxYsSI+OUvf9nj+5dKpSiVSp3X29vbyxkDAKgCZcXGXXfdFS+//HIsXrw4Ro0a1eP7L1iwIObNm1fOQwP0mfE/fTL9Mf5123npjwG9rcdvo2zYsCFuuOGGmDJlSsycObOsB50zZ060tbV1XlpbW8s6DgDQ//X4lY2rr746du/eHb/5zW/KftDa2tqora0t+/4AQPXocWw88cQTMWLEiPjBD36w1/Zdu3ZFRMTGjRvjrLPOioiI3/3ud3HMMccc/JQAQNUq65yN//znP7F8+fIu9+3atatzX0eAAACHrh6fs1EURZeXd999NyIiGhsbO7eNHz++0vMCAFXGr74CAKnEBgCQSmwAAKkO6rdRPm/8+PFRFEWlDgcADBBe2QAAUokNACCV2AAAUokNACCV2AAAUokNACCV2AAAUokNACCV2AAAUokNACCV2AAAUokNACCV2AAAUokNACCV2AAAUokNACCV2AAAUokNACCV2AAAUokNACCV2AAAUokNACCV2AAAUokNACCV2AAAUokNACCV2AAAUokNACCV2AAAUokNACCV2AAAUokNACCV2AAAUokNACCV2AAAUokNACCV2AAAUokNACCV2AAAUokNACCV2AAAUokNACCV2AAAUokNACCV2AAAUokNACCV2AAAUokNACCV2AAAUokNACCV2AAAUokNACCV2AAAUokNACCV2AAAUokNACCV2AAAUokNACCV2AAAUokNACCV2AAAUokNACCV2AAAUokNACCV2AAAUokNACCV2AAAUokNACCV2AAAUokNACCV2AAAUpUVG3fccUfMmDEjmpqaor6+Pmpra2PcuHFx6aWXxurVqys9IwBQxcqKjV/84hfx1FNPxciRI+Nb3/pWnHfeeVFXVxdLliyJ5ubmeOKJJyo9JwBQpQ4v506PP/54NDc3R11d3V7bf/3rX8fVV18dV1xxRbz33ntx+OFlHR4AGEDKemVj8uTJ+4RGRMRVV10VjY2N8eGHH8batWsPejgAoPpV/ATRmpqaiIgYMmRIpQ8NAFShisbGkiVL4q233oqmpqZoamqq5KEBgCp1UCdVLFy4MNasWRPbt2+PN954I9asWRNjx46Nhx9+OAYPHtzt/UqlUpRKpc7r7e3tBzMGANCPHVRsPPPMM/Hcc891Xh83blw8+OCD0dzcvN/7LViwIObNm3cwD92vjP/pk+mP8a/bzkt/jN7i3wvg0HJQb6M8++yzURRFbNmyJZ5//vloamqKKVOmxK233rrf+82ZMyfa2to6L62trQczBgDQj1XknI0RI0ZES0tLLFu2LJqbm2Pu3Lnx8ssvd3v72traGD58+F4XAGBgqugJojU1NXHRRRdFURSxdOnSSh4aAKhSFf/o6+jRoyMiYtOmTZU+NABQhSoeG8uXL4+IiMbGxkofGgCoQj2OjRdffDGefvrp2LNnz17bP/nkk7jrrrtiyZIlccQRR8RFF11UsSEBgOrV44++vv322zFr1qwYPXp0NDc3x6hRo2Lz5s2xevXq+OCDD6Kuri7uv//+aGhoyJgXAKgyPY6NKVOmxPXXXx/Lly+PVatWxebNm2PIkCExfvz4uOCCC+JH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jBNPPDHq6upi7Nixcdlll8XGjRv7ejT60CuvvBK33XZbzJgxI4499tgYNGhQl18G97+sp0PTjh074rHHHovLL788TjrppKirq4uhQ4fGxIkT45Zbbun8VuSuWDOHpjvuuCNmzJgRTU1NUV9fH7W1tTFu3Li49NJLY/Xq1d3ez3rZj6Kf2rlzZ3H66acXEVGMGTOmuPDCC4vTTjutiIji6KOPLt55552+HpE+Mm3atCIi9rnsj/V06Lr33ns718jJJ59cfOc73ynOOeecYtiwYUVEFF/96leLDz/8cJ/7WTOHrlGjRhV1dXXFaaedVkyfPr2YPn16ceKJJxYRUdTU1BRLly7d5z7Wy/7129j42c9+VkREccYZZxRbt27t3H777bcXEVFMmTKl74ajT912223F3Llziz/96U/FBx98UNTW1h4wNqynQ9f9999fXHnllcXatWv32v7+++8XkyZNKiKiuPjii/e5nzVz6HrhhReKnTt37rP9nnvuKSKi+PKXv1x88skne+2zXvavX8ZGqVQq6uvri4goXn311X32T5gwoYiI4h//+EcfTEd/c6DYsJ7ozt///vciIora2tqiVCp1brdm6E5jY2MREcXrr7/euc16ObB+ec7Giy++GG1tbdHY2BiTJk3aZ/8FF1wQERFLly7t7dGoQtYT3en4RuRSqRQfffRR53Zrhu7U1NRERMSQIUM6t1kvB9YvY+P111+PiIhTTjmly/0d21etWtVrM1G9rCe6s27duoj47H8gI0eO7NxuzdCVJUuWxFtvvRVNTU3R1NTUud16ObA++Yn5A9mwYUNERLff19Gxff369b02E9XLeqI7d955Z0RETJ06da+vnLZmiIhYuHBhrFmzJrZv3x5vvPFGrFmzJsaOHRsPP/xwDB48uPN21suB9cvY6Pgo2pFHHtnl/o6vR9+6dWuvzUT1sp7oyrJly+K+++6LmpqamD9//l77rBkiIp555pl47rnnOq+PGzcuHnzwwWhubt7rdtbLgfXLt1EAMr355ptxySWXRFEUsXDhws5zN+Dznn322SiKIrZs2RLPP/98NDU1xZQpU+LWW2/t69GqTr+MjaOOOioiPvsynq5s3749IiKGDRvWazNRvawnPm/jxo0xderU2LJlS8yePTuuueaafW5jzfB5I0aMiJaWlli2bFk0NzfH3Llz4+WXX+7cb70cWL+MjeOOOy4iIt57770u93dsHzduXK/NRPWynujw8ccfx9lnnx3r16+PWbNmxaJFi7q8nTVDV2pqauKiiy6Koij2+mSJ9XJg/TI2Ol7SfPXVV7vc37F9woQJvTYT1ct6IuKz99XPPffcWLt2bcyYMSPuvffebr/m3pqhO6NHj46IiE2bNnVus14OrF/GxuTJk6O+vj7eeeedeO211/bZ/8gjj0RExPnnn9/Lk1GNrCdKpVJMmzYtVq5cGeecc84+nyb4X9YM3Vm+fHlERDQ2NnZus16+gD7+UrFudXz165lnnlls27atc7uvfuV/9eTryq2nQ89///vfYvr06UVEFC0tLcX27du/0P2smUPTCy+8UDz11FPFp59+utf23bt3F7/61a+Kww47rDjiiCOKDRs27LXfetm/fvsT87t27YqzzjorVqxYEWPGjImWlpZYv359rFixIo4++uh46aWX4vjjj+/rMekDTz755F4fVVy5cmUURRHf+MY3OrfNnTs3zjvvvM7r1tOh684774xrr702IiKmT58ew4cP7/J2ixYt6nyJPMKaOVTdf//9MWvWrBg9enQ0NzfHqFGjYvPmzbF69er44IMPoq6uLh544IG48MIL97qf9XIAfRw7+7Vjx45i7ty5RWNjYzFkyJDimGOOKWbOnFm0trb29Wj0ocWLF3f5q6+fvyxevHif+1lPh6abbrrpgOslIop33313n/taM4eedevWFddff30xefLkYsyYMUVNTU0xdOjQ4utf/3rxwx/+sHj77be7va/10r1++8oGADAw9MsTRAGAgUNsAACpxAYAkEpsAACpxAYAkEpsAACpxAYAkEpsAACpxAYAkEpsAACpxAYAkEpsAACpxAYAkOr/A8tGgU2l/WfPAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(array([0, 1, 2, 3, 4, 5, 6, 7, 8]),\n", + " array([ 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]))" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "P_BINS,COSTHETA_BINS" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [ + { + "ename": "AttributeError", + "evalue": "'Model_TH1D_v2' object has no attribute 'classnames'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[29], line 2\u001b[0m\n\u001b[1;32m 1\u001b[0m _tree\u001b[38;5;241m.\u001b[39mclassnames()\n\u001b[0;32m----> 2\u001b[0m \u001b[43mtree\u001b[49m\u001b[43m[\u001b[49m\u001b[43mkey\u001b[49m\u001b[43m]\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mclassnames\u001b[49m()\n", + "\u001b[0;31mAttributeError\u001b[0m: 'Model_TH1D_v2' object has no attribute 'classnames'" + ] + } + ], + "source": [ + "_tree.classnames()\n", + "tree[key].classnames()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "env", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.21" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/python/utils b/python/utils new file mode 160000 index 000000000..981c860c1 --- /dev/null +++ b/python/utils @@ -0,0 +1 @@ +Subproject commit 981c860c18c6e538c6dc6df1ea5bb0b61fb3ffab diff --git a/python/xsec.ipynb b/python/xsec.ipynb new file mode 100644 index 000000000..40eb49027 --- /dev/null +++ b/python/xsec.ipynb @@ -0,0 +1,162 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 0. Setup packages and Constants" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "import uproot\n", + "import numpy as np\n", + "import sys\n", + "\n", + "# Utils\n", + "from utils import plotters\n", + "\n", + "plt.style.use('./utils/style.mplstyle')\n", + "\n", + "\n", + "\n", + "%load_ext autoreload\n", + "%autoreload 2" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "#Path to the ROOT file containing the cross section histograms\n", + "DATA_PATH = '/exp/sbnd/data/users/brindenc/xsec_analysis/test/sbruce/cc1mux_xsec_weight3.root'" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# 1. Load the data" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "tree = uproot.open(DATA_PATH)\n", + "#tree.keys() #display all keys in the ROOT file" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "((array([ 34.8700459 , 72.43497905, 81.34426497, 64.66502684,\n", + " 103.1598215 , 91.22232699, 90.46433482, 78.11680768,\n", + " 126.35322449, nan, nan, nan,\n", + " nan, nan, nan, nan,\n", + " nan, nan, nan]),\n", + " array([ 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.,\n", + " 13., 14., 15., 16., 17., 18., 19.])),\n", + " array([44.26907225, 44.09873665, 37.68189465, 38.29765198, 38.72582211,\n", + " 40.36740753, 47.10434581, 47.08821622, 48.24316928, 0. ,\n", + " 0. , 0. , 0. , 0. , 0. ,\n", + " 0. , 0. , 0. , 0. ]))" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "#Example\n", + "#hist_key = 'EventCountUnits/muoncos#theta/muoncos#theta_total;1'\n", + "#hist_key = 'EventCountUnits/p_{#mu}/p_{#mu}_total;1'\n", + "#hist_key = 'EventCountUnits/binnumber/binnumber_total;1'\n", + "#hist_key = 'XsecUnits/muoncos#theta/muoncos#theta_total;1'\n", + "#hist_key = 'XsecUnits/p_{#mu}/p_{#mu}_total;1'\n", + "hist_key = 'XsecUnits/binnumber/binnumber_total;1'\n", + "\n", + "_tree = tree[hist_key]\n", + "_tree.to_hist()\n", + "_hist = _tree.to_numpy()\n", + "_error = _tree.errors()\n", + "_hist,_error" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "([],\n", + " )" + ] + }, + "execution_count": 36, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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Q6hLw0WGDh0qSXK5XDp58mSYq4k+zz77rA4dOqSXX35Z8fHx4S4nKrW0tOiNN95QcnKypk+fHu5yIF3yRnzf/OY3g1yJeQg2ftqzZ48kKT8/32e/p72qqipkNcG3Q4cOSZLi4+PVu3fvMFcTXaqqqlRSUqLp06dr9OjR4S4nan366adyOBwaNmyYEhMT9fe//11z5szRY489pl//+tc6fvx4uEuMOtnZ2crJydH+/fv11ltvefXt27dPb7zxhr7xjW9o6tSpYaowckXV3b0D6fDhw5LU6d3CPe01NTUhqwm+vfjii5KkiRMnsl15CLW1temRRx5RWlqafvnLX4a7nKi2d+9eSVJ6erruuecevffee1798+fP16pVq/Tggw+Go7yo1KNHD61du1Z33XWXfvjDH6qkpEQDBw5UbW2tPvnkEw0ZMkSvv/46f4z5gRkbP3kuH05KSvLZn5ycLElyOBwhqwkd/e1vf9OqVasUHx+vRYsWhbucqPLSSy9p165dWrp0KdPpYXb69GlJ0l//+le9//77WrlypWpra1VdXa158+appaVFDz/8sHbv3h3eQqPMqFGjtH37dmVnZ6uyslLvvvuutm3bptjYWH33u9/lqlo/EWxgrM8++0wPPfSQ3G63li5d2r7WBsF3+PBhLViwQGPGjFFBQUG4y4l6bW1tkqTW1lYVFxfrscceU58+fdS/f38tXbpU999/v86dO6elS5eGudLo8vbbb2vEiBHKyspSeXm5GhsbdeDAARUUFKikpETjxo2Ty+UKd5kRh2Djp169ekm6sDGcL01NTZIku90esprwpWPHjmnixIk6ffq05syZo8cffzzcJUWVWbNm6ezZs3r55ZfDXQr05e8rST4XD3vatm/fHrKaot2///1vPfzww7riiiu0ceNGjRgxQsnJyRo4cKBeeeUV3XXXXaqsrNTq1avDXWrEYY2Nn/r16ydJOnr0qM9+T3v//v1DVhMuOHXqlCZMmKCamhpNnz5dy5YtC3dJUWfjxo1KS0vTT37yE692p9Mp6ULwHDt2rCTpnXfe0VVXXRXqEqOK5/dQUlKS+vTp06F/wIABkqTa2tpQlhXV3nnnHZ07d04TJ070Cp4eDzzwgDZu3KiPP/5YM2fODEOFkYtg4yfPaY3Kykqf/Z72vLy8kNWEC2ufvve972nv3r2699579eqrryomJibcZUWlM2fOdDoD4HQ62/s8YQfB49mSoqWlRS6Xq8Mi+lOnTkmSzw9YBIfnj9/U1FSf/Z52z/ooXDpORflp1KhRSk1N1cGDB30uuFu3bp0kafLkySGuLHq5XC5NmTJFO3fu1B133KG3335bPXr0CHdZUcl9YfPPDo8vvvhCkpSTk9Pe5pktQPD069dPQ4cOldvt9hk2PW2+9uRCcHhmKT/99FOf/bt27ZIkfj78QLDxU8+ePTV79mxJF9YTeNbUSNLy5ctVVVWlMWPGaPjw4eEqMaqcP39eDz74oD788EONHj1af/7zn9WzZ89wlwVYxs9//nNJ0rx583TixIn29t27d6ukpESSOpw6RPBMmTJFkvTxxx/rt7/9rVdfWVmZfvWrX0n6crNXXDpugtkNTqdTY8eOVXl5eftNMGtqalReXs5NMEPsxRdf1M9+9jNJ0tSpU5WSkuLzecuWLdMVV1wRwsrwVdXV1frWt77FTTDDpKCgQGvXrlVaWppuvfVWtbS0qLS0VC6XS48++qh+97vfhbvEqPLEE0+0rwG87rrrNGTIEB0/flz/+Mc/1NbWphkzZuiVV14Jc5WRh2DTTS0tLVqyZIneeustHTlyRL1799bEiRO1aNGiTjfvQ+A988wzevbZZ7/2eV988QVTu2FEsAkvt9ut1157Ta+88or27dunmJgY5eXl6cc//rEefvjhcJcXlf7yl7/o5ZdfVkVFherr62W323XDDTfo0UcfZcNEPxFsAACAMVhjAwAAjEGwAQAAxiDYAAAAYxBsAACAMQg2AADAGAQbAABgDIINAAAwBsEGAAAYg2ADAACMQbABAADGINgAAABjEGwAAIAxCDYAAMAY/x9XfEiNse9HyQAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plotters.plot_hist_edges(_hist[1], _hist[0], _error)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "env", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.19" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/setup_xsec_analyzer.sh b/setup_xsec_analyzer.sh index 9ce4f4211..a023a7bdc 100755 --- a/setup_xsec_analyzer.sh +++ b/setup_xsec_analyzer.sh @@ -1,5 +1,18 @@ #!/bin/bash +#Set experiment name from argument +# if [ -z "$1" ]; then +# echo "No experiment name provided. Please provide the experiment name as an argument." +# return 1 +# fi +# elif [ "$1" = "uboone" || "$1" = "sbnd" ]; then +# export EXPERIMENT_NAME=$1 +# fi +# else +# echo "Invalid experiment name provided. Please provide either \"uboone\" or \"sbnd\" as an argument." +# return 1 +# fi + # Get the name of the OS release (used to distinguish between SL7 and EL9) MY_OS_REL=$(cat /etc/os-release | grep ^NAME | sed -e 's/NAME=//g' -e 's/"//g') diff --git a/src/app/ProcessNTuples.C b/src/app/ProcessNTuples.C index 23bf619bb..e187f5d18 100644 --- a/src/app/ProcessNTuples.C +++ b/src/app/ProcessNTuples.C @@ -1,5 +1,5 @@ // Post-processing program for the MicroBooNE xsec_analyzer framework. This is -// currently designed for use with the PeLEE group's "searchingfornues" ntuples +// currently designed for use with the PeLEE group"s "searchingfornues" ntuples // // Updated 24 September 2024 // Steven Gardiner @@ -21,10 +21,10 @@ #include "TParameter.h" #include "TTree.h" #include "TVector3.h" +#include "TH1D.h" // XSecAnalyzer includes -#include "XSecAnalyzer/AnalysisEvent.hh" -#include "XSecAnalyzer/Branches.hh" +#include "XSecAnalyzer/Event/AnalysisEventFactory.hh" #include "XSecAnalyzer/Constants.hh" #include "XSecAnalyzer/Functions.hh" @@ -33,7 +33,8 @@ void analyze( const std::vector< std::string >& in_file_names, const std::vector< std::string >& selection_names, - const std::string& output_filename ) + const std::string& output_filename, + const std::string& experiment) { std::cout << "\nRunning ProcessNTuples with options:\n"; std::cout << "\toutput_filename: " << output_filename << '\n'; @@ -45,40 +46,100 @@ void analyze( const std::vector< std::string >& in_file_names, for ( const auto& sel_name : selection_names ) { std::cout << "\t\t- " << sel_name << '\n'; } + std::cout << "\nExperiment: " << experiment << '\n'; // Get the TTrees containing the event ntuples and subrun POT information // Use TChain objects for simplicity in manipulating multiple files - TChain events_ch( "nuselection/NeutrinoSelectionFilter" ); - TChain subruns_ch( "nuselection/SubRun" ); - for ( const auto& f_name : in_file_names ) { - events_ch.Add( f_name.c_str() ); - subruns_ch.Add( f_name.c_str() ); - } - - // OUTPUT TTREE - // Make an output TTree for plotting (one entry per event) + //Initialize variables to be available outside of the if statements + TChain events_ch; + TTree* out_tree; TFile* out_file = new TFile( output_filename.c_str(), "recreate" ); - out_file->cd(); - TTree* out_tree = new TTree( "stv_tree", "STV analysis tree" ); - - // Get the total POT from the subruns TTree. Save it in the output - // TFile as a TParameter. Real data doesn't have this TTree, - // so check that it exists first. + std::cout<< "Created output file: " << output_filename << std::endl; float pot; float summed_pot = 0.; - bool has_pot_branch = ( subruns_ch.GetBranch("pot") != nullptr ); - if ( has_pot_branch ) { - subruns_ch.SetBranchAddress( "pot", &pot ); - for ( int se = 0; se < subruns_ch.GetEntries(); ++se ) { - subruns_ch.GetEntry( se ); - summed_pot += pot; + + //SBND specific variables + TChain syst_ch; + TChain header_ch; + + //MicroBooNE specific variables + TChain subruns_ch; + + if (experiment == "uboone"){ + std::cout<< "Running for MicroBooNE" << std::endl; + events_ch.SetName( "nuselection/NeutrinoSelectionFilter" ); + subruns_ch.SetName( "nuselection/SubRun" ); + + for ( const auto& f_name : in_file_names ) { + events_ch.Add( f_name.c_str() ); + subruns_ch.Add( f_name.c_str() ); + } + + // OUTPUT TTREE + // Make an output TTree for plotting (one entry per event) + std::cout<< "Creating output TTree" << std::endl; + out_file->cd(); + std::cout<< "Creating output TTree2" << std::endl; + out_tree = new TTree( "stv_tree", "STV analysis tree" ); + std::cout<< "Creating output TTree3" << std::endl; + + // Get the total POT from the subruns TTree. Save it in the output + // TFile as a TParameter. Real data doesn"t have this TTree, + // so check that it exists first. + bool has_pot_branch = ( subruns_ch.GetBranch("pot") != nullptr ); + if ( has_pot_branch ) { + subruns_ch.SetBranchAddress( "pot", &pot ); + for ( int se = 0; se < subruns_ch.GetEntries(); ++se ) { + subruns_ch.GetEntry( se ); + summed_pot += pot; + } + } + } + + if (experiment == "sbnd"){ + events_ch.SetName( "events/nominal/slice" ); + syst_ch.SetName( "systs/multisimTree" ); + header_ch.SetName( "events/nominal/header" ); + //subruns_ch.SetName( "events/nominal" ); + + for ( const auto& f_name : in_file_names ) { + events_ch.Add( f_name.c_str() ); + syst_ch.Add( f_name.c_str() ); + header_ch.Add( f_name.c_str() ); + + + events_ch.AddFriend(&syst_ch); + events_ch.AddFriend(&header_ch); + // Read POT + TFile* currentFile = TFile::Open(f_name.c_str()); + TDirectory* dir = currentFile->GetDirectory("events/nominal"); + TH1D* pot_hist = nullptr; + dir->GetObject("POT", pot_hist); + if (pot_hist) { + summed_pot += pot_hist->Integral(); + delete pot_hist; + } + if (currentFile) { + currentFile->Close(); + delete currentFile; + } } + events_ch.Print(); + + // OUTPUT TTREE + // Make an output TTree for plotting (one entry per event) + out_file->cd(); + out_tree = new TTree( "stv_tree", "STV analysis tree" ); + } + + if (!out_file || !out_file->IsOpen()) { + std::cerr << "Error opening file: " << output_filename << std::endl; + return; // Or handle the error appropriately } TParameter* summed_pot_param = new TParameter( "summed_pot", summed_pot ); - summed_pot_param->Write(); std::vector< std::unique_ptr > selections; @@ -101,8 +162,10 @@ void analyze( const std::vector< std::string >& in_file_names, long events_entry = 0; while ( true ) { - - //if ( events_entry > 1000) break; + // Get entry number of systematics tree + // if (experiment == "sbnd"){ + // syst_ch.GetEntry( events_entry ); + // } if ( events_entry % 1000 == 0 ) { std::cout << "Processing event #" << events_entry << '\n'; @@ -110,22 +173,27 @@ void analyze( const std::vector< std::string >& in_file_names, // Create a new AnalysisEvent object. This will reset all analysis // variables for the current event. - AnalysisEvent cur_event; + std::unique_ptr cur_event = create_event(experiment); - // Set branch addresses for the member variables that will be read - // directly from the Event TTree. - set_event_branch_addresses( events_ch, cur_event ); // TChain::LoadTree() returns the entry number that should be used with // the current TTree object, which (together with the TBranch objects - // that it owns) doesn't know about the other TTrees in the TChain. + // that it owns) doesn"t know about the other TTrees in the TChain. // If the return value is negative, there was an I/O error, or we've // attempted to read past the end of the TChain. int local_entry = events_ch.LoadTree( events_entry ); - // If we've reached the end of the TChain (or encountered an I/O error), // then terminate the event loop - if ( local_entry < 0 ) break; + if ( local_entry < 0 ){ + if (events_entry == 0) { + std::cerr << "No entries found in input TTree. Exiting.\n"; + return; + } + break; + } + // Set branch addresses for the member variables that will be read + // directly from the Event TTree. + cur_event->set_event_branch_addresses( events_ch ); // Load all of the branches for which we've called // TChain::SetBranchAddress() above @@ -138,13 +206,13 @@ void analyze( const std::vector< std::string >& in_file_names, create_them = true; created_output_branches = true; } - set_event_output_branch_addresses(*out_tree, cur_event, create_them ); + cur_event->set_event_output_branch_addresses(*out_tree, create_them ); for ( auto& sel : selections ) { - sel->apply_selection( &cur_event ); + sel->apply_selection( &*cur_event ); } - // We're done. Save the results and move on to the next event. + // We"re done. Save the results and move on to the next event. out_tree->Fill(); ++events_entry; } @@ -152,12 +220,12 @@ void analyze( const std::vector< std::string >& in_file_names, for ( auto& sel : selections ) { sel->summary(); } - std::cout << "Wrote output to:" << output_filename << std::endl; for ( auto& sel : selections ) { sel->final_tasks(); } + out_tree->Write(); out_file->Close(); delete out_file; @@ -165,22 +233,23 @@ void analyze( const std::vector< std::string >& in_file_names, void analyzer( const std::string& in_file_name, const std::vector< std::string > selection_names, - const std::string& output_filename) + const std::string& output_filename, + const std::string& experiment ) { std::vector< std::string > in_files = { in_file_name }; - analyze( in_files, selection_names, output_filename ); + analyze( in_files, selection_names, output_filename, experiment ); } int main( int argc, char* argv[] ) { - if ( argc != 4 ) { + if ( argc != 5 ) { std::cout << "Usage: " << argv[0] - << " INPUT_PELEE_NTUPLE_FILE SELECTION_NAMES OUTPUT_FILE\n"; + << " INPUT_PELEE_NTUPLE_FILE SELECTION_NAMES EXPERIMENT_NAME OUTPUT_FILE\n"; return 1; } std::string input_file_name( argv[1] ); - std::string output_file_name( argv[3] ); + std::string output_file_name( argv[4] ); std::vector< std::string > selection_names; @@ -190,7 +259,13 @@ int main( int argc, char* argv[] ) { selection_names.push_back( sel_name ); } - analyzer( input_file_name, selection_names, output_file_name ); + std::string experiment = argv[3]; + if ( experiment != "uboone" && experiment != "sbnd" ) { + std::cerr << "Invalid experiment name: " << experiment << '\n'; + return 1; + } + analyzer( input_file_name, selection_names, output_file_name, experiment ); + std::cout << "Finished running analyzer\n"; return 0; } diff --git a/src/app/Slice_Plots.C b/src/app/Slice_Plots.C index fdd7a2c6f..4c998dcd0 100644 --- a/src/app/Slice_Plots.C +++ b/src/app/Slice_Plots.C @@ -63,7 +63,8 @@ namespace { } // anonymous namespace -void tutorial_slice_plots(std::string FPM_Config, std::string SYST_Config, std::string SLICE_Config, std::string Univ_Output, std::string Plot_OutputDir) { +void tutorial_slice_plots(std::string FPM_Config, std::string SYST_Config, std::string SLICE_Config, std::string Univ_Output, std::string Plot_OutputDir, + std::string experiment) { // Counter to ensure plots aren't overwritten uint FileNameCounter = 0; @@ -78,6 +79,7 @@ void tutorial_slice_plots(std::string FPM_Config, std::string SYST_Config, std:: std::cout << "\tUniv_Output: " << Univ_Output << std::endl; std::cout << "\tPlot_OutputDir: " << Plot_OutputDir << std::endl; std::cout << "\t\tWith filename: " << PlotFileName << std::endl; + std::cout << "\tExperiment: " << experiment << std::endl; std::cout << "\n" << std::endl; #ifdef USE_FAKE_DATA @@ -95,9 +97,18 @@ void tutorial_slice_plots(std::string FPM_Config, std::string SYST_Config, std:: } delete temp_file; - auto* syst_ptr = new MCC9SystematicsCalculator(Univ_Output, SYST_Config); + MCC9SystematicsCalculator* syst_ptr = nullptr; + if (experiment == "uboone"){ + syst_ptr = new MCC9SystematicsCalculator(Univ_Output, SYST_Config); + } + else if (experiment == "sbnd"){ + // Set the correct CV universe name for SBND + // FIXME: Do we need a CV universe name for SBND? + syst_ptr = new MCC9SystematicsCalculator(Univ_Output, SYST_Config, "", "unweighted"); + } auto& syst = *syst_ptr; + // Get access to the relevant histograms owned by the SystematicsCalculator // object. These contain the reco bin counts that we need to populate the // slices below. @@ -111,11 +122,13 @@ void tutorial_slice_plots(std::string FPM_Config, std::string SYST_Config, std:: TH2D* category_hist = syst.cv_universe().hist_categ_.get(); + // Total MC+EXT prediction in reco bin space. Start by getting EXT. TH1D* reco_mc_plus_ext_hist = dynamic_cast< TH1D* >( reco_ext_hist->Clone("reco_mc_plus_ext_hist") ); reco_mc_plus_ext_hist->SetDirectory( nullptr ); + // Add in the CV MC prediction reco_mc_plus_ext_hist->Add( syst.cv_universe().hist_reco_.get() ); @@ -308,9 +321,9 @@ void tutorial_slice_plots(std::string FPM_Config, std::string SYST_Config, std:: } int main(int argc, char* argv[]) { - if ( argc != 6 ) { + if ( argc != 7 ) { std::cout << "Usage: Slice_Plots FPM_CONFIG" - << " SYST_Config SLICE_Config Univ_Output Plot_OutputDir\n"; + << " SYST_Config SLICE_Config Univ_Output Plot_OutputDir EXPERIMENT\n"; return 1; } @@ -323,7 +336,8 @@ int main(int argc, char* argv[]) { std::string SLICE_Config( argv[3] ); std::string Univ_Output( argv[4] ); std::string Plot_OutputDir( argv[5] ); + std::string experiment( argv[6] ); - tutorial_slice_plots(FPM_Config, SYST_Config, SLICE_Config, Univ_Output, Plot_OutputDir); + tutorial_slice_plots(FPM_Config, SYST_Config, SLICE_Config, Univ_Output, Plot_OutputDir, experiment); return 0; } diff --git a/src/app/Unfolder.C b/src/app/Unfolder.C index 3c8867ab1..f98a1a805 100644 --- a/src/app/Unfolder.C +++ b/src/app/Unfolder.C @@ -15,6 +15,8 @@ #include "XSecAnalyzer/SliceBinning.hh" #include "XSecAnalyzer/SliceHistogram.hh" +#include + //Useful DEBUG options which can be turned on/off std::string PlotExtension = ".pdf"; std::string TextExtension = ".txt"; @@ -175,6 +177,7 @@ void Unfolder(std::string XSEC_Config, std::string SLICE_Config, std::string Out } int main( int argc, char* argv[] ) { + feenableexcept(FE_ALL_EXCEPT); if ( argc != 4 ) { std::cout << "Usage: Unfolder.C XSEC_Config" diff --git a/src/binning/BinSchemeFactory.cxx b/src/binning/BinSchemeFactory.cxx index 15c92bedc..724d638c9 100644 --- a/src/binning/BinSchemeFactory.cxx +++ b/src/binning/BinSchemeFactory.cxx @@ -1,6 +1,7 @@ // XSecAnalyzer includes #include "XSecAnalyzer/Binning/BinSchemeFactory.hh" #include "XSecAnalyzer/Binning/TutorialBinScheme.hh" +#include "XSecAnalyzer/Binning/SBND_CC1muX_BinScheme.hh" BinSchemeFactory::BinSchemeFactory() { } @@ -14,6 +15,10 @@ BinSchemeBase* BinSchemeFactory::CreateBinScheme( bs = new TutorialBinScheme; bs->Init(); } + else if ( bin_scheme_name == "SBND_CC1muX_BinScheme" ) { + bs = new SBND_CC1muX_BinScheme; + bs->Init(); + } else { std::cerr << "Binning scheme name requested: " << bin_scheme_name << " is not implemented in " << __FILE__ << '\n'; diff --git a/src/binning/SBND_CC1muX_BinScheme.cxx b/src/binning/SBND_CC1muX_BinScheme.cxx new file mode 100644 index 000000000..d200fe2d1 --- /dev/null +++ b/src/binning/SBND_CC1muX_BinScheme.cxx @@ -0,0 +1,56 @@ +// XSecAnalyzer includes +#include "XSecAnalyzer/Binning/SBND_CC1muX_BinScheme.hh" + +#include + +SBND_CC1muX_BinScheme::SBND_CC1muX_BinScheme() : BinSchemeBase( "SBND_CC1muX_BinScheme" ) {} + +void SBND_CC1muX_BinScheme::DefineBlocks() { + + /////// Set some standard variables before managing the blocks + + // TTree name for the post-processed ntuples + ntuple_ttree_name_ = "stv_tree"; + + // Run numbers to use when plotting migration matrices + runs_to_use_ = { 1 }; + + // Prefix for the output bin and slice configuration text files + out_config_prefix_ = "SBND_CC1muX_"; + + // Selection to use with this binning scheme + selection_name_ = "SBND_CC1muX"; + + // TDirectory file name to use when producing the univmake output histograms + out_tdir_name_ = "SBND_CC1muX_1D"; + + /////// Define the blocks of bins in both true and reco space + + // First block: cos_theta_mu in 1D + std::vector< double > cos_theta_mu_1D_edges = { -1., -0.5, 0., 0.27, + 0.45, 0.62, 0.76, 0.86, 0.94, 1.}; + + Block1D* b1t = new Block1D( "true_leading_muon_costheta", + "muon cos#theta", "\\cos\\theta_{\\mu}", cos_theta_mu_1D_edges, + "MC_Signal", kSignalTrueBin ); + + Block1D* b1r = new Block1D( "leading_muon_costheta", + "muon cos#theta", "\\cos\\theta_{\\mu}", cos_theta_mu_1D_edges, + "Selected", kOrdinaryRecoBin ); + + vect_block.emplace_back( b1t, b1r ); + + // Second block: p_mu in 1D + std::vector< double > pmu_1D_edges = { 0., 0.3, 0.5, 0.7, 0.9, 1.1, 1.3, + 1.5, 2.0, 3.0, 10000.}; + + Block1D* b2t = new Block1D( "true_leading_muon_momentum", + "p_{#mu}; (GeV)", "p_{\\mu}; (GeV)", pmu_1D_edges, + "MC_Signal", kSignalTrueBin ); + + Block1D* b2r = new Block1D( "leading_muon_momentum", + "p_{#mu}; (GeV)", "p_{\\mu}; (GeV)", pmu_1D_edges, + "Selected", kOrdinaryRecoBin ); + + vect_block.emplace_back( b2t, b2r ); +} diff --git a/src/selections/SBND_CC1muX.cxx b/src/selections/SBND_CC1muX.cxx new file mode 100644 index 000000000..930da71af --- /dev/null +++ b/src/selections/SBND_CC1muX.cxx @@ -0,0 +1,68 @@ +// XSecAnalyzer includes +#include "XSecAnalyzer/Selections/SBND_CC1muX.hh" + +SBND_CC1muX::SBND_CC1muX() : SelectionBase( "SBND_CC1muX" ) { + this->define_category_map(); // Define the mapping between event categories and their string labels +} + +void SBND_CC1muX::define_constants() { + // Define reco and true fiducial volumes alongside any other constants used + // within selection cuts +} + +void SBND_CC1muX::compute_reco_observables( AnalysisEvent* event ) { + // Calculate reconstructed kinematic variables to be saved in the output + leading_muon_momentum = event->leading_muon_momentum_; + leading_muon_costheta = event->leading_muon_costheta_; +} + +void SBND_CC1muX::compute_true_observables( AnalysisEvent* event ) { + // Calculate true kinematic variables to be saved in the output + leading_muon_momentum_truth = event->leading_muon_momentum_truth_; + leading_muon_costheta_truth = event->leading_muon_costheta_truth_; +} + +int SBND_CC1muX::categorize_event( AnalysisEvent* event ) { + // Assign the event category of the selected event + return event->event_type_; +} + +bool SBND_CC1muX::define_signal(AnalysisEvent* event) { + // Determine whether an input MC event fulfills the signal definition. + // Only truth information should be used to determine the answer. + return event->event_type_ == 0; +} + +bool SBND_CC1muX::selection( AnalysisEvent* event ) { + // Determine whether an input event satisfies the selection criteria. + // Only reco information should be used to determine the answer. + //return event->is_signal_; + return static_cast(event->is_signal_); +} + +void SBND_CC1muX::define_output_branches() { + // Call set_branch() for every new variable to be saved to the output TTree + set_branch( &leading_muon_momentum, "leading_muon_momentum" ); + set_branch( &leading_muon_costheta, "leading_muon_costheta" ); + set_branch( &leading_muon_momentum_truth, "true_leading_muon_momentum" ); + set_branch( &leading_muon_costheta_truth, "true_leading_muon_costheta" ); +} + +void SBND_CC1muX::reset() { + // Set variables managed by this class to their default values. This function + // is called in preparation for analyzing each new input event. + leading_muon_momentum = BOGUS; + leading_muon_costheta = BOGUS; + leading_muon_momentum_truth = BOGUS; + leading_muon_costheta_truth = BOGUS; +} + +void SBND_CC1muX::define_category_map() { + // Define the mapping between each integer event category and + // a string label / color integer code pair + std::cout<<"Defining category map for SBND_CC1muX"< > CC1muX_MAP = { + { kUnknown, { "Unknown", kGray } }, + { kNuMuCC, { "NuMuCC", kBlue } }, + { kNC, { "NC", kOrange } }, + { kNuECC, { "NuECC", kViolet } }, + { kCosmic, { "Cosmic", kRed } }, + { kOOFV, { "OOFV", kRed } } +}; diff --git a/src/selections/SelectionBase.cxx b/src/selections/SelectionBase.cxx index a0b84d666..a3b07ece2 100644 --- a/src/selections/SelectionBase.cxx +++ b/src/selections/SelectionBase.cxx @@ -14,7 +14,6 @@ SelectionBase::SelectionBase( const std::string& sel_name ) { fv_true_ = { BOGUS, BOGUS, BOGUS, BOGUS, BOGUS, BOGUS }; fv_reco_ = { BOGUS, BOGUS, BOGUS, BOGUS, BOGUS, BOGUS }; - } void SelectionBase::setup( TTree* out_tree, bool create_branches ) { diff --git a/src/selections/SelectionFactory.cxx b/src/selections/SelectionFactory.cxx index 8c11ba791..ae226a6ba 100644 --- a/src/selections/SelectionFactory.cxx +++ b/src/selections/SelectionFactory.cxx @@ -1,5 +1,6 @@ // XSecAnalyzer includes +#include "XSecAnalyzer/Selections/SBND_CC1muX.hh" #include "XSecAnalyzer/Selections/CC1mu1p0pi.hh" #include "XSecAnalyzer/Selections/CC1mu2p0pi.hh" #include "XSecAnalyzer/Selections/CC1muNp0pi.hh" @@ -25,6 +26,9 @@ SelectionBase* SelectionFactory::CreateSelection( else if ( selection_name == "Dummy" ) { sel = new DummySelection; } + else if ( selection_name == "SBND_CC1muX" ) { + sel = new SBND_CC1muX; + } else { std::cerr << "Selection name requested: " << selection_name << " is not implemented in " << __FILE__ << '\n'; diff --git a/src/utils/MakeConfig.cxx b/src/utils/MakeConfig.cxx index c3dc56310..5fdce0c5f 100644 --- a/src/utils/MakeConfig.cxx +++ b/src/utils/MakeConfig.cxx @@ -10,12 +10,13 @@ #include "XSecAnalyzer/HistUtils.hh" #include "XSecAnalyzer/SliceBinning.hh" #include "XSecAnalyzer/UniverseMaker.hh" - #include "XSecAnalyzer/Binning/MakeConfig.hh" + // Lazy way to get compiled code for all the functions defined in headers -#include "XSecAnalyzer/AnalysisEvent.hh" -#include "XSecAnalyzer/Branches.hh" +#include "XSecAnalyzer/Event/AnalysisEvent.hh" +#include "XSecAnalyzer/Event/SBNDEvent.hh" +#include "XSecAnalyzer/Event/uBooNEEvent.hh" #include "XSecAnalyzer/Constants.hh" #include "XSecAnalyzer/ConstrainedCalculator.hh" #include "XSecAnalyzer/CovMatUtils.hh" @@ -214,6 +215,7 @@ void MakeConfig::Print(){ for ( const auto& rb : reco_bins ) out_file << rb << '\n'; out_file.close(); + std::string slice_config_output = std::getenv( "XSEC_ANALYZER_DIR" ) + std::string( "/configs/" ) + BIN_CONFIG + "slice_config.txt"; @@ -236,8 +238,10 @@ void MakeConfig::make_res_plots( const std::string& branchexpr, int num_true_bins, const std::string& mc_branchexpr, const std::string& signal_cuts, - const std::string& mc_event_weight ) + const std::string& mc_event_weight) { + + //this->Print(); // Get the outer edges of the reco-space bins. This will be used to set the // plot range for the true-space histograms. double xmin = bin_low_edges.front(); @@ -251,10 +255,11 @@ void MakeConfig::make_res_plots( const std::string& branchexpr, // true_branchexpr = "mc_" + branchexpr; //} + std::cout << "true_branchexpr: " << true_branchexpr << '\n'; // Get access to the singleton utility class that manages the processed // ntuple files const FilePropertiesManager& fpm = FilePropertiesManager::Instance(); - + std::cout << "FilePropertiesManager instance created\n"; // Make a TChain to process the CV numu ntuples from the requested run(s). // For the resolution studies, this is all we really need. Add the // appropriate ntuples to the TChain. Also tally the total simulated @@ -262,26 +267,34 @@ void MakeConfig::make_res_plots( const std::string& branchexpr, TChain chain( "stv_tree" ); double total_simulated_POT = 0.; + const auto& ntuple_map = fpm.ntuple_file_map(); for ( const auto& run : runs ) { + std::cout << "Adding run: " << run << '\n'; const auto& ntuple_files = ntuple_map.at( run ) .at( NtupleFileType::kNumuMC ); for ( const auto& file_name : ntuple_files ) { + std::cout << "Adding file: " << file_name << '\n'; chain.Add( file_name.c_str() ); + std::cout << "Added file: " << file_name << '\n'; TFile temp_file( file_name.c_str(), "read" ); TParameter* temp_pot = nullptr; temp_file.GetObject( "summed_pot", temp_pot ); double pot = temp_pot->GetVal(); total_simulated_POT += pot; + std::cout << "Added POT: " << pot << '\n'; } } + std::cout << "Total simulated POT: " << total_simulated_POT << '\n'; + // Dummy counter used to ensure that each histogram generated by this // function has a unique name to use with TTree::Draw() // static int hist_count = 0; put it in header file if ( show_bin_plots ) { + std::cout << "Making bin plots\n"; for ( size_t b = 1u; b < bin_low_edges.size(); ++b ) { ++hist_count; @@ -293,6 +306,9 @@ void MakeConfig::make_res_plots( const std::string& branchexpr, + std::to_string(b) + "; " + variable_title + "; events").c_str(), num_true_bins, xmin, xmax ); + std::cout<< "true_hist_plot: " << ("true events in " + variable_title + " reco bin " + + std::to_string(b) + "; " + variable_title + "; events").c_str() << '\n'; + double reco_bin_min = bin_low_edges.at( b - 1 ); double reco_bin_max = bin_low_edges.at( b ); std::string cuts = mc_event_weight + " * (is_mc && " + signal_cuts @@ -300,6 +316,8 @@ void MakeConfig::make_res_plots( const std::string& branchexpr, + std::to_string( reco_bin_min ) + " && " + branchexpr + " < " + std::to_string( reco_bin_max ) + ')'; + std::cout<< "cuts: " << cuts << '\n'; + chain.Draw( (true_branchexpr + " >> " + true_hist_name).c_str(), cuts.c_str(), "goff" ); @@ -336,6 +354,7 @@ void MakeConfig::make_res_plots( const std::string& branchexpr, // Also get the total number of reco bins for the 2D smearing plot int num_reco_bins = bin_low_edges.size() - 1u; + // Compute the smearing matrix for a choice of true bins that exactly // match the ones in reco space. std::string smear_hist_name = "smear_hist" + std::to_string( hist_count ); @@ -350,6 +369,9 @@ void MakeConfig::make_res_plots( const std::string& branchexpr, std::string smear_cuts = mc_event_weight + " * (is_mc && " + signal_cuts + " && " + selection + ')'; + std::cout << "smear_expr: " << smear_expr << '\n'; + std::cout << "smear_cuts: " << smear_cuts << '\n'; + chain.Draw( smear_expr.c_str(), smear_cuts.c_str(), "goff" ); // Before renormalizing the smearing matrix histogram, take a projection @@ -999,4 +1021,6 @@ void MakeConfig::BinScheme() { RUNS = bin_scheme_->runs_to_use_; vect_block = &bin_scheme_->vect_block; + + bs->Print(); } diff --git a/src/utils/SystematicsCalculator.cxx b/src/utils/SystematicsCalculator.cxx index 34efe511d..846c30cb1 100644 --- a/src/utils/SystematicsCalculator.cxx +++ b/src/utils/SystematicsCalculator.cxx @@ -69,9 +69,13 @@ void CovMatrix::add_or_clone( std::unique_ptr& mine, TH2D* other ) { SystematicsCalculator::SystematicsCalculator( const std::string& input_respmat_file_name, const std::string& syst_cfg_file_name, - const std::string& respmat_tdirectoryfile_name ) + const std::string& respmat_tdirectoryfile_name, + const std::string& cv_univ_name ) : syst_config_file_name_( syst_cfg_file_name ) { + // Set the name of the central value universe + CV_UNIV_NAME = cv_univ_name; + // Get access to the FilePropertiesManager singleton class const auto& fpm = FilePropertiesManager::Instance(); @@ -89,7 +93,20 @@ SystematicsCalculator::SystematicsCalculator( // for the combination of all analysis ntuples. Otherwise, we won't // write to the file. // TODO: consider adjusting this to be less dangerous - TFile in_tfile( input_respmat_file_name.c_str(), "update" ); + std::cout << "input_respmat_file_name: " << input_respmat_file_name << '\n'; + // TFile in_tfile(input_respmat_file_name.c_str(), "update"); + // if (in_tfile.IsZombie()) { + // std::cerr << "Error: Could not open file " << input_respmat_file_name << std::endl; + // return; // Handle the error as needed + // } + TFile* in_tfile = nullptr; + try{ + in_tfile = TFile::Open(input_respmat_file_name.c_str(), "read"); + } + catch( const std::exception& e ){ + std::cout<<"whut"<At( 0 )->GetName(); + tdf_name = in_tfile->GetListOfKeys()->At( 0 )->GetName(); std::cout << "respmat_tdirectoryfile_name given to SystematicsCalculator" << " is empty. Using default: " << tdf_name << '\n'; } - in_tfile.GetObject( tdf_name.c_str(), root_tdir ); + in_tfile->GetObject( tdf_name.c_str(), root_tdir ); if ( !root_tdir ) { std::cerr << "tdf_name.c_str():" << tdf_name.c_str() << '\n'; - in_tfile.Print(); + in_tfile->Print(); throw std::runtime_error( "Invalid root TDirectoryFile!" ); } @@ -135,6 +152,7 @@ SystematicsCalculator::SystematicsCalculator( TDirectoryFile* total_subdir = nullptr; root_tdir->GetObject( total_subfolder_name.c_str(), total_subdir ); + std::cout << "total_subdir: " << total_subdir << '\n'; // Use the factory to load and instantiate the selection object used to // categorize events in the universes @@ -145,6 +163,8 @@ SystematicsCalculator::SystematicsCalculator( " event categorization" ); } + std::cout << "sel_for_categ_name: " << *sel_for_categ_name << '\n'; + SelectionFactory sf; //SelectionBase* temp_sb = sf.CreateSelection( *sel_for_categ_name ); //sel_for_categ_.reset( temp_sb ); @@ -154,14 +174,15 @@ SystematicsCalculator::SystematicsCalculator( const auto& category_map = sel_for_categ_->category_map(); Universe::set_num_categories( category_map.size() ); - + std::cout<<"here\n"; if ( !total_subdir ) { - + std::cout << "total_subdir is null\n"; // We couldn't find the pre-computed POT-summed universe histograms, // so make them "on the fly" and store them in this object this->build_universes( *root_tdir ); + std::cout << "total_subfolder_name: " << total_subfolder_name << '\n'; // Create a new TDirectoryFile as a subfolder to hold the POT-summed // universe histograms total_subdir = new TDirectoryFile( total_subfolder_name.c_str(), @@ -170,8 +191,10 @@ SystematicsCalculator::SystematicsCalculator( // Write the universes to the new subfolder for faster loading // later this->save_universes( *total_subdir ); + std::cout << "total_subdir: " << total_subdir << '\n'; } else { + std::cout << "total_subdir is not null\n"; // Retrieve the POT-summed universe histograms that were built // previously this->load_universes( *total_subdir ); @@ -181,6 +204,8 @@ SystematicsCalculator::SystematicsCalculator( std::string* true_bin_spec = nullptr; std::string* reco_bin_spec = nullptr; + std::cout << "TRUE_BIN_SPEC_NAME: " << TRUE_BIN_SPEC_NAME << '\n'; + root_tdir->GetObject( TRUE_BIN_SPEC_NAME.c_str(), true_bin_spec ); root_tdir->GetObject( RECO_BIN_SPEC_NAME.c_str(), reco_bin_spec ); @@ -188,6 +213,8 @@ SystematicsCalculator::SystematicsCalculator( throw std::runtime_error( "Failed to load bin specifications" ); } + std::cout << "true_bin_spec: " << *true_bin_spec << '\n'; + num_signal_true_bins_ = 0u; std::istringstream iss_true( *true_bin_spec ); TrueBin temp_true_bin; @@ -208,6 +235,8 @@ SystematicsCalculator::SystematicsCalculator( reco_bins_.push_back( temp_reco_bin ); } + std::cout << "num_signal_true_bins_: " << num_signal_true_bins_ << '\n'; + } void SystematicsCalculator::load_universes( TDirectoryFile& total_subdir ) { @@ -219,6 +248,11 @@ void SystematicsCalculator::load_universes( TDirectoryFile& total_subdir ) { TList* universe_key_list = total_subdir.GetListOfKeys(); int num_keys = universe_key_list->GetEntries(); + // for (int i=0; iAt(i)->GetName() << '\n'; + // } + + // Loop over the keys in the TDirectoryFile. Build a universe object // for each key ending in "_2d" and store it in the rw_universes_ // map (for reweightable systematic universes), the detvar_universes_ @@ -376,7 +410,7 @@ void SystematicsCalculator::load_universes( TDirectoryFile& total_subdir ) { } void SystematicsCalculator::build_universes( TDirectoryFile& root_tdir ) { - + std::cout << "Building universes from: " << root_tdir.GetName() << '\n'; // Set default values of flags used to signal the presence of fake data. If // fake data are detected, corresponding truth information will be stored and // a check will be performed to prevent mixing real and fake data together. @@ -388,16 +422,20 @@ void SystematicsCalculator::build_universes( TDirectoryFile& root_tdir ) { std::map< int, double > run_to_bnb_trigs_map; std::map< int, double > run_to_ext_trigs_map; + std::cout << "Getting normalization factors\n"; const auto& fpm = FilePropertiesManager::Instance(); + std::cout << "fpm.data_norm_map().size(): " << fpm.data_norm_map().size() << '\n'; const auto& data_norm_map = fpm.data_norm_map(); for ( const auto& run_and_type_pair : fpm.ntuple_file_map() ) { int run = run_and_type_pair.first; const auto& type_map = run_and_type_pair.second; + std::cout << "run: " << run << '\n'; + const auto& bnb_file_set = type_map.at( NFT::kOnBNB ); for ( const std::string& bnb_file : bnb_file_set ) { const auto& pot_and_trigs = data_norm_map.at( bnb_file ); - + std::cout << "pot_and_trigs.pot_: " << pot_and_trigs.pot_ << '\n'; if ( !run_to_bnb_pot_map.count(run) ) { run_to_bnb_pot_map[ run ] = 0.; run_to_bnb_trigs_map[ run ] = 0.; @@ -408,6 +446,8 @@ void SystematicsCalculator::build_universes( TDirectoryFile& root_tdir ) { } // BNB data files + std::cout << "run_to_bnb_pot_map.at( run ): " << run_to_bnb_pot_map.at( run ) << '\n'; + const auto& ext_file_set = type_map.at( NFT::kExtBNB ); for ( const std::string& ext_file : ext_file_set ) { const auto& pot_and_trigs = data_norm_map.at( ext_file ); @@ -420,6 +460,8 @@ void SystematicsCalculator::build_universes( TDirectoryFile& root_tdir ) { } // EXT files + std::cout << "run_to_ext_trigs_map.at( run ): " << run_to_ext_trigs_map.at( run ) << '\n'; + } // runs // Now that we have the accumulated POT over all BNB data runs, sum it @@ -430,6 +472,8 @@ void SystematicsCalculator::build_universes( TDirectoryFile& root_tdir ) { total_bnb_data_pot_ += pair.second; } + std::cout << "total_bnb_data_pot_: " << total_bnb_data_pot_ << '\n'; + // Loop through the ntuple files for the various run / ntuple file type // pairs considered in the analysis. We will react differently in a run- // and type-dependent way. @@ -450,6 +494,7 @@ void SystematicsCalculator::build_universes( TDirectoryFile& root_tdir ) { for ( const std::string& file_name : file_set ) { std::cout << "PROCESSING universes for " << file_name << '\n'; + std::cout << "univ name: " << fpm.ntuple_type_to_string( type ) << '\n'; // Default to assuming that the current ntuple file is not a fake data // sample. If it is a data sample (i.e., if is_mc == false), then the @@ -588,6 +633,7 @@ void SystematicsCalculator::build_universes( TDirectoryFile& root_tdir ) { // Let's handle the fake BNB data samples first. if ( is_fake_data ) { + std::cout<<"is_fake_data\n"; // If this is our first fake BNB data ntuple file, then create // the Universe object that will store the full MC information @@ -646,6 +692,7 @@ void SystematicsCalculator::build_universes( TDirectoryFile& root_tdir ) { // Now we'll take care of the detVar and altCV samples. else if ( is_detVar || is_altCV ) { + std::cout<<"is_detVar or is_altCV\n"; std::string dv_univ_name = fpm.ntuple_type_to_string( type ); @@ -751,7 +798,7 @@ void SystematicsCalculator::build_universes( TDirectoryFile& root_tdir ) { // Now handle the reweightable systematic universes else if ( is_reweightable_mc ) { - + std::cout << "is_reweightable_mc\n"; // If this is our first reweightable MC ntuple file, then build // the map of reweighting universes from the 2D histogram keys in // its TDirectoryFile. @@ -795,6 +842,7 @@ void SystematicsCalculator::build_universes( TDirectoryFile& root_tdir ) { rw_universes_[ univ_name ] = std::vector< std::unique_ptr >(); } + std::cout << "univ_name: " << univ_name << '\n'; // Move this universe into the map. Note that the automatic // sorting of keys in a ROOT TDirectoryFile ensures that the @@ -924,7 +972,7 @@ void SystematicsCalculator::build_universes( TDirectoryFile& root_tdir ) { } - std::cout << "******* USING FAKE DATA *******\n"; + //std::cout << "******* USING FAKE DATA *******\n"; } std::cout << "\nTOTAL BNB DATA POT = " << total_bnb_data_pot_ << '\n'; @@ -1131,7 +1179,7 @@ std::unique_ptr< CovMatrixMap > SystematicsCalculator::get_covariances() const std::ifstream config_file( syst_config_file_name_ ); std::string name, type; while ( config_file >> name >> type ) { - + std::cout << "Making covariance matrix " << name << '\n'; CovMatrix temp_cov_mat = this->make_covariance_matrix( name ); // If the current covariance matrix is defined as a sum of others, then @@ -1263,6 +1311,9 @@ std::unique_ptr< CovMatrixMap > SystematicsCalculator::get_covariances() const auto end = rw_universes_.cend(); auto iter = rw_universes_.find( weight_key ); if ( iter == end ) { + for ( const auto& pair : rw_universes_ ) { + std::cout << pair.first << '\n'; + } throw std::runtime_error( "Missing weight key " + weight_key ); } const auto& alt_univ_vec = iter->second; diff --git a/src/utils/TreeUtils.cxx b/src/utils/TreeUtils.cxx new file mode 100644 index 000000000..415937bfe --- /dev/null +++ b/src/utils/TreeUtils.cxx @@ -0,0 +1,21 @@ +/* +Description: Implementation of TTree utility functions +Date: 2024-10-16 +Authors: Steven Gardiner and Brinden Carlson +*/ + +#include "XSecAnalyzer/TreeUtils.hh" + +// Helper function to set the branch addresses for the AnalysisEvent +void SetBranchAddress(TTree& etree, std::string BranchName, void* Variable) { + if (etree.GetBranch(BranchName.c_str()) == nullptr) { + std::cerr << "Branch " << BranchName << " not found in TTree" << std::endl; + return; + } + if (Variable == nullptr) { + std::cerr << "Variable is nullptr for branch " << BranchName << std::endl; + return; + } + etree.SetBranchAddress(BranchName.c_str(),Variable); + //std::cout << "Set branch address for " << BranchName << std::endl; +} \ No newline at end of file diff --git a/src/utils/UniverseMaker.cxx b/src/utils/UniverseMaker.cxx index 4a84e6475..ccbc2def2 100644 --- a/src/utils/UniverseMaker.cxx +++ b/src/utils/UniverseMaker.cxx @@ -38,7 +38,9 @@ void UniverseMaker::init( std::istream& in_file ) { //SelectionBase* temp_sel = sel_fact.CreateSelection( sel_categ_name ); //sel_for_categories_.reset( temp_sel ); //FIXME: using normal pointer to avoid invalid pointer error + std::cout << "sel_categ_name = " << sel_categ_name << '\n'; sel_for_categories_ = sel_fact.CreateSelection( sel_categ_name); + sel_for_categories_->print_category_map(); // Load the true bin definitions size_t num_true_bins; @@ -60,6 +62,11 @@ void UniverseMaker::init( std::istream& in_file ) { // Load the reco bin definitions size_t num_reco_bins; in_file >> num_reco_bins; + if ( num_reco_bins == 0 ) { + throw std::runtime_error( "The UniverseMaker object must be initialized" + " with at least one reco bin definition." ); + } + std::cout << "num_reco_bins = " << num_reco_bins << '\n'; for ( size_t rb = 0u; rb < num_reco_bins; ++rb ) { RecoBin temp_bin; in_file >> temp_bin; @@ -128,7 +135,12 @@ void UniverseMaker::prepare_formulas() { // Create one TTreeFormula for each true event category const auto& category_map = sel_for_categories_->category_map(); - Universe::set_num_categories( category_map.size() ); + size_t num_categories = category_map.size(); + if ( num_categories == 0 ) { + throw std::runtime_error( "The UniverseMaker object must be initialized" + " with at least one event category definition from the selection." ); + } + Universe::set_num_categories( num_categories ); for ( const auto& category_pair : category_map ) { int cur_category = static_cast< int >( category_pair.first ); @@ -293,6 +305,11 @@ void UniverseMaker::build_universes( } // true bins for ( const auto& rb : matched_reco_bins ) { + if (std::isnan(rb.weight_ * safe_wgt)) { + std::cerr << "NaN detected in hist_reco_ filling for " << wgt_name + << " universe " << u << " at entry " << entry << '\n'; + throw; + } universe.hist_reco_->Fill( rb.bin_index_, rb.weight_ * safe_wgt ); for ( const auto& c : matched_category_indices ) {